dcmgr/lib/dcmgr/cli/network.rb
# -*- coding: utf-8 -*-
require 'ipaddress'
module Dcmgr::Cli
class Network < Base
namespace :network
M=Dcmgr::Models
no_tasks {
include Dcmgr::Constants::Network
@@conf = Dcmgr::Configurations.dcmgr
def validate_ipv4_range
@network_addr = IPAddress::IPv4.new("#{options[:ipv4_network]}/#{options[:prefix]}").network
if options[:ipv4_gw] && !@network_addr.include?(IPAddress::IPv4.new(options[:ipv4_gw]))
Error.raise("ipv4_gw #{options[:ipv4_gw]} is out of range from network address: #{@network_addr}", 100)
end
# DHCP IP address has to be in same IP network.
if options[:dhcp] && !@network_addr.include?(IPAddress::IPv4.new(options[:dhcp]))
Error.raise("dhcp server address #{options[:dhcp]} is out of range from network address: #{@network_addr}", 100)
end
end
private :validate_ipv4_range
def map_network_params
optmap(options) { |c|
c.option(:ipv4_network) {
@network_addr.to_s
}
c.map(:domain, :domain_name)
c.map(:dhcp, :dhcp_server)
c.map(:dns, :dns_server)
c.map(:metadata, :metadata_server)
c.map(:metadata_port, :metadata_server_port)
}
end
private :map_network_params
def self.common_options
method_option :uuid, :type => :string, :desc => "UUID of the network"
method_option :ipv4_network, :type => :string, :desc => "IPv4 network address"
method_option :ipv4_gw, :type => :string, :desc => "Gateway address for IPv4 network"
method_option :prefix, :type => :numeric, :desc => "IP network mask size (1 < prefix < 32)"
method_option :domain, :type => :string, :desc => "DNS domain name of the network"
method_option :dns, :type => :string, :desc => "IP address for DNS server of the network"
method_option :dhcp, :type => :string, :desc => "IP address for DHCP server of the network"
method_option :metadata, :type => :string, :desc => "IP address for metadata server of the network"
method_option :metadata_port, :type => :string, :desc => "Port for the metadata server of the network"
method_option :bandwidth, :type => :numeric, :desc => "The maximum bandwidth for the network in Mbit/s"
method_option :description, :type => :string, :desc => "Description for the network"
method_option :account_id, :type => :string, :desc => "The account ID to own this"
method_option :metric, :type => :numeric, :desc => "Routing priority order of this network segment"
method_option :network_mode, :type => :string, :desc => "Network mode: #{NETWORK_MODES.join(', ')}"
method_option :service_type, :type => :string, :desc => "Service type of the network. (#{@@conf.service_types.keys.sort.join(', ')})"
method_option :display_name, :type => :string, :desc => "Display name of the network"
method_option :ip_assignment, :type => :string, :desc => "How to assign the IP address of the network"
end
}
desc "add [options]", "Register a new network entry"
common_options
method_options[:ipv4_network].required = true
method_options[:prefix].required = true
method_options[:account_id].default = 'a-shpoolxx'
method_options[:metric].default = 100
method_options[:network_mode].default = 'securitygroup'
method_options[:service_type].default = @@conf.default_service_type
method_options[:ip_assignment].default = 'asc'
def add
validate_ipv4_range
fields = map_network_params
puts super(M::Network,fields)
end
desc "del UUID", "Deregister a network entry"
def del(uuid)
super(M::Network,uuid)
end
desc "modify UUID [options]", "Update network information"
common_options
def modify(uuid)
validate_ipv4_range if options[:ipv4_network]
fields = map_network_params
super(M::Network,uuid,fields)
end
desc "show [UUID] [options]", "Show network(s)"
method_option :account_id, :type => :string, :desc => "Show networks with the account"
def show(uuid=nil)
if uuid
nw = M::Network[uuid] || UnknownUUIDError.raise(uuid)
puts ERB.new(<<__END, nil, '-').result(binding)
UUID: <%= nw.canonical_uuid %>
Name: <%= nw.display_name %>
Network Mode: <%= nw.network_mode %>
Service Type: <%= nw.service_type %>
Metric: <%= nw.metric %>
IPv4:
Network address: <%= nw.ipv4_ipaddress %>/<%= nw.prefix %>
Gateway address: <%= nw.ipv4_gw %>
<%- if nw.nat_network_id -%>
Outside NAT network address: <%= nw.nat_network.ipv4_ipaddress %>/<%= nw.nat_network.prefix %> (<%= nw.nat_network.canonical_uuid %>)
<%- end -%>
DHCP Information:
DHCP Server: <%= nw.dhcp_server %>
DNS Server: <%= nw.dns_server %>
<%- if nw.metadata_server -%>
Metadata Server: <%= nw.metadata_server %>
<%- end -%>
Bandwidth:
<%- if nw.bandwidth.nil? -%>
unlimited
<%- else -%>
<%= nw.bandwidth %> Mbit/s
<%- end -%>
<%- if nw.description -%>
Description:
<%= nw.description %>
<%- end -%>
__END
else
cond = {}
cond[:account_id]= options[:account_id] if options[:account_id]
nw = M::Network.filter(cond).all
puts ERB.new(<<__END, nil, '-').result(binding)
<%- nw.each { |row| -%>
<%= row.canonical_uuid %>\t<%= row.ipv4_ipaddress %>/<%= row.prefix %>
<%- } -%>
__END
end
end
desc "leases UUID", "Show IPs used in the network"
def leases(uuid)
nw = M::Network[uuid] || Error.raise("Unknown network UUID: #{uuid}", 100)
print ERB.new(<<__END, nil, '-').result(binding)
<%- nw.network_vif_ip_lease_dataset.order(:ipv4).all.each { |l| -%>
<%= "%-20s %-15s" % [l.ipv4, M::NetworkVifIpLease::TYPE_MESSAGES[l.alloc_type]] %>
<%- } -%>
__END
end
desc "reserve UUID", "Add reserved IP to the network"
method_option :ipv4, :type => :string, :required => true, :desc => "The ip address to reserve"
def reserve(uuid)
nw = M::Network[uuid] || UnknownUUIDError.raise(uuid)
reservaddr = begin
IPAddress(options[:ipv4])
rescue ArgumentError => e
Error.raise("Invalid IP address: #{options[:ipv4]}: #{e.message}", 100)
end
if nw.include?(reservaddr)
nw.network_vif_ip_lease_dataset.add_reserved(reservaddr.to_s)
else
Error.raise("IP address is out of range: #{options[:ipv4]} => #{nw.ipv4_ipaddress}/#{nw.prefix}",100)
end
end
desc "release UUID", "Release a reserved IP from the network"
method_option :ipv4, :type => :string, :required => true, :desc => "The ip address to release"
def release(uuid)
nw = M::Network[uuid] || UnknownUUIDError.raise(uuid)
releaseaddr = begin
IPAddress(options[:ipv4])
rescue ArgumentError => e
Error.raise("Invalid IP address: #{options[:ipv4]}: #{e.message}", 100)
end
if nw.include?(releaseaddr)
if nw.network_vif_ip_lease_dataset.delete_reserved(releaseaddr.to_s) == 0
Error.raise("The IP is not reserved in network #{uuid}: #{options[:ipv4]}", 100)
end
else
Error.raise("IP address is out of range: #{options[:ipv4]} => #{nw.ipv4_ipaddress}/#{nw.prefix}",100)
end
end
desc "forward UUID DCNET", "Set forward interface for the network"
def forward(uuid, dcnet)
nw = M::Network[uuid] || UnknownUUIDError.raise(uuid)
dc = M::DcNetwork.find(:name=>dcnet) || Error.raise("Unknown dc network: #{dcnet}")
nw.dc_network = dc
nw.save
end
#
# Network Vifs
#
class VifOps < Base
namespace :vif
M=Dcmgr::Models
desc "add UUID", "Register a new vif"
method_option :ipv4, :type => :string, :required => true, :desc => "The IP address"
def add(nw_uuid)
nw = M::Network[nw_uuid] || UnknownUUIDError.raise(nw_uuid)
puts nw.add_service_vif(options[:ipv4]).canonical_uuid
end
desc "add-external-ip UUID IP", "Add an external IP to vif"
def add_external_ip(vif_uuid, ip_uuid)
vif = M::NetworkVif[vif_uuid] || UnknownUUIDError.raise(nw_uuid)
ip_handle = M::IpHandle[ip_uuid] || UnknownUUIDError.raise(ip_uuid)
ip_lease = ip_handle.ip_lease || Error.raise("No NetworkVifIpLease found.", 100)
vif.network || Error.raise("Network Vif is not attached to a network.", 100)
ip_lease.network || Error.raise("IP lease is not attached to a network.", 100)
fields = {
:route_type => 'external-ip',
:outer_network_id => ip_lease.network.id,
:inner_network_id => vif.network.id,
:inner_vif_id => vif.id,
:create_options => {
:outer => {
:find_service => 'external-ip',
:ip_handle => ip_handle,
},
:inner => {
:find_ipv4 => :vif_first,
}
}
}
M::NetworkRoute.create(fields)
end
desc "add-ip UUID IP", "Add an IP handle to vif"
method_option :allow_multiple, :type => :boolean, :required => false, :desc => "Allow adding multiple IP leases to the vif"
def add_ip(vif_uuid, ip_uuid)
vif = M::NetworkVif[vif_uuid] || UnknownUUIDError.raise(nw_uuid)
ip = M::IpHandle[ip_uuid] || UnknownUUIDError.raise(ip_uuid)
ip_lease = ip.ip_lease || Error.raise("No NetworkVifIpLease found.")
vif.network == ip_lease.network || Error.raise("Vif and IP lease's network must match.", 100)
fields = {
:ip_lease => ip_lease,
:allow_multiple => options[:allow_multiple],
:attach_network => true,
}
result = vif.add_ip_lease(fields)
puts result.to_hash if result
end
desc "remove-ip UUID IP", "Add an IP handle to vif"
def remove_ip(vif_uuid, ip_uuid)
vif = M::NetworkVif[vif_uuid] || UnknownUUIDError.raise(nw_uuid)
ip = M::IpHandle[ip_uuid] || UnknownUUIDError.raise(ip_uuid)
ip_lease = ip.ip_lease || Error.raise("No NetworkVifIpLease found.", 100)
fields = {
:ip_lease => ip_lease,
# :allow_multiple => options[:allow_multiple],
# :attach_network => true,
}
vif.remove_ip_lease(fields) || Error.raise("Could not remove IP lease from vif.", 100)
end
desc "show NW", "Show network vifs on network"
def show(nw_uuid)
nw = M::Network[nw_uuid] || UnknownUUIDError.raise(nw_uuid)
ds = M::NetworkVif.where(:network_id => nw.id)
table = [['Vif', 'Network', 'Instance', 'IPv4', 'NAT IPv4']]
ds.each { |r|
table << [r.canonical_uuid,
r.network.canonical_uuid,
r.instance ? r.instance.canonical_uuid : nil,
r.direct_ip_lease.first ? r.direct_ip_lease.first.ipv4 : nil,
r.nat_ip_lease.first ? r.nat_ip_lease.first.ipv4 : nil,
]
}
shell.print_table(table)
end
protected
def self.basename
"vdc-manage #{Network.namespace} #{self.namespace}"
end
end
register VifOps, 'vif', "vif [options]", "Maintain virtual interfaces"
#
# IP Pools
#
class PoolOps < Base
namespace :pool
M=Dcmgr::Models
desc "add [options]", "Add new IP pool."
method_option :account_id, :type => :string, :default=>'a-shpoolxx', :required => true, :desc => "The account ID to own this"
method_option :uuid, :type => :string, :required => false, :desc => "UUID of the IP pool"
method_option :display_name, :type => :string, :required => true, :desc => "Display name for the IP pool"
method_option :expire_initial, :type => :numeric, :required => false, :desc => "Expiration time of newly created IP handles (seconds)"
method_option :expire_released, :type => :numeric, :required => false, :desc => "Expiration time of released IP handles (seconds)"
def add()
fields = {
:account_id => options[:account_id],
:display_name => options[:display_name],
}
fields[:uuid] = options[:uuid] if options[:uuid]
fields[:expire_initial] = options[:expire_initial] if options[:expire_initial]
fields[:expire_released] = options[:expire_released] if options[:expire_released]
puts super(M::IpPool, fields)
end
desc "add-dcn POOL DCN [options]", "Add DC Network to IP pool."
def add_dcn(pool_uuid, dcn_uuid)
pool = M::IpPool[pool_uuid] || UnknownUUIDError.raise(pool_uuid)
if M::DcNetwork.check_uuid_format(dcn_uuid)
dcn = M::DcNetwork[dcn_uuid]
else
dcn = M::DcNetwork.find(:name => dcn_uuid)
end
dcn || UnknownUUIDError.raise(dcn_uuid)
fields = {
:ip_pool_id => pool.id,
:dc_network_id => dcn.id,
}
M::IpPoolDcNetwork.create(fields)
end
desc "del-dcn POOL DCN [options]", "Remove DC Network from IP pool."
def del_dcn(pool_uuid, dcn_uuid)
pool = M::IpPool[pool_uuid] || UnknownUUIDError.raise(pool_uuid)
if M::DcNetwork.check_uuid_format(dcn_uuid)
dcn = M::DcNetwork[dcn_uuid]
else
dcn = M::DcNetwork.find(:name => dcn_uuid)
end
dcn || UnknownUUIDError.raise(dcn_uuid)
fields = {
:ip_pool_id => pool.id,
:dc_network_id => dcn.id,
}
assoc = M::IpPoolDcNetwork.find(fields)
assoc && assoc.destroy
end
desc "acquire POOL [options]", "Acquire IP lease and add it to the IP pool."
method_option :network_id, :type => :string, :required => false, :desc => "UUID of the network to lease from"
def acquire(pool_uuid)
ip_pool = M::IpPool[pool_uuid] || UnknownUUIDError.raise(pool_uuid)
network = nil
if options[:network_id]
network = M::Network[options[:network_id]] || UnknownUUIDError.raise(options[:network_id])
end
network || Error.raise("Could not find appropriate network for leasing an IP.", 100)
st = Dcmgr::Scheduler.service_type(@@conf.default_service_type)
lease = st.ip_address.schedule({:network => network, :ip_pool => ip_pool})
puts "#{lease.ip_handle.canonical_uuid} #{lease.ipv4_s}"
end
protected
def self.basename
"vdc-manage #{Network.namespace} #{self.namespace}"
end
end
register PoolOps, 'pool', "pool [options]", "Maintain IP pool information"
class HandleOps < Base
namespace :handle
M=Dcmgr::Models
desc "expire-handles", "Expire IP handles."
def expire_handles
M::IpHandle.dataset.not_leased.expired.alives.each { |handle|
p "#{handle.canonical_uuid}: #{handle.ip_lease.network.canonical_uuid} #{handle.ip_lease.ipv4_s}"
handle.destroy
}
end
protected
def self.basename
"vdc-manage #{Network.namespace} #{self.namespace}"
end
end
register HandleOps, 'handle', "handle [options]", "Maintain IP handle information"
#
# Network Routes
#
class RouteOps < Base
namespace :route
M=Dcmgr::Models
no_tasks {
def from_uuid(uuid)
nw = vif = ip_lease = nil
case uuid
when /^nw-/
nw = M::Network[uuid] || UnknownUUIDError.raise(uuid)
when /^vif-/
vif = M::NetworkVif[uuid] || UnknownUUIDError.raise(uuid)
nw = vif.network || Error.raise("No network associated with uuid: #{vif.canonical_uuid}")
when /^ip-/
ip_handle = M::IpHandle[uuid] || UnknownUUIDError.raise(uuid)
ip_lease = ip_handle.ip_lease
nw = ip_lease.network
vif = ip_lease.network_vif
else
UnknownUUIDError.raise(uuid)
end
[nw, vif, ip_lease]
end
def routes_dataset(outer_uuid, inner_uuid, outer, inner)
ds = M::NetworkRoute.dataset
if outer[2]
ds = ds.where(:network_routes__outer_lease_id => outer[2].id)
elsif outer[1]
ds = ds.join_with_outer_ip_leases.where(:outer_ip_leases__network_vif_id => outer[1].id)
elsif outer[0]
ds = ds.join_with_outer_ip_leases.where(:outer_ip_leases__network_id => outer[0].id)
else
UnknownUUIDError.raise(outer_uuid)
end
if inner[2]
ds = ds.where(:network_routes__inner_lease_id => inner[2].id)
elsif inner[1]
ds = ds.join_with_inner_ip_leases.where(:inner_ip_leases__network_vif_id => inner[1].id)
elsif inner[0]
ds = ds.join_with_inner_ip_leases.where(:inner_ip_leases__network_id => inner[0].id)
else
UnknownUUIDError.raise(inner_uuid)
end
ds
end
}
desc "add OUTER_UUID INNER_UUID", "Add route between two networks"
method_option :route_type, :type => :string, :required => true, :desc => "Route type"
def add(outer_uuid, inner_uuid)
create_options = {:outer => {}, :inner => {}}
outer_nw, outer_vif, outer_lease = from_uuid(outer_uuid)
inner_nw, inner_vif, inner_lease = from_uuid(inner_uuid)
case options[:route_type]
when 'external-ip'
create_options[:outer][:lease_ipv4] = :default if outer_lease.nil?
create_options[:outer][:find_service] = 'external-ip'
create_options[:inner][:find_ipv4] = :vif_first if inner_lease.nil?
else
Error.raise("Unknown route type.", 100)
end
create_options[:outer][:network] = outer_nw if outer_nw
create_options[:inner][:network] = inner_nw if inner_nw
create_options[:outer][:network_vif] = outer_vif if outer_vif
create_options[:inner][:network_vif] = inner_vif if inner_vif
route_data = {
:route_type => options[:route_type],
:create_options => create_options
}
route_data[:outer_lease_id] = outer_lease.id if outer_lease
route_data[:inner_lease_id] = inner_lease.id if inner_lease
result = M::NetworkRoute.create(route_data)
shell.print_table([[route_data[:route_data],
result.outer_network.canonical_uuid,
result.outer_vif ? result.outer_vif.canonical_uuid : nil,
result.outer_lease.ipv4_s,
result.inner_network.canonical_uuid,
result.inner_vif ? result.inner_vif.canonical_uuid : nil,
result.inner_lease.ipv4_s]])
end
desc "del OUTER_UUID INNER_UUID", "Delete routes between two networks"
method_option :all_route_types, :type => :boolean, :required => false, :desc => "Include all route types"
method_option :route_type, :type => :string, :required => false, :desc => "Route type"
def del(outer_uuid, inner_uuid)
outer_nw, outer_vif, outer_lease = from_uuid(outer_uuid)
inner_nw, inner_vif, inner_lease = from_uuid(inner_uuid)
ds = routes_dataset(outer_uuid, inner_uuid, from_uuid(outer_uuid), from_uuid(inner_uuid))
# If no route_type is supplied, require --all-route-types.
if options[:route_type]
ds = ds.where(:network_routes__route_type => options[:route_type])
elsif options[:all_route_types] != true
Error.raise("Either supply a 'route-type' or set 'all-route-types'.", 100)
end
table = [['Type', 'Outer NW', 'Outer Vif', 'Inner NW', 'Inner Vif']]
ds.each { |r|
table << [r.route_type,
r.outer_network ? r.outer_network.canonical_uuid : nil,
r.outer_vif ? r.outer_vif.canonical_uuid : nil,
r.outer_lease.ipv4_s,
r.inner_vif.network ? r.inner_vif.network.canonical_uuid : nil,
r.inner_vif ? r.inner_vif.canonical_uuid : nil,
r.inner_lease.ipv4_s]
r.destroy
}
shell.print_table(table)
end
desc "show NW", "Show routes on network"
def show(uuid)
ds = (M::Network[uuid] || UnknownUUIDError.raise(uuid)).network_routes
table = [['Type', 'Outer NW', 'Outer Vif', 'Inner NW', 'Inner Vif']]
ds.each { |r|
table << [r.route_type,
r.outer_network ? r.outer_network.canonical_uuid : nil,
r.outer_vif ? r.outer_vif.canonical_uuid : nil,
r.outer_lease.ipv4_s,
r.inner_vif.network ? r.inner_vif.network.canonical_uuid : nil,
r.inner_vif ? r.inner_vif.canonical_uuid : nil,
r.inner_lease.ipv4_s]
}
shell.print_table(table)
end
desc "show-between OUTER INNER", "Show routes on network"
def show_between(outer_uuid, inner_uuid)
outer_nw, outer_vif, outer_lease = from_uuid(outer_uuid)
inner_nw, inner_vif, inner_lease = from_uuid(inner_uuid)
ds = routes_dataset(outer_uuid, inner_uuid, from_uuid(outer_uuid), from_uuid(inner_uuid))
table = [['Type', 'Outer NW', 'Outer Vif', 'Inner NW', 'Inner Vif']]
ds.each { |r|
table << [r.route_type,
r.outer_network ? r.outer_network.canonical_uuid : nil,
r.outer_vif ? r.outer_vif.canonical_uuid : nil,
r.outer_lease.ipv4_s,
r.inner_vif.network ? r.inner_vif.network.canonical_uuid : nil,
r.inner_vif ? r.inner_vif.canonical_uuid : nil,
r.inner_lease.ipv4_s]
}
shell.print_table(table)
end
protected
def self.basename
"vdc-manage #{Network.namespace} #{self.namespace}"
end
end
register RouteOps, 'route', "route [options]", "Maintain routing information"
#
# Network Services
#
class ServiceOps < Base
namespace :service
M=Dcmgr::Models
no_tasks {
def get_services(uuid, options)
case uuid
when /^nw-/
filter = {}
filter[:name] = options[:service] if options[:service]
nw = M::Network[uuid] || UnknownUUIDError.raise(uuid)
nw.network_service(filter)
else
InvalidUUIDError.raise(uuid)
end
end
def prepare_vif(uuid, options)
case uuid
when /^nw-/
option_ipv4 = options[:ipv4]
if options[:no_ipv4] != true
option_ipv4 || Error.raise("IP address is required when passing network UUID.", 1)
end
if options[:unique] == true
options[:service] || Error.raise("Unique service parameter requires service arg.", 1)
get_services(uuid, {:service => options[:service]}).empty? || Error.raise("Service must be unique on network.", 1)
end
nw = M::Network[uuid] || UnknownUUIDError.raise(uuid)
nw.add_service_vif(options[:ipv4])
when /^vif-/
options[:ipv4].nil? || Error.raise("Cannot pass IP address for VIF UUID.", 1)
M::NetworkVif[uuid] || UnknownUUIDError.raise(uuid)
else
InvalidUUIDError.raise(uuid)
end
end
}
desc "dhcp VIF", "Set DHCP service for network"
method_option :ipv4, :type => :string, :required => false, :desc => "The ip address"
def dhcp(uuid)
vif = prepare_vif(uuid, options)
puts vif.canonical_uuid
service_data = {
:network_vif_id => vif.id,
:name => 'dhcp',
:incoming_port => 67,
:outgoing_port => 68,
}
M::NetworkService.create(service_data)
end
desc "dns VIF", "Set DNS service for network"
method_option :ipv4, :type => :string, :required => false, :desc => "The ip address"
def dns(uuid)
vif = prepare_vif(uuid, options)
puts vif.canonical_uuid
service_data = {
:network_vif_id => vif.id,
:name => 'dns',
:incoming_port => 53,
}
M::NetworkService.create(service_data)
end
desc "gateway VIF", "Set gateway for network"
method_option :ipv4_from, :type => :string, :required => false, :desc => "The ip address"
def gateway(uuid_from)
vif = prepare_vif(uuid_from, {:ipv4 => options[:ipv4_from]})
nw = vif.network || Error.raise("Not attached to a network: #{uuid_from}", 1)
puts "#{vif.canonical_uuid}"
service_data = {
:network_vif_id => vif.id,
:name => 'gateway',
}
M::NetworkService.create(service_data)
end
desc "external-ip NW", "Add external-ip service to network"
# method_option :no_ip, :type => :boolean, :required => false, :desc => "Don't lease any IP address"
def external_ip(uuid_from)
vif = prepare_vif(uuid_from, {:unique => true, :service => 'external-ip', :no_ipv4 => true})
nw = vif.network || Error.raise("Not attached to a network: #{uuid_from}", 1)
puts "#{vif.canonical_uuid}"
service_data = {
:network_vif_id => vif.id,
:name => 'external-ip',
}
M::NetworkService.create(service_data)
end
desc "show NW", "Show services on network"
method_option :service, :type => :string, :required => false, :desc => "The service name"
def show(uuid)
ds = get_services(uuid, options)
table = [['Vif', 'Name', 'IPv4', 'NAT IPv4', 'Incoming Port', 'Outgoing Port']]
ds.each { |r|
vif = r.network_vif
table << [vif.canonical_uuid,
r.name,
vif.direct_ip_lease.first ? vif.direct_ip_lease.first.ipv4 : nil,
vif.nat_ip_lease.first ? vif.nat_ip_lease.first.ipv4 : nil,
r.incoming_port,
r.outgoing_port]
}
shell.print_table(table)
end
desc "remove NW", "Remove services on network"
method_option :service, :type => :string, :required => true, :desc => "The service name"
def remove(uuid)
ds = get_services(uuid, options)
table = []
ds.each { |r|
table << [r.network_vif.canonical_uuid, r.name]
r.destroy
}
shell.print_table(table)
end
protected
def self.basename
"vdc-manage #{Network.namespace} #{self.namespace}"
end
end
register ServiceOps, 'service', "service [options]", "Maintain network services"
class DcOps < Base
namespace :dc
M=Dcmgr::Models
include Dcmgr::Constants::Network
desc "add NAME [options]", "Add new dc network. (NAME must be unique)"
method_option :uuid, :type => :string, :desc => "UUID of the network"
method_option :description, :type => :string, :desc => "Description for the dc network"
method_option :allow_new_networks, :type => :boolean, :default => false, :desc => "Allow user to create new networks"
def add(name)
M::DcNetwork.find(:name=>name) && Error.raise("Duplicate dc network name: #{name}", 100)
fields=options.dup
fields[:name]=name
puts super(M::DcNetwork, fields)
end
desc "modify UUID/NAME [options]", "Modify dc network parameters"
method_option :uuid, :type => :string, :desc => "UUID of the network"
method_option :name, :type => :string, :desc => "Name of the network"
method_option :description, :type => :string, :desc => "Description for the dc network"
def modify(uuid)
dc = find_by_name_or_uuid(uuid)
super(M::DcNetwork, dc.canonical_uuid, options.dup)
end
desc "add-network-mode UUID/NAME MODENAME", "Add network mode (#{NETWORK_MODES.join(', ')})"
def add_network_mode(uuid, modename)
dc = find_by_name_or_uuid(uuid)
dc.offering_network_modes.push(modename)
dc.save
end
desc "del-network-mode UUID/NAME MODENAME", "Delete network mode (#{NETWORK_MODES.join(', ')})"
def del_network_mode(uuid, modename)
dc = find_by_name_or_uuid(uuid)
dc.offering_network_modes.delete(modename)
dc.save
end
desc "del UUID/NAME [options]", "Delete dc network"
def del(name)
dc = find_by_name_or_uuid(name)
dc.destroy
end
desc "show [UUID/NAME]", "Show/List dc network"
def show(name=nil)
if name
dc = find_by_name_or_uuid(uuid)
print ERB.new(<<__END, nil, '-').result(binding)
DC Network UUID: <%= dc.canonical_uuid %>
DC Network Name: <%= dc.name %>
Offering Network Mode: <%= dc.offering_network_modes.join(', ') %>
<%- if dc.description -%>
Description:
<%= dc.description %>
<%- end -%>
__END
else
print ERB.new(<<__END, nil, '-').result(binding)
<%- M::DcNetwork.order(:id).all.each { |l| -%>
<%= "%-20s %-15s" % [l.canonical_uuid, l.name] %>
<%- } -%>
__END
end
end
protected
def self.basename
"vdc-manage #{Network.namespace} #{self.namespace}"
end
no_tasks {
def find_by_name_or_uuid(name)
begin
M::DcNetwork[name]
rescue
M::DcNetwork.find(:name=>name) || Error.raise("Unknown dc network: #{name}", 100)
end
end
}
end
register DcOps, 'dc', "dc [options]", "Maintain dc network"
class DhcpOps < Base
namespace :dhcp
M=Dcmgr::Models
desc "addrange UUID ADDRESS_BEGIN ADDRESS_END", "Add dynamic IP address range to the network"
def addrange(uuid, range_begin, range_end)
nw = M::Network[uuid] || UnknownUUIDEntry.raise
nw.add_ipv4_dynamic_range(range_begin, range_end)
end
desc "delrange UUID ADDRESS_BEGIN ADDRESS_END", "Delete dynamic IP address range from the network"
def delrange(uuid, range_begin, range_end)
nw = M::Network[uuid] || UnknownUUIDEntry.raise
nw.del_ipv4_dynamic_range(range_begin, range_end)
end
desc "show [UUID]", "Show dynamic IP address range"
def show(uuid=nil)
if uuid
nw = M::Network[uuid] || UnknownUUIDEntry.raise
print ERB.new(<<__END, nil, '-').result(binding)
Network UUID:
<%= nw.canonical_uuid %>
Dynamic IP Address Range:
<%- nw.dhcp_range_dataset.order_by(:range_begin).each { |r| -%>
<%= r.range_begin.to_s %> - <%= r.range_end.to_s %>
<%- } -%>
__END
else
cond = {}
nw = M::Network.filter(cond).all
print ERB.new(<<__END, nil, '-').result(binding)
<%- nw.each { |row| -%>
<%= row.canonical_uuid %>\t<%= row.dhcp_range_dataset.count %>
<%- } -%>
__END
end
end
protected
def self.basename
"vdc-manage #{Network.namespace} #{self.namespace}"
end
end
register DhcpOps, 'dhcp', "dhcp [options]", "Maintain dhcp parameters"
end
end