1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-28 17:57:22 +03:00

F #4913: Add code required by Sunstone to import existing disks and nics in vcenter templates

This commit is contained in:
mcabrerizo 2017-03-31 14:06:33 +02:00
parent 212673429c
commit fe8e9886bb
6 changed files with 207 additions and 100 deletions

View File

@ -99,7 +99,6 @@ get '/vcenter/templates' do
error 404, error.to_json error 404, error.to_json
end end
#ctemplates = templates.select{|t| t[:host] == params[:name]}
[200, templates.to_json] [200, templates.to_json]
rescue Exception => e rescue Exception => e
logger.error("[vCenter] " + e.message) logger.error("[vCenter] " + e.message)
@ -108,6 +107,50 @@ get '/vcenter/templates' do
end end
end end
get '/vcenter/template/:vcenter_ref' do
begin
t = {}
t[:one] = ""
template = VCenterDriver::VirtualMachine.new_from_ref(params[:vcenter_ref], vcenter_client)
vc_uuid = vcenter_client.vim.serviceContent.about.instanceUuid
dpool = VCenterDriver::VIHelper.one_pool(OpenNebula::DatastorePool)
ipool = VCenterDriver::VIHelper.one_pool(OpenNebula::ImagePool)
npool = VCenterDriver::VIHelper.one_pool(OpenNebula::VirtualNetworkPool)
# Create images or get disks information for template
error, template_disks = template.import_vcenter_disks(vc_uuid, dpool, ipool)
if !error.empty?
msg = error
logger.error("[vCenter] " + msg)
error = Error.new(msg)
error 404, error.to_json
end
t[:one] << template_disks
# Create images or get nics information for template
error, template_nics = template.import_vcenter_nics(vc_uuid, npool)
if !error.empty?
msg = error
logger.error("[vCenter] " + msg)
error = Error.new(msg)
error 404, error.to_json
end
t[:one] << template_nics
[200, t.to_json]
rescue Exception => e
logger.error("[vCenter] " + e.message)
error = Error.new(e.message)
error 403, error.to_json
end
end
get '/vcenter/networks' do get '/vcenter/networks' do
begin begin
dc_folder = VCenterDriver::DatacenterFolder.new(vcenter_client) dc_folder = VCenterDriver::DatacenterFolder.new(vcenter_client)

View File

@ -236,6 +236,21 @@ class DatacenterFolder
template_ccr = template['runtime.host.parent'] template_ccr = template['runtime.host.parent']
# Check if template has nics or disks to be imported later
has_nics_and_disks = false
template["config.hardware.device"].each do |device|
if VCenterDriver::Storage.is_disk_or_iso?(device)
has_nics_and_disks = true
break
end
if VCenterDriver::Network.is_nic?(device)
has_nics_and_disks = true
break
end
end
#Get resource pools #Get resource pools
rp_cache = {} rp_cache = {}
if !rp_cache[template_ccr.name.to_s] if !rp_cache[template_ccr.name.to_s]
@ -256,6 +271,7 @@ class DatacenterFolder
rp = rp_cache[template_ccr.name.to_s] rp = rp_cache[template_ccr.name.to_s]
object = template.to_one_template(template, object = template.to_one_template(template,
has_nics_and_disks,
rp, rp,
rp_list, rp_list,
vcenter_uuid) vcenter_uuid)

View File

@ -112,6 +112,13 @@ class Storage
return element return element
end end
# Checks if a RbVmomi::VIM::VirtualDevice is a disk or an iso file
def self.is_disk_or_iso?(device)
is_disk = !(device.class.ancestors.index(RbVmomi::VIM::VirtualDisk)).nil?
is_iso = device.backing.is_a? RbVmomi::VIM::VirtualCdromIsoBackingInfo
is_disk || is_iso
end
def monitor def monitor
summary = self['summary'] summary = self['summary']

View File

@ -119,12 +119,12 @@ def self.import_templates(con_ops, options)
template = t[:template] template = t[:template]
error, template_disks_and_nics = template.import_vcenter_disks(vc_uuid, error, template_disks = template.import_vcenter_disks(vc_uuid,
dpool, dpool,
ipool) ipool)
if error.empty? if error.empty?
t[:one] << template_disks_and_nics t[:one] << template_disks
else else
STDOUT.puts error STDOUT.puts error
next next

View File

@ -61,6 +61,12 @@ class Network
@item = item @item = item
end end
# Checks if a RbVmomi::VIM::VirtualDevice is a network interface
def self.is_nic?(device)
!device.class.ancestors.index(RbVmomi::VIM::VirtualEthernetCard).nil?
end
def self.to_one_template(network_name, network_ref, network_type, def self.to_one_template(network_name, network_ref, network_type,
ccr_ref, ccr_name, vcenter_uuid) ccr_ref, ccr_name, vcenter_uuid)

View File

@ -59,6 +59,22 @@ class VirtualMachine
def initialize(item=nil, vi_client=nil) def initialize(item=nil, vi_client=nil)
@item = item @item = item
@vi_client = vi_client @vi_client = vi_client
@locking = true
end
# Locking function. Similar to flock
def lock
if @locking
@locking_file = File.open("/tmp/vcenter-importer-lock","w")
@locking_file.flock(File::LOCK_EX)
end
end
# Unlock driver execution mutex
def unlock
if @locking
@locking_file.close
end
end end
############################################################################ ############################################################################
@ -1351,51 +1367,25 @@ class VirtualMachine
disk_info = "" disk_info = ""
error = "" error = ""
ccr_ref = self["runtime.host.parent._ref"] begin
lock #Lock import operation, to avoid concurrent creation of images
#Get disks and info required ccr_ref = self["runtime.host.parent._ref"]
vc_disks = get_vcenter_disks
# Track allocated images #Get disks and info required
allocated_images = [] vc_disks = get_vcenter_disks
vc_disks.each do |disk| # Track allocated images
allocated_images = []
datastore_found = VCenterDriver::Storage.get_one_image_ds_by_ref_and_ccr(disk[:datastore]._ref, vc_disks.each do |disk|
ccr_ref,
vc_uuid,
dpool)
if datastore_found.nil?
error = " Error datastore #{disk[:datastore].name}: has to be imported first as an image datastore!\n"
#Rollback delete disk images datastore_found = VCenterDriver::Storage.get_one_image_ds_by_ref_and_ccr(disk[:datastore]._ref,
allocated_images.each do |i| ccr_ref,
i.delete vc_uuid,
end dpool)
if datastore_found.nil?
break error = " Error datastore #{disk[:datastore].name}: has to be imported first as an image datastore!\n"
end
image_import = VCenterDriver::Datastore.get_image_import_template(disk[:datastore].name,
disk[:path],
disk[:type], ipool)
#Image is already in the datastore
if image_import[:one]
# This is the disk info
disk_info << "DISK=[\n"
disk_info << "IMAGE_ID=\"#{image_import[:one]["ID"]}\",\n"
disk_info << "OPENNEBULA_MANAGED=\"NO\"\n"
disk_info << "]\n"
elsif !image_import[:template].empty?
# Then the image is created as it's not in the datastore
one_i = VCenterDriver::VIHelper.new_one_item(OpenNebula::Image)
allocated_images << one_i
rc = one_i.allocate(image_import[:template], datastore_found['ID'].to_i)
if ::OpenNebula.is_error?(rc)
error = " Error creating disk from template: #{rc.message}. Cannot import the template\n"
#Rollback delete disk images #Rollback delete disk images
allocated_images.each do |i| allocated_images.each do |i|
@ -1405,14 +1395,49 @@ class VirtualMachine
break break
end end
#Add info for One template image_import = VCenterDriver::Datastore.get_image_import_template(disk[:datastore].name,
one_i.info disk[:path],
disk_info << "DISK=[\n" disk[:type], ipool)
disk_info << "IMAGE_ID=\"#{one_i["ID"]}\",\n" #Image is already in the datastore
disk_info << "IMAGE_UNAME=\"#{one_i["UNAME"]}\",\n" if image_import[:one]
disk_info << "OPENNEBULA_MANAGED=\"NO\"\n" # This is the disk info
disk_info << "]\n" disk_info << "DISK=[\n"
disk_info << "IMAGE_ID=\"#{image_import[:one]["ID"]}\",\n"
disk_info << "OPENNEBULA_MANAGED=\"NO\"\n"
disk_info << "]\n"
elsif !image_import[:template].empty?
# Then the image is created as it's not in the datastore
one_i = VCenterDriver::VIHelper.new_one_item(OpenNebula::Image)
allocated_images << one_i
rc = one_i.allocate(image_import[:template], datastore_found['ID'].to_i)
if ::OpenNebula.is_error?(rc)
error = " Error creating disk from template: #{rc.message}. Cannot import the template\n"
#Rollback delete disk images
allocated_images.each do |i|
i.delete
end
break
end
#Add info for One template
one_i.info
disk_info << "DISK=[\n"
disk_info << "IMAGE_ID=\"#{one_i["ID"]}\",\n"
disk_info << "IMAGE_UNAME=\"#{one_i["UNAME"]}\",\n"
disk_info << "OPENNEBULA_MANAGED=\"NO\"\n"
disk_info << "]\n"
end
end end
rescue Exception => e
error = "There was an error trying to create an image for disk in vcenter template. Reason: #{e.message}"
ensure
unlock
end end
return error, disk_info return error, disk_info
@ -1479,69 +1504,78 @@ class VirtualMachine
nic_info = "" nic_info = ""
error = "" error = ""
ccr_ref = self["runtime.host.parent._ref"] begin
ccr_name = self["runtime.host.parent.name"] lock #Lock import operation, to avoid concurrent creation of images
#Get disks and info required ccr_ref = self["runtime.host.parent._ref"]
vc_nics = get_vcenter_nics ccr_name = self["runtime.host.parent.name"]
# Track allocated networks #Get disks and info required
allocated_networks = [] vc_nics = get_vcenter_nics
vc_nics.each do |nic| # Track allocated networks
allocated_networks = []
network_found = VCenterDriver::Network.get_one_vnet_ds_by_ref_and_ccr(nic[:net_ref], vc_nics.each do |nic|
ccr_ref,
vc_uuid,
npool)
#Network is already in the datastore
if network_found
# This is the existing nic info
nic_info << "NIC=[\n"
nic_info << "NETWORK_ID=\"#{network_found["ID"]}\",\n"
nic_info << "OPENNEBULA_MANAGED=\"NO\"\n"
nic_info << "]\n"
else
# Then the network has to be created as it's not in OpenNebula
one_vn = VCenterDriver::VIHelper.new_one_item(OpenNebula::VirtualNetwork)
allocated_networks << one_vn network_found = VCenterDriver::Network.get_one_vnet_ds_by_ref_and_ccr(nic[:net_ref],
ccr_ref,
vc_uuid,
npool)
#Network is already in the datastore
if network_found
# This is the existing nic info
nic_info << "NIC=[\n"
nic_info << "NETWORK_ID=\"#{network_found["ID"]}\",\n"
nic_info << "OPENNEBULA_MANAGED=\"NO\"\n"
nic_info << "]\n"
else
# Then the network has to be created as it's not in OpenNebula
one_vn = VCenterDriver::VIHelper.new_one_item(OpenNebula::VirtualNetwork)
one_vnet = VCenterDriver::Network.to_one_template(nic[:net_name], allocated_networks << one_vn
nic[:net_ref],
nic[:pg_type],
ccr_ref,
ccr_name,
vc_uuid)
# By default add an ethernet range to network size 255 one_vnet = VCenterDriver::Network.to_one_template(nic[:net_name],
ar_str = "" nic[:net_ref],
ar_str << "AR=[\n" nic[:pg_type],
ar_str << "TYPE=\"ETHER\",\n" ccr_ref,
ar_str << "SIZE=\"255\"\n" ccr_name,
ar_str << "]\n" vc_uuid)
one_vnet[:one] << ar_str
rc = one_vn.allocate(one_vnet[:one]) # By default add an ethernet range to network size 255
ar_str = ""
ar_str << "AR=[\n"
ar_str << "TYPE=\"ETHER\",\n"
ar_str << "SIZE=\"255\"\n"
ar_str << "]\n"
one_vnet[:one] << ar_str
if ::OpenNebula.is_error?(rc) rc = one_vn.allocate(one_vnet[:one])
error = " Error creating virtual network from template: #{rc.message}. Cannot import the template\n"
#Rollback, delete virtual networks if ::OpenNebula.is_error?(rc)
allocated_networks.each do |n| error = " Error creating virtual network from template: #{rc.message}. Cannot import the template\n"
n.delete
#Rollback, delete virtual networks
allocated_networks.each do |n|
n.delete
end
break
end end
break #Add info for One template
one_vn.info
nic_info << "NIC=[\n"
nic_info << "NETWORK_ID=\"#{one_vn["ID"]}\",\n"
nic_info << "OPENNEBULA_MANAGED=\"NO\"\n"
nic_info << "]\n"
end end
#Add info for One template
one_vn.info
nic_info << "NIC=[\n"
nic_info << "NETWORK_ID=\"#{one_vn["ID"]}\",\n"
nic_info << "OPENNEBULA_MANAGED=\"NO\"\n"
nic_info << "]\n"
end end
rescue Exception => e
error = "There was an error trying to create a virtual network for network in vcenter template. Reason: #{e.message}"
ensure
unlock
end end
return error, nic_info return error, nic_info
@ -1880,7 +1914,7 @@ class VirtualMachine
return str return str
end end
def to_one_template(template, rp, rp_list, vcenter_uuid) def to_one_template(template, has_nics_and_disks, rp, rp_list, vcenter_uuid)
template_name = template['name'] template_name = template['name']
template_ref = template['_ref'] template_ref = template['_ref']
@ -1898,6 +1932,7 @@ class VirtualMachine
one_tmp[:rp] = rp one_tmp[:rp] = rp
one_tmp[:rp_list] = rp_list one_tmp[:rp_list] = rp_list
one_tmp[:template] = template one_tmp[:template] = template
one_tmp[:import_disks_and_nics] = has_nics_and_disks
return one_tmp return one_tmp
end end