1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

Feature #3306: Add Distributed Network support for vCenter

Add VLAN retrieval
This commit is contained in:
Tino Vazquez 2014-11-27 19:21:10 +01:00 committed by Ruben S. Montero
parent 547bc6c8a5
commit 256d8a73db
2 changed files with 197 additions and 10 deletions

View File

@ -214,4 +214,95 @@ cmd=CommandParser::CmdParser.new(ARGV) do
exit 0
end
network_desc = <<-EOT.unindent
Import vCenter networks into OpenNebula
EOT
command :networks, network_desc, :options=>[ VCENTER, USER, PASS ] do
if options[:vuser].nil? ||
options[:vpass].nil? ||
options[:vcenter].nil?
STDERR.puts "vCenter connection parameters are mandatory to import"\
" vCenter networks:\n"\
"\t --vcenter vCenter hostname\n"\
"\t --vuser username to login in vcenter\n"\
"\t --vpass password for the user"
exit -1
end
begin
STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
vc = VCenterDriver::VIClient.new_connection(
:user => options[:vuser],
:password => options[:vpass],
:host => options[:vcenter])
STDOUT.print "done!\n\n"
STDOUT.print "Looking for vCenter networks..."
rs = vc.vcenter_networks
STDOUT.print "done!\n"
rs.each {|dc, tmps|
STDOUT.print "\nDo you want to process datacenter #{dc} [y/n]? "
next if STDIN.gets.strip.downcase != 'y'
if tmps.empty?
STDOUT.print " No Networks found in #{dc}...\n\n"
next
end
tmps.each{ |n|
print_str = "\n * Network found:\n"\
" - Name : #{n[:name]}\n"\
" - Type : #{n[:type]}\n"
print_str += " - VLAN ID : #{n[:vlan]}\n" if n[:vlan]
print_str += " Import this Network [y/n]? "
STDOUT.print print_str
next if STDIN.gets.strip.downcase != 'y'
STDOUT.print " How many VMs are you planning"\
" to fit into this network [255]? "
size = STDIN.gets.strip
size = "255" if size.to_i.to_s != size
one_vn = ::OpenNebula::VirtualNetwork.new(
::OpenNebula::Template.build_xml, vc.one)
vnet_template = "NAME=\"#{n[:name]}\"\n" +
"BRIDGE=\"#{n[:name]}\"\n" +
"VCENTER_TYPE=\"#{n[:type]}\"" +
"AR=[\n" +
" TYPE = \"ETHER\"\n," +
" SIZE = \"#{size.to_i}\"\n]"
vnet_template += "VLAN=\"YES\"\nVLAN_ID=#{n[:vlan]}" if n[:vlan]
rc = one_vn.allocate(vnet_template)
if ::OpenNebula.is_error?(rc)
STDOUT.puts " Error creating virtual network: " +
" #{rc.message}\n"
else
STDOUT.puts " OpenNebula virtual network " +
"#{one_vn.id} created with size #{size}!\n"
end
}
}
rescue Exception => e
STDOUT.puts "error: #{e.message}"
exit -1
end
exit 0
end
end

View File

@ -129,7 +129,7 @@ class VIClient
########################################################################
# Initialize a VIConnection based just on the VIM parameters. The
# OpenNebula client is also initilialize
# OpenNebula client is also initilialized
########################################################################
def self.new_connection(user_opts)
@ -166,6 +166,23 @@ class VIClient
end
end
########################################################################
# Searches the associated vmFolder of the DataCenter for the current
# connection. Returns a RbVmomi::VIM::VirtualMachine or nil if not found
# @param vm_name [String] the UUID of the VM or VM Template
########################################################################
def find_vm(vm_name)
vms = get_entities(@dc.vmFolder, 'VirtualMachine')
return vms.find do |v|
begin
v.name == vm_name
rescue ManagedObjectNotFound
false
end
end
end
########################################################################
# Builds a hash with the DataCenter / ClusterComputeResource hierarchy
# for this VCenter.
@ -219,6 +236,63 @@ class VIClient
return vm_templates
end
########################################################################
# Builds a hash with the Datacenter / CCR (Distributed)Networks
# for this VCenter
# @return [Hash] in the form
# { dc_name [String] => Networks [Array] }
########################################################################
def vcenter_networks
vcenter_networks = {}
datacenters = get_entities(@root, 'Datacenter')
datacenters.each { |dc|
networks = get_entities(dc.networkFolder, 'Network' )
one_nets = []
networks.each { |n|
one_nets << {:name => n.name,
:bridge => n.name,
:type => "Port Group"}
}
vcenter_networks[dc.name] = one_nets
networks = get_entities(dc.networkFolder,
'DistributedVirtualPortgroup' )
one_nets = []
networks.each { |n|
one_net = {:name => n.name,
:bridge => n.name,
:type=> "Distributed Port Group"}
vlan = n.config.defaultPortConfig.vlan.vlanId
if vlan != 0
if vlan.is_a? Array
vlan_str = ""
vlan.each{|v|
vlan_str += v.start + ".." + v.end + ","
}
vlan_str.chop!
else
vlan_str = vlan.to_s
end
one_net[:vlan] = vlan_str
end
one_nets << one_net
}
vcenter_networks[dc.name] += one_nets
}
return vcenter_networks
end
def self.translate_hostname(hostname)
host_pool = OpenNebula::HostPool.new(::OpenNebula::Client.new())
rc = host_pool.info
@ -820,7 +894,9 @@ private
# Returns the spec to reconfig a VM and add a NIC
########################################################################
def self.calculate_addnic_spec(vm, mac, bridge, model)
model = model.nil? ? nil : model.downcase
network = vm.runtime.host.network.select{|n| n.name==bridge}
backing = nil
if network.empty?
raise "Network #{bridge} not found in host #{vm.runtime.host.name}"
@ -836,8 +912,6 @@ private
end
}
model = model.nil? ? nil : model.downcase
nic_card = case model
when "virtuale1000"
RbVmomi::VIM::VirtualE1000
@ -857,9 +931,19 @@ private
RbVmomi::VIM::VirtualE1000
end
backing = RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(
:deviceName => bridge,
:network => network)
if network.class == RbVmomi::VIM::Network
backing = RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(
:deviceName => bridge,
:network => network)
else
port = RbVmomi::VIM::DistributedVirtualSwitchPortConnection(
:switchUuid =>
network.config.distributedVirtualSwitch.uuid,
:portgroupKey => network.key)
backing =
RbVmomi::VIM.VirtualEthernetCardDistributedVirtualPortBackingInfo(
:port => port)
end
return {:operation => :add,
:device => nic_card.new(
@ -920,10 +1004,22 @@ private
:powerOn => false,
:template => false)
vm = vc_template.CloneVM_Task(
:folder => vc_template.parent,
:name => "one-#{vmid}",
:spec => clone_spec).wait_for_completion
begin
vm = vc_template.CloneVM_Task(
:folder => vc_template.parent,
:name => "one-#{vmid}",
:spec => clone_spec).wait_for_completion
rescue Exception => e
if e.message.start_with?('DuplicateName')
vm = connection.find_vm("one-#{vmid}")
vm.Destroy_Task.wait_for_completion
vm = vc_template.CloneVM_Task(
:folder => vc_template.parent,
:name => "one-#{vmid}",
:spec => clone_spec).wait_for_completion
end
end
vm_uuid = vm.config.uuid