From 331306b05b18971a12ca61b468628cfb908b0059 Mon Sep 17 00:00:00 2001 From: sergio semedi Date: Wed, 19 Sep 2018 11:11:03 +0200 Subject: [PATCH] F #2387: vCenter vm resource architecture ======================================== F #2387:(vCenter) vm Resource, disk and nic classes F #2387:(vCenter) new methods for vm disk --- .../lib/vcenter_driver/virtual_machine.rb | 187 +++++++++++++++++- .../remotes/lib/vcenter_driver/vm_template.rb | 11 +- 2 files changed, 194 insertions(+), 4 deletions(-) diff --git a/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb b/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb index 831454b3c8..c0fb59b25b 100644 --- a/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb +++ b/src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb @@ -65,6 +65,68 @@ end # class VirtualMachineFolder class VirtualMachine < VCenterDriver::Template + + # Resource base class + class Resource + def initialize(id, one_res, vc_res) + @id = id + @one_res = one_res + @vc_res = vc_res + end + + def managed? + !(@one_res['OPENNEBULA_MANAGED'] && @one_res['OPENNEBULA_MANAGED'].downcase == "no") + end + end + + class Nic < Resource + def initialize(id, one_res, vc_res) + super(id, one_res, vc_res) + end + end + + class Disk < Resource + def initialize(id, one_res, vc_res) + super(id, one_res, vc_res) + end + + def path + @vc_res[:path_wo_ds] + end + + def ds + @vc_res[:datastore] + end + + def ds_ref + @one_res['VCENTER_DS_REF'] + end + + def key + @vc_res[:key] + end + + def prefix + @vc_res[:prefix] + end + + def type + @vc_res[:type] + end + + def file + path.split('/').last + end + + def persistent? + @one_res['PERSISTENT'] == 'YES' + end + + def connected? + @vc_res[:device].connectable.connected + end + end + VM_PREFIX_DEFAULT = "one-$i-" POLL_ATTRIBUTE = OpenNebula::VirtualMachine::Driver::POLL_ATTRIBUTE @@ -88,6 +150,7 @@ class VirtualMachine < VCenterDriver::Template @vm_id = one_id @locking = true @vm_info = nil + @disks = {} end ############################################################################ @@ -119,6 +182,7 @@ class VirtualMachine < VCenterDriver::Template @one_item end + # set the vmware item directly to the vm def set_item(item) @item = item @@ -352,8 +416,7 @@ class VirtualMachine < VCenterDriver::Template # @param one_item OpenNebula::VirtualMachine # @param vi_client VCenterDriver::VIClient # @return String vmware ref - def clone_vm(drv_action) - + def clone_vm(drv_action) vcenter_name = get_vcenter_name vc_template_ref = drv_action['USER_TEMPLATE/VCENTER_TEMPLATE_REF'] @@ -567,6 +630,126 @@ class VirtualMachine < VCenterDriver::Template clone_parameters end + def nics + @nics.size == get_one_nics.size + end + + def synced_disks? + @disks.size == get_one_disks.size + end + + def disks + return @disks if synced_disks? + + sync_disks + end + + def get_template_ref + one_item['USER_TEMPLATE/VCENTER_TEMPLATE_REF'] + end + + def get_one_disks + one_item.retrieve_xmlelements("TEMPLATE/DISK") + end + + def get_one_nics + one_item.retrieve_xmlelements("TEMPLATE/NICS") + end + + def query_disk(one_disk, keys, vc_disks) + index = one_disk["DISK_ID"] + perst = one_disk["PERSISTENT"] + + if keys["opennebula.disk.#{index}"] + key = keys["opennebula.disk.#{index}"].to_i + query = vc_disks.select {|dev| key == dev[:key]} + else + path = perst ? one_disk['SOURCE'] : disk_real_path(one_disk, index) + query = vc_disks.select {|dev| path == dev[:path_wo_ds]} + end + + raise "opennebula disk #{index} not found in vCenter" unless query.size == 1 + + return query.first + end + + def sync_nics + end + + def sync_disks + + keys = get_unmanaged_keys + vc_disks = get_vcenter_disks + one_disks = get_one_disks + size = one_disks.size + + one_disks.each do |one_disk| + index = one_disk["DISK_ID"] + + disk = query_disk(one_disk, keys, vc_disks) + + vc_dev = vc_disks.delete(disk) + + @disks[index] = Disk.new(index.to_i, one_disk, vc_dev) + end + + @disks + end + + def disk(index, opts = {}) + return @disks[index] if @disks[index] && opts[:sync].nil? + one_disk = one_item.retrieve_xmlelements("TEMPLATE/DISK[DISK_ID='#{index}']").first rescue nil + + raise "disk #{index} not found" unless one_disk + + keys = opts[:keys].nil? ? get_unmanaged_keys : opts[:keys] + vc_disks = opts[:disks].nil? ? get_vcenter_disks : opts[:disks] + + vc_disk = query_disk(one_disk, keys, vc_disks) + + @disks[index] = Disk.new(index.to_i, one_disk, vc_disk) + end + + def resize_unmanaged_disks(disk, new_size) + + resize_hash = {} + disks = [] + found = false + + unmanaged_keys = get_unmanaged_keys + vc_disks = get_vcenter_disks + + vc_disks.each do |vcenter_disk| + if unmanaged_keys.key?("opennebula.disk.#{disk["DISK_ID"]}") + device_key = unmanaged_keys["opennebula.disk.#{disk["DISK_ID"]}"].to_i + + if device_key == vcenter_disk[:key].to_i + + if disk["SIZE"].to_i <= disk["ORIGINAL_SIZE"].to_i + raise "Disk size cannot be shrinked." + end + + # Edit capacity setting new size in KB + d = vcenter_disk[:device] + d.capacityInKB = disk["SIZE"].to_i * 1024 + disks << { :device => d, :operation => :edit } + + found = true + break + end + end + end + + raise "Unmanaged disk could not be found to apply resize operation." if !found + + if !disks.empty? + resize_hash[:deviceChange] = disks + @item.ReconfigVM_Task(:spec => resize_hash).wait_for_completion + else + raise "Device was not found after attaching it to VM in poweroff." + end + end + def reference_unmanaged_devices(template_ref) extraconfig = [] diff --git a/src/vmm_mad/remotes/lib/vcenter_driver/vm_template.rb b/src/vmm_mad/remotes/lib/vcenter_driver/vm_template.rb index 106328218d..fd4a5fcfaf 100644 --- a/src/vmm_mad/remotes/lib/vcenter_driver/vm_template.rb +++ b/src/vmm_mad/remotes/lib/vcenter_driver/vm_template.rb @@ -404,7 +404,7 @@ class Template ccr_name = self["runtime.host.parent.name"] #Get disks and info required - vc_nics = get_vcenter_nics + vc_nics = get_vcenter_nics_hash # Track allocated networks for rollback allocated_networks = [] @@ -603,6 +603,13 @@ class Template return disks end + def get_vcenter_nics + nics = [] + self["config.hardware.device"].each { |device| nics << device if is_nic?(device)} + + nics + end + def retrieve_from_device(device) res = {} @@ -634,7 +641,7 @@ class Template res end - def get_vcenter_nics + def get_vcenter_nics_hash parse_live = ->(inets_raw) { h = nil begin