From 23fdae31d33db6d9ff8d5f0f6cb9e046490255d5 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Mon, 16 Mar 2015 18:33:52 +0100 Subject: [PATCH 01/28] feature-3532: vCenter monitoring returns one template for wild VMs Sunstone presents wild VMs in new tab, ready to import (missing import code) --- src/sunstone/public/js/plugins/hosts-tab.js | 48 +++++++++++++++++++ src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 4 ++ 2 files changed, 52 insertions(+) diff --git a/src/sunstone/public/js/plugins/hosts-tab.js b/src/sunstone/public/js/plugins/hosts-tab.js index 4e6fdda278..d0ad8cf089 100644 --- a/src/sunstone/public/js/plugins/hosts-tab.js +++ b/src/sunstone/public/js/plugins/hosts-tab.js @@ -962,6 +962,26 @@ function updateHostInfo(request,host){ ' } + var wilds_info_tab = { + title: tr("WILDS"), + icon: "fa-hdd-o", + content : '
\ +
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
' + tr("VM name") + '' + tr("UUID") + '' + tr("Import") + '
\ +
\ +
' + } + //Sunstone.updateInfoPanelTab(info_panel_name,tab_name, new tab object); Sunstone.updateInfoPanelTab("host_info_panel","host_info_tab",info_tab); Sunstone.updateInfoPanelTab("host_info_panel","host_monitoring_tab",monitor_tab); @@ -969,11 +989,13 @@ function updateHostInfo(request,host){ if (host_info.TEMPLATE.HYPERVISOR == "vcenter") { Sunstone.updateInfoPanelTab("host_info_panel","host_esx_tab",esx_info_tab); + Sunstone.updateInfoPanelTab("host_info_panel","host_wilds_tab",wilds_info_tab); } Sunstone.popUpInfoPanel("host_info_panel", "hosts-tab"); if (host_info.TEMPLATE.HYPERVISOR == "vcenter") { + // ESX datatable var dataTable_esx_hosts = $("#datatable_host_esx",main_tabs_context).dataTable({ "bSortClasses" : false, "bDeferRender": true @@ -1003,6 +1025,32 @@ function updateHostInfo(request,host){ dataTable_esx_hosts.fnAddData(host_list_array); delete host_info.TEMPLATE.HOST; } + + // WILDS datatable + var dataTable_wilds_hosts = $("#datatable_host_wilds",main_tabs_context).dataTable({ + "bSortClasses" : false, + "bDeferRender": true + }); + + var wilds_list_array = []; + + if (host_info.TEMPLATE.WILDS) { + wilds = host_info.TEMPLATE.WILDS.split(","); + + $.each(wilds, function(){ + name = this.split("_")[0]; + uuid = this.split("_")[1]; + + wilds_list_array.push([ + name, + uuid, + '' + ]); + }); + } + + dataTable_wilds_hosts.fnAddData(wilds_list_array); + delete host_info.TEMPLATE.WILDS; } var dataTable_host_vMachines = $("#datatable_host_vms", $("#host_info_panel")).dataTable({ diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 33c4a639ea..a177e56ecf 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -644,6 +644,10 @@ class VCenterHost < ::OpenNebula::Host str_info << "ID=#{number}," str_info << "DEPLOY_ID=\"#{vm.vm.config.uuid}\"," str_info << "VM_NAME=\"#{name}\"," + if number == -1 + vm_template_to_one = Base64.encode64(vm.vm_to_one).gsub("\n","") + str_info << "IMPORT_TEMPLATE=\"#{vm_template_to_one}\"," + end str_info << "POLL=\"#{vm.info}\"]" } From 364a30a90033e775e16d8c4f023c11013270e58a Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Tue, 17 Mar 2015 12:46:53 +0100 Subject: [PATCH 02/28] feature #3532: add import template to KVM poll --- src/vmm_mad/remotes/poll_xen_kvm.rb | 152 +++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/src/vmm_mad/remotes/poll_xen_kvm.rb b/src/vmm_mad/remotes/poll_xen_kvm.rb index 95e3201e2a..ea311bc0d1 100755 --- a/src/vmm_mad/remotes/poll_xen_kvm.rb +++ b/src/vmm_mad/remotes/poll_xen_kvm.rb @@ -18,6 +18,7 @@ require 'pp' require 'rexml/document' +require 'base64' ENV['LANG']='C' @@ -69,7 +70,9 @@ module KVM values[:usedcpu] = cpu[vm[:pid]] if cpu[vm[:pid]] values[:usedmemory] = [resident_mem, max_mem].max - values.merge!(get_interface_statistics(one_vm)) + xml = dump_xml(vmid) + + values.merge!(get_interface_statistics(one_vm, xml)) return values end @@ -125,7 +128,14 @@ module KVM values[:usedcpu] = cpu[vm[:pid]] if cpu[vm[:pid]] values[:usedmemory] = [resident_mem, max_mem].max - values.merge!(get_interface_statistics(name)) + xml = dump_xml(name) + + values.merge!(get_interface_statistics(name, xml)) + + if !name.match(/^one-\d+/) + uuid, template = xml_to_one(xml) + values[:template] = Base64.encode64(template).delete("\n") + end vms_info[vm[:name]] = values end @@ -213,11 +223,19 @@ module KVM hash end + # Get dumpxml output of a VM + # @param the ID of the VM as defined in libvirt + # @return [String] xml output of virsh dumpxml + def self.dump_xml(vmid) + `#{virsh(:dumpxml)} '#{vmid}'` + end + # Aggregate statics of all VM NICs # @param the ID of the VM as defined in libvirt + # @param text [nil, String] dumpxml output or nil to execute dumpxml # @return [Hash] with network stats, by name [symbol] :netrx, :nettx - def self.get_interface_statistics(vmid) - text = `#{virsh(:dumpxml)} #{vmid}` + def self.get_interface_statistics(vmid, text = nil) + text = dump_xml(vmid) if !text return {} if $?.exitstatus != 0 @@ -278,6 +296,126 @@ module KVM '-' end end + + # Convert the output of dumpxml to an OpenNebula template + # @param xml [String] output of dumpxml + # @return [Array] uuid and OpenNebula template encoded in base64 + def self.xml_to_one(xml) + doc = REXML::Document.new(xml) + + name = REXML::XPath.first(doc, '/domain/name').text + uuid = REXML::XPath.first(doc, '/domain/uuid').text + vcpu = REXML::XPath.first(doc, '/domain/vcpu').text + memory = REXML::XPath.first(doc, '/domain/memory').text.to_i / 1024 + arch = REXML::XPath.first(doc, '/domain/os/type').attributes['arch'] + + disks = [] + REXML::XPath.each(doc, '/domain/devices/disk') do |d| + type = REXML::XPath.first(d, '//disk').attributes['type'] + driver = REXML::XPath.first(d, '//disk/driver').attributes['type'] + source = REXML::XPath.first(d, '//disk/source').attributes[type] + target = REXML::XPath.first(d, '//disk/target').attributes['dev'] + + disks << { + :type => type, + :driver => driver, + :source => source, + :target => target + } + end + + disks_txt = '' + + disks.each do |disk| + disks_txt << "DISK=[\n" + disks_txt << " SOURCE=\"#{disk[:source]}\",\n" + disks_txt << " DRIVER=\"#{disk[:driver]}\",\n" + disks_txt << " TARGET=\"#{disk[:target]}\"" + disks_txt << "]\n" + end + + + interfaces = [] + REXML::XPath.each(doc, + "/domain/devices/interface[@type='bridge']") do |i| + mac = REXML::XPath.first(i, '//interface/mac'). + attributes['address'] + bridge = REXML::XPath.first(i, '//interface/source') + .attributes['bridge'] + model = REXML::XPath.first(i, '//interface/model') + .attributes['type'] + + interfaces << { + :mac => mac, + :bridge => bridge, + :model => model + } + end + + interfaces_txt = '' + + interfaces.each do |interface| + interfaces_txt << "NIC=[\n" + interfaces_txt << " MAC=\"#{interface[:mac]}\",\n" + interfaces_txt << " BRIDGE=\"#{interface[:bridge]}\",\n" + interfaces_txt << " MODEL=\"#{interface[:model]}\"" + interfaces_txt << "]\n" + end + + + spice = REXML::XPath.first(doc, + "/domain/devices/graphics[@type='spice']") + spice = spice.attributes['port'] if spice + + spice_txt = '' + if spice + spice_txt = %Q + end + + vnc = REXML::XPath.first(doc, "/domain/devices/graphics[@type='vnc']") + vnc = vnc.attributes['port'] if vnc + + vnc_txt = '' + if vnc + vnc_txt = %Q + end + + + feature_list = %w{acpi apic pae} + features = [] + + feature_list.each do |feature| + if REXML::XPath.first(doc, "/domain/features/#{feature}") + features << feature + end + end + + feat = [] + features.each do |feature| + feat << %Q[ #{feature.upcase}="yes"] + end + + features_txt = "FEATURES=[\n" + features_txt << feat.join(",\n") + features_txt << "]\n" + + + template = < Date: Thu, 19 Mar 2015 09:40:46 +0100 Subject: [PATCH 03/28] feature-3532: Import import wild form in Sunstone --- src/sunstone/public/js/plugins/hosts-tab.js | 63 +++++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/sunstone/public/js/plugins/hosts-tab.js b/src/sunstone/public/js/plugins/hosts-tab.js index d0ad8cf089..69854974d6 100644 --- a/src/sunstone/public/js/plugins/hosts-tab.js +++ b/src/sunstone/public/js/plugins/hosts-tab.js @@ -962,10 +962,13 @@ function updateHostInfo(request,host){ ' } + // TODO make wilds configurable + var wilds_info_tab = { title: tr("WILDS"), icon: "fa-hdd-o", - content : '
\ + content : '
\ +
\
\ \ \ @@ -973,14 +976,62 @@ function updateHostInfo(request,host){ \ \ \ + \ \ \ \
' + tr("VM name") + '' + tr("UUID") + '' + tr("Import") + '\
\
\ -
' - } +
\ + ' + } + + // Add event listener for importing WILDS + $('#import_wilds').on('click', function () { + var row = $(this).closest('table').DataTable().row( $(this).closest('tr') ); + + if ( row.child.isShown() ) { + row.child.hide(); + $(this).children("span").addClass('fa-chevron-down'); + $(this).children("span").removeClass('fa-chevron-up'); + } + else { + var html = '
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + '; + + $.each(row.data().SECURITY_GROUP_RULES, function(index, elem){ + var rule_st = sg_rule_to_st(this); + + var new_tr = '\ + \ + \ + \ + \ + \ + \ + \ + ' + + html += new_tr; + }); + + row.child( html ).show(); + $(this).children("span").removeClass('fa-chevron-down'); + $(this).children("span").addClass('fa-chevron-up'); + } + } ); //Sunstone.updateInfoPanelTab(info_panel_name,tab_name, new tab object); Sunstone.updateInfoPanelTab("host_info_panel","host_info_tab",info_tab); @@ -1039,16 +1090,18 @@ function updateHostInfo(request,host){ $.each(wilds, function(){ name = this.split("_")[0]; - uuid = this.split("_")[1]; + uuid = "-"; // TODO get uuid from template and present it, CPU, MEMORY ?? wilds_list_array.push([ name, uuid, - '' + '' ]); }); } + //$(".import_'+name+'", trow).data("wild_template", COREVALUE) + dataTable_wilds_hosts.fnAddData(wilds_list_array); delete host_info.TEMPLATE.WILDS; } From f4d54779c80a3dcd56ed2675e92e3eb7d496d6d9 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 19 Mar 2015 15:39:56 +0100 Subject: [PATCH 04/28] feature #3532: Keep information about WILD VMS in host template --- src/host/Host.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/host/Host.cc b/src/host/Host.cc index 02a4f88c71..3bea63e191 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -383,6 +383,8 @@ int Host::update_info(Template &tmpl, zombie << zname; } } + + delete *it; } else if (rc == 0) //not ours { @@ -401,9 +403,9 @@ int Host::update_info(Template &tmpl, } wild << wname; - } - delete *it; + obj_template->set(*it); + } } for(set_it = tmp_lost_vms.begin(); set_it != tmp_lost_vms.end(); set_it++) From 21bee73dc3c54a319c5a7c996a1179fb8799bb3a Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Thu, 19 Mar 2015 17:56:41 +0100 Subject: [PATCH 05/28] Backlog #3691: Check if running VM in vCenter has VNC open port and set GRAPHICS section with right port --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index a177e56ecf..ce36a322e4 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -181,7 +181,7 @@ class VIClient false end end - end + end ######################################################################## # Builds a hash with the DataCenter / ClusterComputeResource hierarchy @@ -1070,6 +1070,16 @@ class VCenterVm "IMPORT_VM_ID = \"#{@vm.config.uuid}\"\n"\ "SCHED_REQUIREMENTS=\"NAME=\\\"#{@vm.runtime.host.parent.name}\\\"\"\n" + vp=@vm.config.extraConfig.select{|v| v[:key]=="remotedisplay.vnc.port"} + + if vp.size > 0 + str << "GRAPHICS = [\n"\ + " TYPE =\"vnc\",\n"\ + " LISTEN =\"0.0.0.0\",\n"\ + " PORT =\"#{vp[0][:value]}\"\n"\ + "]\n" + end + if @vm.config.annotation.nil? || @vm.config.annotation.empty? str << "DESCRIPTION = \"vCenter Virtual Machine imported by OpenNebula"\ " from Cluster #{@vm.runtime.host.parent.name}\"\n" From 6d747c7aac58df44cfadaae7983e6b4809a72b16 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Mon, 23 Mar 2015 12:50:29 +0100 Subject: [PATCH 06/28] feature #3532: fix bug with ruby 1.8 --- src/vmm_mad/remotes/poll_xen_kvm.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vmm_mad/remotes/poll_xen_kvm.rb b/src/vmm_mad/remotes/poll_xen_kvm.rb index ea311bc0d1..d08d5fcaa4 100755 --- a/src/vmm_mad/remotes/poll_xen_kvm.rb +++ b/src/vmm_mad/remotes/poll_xen_kvm.rb @@ -340,10 +340,10 @@ module KVM "/domain/devices/interface[@type='bridge']") do |i| mac = REXML::XPath.first(i, '//interface/mac'). attributes['address'] - bridge = REXML::XPath.first(i, '//interface/source') - .attributes['bridge'] - model = REXML::XPath.first(i, '//interface/model') - .attributes['type'] + bridge = REXML::XPath.first(i, '//interface/source'). + attributes['bridge'] + model = REXML::XPath.first(i, '//interface/model'). + attributes['type'] interfaces << { :mac => mac, From cc103c517987b898437835e4e4f384af2cf4db90 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Mon, 23 Mar 2015 12:53:11 +0100 Subject: [PATCH 07/28] feature #3532: generate import template for xen --- src/vmm_mad/remotes/poll_xen_kvm.rb | 50 ++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/vmm_mad/remotes/poll_xen_kvm.rb b/src/vmm_mad/remotes/poll_xen_kvm.rb index d08d5fcaa4..44d8ad6b40 100755 --- a/src/vmm_mad/remotes/poll_xen_kvm.rb +++ b/src/vmm_mad/remotes/poll_xen_kvm.rb @@ -19,6 +19,7 @@ require 'pp' require 'rexml/document' require 'base64' +require 'uri' ENV['LANG']='C' @@ -447,6 +448,12 @@ module XEN # @return [Hash, nil] Hash with the VM information or nil in case of error def self.get_all_vm_info begin + begin + vm_templates = get_vm_templates + rescue + vm_templates = {} + end + text = `#{CONF['XM_POLL']}` return nil if $?.exitstatus != 0 @@ -481,6 +488,11 @@ module XEN dom_hash[:nettx] = dom_data[10].to_i * 1024 dom_hash[:netrx] = dom_data[11].to_i * 1024 + if !dom_data[0].match(/^one-\d/) && vm_templates[dom_data[0]] + dom_hash[:template] = + Base64.encode64(vm_templates[dom_data[0]]).delete("\n") + end + domains[dom_hash[:name]] = dom_hash end @@ -512,6 +524,42 @@ module XEN '-' end end + + def self.get_vm_templates + begin + require 'rubygems' + require 'json' + rescue LoadError + return {} + end + + text = `#{CONF['XM_LIST']} -l` + doms = JSON.parse(text) + + dom_tmpl = {} + + doms.each do |dom| + name = dom['config']['c_info']['name'] + name = URI.escape(name) + + tmp = %Q + + vcpus = dom['config']['b_info']['max_vcpus'].to_i + vcpus = 1 if vcpus < 1 + + tmp << %Q + tmp << %Q + + memory = dom['config']['b_info']['max_memkb'] + memory /= 1024 + + tmp << %Q + + dom_tmpl[name] = tmp + end + + dom_tmpl + end end ################################################################################ @@ -548,7 +596,7 @@ def setup_hypervisor case hypervisor.name when 'XEN' file = 'xenrc' - vars = %w{XM_POLL} + vars = %w{XM_POLL XM_LIST} when 'KVM' file = 'kvmrc' vars = %w{LIBVIRT_URI} From 16931004cc2e465a88c41b8121a427e476bd84b4 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Tue, 24 Mar 2015 17:34:33 +0100 Subject: [PATCH 08/28] feature #3718: add disk usage to kvm probe --- src/vmm_mad/remotes/poll_xen_kvm.rb | 46 +++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/vmm_mad/remotes/poll_xen_kvm.rb b/src/vmm_mad/remotes/poll_xen_kvm.rb index 44d8ad6b40..0d49ddc436 100755 --- a/src/vmm_mad/remotes/poll_xen_kvm.rb +++ b/src/vmm_mad/remotes/poll_xen_kvm.rb @@ -21,6 +21,15 @@ require 'rexml/document' require 'base64' require 'uri' +begin + require 'rubygems' + require 'json' + + JSON_LOADED = true +rescue LoadError + JSON_LOADED = false +end + ENV['LANG']='C' ################################################################################ @@ -132,6 +141,7 @@ module KVM xml = dump_xml(name) values.merge!(get_interface_statistics(name, xml)) + values.merge!(get_disk_usage(xml)) if !name.match(/^one-\d+/) uuid, template = xml_to_one(xml) @@ -298,6 +308,35 @@ module KVM end end + def self.get_disk_usage(xml) + return {} if !JSON_LOADED + + doc=REXML::Document.new(xml) + size = 0 + + data = { + :disk_actual_size => 0.0, + :disk_virtual_size => 0.0 + } + + doc.elements.each('domain/devices/disk/source') do |ele| + next if !ele.attributes['file'] + + text = `qemu-img info --output=json #{ele.attributes['file']}` + next if !$? || !$?.success? + + json = JSON.parse(text) + + data[:disk_actual_size] += json['actual-size'].to_f/1024/1024 + data[:disk_virtual_size] += json['virtual-size'].to_f/1024/1024 + end + + data[:disk_actual_size] = data[:disk_actual_size].round + data[:disk_virtual_size] = data[:disk_virtual_size].round + + data + end + # Convert the output of dumpxml to an OpenNebula template # @param xml [String] output of dumpxml # @return [Array] uuid and OpenNebula template encoded in base64 @@ -526,12 +565,7 @@ module XEN end def self.get_vm_templates - begin - require 'rubygems' - require 'json' - rescue LoadError - return {} - end + return {} if !JSON_LOADED text = `#{CONF['XM_LIST']} -l` doms = JSON.parse(text) From b1b200710038b5f4d8c96d78c1ac369cc1d440f9 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Tue, 24 Mar 2015 17:36:37 +0100 Subject: [PATCH 09/28] feature #3718: add disk usage to xen probe --- src/vmm_mad/remotes/poll_xen_kvm.rb | 55 +++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/vmm_mad/remotes/poll_xen_kvm.rb b/src/vmm_mad/remotes/poll_xen_kvm.rb index 0d49ddc436..d0226757a7 100755 --- a/src/vmm_mad/remotes/poll_xen_kvm.rb +++ b/src/vmm_mad/remotes/poll_xen_kvm.rb @@ -488,11 +488,14 @@ module XEN def self.get_all_vm_info begin begin - vm_templates = get_vm_templates + list_long = get_vm_list_long rescue - vm_templates = {} + list_long = [] end + vm_templates = get_vm_templates(list_long) + vm_disk_stats = get_vm_disk_stats(list_long) + text = `#{CONF['XM_POLL']}` return nil if $?.exitstatus != 0 @@ -518,21 +521,25 @@ module XEN domain_lines.each do |dom| dom_data = dom.gsub('no limit', 'no-limit').strip.split + name = dom_data[0] + dom_hash = Hash.new - dom_hash[:name] = dom_data[0] + dom_hash[:name] = name dom_hash[:state] = get_state(dom_data[1]) dom_hash[:usedcpu] = dom_data[3] dom_hash[:usedmemory] = dom_data[4] dom_hash[:nettx] = dom_data[10].to_i * 1024 dom_hash[:netrx] = dom_data[11].to_i * 1024 - if !dom_data[0].match(/^one-\d/) && vm_templates[dom_data[0]] + if !name.match(/^one-\d/) && vm_templates[name] dom_hash[:template] = - Base64.encode64(vm_templates[dom_data[0]]).delete("\n") + Base64.encode64(vm_templates[name]).delete("\n") end - domains[dom_hash[:name]] = dom_hash + dom_hash.merge!(vm_disk_stats[name]) if vm_disk_stats[name] + + domains[name] = dom_hash end domains @@ -564,12 +571,14 @@ module XEN end end - def self.get_vm_templates + def self.get_vm_list_long return {} if !JSON_LOADED text = `#{CONF['XM_LIST']} -l` doms = JSON.parse(text) + end + def self.get_vm_templates(doms) dom_tmpl = {} doms.each do |dom| @@ -594,6 +603,38 @@ module XEN dom_tmpl end + + def self.get_vm_disk_stats(doms) + dom_disk_stats = {} + + doms.each do |dom| + data = { + :disk_actual_size => 0.0, + :disk_virtual_size => 0.0 + } + + dom['config']['disks'].each do |disk| + next if !disk['pdev_path'] + + path = disk['pdev_path'] + + text = `qemu-img info --output=json #{path}` + next if !$? || !$?.success? + + json = JSON.parse(text) + + data[:disk_actual_size] += json['actual-size'].to_f/1024/1024 + data[:disk_virtual_size] += json['virtual-size'].to_f/1024/1024 + end + + data[:disk_actual_size] = data[:disk_actual_size].round + data[:disk_virtual_size] = data[:disk_virtual_size].round + + data + end + + dom_disk_stats + end end ################################################################################ From 4d151b1745d08c9e366825f438b3cb5fa9d25313 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Fri, 27 Mar 2015 14:32:02 +0100 Subject: [PATCH 10/28] Feature #3532: finishing Sunstone wilds import for vCenter --- src/sunstone/public/js/plugins/hosts-tab.js | 235 +++++--------------- src/sunstone/public/js/plugins/vms-tab.js | 6 + 2 files changed, 66 insertions(+), 175 deletions(-) diff --git a/src/sunstone/public/js/plugins/hosts-tab.js b/src/sunstone/public/js/plugins/hosts-tab.js index 69854974d6..99d42cf60a 100644 --- a/src/sunstone/public/js/plugins/hosts-tab.js +++ b/src/sunstone/public/js/plugins/hosts-tab.js @@ -785,7 +785,7 @@ function updateHostInfo(request,host){ else { for (key in host_info.TEMPLATE) - if(!key.match(/HOST/)) + if(!key.match(/^HOST$/) && !key.match(/^VM$/) && !key.match(/^WILDS$/)) stripped_host_template[key]=host_info.TEMPLATE[key]; else unshown_values[key]=host_info.TEMPLATE[key]; @@ -856,10 +856,6 @@ function updateHostInfo(request,host){ \ \ \ - \ - \ - \ - \ \
'+tr("Security Group")+''+tr("Protocol")+''+tr("Type")+''+tr("Range")+''+tr("Network")+''+tr("ICMP Type")+'
'+this.SECURITY_GROUP_ID+''+this.SECURITY_GROUP_NAME+''+rule_st.PROTOCOL+''+rule_st.RULE_TYPE+''+rule_st.RANGE+''+rule_st.NETWORK+''+rule_st.ICMP_TYPE+'
' + tr("Real CPU") + ''+cpu_bars.real+'
' + tr("Running VMs") + ''+host_info.HOST_SHARE.RUNNING_VMS+'
' + insert_datastores_capacity_table(host_info.HOST_SHARE) + @@ -962,76 +958,72 @@ function updateHostInfo(request,host){
' } - // TODO make wilds configurable - var wilds_info_tab = { title: tr("WILDS"), icon: "fa-hdd-o", - content : '
\ -
\ + content : '
\
\ + \ \ \ \ + \ \ \ - \ - \ \ \ \
' + tr("VM name") + '' + tr("UUID") + '' + tr("Import") + '\
\
\ -
\ - ' +
' } // Add event listener for importing WILDS - $('#import_wilds').on('click', function () { - var row = $(this).closest('table').DataTable().row( $(this).closest('tr') ); - - if ( row.child.isShown() ) { - row.child.hide(); - $(this).children("span").addClass('fa-chevron-down'); - $(this).children("span").removeClass('fa-chevron-up'); - } - else { - var html = '
\ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - '; + $('#import_wilds').die( "click" ); + $('#import_wilds').live('click', function () { + $.each($("#import_wild_checker:checked", "#datatable_host_wilds"), function(){ + var vm_json = { + "vm": { + "vm_raw": $(this).data("wild_template") + } + }; - $.each(row.data().SECURITY_GROUP_RULES, function(index, elem){ - var rule_st = sg_rule_to_st(this); + var import_host_id = $(this).data("host_id"); + var wild_row = $(this).closest('tr'); - var new_tr = '\ - \ - \ - \ - \ - \ - \ - \ - ' + // Create the VM in OpenNebula + OpenNebula.VM.create({ + timeout: true, + data: vm_json, + success: function(request, response) { + OpenNebula.Helper.clear_cache("VM"); - html += new_tr; - }); + var extra_info = {}; - row.child( html ).show(); - $(this).children("span").removeClass('fa-chevron-down'); - $(this).children("span").addClass('fa-chevron-up'); - } - } ); + extra_info['host_id'] = import_host_id; + extra_info['ds_id'] = -1; + extra_info['enforce'] = false; + + // Deploy the VM + Sunstone.runAction("VM.silent_deploy_action", + response.VM.ID, + extra_info); + + // Notify + notifyCustom(tr("VM imported"), " ID: " + response.VM.ID, false); + + // Delete row (shouldn't be there in next monitorization) + dataTable_wilds_hosts = $("#datatable_host_wilds").dataTable(); + dataTable_wilds_hosts.fnDeleteRow(wild_row); + + }, + error: function (request, error_json){ + notifyError(error_json.error.message || tr("Cannot contact server: is it running and reachable?")); + } + }); + }) + }); //Sunstone.updateInfoPanelTab(info_panel_name,tab_name, new tab object); Sunstone.updateInfoPanelTab("host_info_panel","host_info_tab",info_tab); @@ -1085,25 +1077,31 @@ function updateHostInfo(request,host){ var wilds_list_array = []; - if (host_info.TEMPLATE.WILDS) { - wilds = host_info.TEMPLATE.WILDS.split(","); + if (host_info.TEMPLATE.VM) { + wilds = host_info.TEMPLATE.VM; $.each(wilds, function(){ - name = this.split("_")[0]; - uuid = "-"; // TODO get uuid from template and present it, CPU, MEMORY ?? + name = this.VM_NAME; + safe_name = name.replace(/ /g,"_").replace(/./g,"_"); + uuid = this.DEPLOY_ID; wilds_list_array.push([ + '', name, - uuid, - '' + uuid ]); + + dataTable_wilds_hosts.fnAddData(wilds_list_array); + + $(".import_"+safe_name, dataTable_wilds_hosts).data("wild_template", atob(this.IMPORT_TEMPLATE)); + $(".import_"+safe_name, dataTable_wilds_hosts).data("host_id", host_info.ID); + + wilds_list_array = []; }); } - //$(".import_'+name+'", trow).data("wild_template", COREVALUE) - - dataTable_wilds_hosts.fnAddData(wilds_list_array); delete host_info.TEMPLATE.WILDS; + delete host_info.TEMPLATE.VM; } var dataTable_host_vMachines = $("#datatable_host_vms", $("#host_info_panel")).dataTable({ @@ -1254,112 +1252,6 @@ function fillVCenterTemplates(opts) { return false; } -/* - Retrieve the list of running VMs from vCenter and fill the container with them - - opts = { - datacenter: "Datacenter Name", - cluster: "Cluster Name", - container: Jquery div to inject the html, - vcenter_user: vCenter Username, - vcenter_password: vCenter Password, - vcenter_host: vCenter Host - } - */ -function fillVCenterVMs(opts) { - var path = '/vcenter/vms'; - opts.container.html(generateAdvancedSection({ - html_id: path, - title: tr("Running VMs"), - content: ''+ - ''+ - ''+ - '' - })) - - $('a', opts.container).trigger("click") - - $.ajax({ - url: path, - type: "GET", - data: {timeout: false}, - dataType: "json", - headers: { - "X_VCENTER_USER": opts.vcenter_user, - "X_VCENTER_PASSWORD": opts.vcenter_password, - "X_VCENTER_HOST": opts.vcenter_host - }, - success: function(response){ - $(".content", opts.container).html(""); - - $('
' + - '
' + - '

' + tr("Please select the vCenter running VMs to be imported to OpenNebula.") + '

' + - '
' + - '
').appendTo($(".content", opts.container)) - - $.each(response, function(datacenter_name, vms){ - $('
' + - '
' + - '
' + - datacenter_name + ' ' + tr("DataCenter") + - '
' + - '
' + - '
').appendTo($(".content", opts.container)) - - if (vms.length == 0) { - $('
' + - '
' + - '' + - '
' + - '
').appendTo($(".content", opts.container)) - } else { - $.each(vms, function(id, vm){ - if (vm.host_id === parseInt(vm.host_id, 10)) { - var trow = $('
' + - '
' + - '
' + - '
' + - '
'+ - '
'+ - '
'+ - '
').appendTo($(".content", opts.container)) - - $(".vm_name", trow).data("vm_name", vm.name) - $(".vm_name", trow).data("one_vm", vm.one) - $(".vm_name", trow).data("vm_to_host", vm.host_id) - } - }); - - if ($(".vcenter_vm").length == 0) { - $('
' + - '
' + - '' + - '
' + - '
').appendTo($(".content", opts.container)) - } - }; - }); - }, - error: function(response){ - opts.container.html(""); - onError({}, OpenNebula.Error(response)); - } - }); - - return false; -} - /* Retrieve the list of networks from vCenter and fill the container with them @@ -1681,13 +1573,6 @@ function setupCreateHostDialog(){ vcenter_host: vcenter_host }); - fillVCenterVMs({ - container: vms_container, - vcenter_user: vcenter_user, - vcenter_password: vcenter_password, - vcenter_host: vcenter_host - }); - fillVCenterNetworks({ container: networks_container, vcenter_user: vcenter_user, diff --git a/src/sunstone/public/js/plugins/vms-tab.js b/src/sunstone/public/js/plugins/vms-tab.js index 1a19393908..2078f9275f 100644 --- a/src/sunstone/public/js/plugins/vms-tab.js +++ b/src/sunstone/public/js/plugins/vms-tab.js @@ -369,6 +369,12 @@ var vm_actions = { notify: true }, + "VM.silent_deploy_action" : { + type: "single", + call: OpenNebula.VM.deploy, + error: onError + }, + "VM.migrate" : { type: "custom", call: function(){ From 90b0c49195ecf7d93119d46caf19d6fc9532e329 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Fri, 27 Mar 2015 18:23:39 +0100 Subject: [PATCH 11/28] Feature #3532: Add purty table for Wild VMs in CLI --- src/cli/one_helper/onehost_helper.rb | 31 ++++++++++++++++++++++++++ src/oca/ruby/opennebula/host.rb | 7 ++++++ src/oca/ruby/opennebula/xml_element.rb | 4 ++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/cli/one_helper/onehost_helper.rb b/src/cli/one_helper/onehost_helper.rb index 8038cc93a9..52ac87b160 100644 --- a/src/cli/one_helper/onehost_helper.rb +++ b/src/cli/one_helper/onehost_helper.rb @@ -406,8 +406,39 @@ class OneHostHelper < OpenNebulaHelper::OneHelper CLIHelper.print_header(str_h1 % "MONITORING INFORMATION", false) + wilds = host.to_hash['HOST']['TEMPLATE']['VM'] + + host.delete_element("TEMPLATE/VM") + host.delete_element("TEMPLATE_WILDS") + puts host.template_str + puts + CLIHelper.print_header("WILD VIRTUAL MACHINES", false) + puts + + format = "%30s %36s %4s %10s" + CLIHelper.print_header(format % ["NAME", "UUID", "CPU", "MEMORY"], + false) + + wilds.each do |wild| + wild_tmplt = Base64::decode64(wild['IMPORT_TEMPLATE']).split("\n") + name = wild_tmplt.select { |line| + line[/^NAME/] + }[0].split("=")[1].gsub("\"", " ").strip + uuid = wild_tmplt.select { |line| + line[/^IMPORT_VM_ID/] + }[0].split("=")[1].gsub("\"", " ").strip + memory = wild_tmplt.select { |line| + line[/^MEMORY/] + }[0].split("=")[1].gsub("\"", " ").strip + cpu = wild_tmplt.select { |line| + line[/^MEMORY/] + }[0].split("=")[1].gsub("\"", " ").strip + + puts format % [name, uuid, memory, cpu] + end + puts CLIHelper.print_header("VIRTUAL MACHINES", false) puts diff --git a/src/oca/ruby/opennebula/host.rb b/src/oca/ruby/opennebula/host.rb index 1a0980c3c0..5ab9e0f993 100644 --- a/src/oca/ruby/opennebula/host.rb +++ b/src/oca/ruby/opennebula/host.rb @@ -16,6 +16,7 @@ require 'opennebula/pool_element' +require 'base64' module OpenNebula class Host < PoolElement @@ -206,6 +207,12 @@ module OpenNebula SHORT_HOST_STATES[state_str] end + # Returns the
'+tr("Security Group")+''+tr("Protocol")+''+tr("Type")+''+tr("Range")+''+tr("Network")+''+tr("ICMP Type")+'
'+this.SECURITY_GROUP_ID+''+this.SECURITY_GROUP_NAME+''+rule_st.PROTOCOL+''+rule_st.RULE_TYPE+''+rule_st.RANGE+''+rule_st.NETWORK+''+rule_st.ICMP_TYPE+'