diff --git a/install.sh b/install.sh index 243d315571..512fefa211 100755 --- a/install.sh +++ b/install.sh @@ -236,7 +236,8 @@ LIB_DIRS="$LIB_LOCATION/ruby \ $LIB_LOCATION/mads \ $LIB_LOCATION/sh \ $LIB_LOCATION/ruby/cli \ - $LIB_LOCATION/ruby/cli/one_helper" + $LIB_LOCATION/ruby/cli/one_helper \ + $LIB_LOCATION/ruby/vcenter_driver" VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/im \ @@ -258,6 +259,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/vnm/ebtables \ $VAR_LOCATION/remotes/vnm/fw \ $VAR_LOCATION/remotes/vnm/ovswitch \ + $VAR_LOCATION/remotes/vnm/vcenter \ $VAR_LOCATION/remotes/tm/ \ $VAR_LOCATION/remotes/tm/dummy \ $VAR_LOCATION/remotes/tm/shared \ @@ -381,6 +383,7 @@ INSTALL_FILES=( AUTH_DUMMY_FILES:$VAR_LOCATION/remotes/auth/dummy AUTH_PLAIN_FILES:$VAR_LOCATION/remotes/auth/plain VMM_EXEC_LIB_FILES:$VAR_LOCATION/remotes/vmm/lib + VMM_EXEC_LIB_VCENTER_FILES:$LIB_LOCATION/ruby/vcenter_driver VMM_EXEC_KVM_SCRIPTS:$VAR_LOCATION/remotes/vmm/kvm VMM_EXEC_VCENTER_SCRIPTS:$VAR_LOCATION/remotes/vmm/vcenter VMM_EXEC_EC2_SCRIPTS:$VAR_LOCATION/remotes/vmm/ec2 @@ -413,6 +416,7 @@ INSTALL_FILES=( NETWORK_EBTABLES_FILES:$VAR_LOCATION/remotes/vnm/ebtables NETWORK_FW_FILES:$VAR_LOCATION/remotes/vnm/fw NETWORK_OVSWITCH_FILES:$VAR_LOCATION/remotes/vnm/ovswitch + NETWORK_VCENTER_FILES:$VAR_LOCATION/remotes/vnm/vcenter EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples WEBSOCKIFY_SHARE_FILES:$SHARE_LOCATION/websockify INSTALL_GEMS_SHARE_FILES:$SHARE_LOCATION @@ -519,6 +523,7 @@ INSTALL_ONEFLOW_ETC_FILES=( INSTALL_ETC_FILES=( ETC_FILES:$ETC_LOCATION EC2_ETC_FILES:$ETC_LOCATION + VCENTER_ETC_FILES:$ETC_LOCATION AZ_ETC_FILES:$ETC_LOCATION VMM_EXEC_ETC_FILES:$ETC_LOCATION/vmm_exec HM_ETC_FILES:$ETC_LOCATION/hm @@ -643,6 +648,22 @@ MADS_LIB_FILES="src/mad/sh/madcommon.sh \ VMM_EXEC_LIB_FILES="src/vmm_mad/remotes/lib/poll_common.rb" +#------------------------------------------------------------------------------- +# VMM Lib vcenter files, used by the vCenter Driver to be installed in +# $REMOTES_LOCATION/vmm/lib/vcenter +#------------------------------------------------------------------------------- + +VMM_EXEC_LIB_VCENTER_FILES="src/vmm_mad/remotes/lib/vcenter_driver/datastore.rb + src/vmm_mad/remotes/lib/vcenter_driver/vi_client.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/importer.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/file_helper.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/host.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/vi_helper.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/memoize.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/datacenter.rb \ + src/vmm_mad/remotes/lib/vcenter_driver/network.rb" + #------------------------------------------------------------------------------- # VMM SH Driver KVM scripts, to be installed under $REMOTES_LOCATION/vmm/kvm #------------------------------------------------------------------------------- @@ -692,8 +713,8 @@ VMM_EXEC_VCENTER_SCRIPTS="src/vmm_mad/remotes/vcenter/cancel \ src/vmm_mad/remotes/vcenter/poll \ src/vmm_mad/remotes/vcenter/shutdown \ src/vmm_mad/remotes/vcenter/reconfigure \ - src/vmm_mad/remotes/vcenter/prereconfigure \ - src/vmm_mad/remotes/vcenter/resize_disk" + src/vmm_mad/remotes/vcenter/preconfigure \ + src/vmm_mad/remotes/vcenter/prereconfigure" #------------------------------------------------------------------------------ # VMM Driver EC2 scripts, to be installed under $REMOTES_LOCATION/vmm/ec2 @@ -763,7 +784,7 @@ IM_PROBES_KVM_PROBES_FILES="src/im_mad/remotes/kvm-probes.d/kvm.rb \ src/im_mad/remotes/common.d/version.sh \ src/im_mad/remotes/common.d/collectd-client-shepherd.sh" -IM_PROBES_VCENTER_FILES="src/im_mad/remotes/vcenter.d/vcenter.rb" +IM_PROBES_VCENTER_FILES="src/im_mad/remotes/vcenter.d/poll" IM_PROBES_EC2_FILES="src/im_mad/remotes/ec2.d/poll" @@ -840,6 +861,10 @@ NETWORK_OVSWITCH_FILES="src/vnm_mad/remotes/ovswitch/clean \ src/vnm_mad/remotes/ovswitch/update_sg \ src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb" +NETWORK_VCENTER_FILES="src/vnm_mad/remotes/vcenter/pre \ + src/vnm_mad/remotes/vcenter/post \ + src/vnm_mad/remotes/vcenter/clean" + #------------------------------------------------------------------------------- # IPAM drivers to be installed under $REMOTES_LOCATION/ipam #------------------------------------------------------------------------------- @@ -1004,9 +1029,11 @@ TM_VCENTER_FILES="src/tm_mad/vcenter/clone \ src/tm_mad/vcenter/snap_delete \ src/tm_mad/vcenter/snap_revert \ src/tm_mad/vcenter/failmigrate \ - src/datastore_mad/remotes/vcenter/monitor \ - src/tm_mad/vcenter/delete \ - src/tm_mad/vcenter/resize" + src/tm_mad/vcenter/context \ + src/tm_mad/vcenter/monitor \ + src/tm_mad/vcenter/mkimage \ + src/tm_mad/vcenter/mkswap \ + src/tm_mad/vcenter/delete" TM_ISCSI_FILES="src/tm_mad/iscsi_libvirt/clone \ src/tm_mad/iscsi_libvirt/ln \ @@ -1198,6 +1225,8 @@ EC2_ETC_FILES="src/vmm_mad/remotes/ec2/ec2_driver.conf \ AZ_ETC_FILES="src/vmm_mad/remotes/az/az_driver.conf \ src/vmm_mad/remotes/az/az_driver.default" +VCENTER_ETC_FILES="src/vmm_mad/remotes/lib/vcenter_driver/vcenter_driver.default" + #------------------------------------------------------------------------------- # Virtualization drivers config. files, to be installed under $ETC_LOCATION # - ssh, $ETC_LOCATION/vmm_exec diff --git a/share/doc/xsd/oned.conf b/share/doc/xsd/oned.conf index 0d9318825c..7c9321f35d 100644 --- a/share/doc/xsd/oned.conf +++ b/share/doc/xsd/oned.conf @@ -538,7 +538,7 @@ TM_MAD = [ DATASTORE_MAD = [ EXECUTABLE = "one_datastore", - ARGUMENTS = "-t 15 -d dummy,fs,lvm,ceph,dev,iscsi_libvirt,vcenter -s shared,ssh,ceph,fs_lvm" + ARGUMENTS = "-t 15 -d dummy,fs,lvm,ceph,dev,iscsi_libvirt,vcenter -s shared,ssh,ceph,fs_lvm,vcenter" ] #******************************************************************************* @@ -770,7 +770,7 @@ VM_RESTRICTED_ATTR = "MEMORY_COST" VM_RESTRICTED_ATTR = "DISK_COST" VM_RESTRICTED_ATTR = "PCI" VM_RESTRICTED_ATTR = "USER_INPUTS" -VM_RESTRICTED_ATTR = "DEPLOY_FOLDER" +VM_RESTRICTED_ATTR = "VCENTER_VM_FOLDER" #VM_RESTRICTED_ATTR = "RANK" #VM_RESTRICTED_ATTR = "SCHED_RANK" @@ -834,15 +834,30 @@ INHERIT_DATASTORE_ATTR = "GLUSTER_HOST" INHERIT_DATASTORE_ATTR = "GLUSTER_VOLUME" INHERIT_DATASTORE_ATTR = "DISK_TYPE" -INHERIT_DATASTORE_ATTR = "ADAPTER_TYPE" +INHERIT_DATASTORE_ATTR = "VCENTER_ADAPTER_TYPE" +INHERIT_DATASTORE_ATTR = "VCENTER_DS_REF" +INHERIT_DATASTORE_ATTR = "VCENTER_DS_IMAGE_DIR" +INHERIT_DATASTORE_ATTR = "VCENTER_DS_VOLATILE_DIR" INHERIT_IMAGE_ATTR = "DISK_TYPE" -INHERIT_IMAGE_ATTR = "ADAPTER_TYPE" +INHERIT_IMAGE_ATTR = "VCENTER_ADAPTER_TYPE" INHERIT_VNET_ATTR = "VLAN_TAGGED_ID" INHERIT_VNET_ATTR = "FILTER_IP_SPOOFING" INHERIT_VNET_ATTR = "FILTER_MAC_SPOOFING" INHERIT_VNET_ATTR = "MTU" +INHERIT_VNET_ATTR = "INBOUND_AVG_BW" +INHERIT_VNET_ATTR = "INBOUND_PEAK_BW" +INHERIT_VNET_ATTR = "INBOUND_PEAK_KB" +INHERIT_VNET_ATTR = "OUTBOUND_AVG_BW" +INHERIT_VNET_ATTR = "OUTBOUND_PEAK_BW" +INHERIT_VNET_ATTR = "OUTBOUND_PEAK_KB" + +INHERIT_VNET_ATTR = "VCENTER_NET_REF" +INHERIT_VNET_ATTR = "VCENTER_SWITCH_NAME" +INHERIT_VNET_ATTR = "VCENTER_PORTGROUP_TYPE" +INHERIT_VNET_ATTR = "VCENTER_CCR_REF" +INHERIT_VNET_ATTR = "VCENTER_INSTANCE_ID" #******************************************************************************* # Transfer Manager Driver Behavior Configuration @@ -958,7 +973,9 @@ DS_MAD_CONF = [ ] DS_MAD_CONF = [ - NAME = "vcenter", REQUIRED_ATTRS = "VCENTER_CLUSTER", PERSISTENT_ONLY = "YES", + NAME = "vcenter", + REQUIRED_ATTRS = "VCENTER_ONE_HOST_ID, VCENTER_INSTANCE_ID, VCENTER_DS_REF, VCENTER_CCR_REF", + PERSISTENT_ONLY = "YES", MARKETPLACE_ACTIONS = "export" ] diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 2cd220f4bb..0d258da3f1 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -248,10 +248,10 @@ VXLAN_IDS = [ # DEFAULT_CDROM_DEVICE_PREFIX: Same as above but for CDROM devices. # # DEFAULT_IMAGE_PERSISTENT: Control the default value for the PERSISTENT -# attribute on image creation (oneimage clone, onevm disk-saveas). If blank +# attribute on image creation (oneimage clone, onevm disk-saveas). If blank # images will inherit the persistent attribute from the base image. # -# DEFAULT_IMAGE_PERSISTENT_NEW: Control the default value for the PERSISTENT +# DEFAULT_IMAGE_PERSISTENT_NEW: Control the default value for the PERSISTENT # attribute on image creation (oneimage create). By default images are no # persistent if not set. #******************************************************************************* @@ -569,7 +569,7 @@ TM_MAD = [ DATASTORE_MAD = [ EXECUTABLE = "one_datastore", - ARGUMENTS = "-t 15 -d dummy,fs,lvm,ceph,dev,iscsi_libvirt,vcenter -s shared,ssh,ceph,fs_lvm,qcow2" + ARGUMENTS = "-t 15 -d dummy,fs,lvm,ceph,dev,iscsi_libvirt,vcenter -s shared,ssh,ceph,fs_lvm,qcow2,vcenter" ] #******************************************************************************* @@ -814,8 +814,8 @@ DEFAULT_UMASK = 177 VM_ADMIN_OPERATIONS = "migrate, delete, recover, retry, deploy, resched" -VM_MANAGE_OPERATIONS = "undeploy, hold, release, stop, suspend, resume, reboot, - poweroff, disk-attach, nic-attach, disk-snapshot, terminate, disk-resize, +VM_MANAGE_OPERATIONS = "undeploy, hold, release, stop, suspend, resume, reboot, + poweroff, disk-attach, nic-attach, disk-snapshot, terminate, disk-resize, snapshot, updateconf, rename, resize, update, disk-saveas" VM_USE_OPERATIONS = "" @@ -856,7 +856,7 @@ VM_RESTRICTED_ATTR = "EMULATOR" VM_RESTRICTED_ATTR = "USER_INPUTS/CPU" VM_RESTRICTED_ATTR = "USER_INPUTS/MEMORY" VM_RESTRICTED_ATTR = "USER_INPUTS/VCPU" -VM_RESTRICTED_ATTR = "DEPLOY_FOLDER" +VM_RESTRICTED_ATTR = "VCENTER_VM_FOLDER" #VM_RESTRICTED_ATTR = "RANK" #VM_RESTRICTED_ATTR = "SCHED_RANK" @@ -920,10 +920,13 @@ INHERIT_DATASTORE_ATTR = "GLUSTER_HOST" INHERIT_DATASTORE_ATTR = "GLUSTER_VOLUME" INHERIT_DATASTORE_ATTR = "DISK_TYPE" -INHERIT_DATASTORE_ATTR = "ADAPTER_TYPE" +INHERIT_DATASTORE_ATTR = "VCENTER_ADAPTER_TYPE" +INHERIT_DATASTORE_ATTR = "VCENTER_DS_REF" +INHERIT_DATASTORE_ATTR = "VCENTER_DS_IMAGE_DIR" +INHERIT_DATASTORE_ATTR = "VCENTER_DS_VOLATILE_DIR" INHERIT_IMAGE_ATTR = "DISK_TYPE" -INHERIT_IMAGE_ATTR = "ADAPTER_TYPE" +INHERIT_IMAGE_ATTR = "VCENTER_ADAPTER_TYPE" INHERIT_VNET_ATTR = "VLAN_TAGGED_ID" INHERIT_VNET_ATTR = "FILTER_IP_SPOOFING" @@ -936,6 +939,12 @@ INHERIT_VNET_ATTR = "OUTBOUND_AVG_BW" INHERIT_VNET_ATTR = "OUTBOUND_PEAK_BW" INHERIT_VNET_ATTR = "OUTBOUND_PEAK_KB" +INHERIT_VNET_ATTR = "VCENTER_NET_REF" +INHERIT_VNET_ATTR = "VCENTER_SWITCH_NAME" +INHERIT_VNET_ATTR = "VCENTER_PORTGROUP_TYPE" +INHERIT_VNET_ATTR = "VCENTER_CCR_REF" +INHERIT_VNET_ATTR = "VCENTER_INSTANCE_ID" + #******************************************************************************* # Transfer Manager Driver Behavior Configuration #******************************************************************************* @@ -1050,7 +1059,9 @@ DS_MAD_CONF = [ ] DS_MAD_CONF = [ - NAME = "vcenter", REQUIRED_ATTRS = "VCENTER_CLUSTER", PERSISTENT_ONLY = "YES", + NAME = "vcenter", + REQUIRED_ATTRS = "VCENTER_ONE_HOST_ID, VCENTER_INSTANCE_ID, VCENTER_DS_REF, VCENTER_CCR_REF", + PERSISTENT_ONLY = "NO", MARKETPLACE_ACTIONS = "export" ] diff --git a/share/vendor/ruby/gems/rbvmomi/vmodl.db b/share/vendor/ruby/gems/rbvmomi/vmodl.db index c332918483..15440ef703 100644 Binary files a/share/vendor/ruby/gems/rbvmomi/vmodl.db and b/share/vendor/ruby/gems/rbvmomi/vmodl.db differ diff --git a/src/cli/one_helper.rb b/src/cli/one_helper.rb index 86d60f897f..c0e118f7c0 100644 --- a/src/cli/one_helper.rb +++ b/src/cli/one_helper.rb @@ -354,11 +354,11 @@ EOT :description => 'Sends READY=YES to OneGate, useful for OneFlow' }, { - :name => 'deploy_folder', - :large => '--deploy_folder path', + :name => 'vcenter_vm_folder', + :large => '--vcenter_vm_folder path', :format => String, :description => "In a vCenter environment sets the the VMs and Template folder where the VM will be placed in." \ - " The path uses slashes to separate folders. For example: --deploy_folder \"/Management/VMs\"" + " The path uses slashes to separate folders. For example: --vcenter_vm_folder \"/Management/VMs\"" } ] @@ -1133,7 +1133,7 @@ EOT template<<' ]' << "\n" end - template<<"DEPLOY_FOLDER=#{options[:deploy_folder]}\n" if options[:deploy_folder] + template<<"VCENTER_VM_FOLDER=#{options[:vcenter_vm_folder]}\n" if options[:vcenter_vm_folder] context=create_context(options) template< "disk_type", :large => "--disk_type disk_type", :description => "Type of the image \n"<< - " "*31<<"for KVM: BLOCK, CDROM, RBD or FILE \n"<< - " "*31<<"for vCenter: THIN, TICHK, ZEOREDTHICK " << + " " * 31 << "BLOCK, CDROM, RBD or FILE \n" << "(for others, check the documentation) ", :format => String }, { - :name => "adapter_type", - :large => "--adapter_type adapter_type", + :name => "vcenter_disk_type", + :large => "--vcenter_disk_type vcenter_disk_type", + :description => "The vCenter Disk Type of the image \n"<< + " " * 31 << + "for vCenter: THIN, THICK, ZEROEDTHICK " << + "(for others, check the documentation) ", + :format => String + }, + { + :name => "vcenter_adapter_type", + :large => "--vcenter_adapter_type vcenter_adapter_type", :description => "Controller that will handle this image in " << "vCenter (lsiLogic, ide, busLogic). For other "<< "values check the documentation", @@ -358,16 +366,16 @@ class OneImageHelper < OpenNebulaHelper::OneHelper end def self.create_image_variables(options, name) - if Array===name - names=name + if Array === name + names = name else - names=[name] + names = [name] end - t='' + t = '' names.each do |n| if options[n] - t<<"#{n.to_s.upcase}=\"#{options[n]}\"\n" + t << "#{n.to_s.upcase}=\"#{options[n]}\"\n" end end @@ -375,16 +383,21 @@ class OneImageHelper < OpenNebulaHelper::OneHelper end def self.create_image_template(options) - template_options=TEMPLATE_OPTIONS.map do |o| + template_options = TEMPLATE_OPTIONS.map do |o| o[:name].to_sym end - template=create_image_variables( - options, template_options-[:persistent, :dry, :prefix]) + template = create_image_variables( + options, + template_options - [:persistent, :dry, :prefix ] + ) + + if options[:persistent] + template << "PERSISTENT=YES\n" + end - template<<"PERSISTENT=YES\n" if options[:persistent] if options[:prefix] - template<<"DEV_PREFIX=\"#{options[:prefix]}\"\n" + template << "DEV_PREFIX=\"#{options[:prefix]}\"\n" end [0, template] diff --git a/src/cli/onevcenter b/src/cli/onevcenter index 2b0f16f880..2f9ea7862f 100755 --- a/src/cli/onevcenter +++ b/src/cli/onevcenter @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # -------------------------------------------------------------------------- # -# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # +# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # @@ -65,9 +65,9 @@ cmd=CommandParser::CmdParser.new(ARGV) do helper.set_client(options) end - ######################################################################## + ############################################################################ # Global Options - ######################################################################## + ############################################################################ cmd_options=CommandParser::OPTIONS-[CommandParser::VERBOSE] set :option, cmd_options+OpenNebulaHelper::CLIENT_OPTIONS @@ -93,6 +93,13 @@ cmd=CommandParser::CmdParser.new(ARGV) do :format => String } + USE_DEFAULTS = { + :name => "defaults", + :large => "--use-defaults", + :description => "Use defaults for answers to questions", + :format => String + } + ############################################################################ # Import clusters ############################################################################ @@ -100,470 +107,80 @@ cmd=CommandParser::CmdParser.new(ARGV) do Import vCenter clusters as OpenNebula hosts EOT - command :hosts, hosts_desc, :options=>[ VCENTER, USER, PASS ] do + command :hosts, hosts_desc, :options=>[ VCENTER, USER, PASS, USE_DEFAULTS ] do con_ops = connection_options("Hosts", options) - begin - STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..." - - vc = VCenterDriver::VIClient.new_connection(con_ops) - - STDOUT.print "done!\n\n" - - STDOUT.print "Exploring vCenter resources..." - - rs = vc.hierarchy - - STDOUT.print "done!\n\n" - - rs.each {|dc, cluster| - STDOUT.print "Do you want to process datacenter #{dc} [y/n]? " - - next if STDIN.gets.strip.downcase != 'y' - - if cluster.empty? - STDOUT.puts " No new clusters found in #{dc}..." - next - end - - cluster.each{ |c| - STDOUT.print " * Import cluster #{c} [y/n]? " - - next if STDIN.gets.strip.downcase != 'y' - - r, m = VCenterDriver::VCenterHost.to_one(c, vc) - - if r == 0 - STDOUT.puts " OpenNebula host #{c} with id #{m}"\ - " successfully created." - else - STDOUT.puts " Error: #{m}" - end - - STDOUT.puts - } - } - rescue Exception => e - STDOUT.puts "error: #{e.message}" - exit -1 - end + VCenterDriver::Importer.import_clusters(con_ops, options) exit 0 end + ############################################################################ + # Import templates + ############################################################################ templates_desc = <<-EOT.unindent Import vCenter VM Templates into OpenNebula EOT - command :templates, templates_desc, :options=>[ VCENTER, USER, PASS ] do + command :templates, templates_desc, :options=>[ VCENTER, USER, PASS, USE_DEFAULTS ] do con_ops = connection_options("VM Templates", options) - begin - STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..." - - vc = VCenterDriver::VIClient.new_connection(con_ops) - - STDOUT.print "done!\n\n" - - STDOUT.print "Looking for VM Templates..." - - rs = vc.vm_templates - - 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 new VM Templates found in #{dc}...\n\n" - next - end - - tmps.each{ |t| - STDOUT.print "\n * VM Template found:\n"\ - " - Name : #{t[:name]}\n"\ - " - UUID : #{t[:uuid]}\n"\ - " - Cluster: #{t[:host]}\n"\ - " Import this VM template [y/n]? " - - next if STDIN.gets.strip.downcase != 'y' - - ds_input = "" - rp_input = "" - - # Datastores - - STDOUT.print "\n This template is currently set to be "\ - "deployed in datastore #{t[:default_ds]}."\ - "\n Press y to keep the default, n to select"\ - " a new datastore or d to delegate the choice"\ - " to the user [y/n/d]? " - - answer = STDIN.gets.strip.downcase - - case answer - when 'd' - ds_split = t[:ds].split("|") - list_of_ds = ds_split[-2] - default_ds = ds_split[-1] - ds_input = ds_split[0] + "|" + ds_split[1] + "|" + - ds_split[2] + "|" - - # Available list of datastores - - input_str = " The list of available datastores to be"\ - " presented to the user are \"#{list_of_ds}\"" - input_str+= "\n Press y to agree, or input a comma"\ - " separated list of datastores to edit "\ - "[y/comma separated list] " - STDOUT.print input_str - - answer = STDIN.gets.strip - - if answer.downcase == 'y' - ds_input += ds_split[3] + "|" - else - ds_input += answer + "|" - end - - # Default - input_str = " The default datastore presented to "\ - "the end user is set to \"#{default_ds}\"." - input_str+= "\n Press y to agree, or input a new "\ - "datastore [y/datastore name] " - STDOUT.print input_str - - answer = STDIN.gets.strip - - if answer.downcase == 'y' - ds_input += ds_split[4] - else - ds_input += answer - end - when 'n' - ds_split = t[:ds].split("|") - list_of_ds = ds_split[-2] - - input_str = " The list of available datastores is"\ - " \"#{list_of_ds}\"." - input_str+= "\n Please input the new default datastore: " - STDOUT.print input_str - - answer = STDIN.gets.strip - - t[:one] += "VCENTER_DATASTORE=\"#{answer}\"\n" - end - - # Resource Pools - - rp_split = t[:rp].split("|") - - if rp_split.size > 3 - STDOUT.print "\n This template is currently set to "\ - "launch VMs in the default resource pool."\ - "\n Press y to keep this behaviour, n to select"\ - " a new resource pool or d to delegate the choice"\ - " to the user [y/n/d]? " - - answer = STDIN.gets.strip.downcase - - case answer - when 'd' - list_of_rp = rp_split[-2] - default_rp = rp_split[-1] - rp_input = rp_split[0] + "|" + rp_split[1] + "|" + - rp_split[2] + "|" - - # Available list of resource pools - - input_str = " The list of available resource pools "\ - "to be presented to the user are "\ - "\"#{list_of_rp}\"" - input_str+= "\n Press y to agree, or input a comma"\ - " separated list of resource pools to edit "\ - "[y/comma separated list] " - STDOUT.print input_str - - answer = STDIN.gets.strip - - if answer.downcase == 'y' - rp_input += rp_split[3] + "|" - else - rp_input += answer + "|" - end - - # Default - input_str = " The default resource pool presented "\ - "to the end user is set to"\ - " \"#{default_rp}\"." - input_str+= "\n Press y to agree, or input a new "\ - "resource pool [y/resource pool name] " - STDOUT.print input_str - - answer = STDIN.gets.strip - - if answer.downcase == 'y' - rp_input += rp_split[4] - else - rp_input += answer - end - when 'n' - list_of_rp = rp_split[-2] - - input_str = " The list of available resource pools is"\ - " \"#{list_of_rp}\"." - input_str+= "\n Please input the new default resource pool: " - STDOUT.print input_str - - answer = STDIN.gets.strip - - t[:one] += "RESOURCE_POOL=\"#{answer}\"\n" - end - end - - if ds_input != "" || - rp_input != "" - t[:one] += "USER_INPUTS=[" - t[:one] += "VCENTER_DATASTORE=\"#{ds_input}\"," if ds_input != "" - t[:one] += "RESOURCE_POOL=\"#{rp_input}\"," if rp_input != "" - t[:one] = t[:one][0..-2] - t[:one] += "]" - end - - one_t = ::OpenNebula::Template.new( - ::OpenNebula::Template.build_xml, vc.one) - - rc = one_t.allocate(t[:one]) - - if ::OpenNebula.is_error?(rc) - STDOUT.puts " Error creating template: #{rc.message}\n" - else - STDOUT.puts " OpenNebula template #{one_t.id} created!\n" - end - } - } - rescue Exception => e - STDOUT.puts "error: #{e.message}" - exit -1 - end + VCenterDriver::Importer.import_templates(con_ops, options) exit 0 end + ############################################################################ + # Import vms (deprecated) + ############################################################################ vms_desc = <<-EOT.unindent Deprecated action in onevcenter, please use onehost importvm instead EOT - command :vms, vms_desc, :options=>[ VCENTER, USER, PASS ] do + command :vms, vms_desc, :options=>[ VCENTER, USER, PASS, USE_DEFAULTS ] do STDERR.puts "Deprecated action in onevcenter, please use onehost "\ "importvm instead" - exit -1 end + ############################################################################ + # Import networks + ############################################################################ network_desc = <<-EOT.unindent Import vCenter networks into OpenNebula EOT - command :networks, network_desc, :options=>[ VCENTER, USER, PASS ] do + command :networks, network_desc, :options=>[ VCENTER, USER, PASS, USE_DEFAULTS ] do con_ops = connection_options("Networks", options) - begin - STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..." - - vc = VCenterDriver::VIClient.new_connection(con_ops) - - 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 new 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 += " - Cluster : #{n[:cluster]}\n" - print_str += " Import this Network [y/n]? " - - STDOUT.print print_str - - next if STDIN.gets.strip.downcase != 'y' - - # Size - - 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 - - # Type - - STDOUT.print " What type of Virtual Network"\ - " do you want to create (IPv[4],IPv[6]"\ - ",[E]thernet) ?" - - type = STDIN.gets.strip - - ar_str = "\nAR=[TYPE=\"" - - case type.downcase - when "4" - ar_str += "IP4\"" - STDOUT.print " Please input the first IP "\ - "in the range: " - ip = STDIN.gets.strip - ar_str += ",IP=" + ip - - STDOUT.print " Please input the first MAC "\ - "in the range [Enter for default]: " - mac = STDIN.gets.strip - ar_str += ",MAC=" + mac if !mac.empty? - when "6" - ar_str += "IP6\"" - STDOUT.print " Please input the first MAC "\ - "in the range [Enter for default]: " - mac = STDIN.gets.strip - ar_str += ",MAC=" + mac if !mac.empty? - - STDOUT.print " Please input the GLOBAL PREFIX "\ - "[Enter for default]: " - gp = STDIN.gets.strip - ar_str += ",GLOBAL_PREFIX=" + gp if !gp.empty? - - STDOUT.print " Please input the ULA PREFIX "\ - "[Enter for default]: " - up = STDIN.gets.strip - ar_str += ",ULA_PREFIX=" + up if !up.empty? - when "e" - ar_str += "ETHER\"" - STDOUT.print " Please input the first MAC "\ - "in the range [Enter for default]: " - mac = STDIN.gets.strip - ar_str += ",MAC=" + mac if !mac.empty? - else - STDOUT.puts " Type [#{type}] not supported,"\ - " defaulting to Ethernet." - ar_str += "ETHER\"" - STDOUT.print " Please input the first MAC "\ - "in the range [Enter for default]: " - mac = STDIN.gets.strip - ar_str += ",MAC=" + mac if !mac.empty? - end - - ar_str += ",SIZE = \"#{size}\"]" - - one_vn = ::OpenNebula::VirtualNetwork.new( - ::OpenNebula::Template.build_xml, vc.one) - - vnet_template = n[:one] + ar_str - - 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 + VCenterDriver::Importer.import_networks(con_ops, options) exit 0 end + ############################################################################ + # Import datastores + ############################################################################ datastores_desc = <<-EOT.unindent Import vCenter Datastores into OpenNebula EOT - command :datastores, datastores_desc, :options=>[ VCENTER, USER, PASS ] do + command :datastores, datastores_desc, :options=>[ VCENTER, USER, PASS, USE_DEFAULTS ] do con_ops = connection_options("Datastores", options) - begin - STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..." - - vc = VCenterDriver::VIClient.new_connection(con_ops) - - STDOUT.print "done!\n\n" - - STDOUT.print "Looking for Datastores..." - - rs = vc.vcenter_datastores - - 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 new Datastores found in #{dc}...\n\n" - next - end - - tmps.each{ |d| - STDOUT.print "\n * Datastore found:\n"\ - " - Name : #{d[:name]}\n"\ - " - Total MB : #{d[:total_mb]}\n"\ - " - Free MB : #{d[:free_mb]}\n"\ - " - Cluster : #{d[:cluster]}\n"\ - " Import this Datastore [y/n]? " - - next if STDIN.gets.strip.downcase != 'y' - - one_d = ::OpenNebula::Datastore.new( - ::OpenNebula::Datastore.build_xml, vc.one) - - rc = one_d.allocate(d[:one]) - - if ::OpenNebula.is_error?(rc) - STDOUT.puts " Error creating datastore: #{rc.message}\n"\ - " One datastore can exist only once, and "\ - "can be used in any vCenter Cluster that "\ - "has access to it. Also, no spaces allowed "\ - "in datastore name (rename it in vCenter "\ - "and try again)" - else - STDOUT.puts " OpenNebula datastore #{one_d.id} created!\n" - end - } - } - rescue Exception => e - STDOUT.puts "error: #{e.message}" - exit -1 - end + VCenterDriver::Importer.import_datastore(con_ops, options) exit 0 end + ############################################################################ + # Import images + ############################################################################ images_desc = <<-EOT.unindent Import vCenter Images into OpenNebula EOT - command :images, images_desc, :ds_name, :options=>[ VCENTER, USER, PASS ] do + command :images, images_desc, :ds_name, :options=>[ VCENTER, USER, PASS, USE_DEFAULTS ] do ds_name = args[0] if !ds_name @@ -573,49 +190,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do con_ops = connection_options("Images", options) - begin - STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..." - - vc = VCenterDriver::VIClient.new_connection(con_ops) - - STDOUT.print "done!\n\n" - - STDOUT.print "Looking for Images..." - - images = vc.vcenter_images(ds_name) - - STDOUT.print "done!\n" - - images.each{ |i| - STDOUT.print "\n * Image found:\n"\ - " - Name : #{i[:name]}\n"\ - " - Path : #{i[:path]}\n"\ - " - Type : #{i[:type]}\n"\ - " Import this Image [y/n]? " - - next if STDIN.gets.strip.downcase != 'y' - - one_i = ::OpenNebula::Image.new( - ::OpenNebula::Image.build_xml, vc.one) - - rc = one_i.allocate(i[:one], i[:dsid].to_i) - - if ::OpenNebula.is_error?(rc) - STDOUT.puts "Error creating image: #{rc.message}\n" - if rc.message == "[ImageAllocate] Not enough space "\ - "in datastore" - STDOUT.puts "Please disable DATASTORE_CAPACITY_"\ - "CHECK in /etc/one/oned.conf and "\ - "restart OpenNebula." - end - else - STDOUT.puts " OpenNebula image #{one_i.id} created!\n" - end - } - rescue Exception => e - STDOUT.puts "error: #{e.message}" - exit -1 - end + VCenterDriver::Importer.import_images(con_ops, ds_name, options) exit 0 end diff --git a/src/datastore_mad/remotes/vcenter/clone b/src/datastore_mad/remotes/vcenter/clone index 62fe90228e..bde317746b 100755 --- a/src/datastore_mad/remotes/vcenter/clone +++ b/src/datastore_mad/remotes/vcenter/clone @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # ---------------------------------------------------------------------------- # -# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # +# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # @@ -16,10 +16,6 @@ # limitations under the License. # # ---------------------------------------------------------------------------- # -############################################################################### -# This script is used retrieve the file size of a disk -############################################################################### - ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION @@ -32,7 +28,6 @@ $: << RUBY_LIB_LOCATION $: << File.dirname(__FILE__) require 'vcenter_driver' -require 'digest' drv_action_enc = ARGV[0] id = ARGV[1] @@ -40,26 +35,43 @@ id = ARGV[1] drv_action = OpenNebula::XMLElement.new drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA') -ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"] -hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"] -img_path = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"] +target_ds_ref = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_REF"] +host_id = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"] +ds_image_dir = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_IMAGE_DIR"] || "one" +src_path = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"] +src_img_id = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/CLONING_ID"] -if ds_name.nil? || hostname.nil? || img_path.nil? - STDERR.puts "Not enough information to clone the image, missing datastore"\ - " name or vcenter cluster name or image path." - exit -1 -end +check_valid src_img_id, "cloning id" +check_valid host_id, "vcenter cluster" +check_valid src_path, "image path" +check_valid target_ds_ref, "target ds ref" + +# Get source ds_ref +source_img = VCenterDriver::VIHelper.one_item(OpenNebula::Image, src_img_id) +source_ds_id = source_img['DATASTORE_ID'] +source_ds = VCenterDriver::VIHelper.one_item(OpenNebula::Datastore, source_ds_id) +source_ds_ref = source_ds['TEMPLATE/VCENTER_DS_REF'] # Generate target path -str_for_target_path = Time.now.to_s + id.to_s -target_path = Digest::MD5.hexdigest(str_for_target_path) + ".vmdk" +target_path = "#{ds_image_dir}/#{id}/one-#{id}.vmdk" begin - host_id = VCenterDriver::VIClient.translate_hostname(hostname) - vi_client = VCenterDriver::VIClient.new host_id + vi_client = VCenterDriver::VIClient.new_from_host(host_id) + + + ds = VCenterDriver::Datastore.new_from_ref(source_ds_ref, vi_client) + + target_ds_vc = VCenterDriver::Datastore.new_from_ref(target_ds_ref, vi_client) + + target_ds_name = target_ds_vc['name'] + + puts ds.copy_virtual_disk(src_path, target_ds_vc, target_path) - puts vi_client.copy_virtual_disk(img_path, ds_name, target_path) rescue Exception => e - STDERR.puts "Error cloning img #{img_path} size. Reason: #{e.message}" + message = "Error cloning img #{src_path} to #{target_ds_name}"\ + " Reason: \"#{e.message}\"\n#{e.backtrace}" + STDERR.puts error_message(message) exit -1 +ensure + vi_client.close_connection if vi_client end diff --git a/src/datastore_mad/remotes/vcenter/cp b/src/datastore_mad/remotes/vcenter/cp index faae47d14c..a207d47a69 100755 --- a/src/datastore_mad/remotes/vcenter/cp +++ b/src/datastore_mad/remotes/vcenter/cp @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # ---------------------------------------------------------------------------- # -# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # +# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # @@ -16,10 +16,6 @@ # limitations under the License. # # ---------------------------------------------------------------------------- # -############################################################################### -# This script is used retrieve the file size of a disk -############################################################################### - ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) if !ONE_LOCATION @@ -33,123 +29,7 @@ end $: << RUBY_LIB_LOCATION $: << File.dirname(__FILE__) -require 'opennebula' -require 'fileutils' -require 'tempfile' - -def is_remote?(file) - file.match(%r{^https?://}) -end - -def is_vmdk?(file) - type = %x{file #{file}} - - type.include? "VMware" -end - -def get_type(file) - type = %x{file -b --mime-type #{file}} - if $?.exitstatus != 0 - STDERR.puts "Can not read file #{file}" - exit(-1) - end - - type.strip -end - -def needs_unpack?(file) - temp = Tempfile.new('one-') - temp.close - - file_path = file - - if is_remote?(file) - rc = system("curl --fail -sS -k -L #{file_path} | head -c 1024 > #{temp.path}") - if !rc - STDERR.puts "Can not download file #{file_path}" - exit(-1) - end - file_path = temp.path - end - - type = get_type(file_path) - type.gsub!(%r{^application/(x-)?}, '') - unpack = %w{bzip2 gzip tar}.include?(type) - - temp.unlink - - unpack -end - -def vmdk_info(file) - file_path = file - - if File.directory?(file_path) - files = Dir["#{file_path}/*.vmdk"] - found = false - count = 0 - last = nil - - files.each do |f| - if get_type(f).strip == "text/plain" - file_path = f - found = true - break - else - count += 1 - last = f - end - end - - if !found - if count == 1 - file_path = last - found = true - else - STDERR.puts "Could not find vmdk" - exit(-1) - end - end - end - - case get_type(file_path).strip - when "application/octet-stream" - return { - :type => :standalone, - :file => file_path, - :dir => File.dirname(file_path) - } - when "application/x-iso9660-image" - return { - :type => :standalone, - :file => file_path, - :dir => File.dirname(file_path), - :extension => '.iso' - } - when "text/plain" - info = { - :type => :flat, - :file => file_path, - :dir => File.dirname(file_path) - } - - files_list = [] - descriptor = File.read(file_path).split("\n") - flat_files = descriptor.select {|l| l.start_with?("RW")} - - flat_files.each do |f| - files_list << info[:dir] + "/" + - f.split(" ")[3].chomp.chomp('"').reverse.chomp('"').reverse - end - - info[:flat_files] = files_list - - return info - else - STDERR.puts "Unrecognized file type" - exit(-1) - end -end +require 'vcenter_driver' drv_action_enc = ARGV[0] id = ARGV[1] @@ -157,65 +37,61 @@ id = ARGV[1] drv_action = OpenNebula::XMLElement.new drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA') -img_path = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"] -md5 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5"] -sha1 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/SHA1"] -nodecomp = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/NO_DECOMPRESS"] -limit_bw = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LIMIT_TRANSFER_BW"] -hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"] -ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"] +img_path = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"] +host_id = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"] +ds_ref = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_REF"] +ds_image_dir = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_IMAGE_DIR"] || "one" +md5 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5"] +sha1 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/SHA1"] +nodecomp = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/NO_DECOMPRESS"] +limit_bw = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LIMIT_TRANSFER_BW"] +check_valid img_path, "img_path" -if img_path.nil? - STDERR.puts "Not enough information to register the image,"\ - " missing image path." - exit(-1) -end - +# if image is already in a vCenter datastore return the path if img_path.start_with? "vcenter://" - # File already in the vCenter datastore - puts img_path.sub("vcenter://","") exit(0) end -downsh_args = " " -downsh_args += "--md5 #{md5} " if md5 and !md5.empty? and !md5.eql? "-" -downsh_args += "--sha1 #{sha1} " if sha1 and !sha1.empty? -downsh_args += "--nodecomp " if nodecomp and !nodecomp.empty? -downsh_args += "--limit #{limit_bw} " if limit_bw and !limit_bw.empty? +temp_file = nil +filename = File.basename(img_path) +target_path = "#{ds_image_dir}/#{id}" -downloader = "#{File.dirname(__FILE__)}/../downloader.sh #{downsh_args}" +# If image is in a remote http location it has to be downloaded +# or if is a zipped file it has to be unzipped in a temp folder -# Generate target path -str_for_target_path = Time.now.to_s + id.to_s -target_path = Digest::MD5.hexdigest(str_for_target_path) +if VCenterDriver::FileHelper.is_remote_or_needs_unpack?(img_path) + temp_folder = File.join(VAR_LOCATION, "vcenter/#{target_path}") + temp_file = File.join(temp_folder, File.basename(img_path)) -files_to_upload = Array.new + # Create tmp directory + FileUtils.mkdir_p(temp_folder) -file_path = img_path -skip_download = false -delete_file = false -files_to_upload = [] + # Specify downloader args + downsh_args = " " + downsh_args << "--md5 #{md5} " if md5 && !md5.empty? && !md5.eql?("-") + downsh_args << "--sha1 #{sha1} " if sha1 && !sha1.empty? + downsh_args << "--nodecomp " if nodecomp && !nodecomp.empty? + downsh_args << "--limit #{limit_bw} " if limit_bw && !limit_bw.empty? -if is_remote?(file_path) || needs_unpack?(file_path) - temp_folder = File.join(VAR_LOCATION, "vcenter") - temp_file = File.join(temp_folder, File.basename(target_path)) - FileUtils.mkdir_p(temp_folder) if !File.directory?(temp_folder) + downloader = "#{File.dirname(__FILE__)}/../downloader.sh #{downsh_args}" + + rc = system("#{downloader} #{img_path} #{temp_file}") - rc = system("#{downloader} #{file_path} #{temp_file}") if !rc - STDERR.puts "Error downloading #{file_path}" + STDERR.puts "Error downloading #{img_path}" FileUtils.rm_rf(temp_file) - exit(-1) + exit -1 end - delete_file = true - original_path = File.basename(file_path) - file_path = temp_file + img_path = temp_file end -info = vmdk_info(file_path) +# Time to upload files to vCenter +files_to_upload = [] + +info = VCenterDriver::FileHelper.vcenter_file_info(img_path) extension = info[:extension] || '' case info[:type] @@ -227,34 +103,40 @@ when :flat end files_to_upload.each_with_index do |f, index| - path = "#{target_path}/#{File.basename(f)}" + + path = "#{target_path}/#{File.basename(f)}" # Change path for gzipped standalone file if(target_path == File.basename(f)) - path = "#{target_path}/#{original_path}" - + path = "#{target_path}/#{filename}" + # remove gz or bz2 if part of filename - if path.end_with?("gz") and is_vmdk?(f) - path.gsub!(/gz$/,'') + if path.end_with?("gz") && VCenterDriver::FileHelper.is_vmdk?(f) + path.gsub!(/gz$/,'') end - if path.end_with?("bz2") and is_vmdk?(f) - path.gsub!(/bz2$/,'') - end - end + if path.end_with?("bz2") && VCenterDriver::FileHelper.is_vmdk?(f) + path.gsub!(/bz2$/,'') + end + end - # Change path if vmdk is part of filename - # but it's not the extension' - if /[^.]+vmdk$/.match(path) and is_vmdk?(f) + # Change path if vmdk is part of filename but it's not the extension + if /[^.]+vmdk$/.match(path) && VCenterDriver::FileHelper.is_vmdk?(f) path.gsub!(/vmdk$/,'') - extension = '.vmdk' + extension = '.vmdk' + end + + # Add iso extension if file is an ISO file + if VCenterDriver::FileHelper.is_iso?(f) + path = "#{File.dirname(path)}/#{File.basename(path,".*")}" + extension = '.iso' end if index == files_to_upload.size - 1 - uploader_args = hostname + " " + ds_name + " " + + uploader_args = host_id + " " + ds_ref + " " + "#{path}#{extension}" + " " + f else - uploader_args = hostname + " " + ds_name + " " + + uploader_args = host_id + " " + ds_ref + " " + path + " " + f + " &> /dev/null" end @@ -262,12 +144,11 @@ files_to_upload.each_with_index do |f, index| rc = system(cmd) if !rc - STDERR.puts "Can not upload file #{f}" - FileUtils.rm_rf(temp_file) if delete_file + STDERR.puts "Cannot upload file #{f}" + FileUtils.rm_rf(temp_file) if temp_file exit(-1) end end - -FileUtils.rm_rf(temp_file) if delete_file +FileUtils.rm_rf(temp_file) if temp_file diff --git a/src/datastore_mad/remotes/vcenter/export b/src/datastore_mad/remotes/vcenter/export index 69acfcb077..5acb7372d4 100755 --- a/src/datastore_mad/remotes/vcenter/export +++ b/src/datastore_mad/remotes/vcenter/export @@ -17,7 +17,7 @@ # ---------------------------------------------------------------------------- # ############################################################################### -# This script is used retrieve the file size of a disk +# This script is used retrieve the file size of a disk ############################################################################### ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) @@ -39,21 +39,20 @@ id = ARGV[1] drv_action = OpenNebula::XMLElement.new drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA') - - img_source = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SOURCE"] img_size = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SIZE"] md5 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5"] md5 = md5.nil? ? "-" : md5 -hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"] +hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"] ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"] if img_source.nil? - STDERR.puts "Not enough information to export the image,"\ - " missing image source." + message = "Not enough information to export the image,"\ + " missing image source." + STDERR.puts error_message(message) exit -1 end diff --git a/src/datastore_mad/remotes/vcenter/mkfs b/src/datastore_mad/remotes/vcenter/mkfs index b2b7cf3e3b..ae48cad71f 100755 --- a/src/datastore_mad/remotes/vcenter/mkfs +++ b/src/datastore_mad/remotes/vcenter/mkfs @@ -17,7 +17,7 @@ # ---------------------------------------------------------------------------- # ############################################################################### -# This script is used retrieve the file size of a disk +# This script is used retrieve the file size of a disk ############################################################################### ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) @@ -36,37 +36,48 @@ require 'vcenter_driver' drv_action_enc = ARGV[0] id = ARGV[1] -drv_action =OpenNebula::XMLElement.new +drv_action = OpenNebula::XMLElement.new drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA') -ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"] -hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"] -adapter_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/ADAPTER_TYPE"] -disk_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/DISK_TYPE"] -size = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SIZE"] -img_name = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/NAME"] +ds_ref = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_REF"] +host_id = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"] +ds_image_dir = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_IMAGE_DIR"] || "one" +img_id = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/ID"] +adapter_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/VCENTER_ADAPTER_TYPE"] || + VCenterDriver::VIHelper.get_default("IMAGE/TEMPLATE/VCENTER_ADAPTER_TYPE") +disk_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/VCENTER_DISK_TYPE"] || + VCenterDriver::VIHelper.get_default("IMAGE/TEMPLATE/VCENTER_DISK_TYPE") +size = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SIZE"] +fs_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/FSTYPE"] -if ds_name.nil? || - hostname.nil? || - adapter_type.nil? || - disk_type.nil? || - size.nil? || - img_name.nil? - STDERR.puts "Not enough information to create the image." - exit -1 +check_valid img_id, "img_id" +check_valid host_id, "vcenter_cluster" +check_valid adapter_type, "adapter_type" +check_valid disk_type, "disk_type" +check_valid size, "size" +check_valid ds_ref, "ds_ref" + +# TODO path in vCenter? choose a specific directory + +img_name = "#{ds_image_dir}/#{img_id}/one-#{img_id}" + +if fs_type == "save_as" + puts img_name + ".vmdk" + exit 0 end begin - host_id = VCenterDriver::VIClient.translate_hostname(hostname) - vi_client = VCenterDriver::VIClient.new host_id + vi_client = VCenterDriver::VIClient.new_from_host(host_id) + + ds = VCenterDriver::Datastore.new_from_ref(ds_ref, vi_client) + + puts ds.create_virtual_disk(img_name, size, adapter_type, disk_type) - puts vi_client.create_virtual_disk(img_name, - ds_name, - size, - adapter_type, - disk_type) rescue Exception => e - STDERR.puts "Error creating virtual disk in #{ds_name}."\ - " Reason: #{e.message}" + message = "Error creating virtual disk #{img_name}."\ + " Reason: \"#{e.message}\"\n#{e.backtrace}" + STDERR.puts error_message(message) exit -1 +ensure + vi_client.close_connection if vi_client end diff --git a/src/datastore_mad/remotes/vcenter/monitor b/src/datastore_mad/remotes/vcenter/monitor index a07f8136c9..bbca555fd0 100755 --- a/src/datastore_mad/remotes/vcenter/monitor +++ b/src/datastore_mad/remotes/vcenter/monitor @@ -39,21 +39,26 @@ id = ARGV[1] drv_action = OpenNebula::XMLElement.new drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA') -ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"] -hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"] +host_id = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"] +ds_ref = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_REF"] +check_valid ds_ref, "ds_ref" -if ds_name.nil? || - hostname.nil? +if host_id.nil? || ds_ref.nil? STDERR.puts "Not enough information to monitor the image." exit -1 end begin - host_id = VCenterDriver::VIClient.translate_hostname(hostname) - vi_client = VCenterDriver::VIClient.new host_id + vi_client = VCenterDriver::VIClient.new_from_host(host_id) + + storage = VCenterDriver::Storage.new_from_ref(ds_ref, vi_client) + puts storage.monitor - puts vi_client.monitor_ds(ds_name) rescue Exception => e - STDERR.puts "Error monitoring #{ds_name}. Reason: #{e.message}" + message = "Error monitoring host #{id}."\ + " Reason: \"#{e.message}\"\n#{e.backtrace}" + STDERR.puts error_message(message) exit -1 +ensure + vi_client.close_connection if vi_client end diff --git a/src/datastore_mad/remotes/vcenter/rm b/src/datastore_mad/remotes/vcenter/rm index 9f40353d2d..2b67d53723 100755 --- a/src/datastore_mad/remotes/vcenter/rm +++ b/src/datastore_mad/remotes/vcenter/rm @@ -17,7 +17,7 @@ # ---------------------------------------------------------------------------- # ############################################################################### -# This script is used retrieve the file size of a disk +# This script is used retrieve the file size of a disk ############################################################################### ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) @@ -39,25 +39,43 @@ id = ARGV[1] drv_action =OpenNebula::XMLElement.new drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA') -ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"] -hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"] -img_src = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SOURCE"] +ds_ref = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_REF"] +host_id = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"] +img_src = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SOURCE"] +imported = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/VCENTER_IMPORTED"] -if ds_name.nil? || - hostname.nil? || - img_src.nil? - STDERR.puts "Not enough information to delete the image." - exit -1 -end +check_valid ds_ref, "ds_ref" +check_valid host_id, "vcenter_cluster" +check_valid img_src, "img_src" + +CDROM = "1" begin - host_id = VCenterDriver::VIClient.translate_hostname(hostname) - vi_client = VCenterDriver::VIClient.new host_id + #TODO should imported disks be deleted? + if imported.nil? || imported.empty? + vi_client = VCenterDriver::VIClient.new_from_host(host_id) - vi_client.delete_virtual_disk(img_src, - ds_name) + ds = VCenterDriver::Datastore.new_from_ref(ds_ref, vi_client) + + img_dir = img_src.split('/')[0..-2].join('/') + + img_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TYPE"] + + if img_type != CDROM + # delete the disk + ds.delete_virtual_disk(img_src) + else + # delete the CDROM iso + ds.delete_file(img_src) + end + + ds.rm_directory(img_dir) if ds.dir_empty?(img_dir) + end rescue Exception => e - STDERR.puts "Error delete virtual disk #{img_src} in #{ds_name}."\ - " Reason: #{e.message}" + message = "Error deleting virtual disk #{img_src}."\ + " Reason: \"#{e.message}\"\n#{e.backtrace}" + STDERR.puts error_message(message) exit -1 +ensure + vi_client.close_connection if vi_client end diff --git a/src/datastore_mad/remotes/vcenter/stat b/src/datastore_mad/remotes/vcenter/stat index b3dab82226..2b3ca2fffc 100755 --- a/src/datastore_mad/remotes/vcenter/stat +++ b/src/datastore_mad/remotes/vcenter/stat @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # ---------------------------------------------------------------------------- # -# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # +# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # @@ -17,7 +17,7 @@ # ---------------------------------------------------------------------------- # ############################################################################### -# This script is used retrieve the file size of a disk +# This script is used retrieve the file size of a disk ############################################################################### ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) @@ -39,32 +39,31 @@ id = ARGV[1] drv_action =OpenNebula::XMLElement.new drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA') -ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"] -hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"] +ds_ref = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_DS_REF"] +host_id = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_ONE_HOST_ID"] img_path = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"] -if ds_name.nil? || - hostname.nil? || - img_path.nil? - STDERR.puts "Not enough information to stat the image." - exit -1 -end +check_valid ds_ref, "ds_ref" +check_valid host_id, "vcenter_cluster" +check_valid img_path, "img_path" if img_path.start_with? "vcenter://" begin - img_path = img_path.sub("vcenter://","") - host_id = VCenterDriver::VIClient.translate_hostname(hostname) - vi_client = VCenterDriver::VIClient.new host_id + vi_client = VCenterDriver::VIClient.new_from_host(host_id) + + ds = VCenterDriver::Datastore.new_from_ref(ds_ref, vi_client) + + puts ds.stat(img_path.sub("vcenter://","")) - puts vi_client.stat(ds_name, img_path) rescue Exception => e - STDERR.puts "Error calculating image #{img_path} size."\ - " Reason: #{e.message}" + message = "Error calculating image #{img_path} size."\ + " Reason: \"#{e.message}\"\n#{e.backtrace}" + STDERR.puts error_message(message) exit -1 + ensure + vi_client.close_connection if vi_client end else cmd = "#{File.dirname(__FILE__)}/../fs/stat #{drv_action_enc}" system(cmd) end - - diff --git a/src/datastore_mad/remotes/vcenter_downloader.rb b/src/datastore_mad/remotes/vcenter_downloader.rb index 7beb68beb6..9f605f51dc 100755 --- a/src/datastore_mad/remotes/vcenter_downloader.rb +++ b/src/datastore_mad/remotes/vcenter_downloader.rb @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # ---------------------------------------------------------------------------- # -# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # +# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # @@ -34,28 +34,24 @@ require 'uri' require 'cgi' require 'fileutils' -vcenter_url = ARGV[0] +vcenter_url = ARGV[0] -u = URI.parse(vcenter_url) -params = CGI.parse(u.query) +u = URI.parse(vcenter_url) +params = CGI.parse(u.query) -hostname = params["param_host"][0] -ds_name = params["param_dsname"][0] -img_src = u.host + u.path +vc_cluster_name = params["param_host"][0] +ds_name = params["param_dsname"][0] +img_src = u.host + u.path begin - host_id = VCenterDriver::VIClient.translate_hostname(hostname) - vi_client = VCenterDriver::VIClient.new host_id - ds = vi_client.get_datastore(ds_name) + host = VCenterDriver::VIHelper.find_by_name(OpenNebula::HostPool, vc_cluster_name) + host_id = host['ID'] - if ds.is_a? RbVmomi::VIM::StoragePod - STDERR.puts "Cannot download images from StoragePod #{ds_name} on #{hostname}."\ - "Reason: Not supported" - exit(-1) - end + vi_client = VCenterDriver::VIClient.new_from_host(host_id) + ds = VCenterDriver::Datastore.new_from_ref(source_ds_ref, vi_client) - if ds.is_descriptor? img_src + if ds.is_descriptor?(img_src) descriptor_name = File.basename u.path temp_folder = VAR_LOCATION + "/vcenter/" + descriptor_name + "/" FileUtils.mkdir_p(temp_folder) if !File.directory?(temp_folder) @@ -73,7 +69,7 @@ begin VCenterDriver::VIClient.in_silence do files_to_download.each{|file| - ds.download(url_prefix + file, temp_folder + file) + ds.download_file(url_prefix + file, temp_folder + file) } end @@ -91,11 +87,14 @@ begin else # Setting "." as the source will read from the stdin VCenterDriver::VIClient.in_stderr_silence do - ds.download_to_stdout img_src + ds.download_to_stdout(img_src) end end + rescue Exception => e STDERR.puts "Cannot download image #{u.path} from datastore #{ds_name} "\ - "on #{hostname}. Reason: #{e.message}" + "on #{hostname}. Reason: \"#{e.message}\"\n#{e.backtrace}" exit -1 +ensure + vi_client.close_connection if vi_client end diff --git a/src/datastore_mad/remotes/vcenter_uploader.rb b/src/datastore_mad/remotes/vcenter_uploader.rb index a5ca52245d..4d3443ff0d 100755 --- a/src/datastore_mad/remotes/vcenter_uploader.rb +++ b/src/datastore_mad/remotes/vcenter_uploader.rb @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # ---------------------------------------------------------------------------- # -# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # +# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # @@ -29,62 +29,31 @@ $: << File.dirname(__FILE__) require 'vcenter_driver' -hostname = ARGV[0] -ds_name = ARGV[1] -target_path = ARGV[2] -source_path = ARGV[3] +host_id = ARGV[0] +target_ds_ref = ARGV[1] +target_path = ARGV[2] +source_path = ARGV[3] begin - host_id = VCenterDriver::VIClient.translate_hostname(hostname) - vi_client = VCenterDriver::VIClient.new host_id + vi_client = VCenterDriver::VIClient.new_from_host(host_id) + ds = VCenterDriver::Datastore.new_from_ref(target_ds_ref, vi_client) - ds = vi_client.get_datastore(ds_name) + # Setting "." as the source will read from the stdin + source_path = "." if source_path.nil? - if ds.is_a? RbVmomi::VIM::StoragePod - STDERR.puts "Cannot upload image to StoragePod #{ds_name} on #{hostname}."\ - "Reason: Not supported" - exit(-1) - end - - # Monkey path datastore objects. Can not be done patching the class - # as the library redefines it when a new object is created. Using both - # the database vmodl.db and the Datastore.rb - # - # This patch fixes a bug in rbvmomi. It does not specify the path of the - # datacenter. If it is inside a folder it could not be found. - class < e - STDERR.puts "Cannot upload image to datastore #{ds_name} on #{hostname}."\ - "Reason: #{e.message}" + STDERR.puts "Cannot upload image to datastore #{ds_name} "\ + "Reason: \"#{e.message}\"\n#{e.backtrace}" exit -1 +ensure + vi_client.close_connection if vi_client end diff --git a/src/im_mad/remotes/vcenter.d/vcenter.rb b/src/im_mad/remotes/vcenter.d/poll similarity index 56% rename from src/im_mad/remotes/vcenter.d/vcenter.rb rename to src/im_mad/remotes/vcenter.d/poll index b50077406e..b35e10a61f 100755 --- a/src/im_mad/remotes/vcenter.d/vcenter.rb +++ b/src/im_mad/remotes/vcenter.d/poll @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # ---------------------------------------------------------------------------- # -# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # +# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # @@ -29,24 +29,46 @@ $: << RUBY_LIB_LOCATION require 'vcenter_driver' host_id = ARGV[4] +check_valid host_id, "host_id" -if !host_id - exit -1 +begin + vi_client = VCenterDriver::VIClient.new_from_host(host_id) + + # Get CCR reference + client = OpenNebula::Client.new + host = OpenNebula::Host.new_with_id(host_id, client) + rc = host.info + if OpenNebula::is_error? rc + STDERR.puts rc.message + exit 1 + end + + ccr_ref = host["TEMPLATE/VCENTER_CCR_REF"] + + # Get vCenter Cluster + cluster = VCenterDriver::ClusterComputeResource.new_from_ref(ccr_ref, vi_client) + + # Print monitoring info + puts cluster.monitor + puts cluster.monitor_host_systems + + vm_monitor_info = cluster.monitor_vms + if !vm_monitor_info.empty? + puts "VM_POLL=YES" + puts vm_monitor_info + end + + puts cluster.monitor_customizations + + dc = cluster.get_dc + ds_folder = dc.datastore_folder + ds_folder.fetch! + puts ds_folder.monitor + +rescue Exception => e + STDERR.puts "IM poll for vcenter cluster #{host_id} failed due to "\ + "\"#{e.message}\"\n#{e.backtrace}" + exit(-1) +ensure + vi_client.close_connection if vi_client end - -vi_client = VCenterDriver::VIClient.new host_id - -vcenter_host = VCenterDriver::VCenterHost.new vi_client - -cluster_info = vcenter_host.monitor_cluster -cluster_info << vcenter_host.monitor_host_systems -vm_monitor_info = vcenter_host.monitor_vms - -cluster_info << "\nVM_POLL=YES" -cluster_info << "#{vm_monitor_info}" if !vm_monitor_info.empty? - -cluster_info << "\n" -cluster_info << vcenter_host.monitor_customizations -cluster_info << vcenter_host.get_available_ds - -puts cluster_info diff --git a/src/nebula/NebulaTemplate.cc b/src/nebula/NebulaTemplate.cc index 92039bda5a..363970757f 100644 --- a/src/nebula/NebulaTemplate.cc +++ b/src/nebula/NebulaTemplate.cc @@ -156,6 +156,9 @@ void OpenNebulaTemplate::set_multiple_conf_default() set_conf_ds("shared", "", "NO"); set_conf_ds("ssh", "", "NO"); set_conf_ds("vmfs", "BRIDGE_LIST", "NO"); + set_conf_ds("vcenter", + "VCENTER_ONE_HOST_ID, VCENTER_INSTANCE_ID, VCENTER_DS_REF, VCENTER_CCR_REF", + "NO"); set_conf_ds("ceph", "DISK_TYPE,BRIDGE_LIST,CEPH_HOST,CEPH_USER,CEPH_SECRET", "NO"); diff --git a/src/oca/java/test/oned.conf b/src/oca/java/test/oned.conf index c3da2c7945..06abbbae09 100644 --- a/src/oca/java/test/oned.conf +++ b/src/oca/java/test/oned.conf @@ -371,7 +371,7 @@ IM_MAD = [ # # type : driver type, supported drivers: xen, kvm, xml # -# keep_snapshots: do not remove snapshots on power on/off cycles and live +# keep_snapshots: do not remove snapshots on power on/off cycles and live # migrations if the hypervisor supports that. # # imported_vms_actions : comma-separated list of actions supported @@ -833,10 +833,10 @@ INHERIT_DATASTORE_ATTR = "GLUSTER_HOST" INHERIT_DATASTORE_ATTR = "GLUSTER_VOLUME" INHERIT_DATASTORE_ATTR = "DISK_TYPE" -INHERIT_DATASTORE_ATTR = "ADAPTER_TYPE" +INHERIT_DATASTORE_ATTR = "VCENTER_ADAPTER_TYPE" INHERIT_IMAGE_ATTR = "DISK_TYPE" -INHERIT_IMAGE_ATTR = "ADAPTER_TYPE" +INHERIT_IMAGE_ATTR = "VCENTER_ADAPTER_TYPE" INHERIT_VNET_ATTR = "VLAN_TAGGED_ID" INHERIT_VNET_ATTR = "FILTER_IP_SPOOFING" @@ -957,7 +957,9 @@ DS_MAD_CONF = [ ] DS_MAD_CONF = [ - NAME = "vcenter", REQUIRED_ATTRS = "VCENTER_CLUSTER", PERSISTENT_ONLY = "YES", + NAME = "vcenter", + REQUIRED_ATTRS = "VCENTER_ONE_HOST_ID, VCENTER_INSTANCE_ID, VCENTER_DS_REF, VCENTER_CCR_REF", + PERSISTENT_ONLY = "YES", MARKETPLACE_ACTIONS = "export" ] diff --git a/src/oca/ruby/opennebula/host.rb b/src/oca/ruby/opennebula/host.rb index 42f8ff82ab..d707e3c151 100644 --- a/src/oca/ruby/opennebula/host.rb +++ b/src/oca/ruby/opennebula/host.rb @@ -223,12 +223,23 @@ module OpenNebula xml = OpenNebula::VirtualMachine.build_xml vm = OpenNebula::VirtualMachine.new(xml, @client) - rc = vm.allocate(template) + # vCenter wild VMs has a different process + # image and vnets objects representing existing nics and disks + # must be created and referenced + vcenter_wild_vm = wild.key? "VCENTER_TEMPLATE" + if vcenter_wild_vm + require 'vcenter_driver' + host_id = self["ID"] + vm_ref = wild["DEPLOY_ID"] + return VCenterDriver::Importer.import_wild(host_id, vm_ref, vm, template) + else + rc = vm.allocate(template) - return rc if OpenNebula.is_error?(rc) + return rc if OpenNebula.is_error?(rc) - vm.deploy(id, false) - return vm.id + vm.deploy(id, false) + return vm.id + end end ####################################################################### diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index 2d0c1379a3..7d52e4c285 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -349,7 +349,7 @@ module OpenNebula ds = OpenNebula::Datastore.new_with_id(ds_id, @client) rc = ds.info return rc if OpenNebula.is_error?(rc) - self.update("VCENTER_DATASTORE=#{ds['/DATASTORE/NAME']}", true) + self.update("VCENTER_DS_REF=#{ds['/DATASTORE/VCENTER_DS_REF']}", true) end return call(VM_METHODS[:deploy], @@ -744,13 +744,6 @@ module OpenNebula self['DEPLOY_ID'] end - # Returns the deploy_id of the VirtualMachine (numeric value) - def keep_disks? - !self['USER_TEMPLATE/KEEP_DISKS_ON_DONE'].nil? && - self['USER_TEMPLATE/KEEP_DISKS_ON_DONE'].downcase=="yes" - end - - # Clones the VM's source Template, replacing the disks with live snapshots # of the current disks. The VM capacity and NICs are also preserved # diff --git a/src/oca/ruby/opennebula/xml_element.rb b/src/oca/ruby/opennebula/xml_element.rb index 4ccd2f8ac7..2225b29f30 100644 --- a/src/oca/ruby/opennebula/xml_element.rb +++ b/src/oca/ruby/opennebula/xml_element.rb @@ -45,6 +45,7 @@ module OpenNebula end end end + @xml end # Builds a XML document @@ -167,6 +168,23 @@ module OpenNebula end + # Iterates over every Element in the XPath and returns an array + # with XMLElements + # @return [XMLElement] + def retrieve_xmlelements(xpath_str) + collection = [] + if NOKOGIRI + @xml.xpath(xpath_str).each { |pelem| + collection << XMLElement.new(pelem) + } + else + @xml.elements.each(xpath_str) { |pelem| + collection << XMLElement.new(pelem) + } + end + collection + end + # Gets an attribute from an element # key:: _String_ xpath for the element # name:: _String_ name of the attribute diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb index 2668a72f74..af07da99e5 100644 --- a/src/sunstone/OpenNebulaVNC.rb +++ b/src/sunstone/OpenNebulaVNC.rb @@ -211,8 +211,8 @@ class OpenNebulaVNC vnc_port = vm_resource['TEMPLATE/GRAPHICS/PORT'] vnc_pw = vm_resource['TEMPLATE/GRAPHICS/PASSWD'] - if vm_resource['MONITORING/ESX_HOST'] # It is behind a vCenter - host = vm_resource['MONITORING/ESX_HOST'] + if vm_resource['MONITORING/VCENTER_ESX_HOST'] # It is behind a vCenter + host = vm_resource['MONITORING/VCENTER_ESX_HOST'] end # Generate token random_str: host:port diff --git a/src/sunstone/etc/sunstone-views/admin.yaml b/src/sunstone/etc/sunstone-views/admin.yaml index 71a38c86c1..790b0fe071 100644 --- a/src/sunstone/etc/sunstone-views/admin.yaml +++ b/src/sunstone/etc/sunstone-views/admin.yaml @@ -52,7 +52,7 @@ features: # True to show an input to specify the the VMs and Template path/folder where a vCenter VM will # deployed to - vcenter_deploy_folder: false + vcenter_vm_folder: false tabs: dashboard-tab: # The following widgets can be used inside any of the '_per_row' settings diff --git a/src/sunstone/etc/sunstone-views/admin_vcenter.yaml b/src/sunstone/etc/sunstone-views/admin_vcenter.yaml index 75ef5ef014..7e7e2288e3 100644 --- a/src/sunstone/etc/sunstone-views/admin_vcenter.yaml +++ b/src/sunstone/etc/sunstone-views/admin_vcenter.yaml @@ -17,8 +17,8 @@ enabled_tabs: - datastores-tab - images-tab #- files-tab - #- marketplaces-tab - #- marketplaceapps-tab + - marketplaces-tab + - marketplaceapps-tab - network-top-tab - vnets-tab - vnets-topology-tab @@ -52,7 +52,7 @@ features: # True to show an input to specify the the VMs and Template path/folder where a vCenter VM will # deployed to - vcenter_deploy_folder: true + vcenter_vm_folder: true tabs: dashboard-tab: # The following widgets can be used inside any of the '_per_row' settings @@ -345,7 +345,7 @@ tabs: VM.resize: true VM.attachdisk: true VM.detachdisk: true - VM.disk_saveas: false + VM.disk_saveas: true VM.attachnic: true VM.detachnic: true VM.snapshot_create: true @@ -544,7 +544,7 @@ tabs: #- 13 # Search data actions: Datastore.refresh: true - Datastore.create_dialog: true + Datastore.create_dialog: false Datastore.import_dialog: true Datastore.addtocluster: true Datastore.rename: true diff --git a/src/sunstone/etc/sunstone-views/groupadmin.yaml b/src/sunstone/etc/sunstone-views/groupadmin.yaml index 942acdc0bf..443ac0e573 100644 --- a/src/sunstone/etc/sunstone-views/groupadmin.yaml +++ b/src/sunstone/etc/sunstone-views/groupadmin.yaml @@ -52,7 +52,7 @@ features: # True to show an input to specify the the VMs and Template path/folder where a vCenter VM will # deployed to - vcenter_deploy_folder: false + vcenter_vm_folder: false tabs: dashboard-tab: # The following widgets can be used inside any of the '_per_row' settings diff --git a/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml b/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml index bd8324a778..c50796b713 100644 --- a/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml +++ b/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml @@ -52,7 +52,7 @@ features: # True to show an input to specify the the VMs and Template path/folder where a vCenter VM will # deployed to - vcenter_deploy_folder: false + vcenter_vm_folder: false tabs: dashboard-tab: # The following widgets can be used inside any of the '_per_row' settings diff --git a/src/sunstone/etc/sunstone-views/user.yaml b/src/sunstone/etc/sunstone-views/user.yaml index 389a1d7887..4cc5d7c7c0 100644 --- a/src/sunstone/etc/sunstone-views/user.yaml +++ b/src/sunstone/etc/sunstone-views/user.yaml @@ -52,7 +52,7 @@ features: # True to show an input to specify the the VMs and Template path/folder where a vCenter VM will # deployed to - vcenter_deploy_folder: false + vcenter_vm_folder: false tabs: dashboard-tab: # The following widgets can be used inside any of the '_per_row' settings diff --git a/src/sunstone/public/app/tabs/datastores-tab/form-panels/create.js b/src/sunstone/public/app/tabs/datastores-tab/form-panels/create.js index 3789933341..e67093a2d3 100644 --- a/src/sunstone/public/app/tabs/datastores-tab/form-panels/create.js +++ b/src/sunstone/public/app/tabs/datastores-tab/form-panels/create.js @@ -183,7 +183,6 @@ define(function(require) { break; case "vcenter": - $('input#system_ds_type', dialog).attr('disabled', 'disabled'); $('input#file_ds_type', dialog).attr('disabled', 'disabled'); _selectvCenter(dialog); break; diff --git a/src/sunstone/public/app/tabs/datastores-tab/panels/info.js b/src/sunstone/public/app/tabs/datastores-tab/panels/info.js index 0d9ffb0093..07da9e4e3b 100644 --- a/src/sunstone/public/app/tabs/datastores-tab/panels/info.js +++ b/src/sunstone/public/app/tabs/datastores-tab/panels/info.js @@ -67,9 +67,18 @@ define(function(require) { function _html() { var renameTrHTML = RenameTr.html(TAB_ID, RESOURCE, this.element.NAME); - var templateTableHTML = TemplateTable.html( - this.element.TEMPLATE, RESOURCE, - Locale.tr("Attributes")); + var strippedTemplate = {}; + var strippedTemplateVcenter = {}; + $.each(this.element.TEMPLATE, function(key, value) { + if (key.match(/^VCENTER_*/)){ + strippedTemplateVcenter[key] = value; + } + else { + strippedTemplate[key] = value; + } + }); + var templateTableHTML = TemplateTable.html(strippedTemplate, RESOURCE, Locale.tr("Attributes"), true); + var templateTableVcenterHTML = TemplateTable.html(strippedTemplateVcenter, RESOURCE, Locale.tr("Vcenter information"), false); var permissionsTableHTML = PermissionsTable.html(TAB_ID, RESOURCE, this.element); var capacityBar = DatastoreCapacityBar.html(this.element); var stateStr = OpenNebulaDatastore.stateStr(this.element.STATE); @@ -84,6 +93,7 @@ define(function(require) { 'element': this.element, 'renameTrHTML': renameTrHTML, 'templateTableHTML': templateTableHTML, + 'templateTableVcenterHTML': templateTableVcenterHTML, 'permissionsTableHTML': permissionsTableHTML, 'capacityBar': capacityBar, 'stateStr': stateStr, @@ -94,7 +104,20 @@ define(function(require) { function _setup(context) { RenameTr.setup(TAB_ID, RESOURCE, this.element.ID, context); - TemplateTable.setup(this.element.TEMPLATE, RESOURCE, this.element.ID, context); + var strippedTemplate = {}; + var strippedTemplateVcenter = {}; + $.each(this.element.TEMPLATE, function(key, value) { + if (key.match(/^VCENTER_*/)){ + strippedTemplateVcenter[key] = value; + } + else { + strippedTemplate[key] = value; + } + }); + if($.isEmptyObject(strippedTemplateVcenter)){ + $('.vcenter', context).hide(); + } + TemplateTable.setup(strippedTemplate, RESOURCE, this.element.ID, context); PermissionsTable.setup(TAB_ID, RESOURCE, this.element, context); return false; } diff --git a/src/sunstone/public/app/tabs/datastores-tab/panels/info/html.hbs b/src/sunstone/public/app/tabs/datastores-tab/panels/info/html.hbs index 987a5a47d1..442279c487 100644 --- a/src/sunstone/public/app/tabs/datastores-tab/panels/info/html.hbs +++ b/src/sunstone/public/app/tabs/datastores-tab/panels/info/html.hbs @@ -58,6 +58,9 @@ {{{permissionsTableHTML}}} +
+
{{{templateTableVcenterHTML}}}
+
{{{templateTableHTML}}}
diff --git a/src/sunstone/public/app/tabs/hosts-tab/panels/info.js b/src/sunstone/public/app/tabs/hosts-tab/panels/info.js index 52cc8a3332..3a670c94c6 100644 --- a/src/sunstone/public/app/tabs/hosts-tab/panels/info.js +++ b/src/sunstone/public/app/tabs/hosts-tab/panels/info.js @@ -65,12 +65,17 @@ define(function(require) { // in the template table. Unshow values are stored in the unshownTemplate // object to be used when the host info is updated. that.unshownTemplate = {}; + that.strippedTemplateVcenter = {}; that.strippedTemplate = {}; var unshownKeys = ['HOST', 'VM', 'WILDS', 'ZOMBIES', 'RESERVED_CPU', 'RESERVED_MEM']; $.each(that.element.TEMPLATE, function(key, value) { if ($.inArray(key, unshownKeys) > -1) { - that.unshownTemplate[key] = value; - } else { + that.unshownTemplate[key] = value; + } + else if (key.match(/^VCENTER_*/)){ + that.strippedTemplateVcenter[key] = value; + } + else { that.strippedTemplate[key] = value; } }); @@ -92,6 +97,10 @@ define(function(require) { this.strippedTemplate, RESOURCE, Locale.tr("Attributes")); + var templateTableVcenterHTML = TemplateTable.html( + this.strippedTemplateVcenter, + RESOURCE, + Locale.tr("Vcenter information"),false); var renameTrHTML = RenameTr.html(TAB_ID, RESOURCE, this.element.NAME); var clusterTrHTML = ClusterTr.html(this.element.CLUSTER); var permissionsTableHTML = PermissionsTable.html(TAB_ID, RESOURCE, this.element); @@ -106,6 +115,7 @@ define(function(require) { 'renameTrHTML': renameTrHTML, 'clusterTrHTML': clusterTrHTML, 'templateTableHTML': templateTableHTML, + 'templateTableVcenterHTML': templateTableVcenterHTML, 'permissionsTableHTML': permissionsTableHTML, 'cpuBars': cpuBars, 'memoryBars': memoryBars, @@ -137,6 +147,10 @@ define(function(require) { TemplateTable.setup(this.strippedTemplate, RESOURCE, this.element.ID, context, this.unshownTemplate); PermissionsTable.setup(TAB_ID, RESOURCE, this.element, context); + if($.isEmptyObject(this.strippedTemplateVcenter)){ + $('.vcenter', context).hide(); + } + //.off and .on prevent multiple clicks events $(document).off('click', '.update_reserved_hosts').on("click", '.update_reserved', function(){ var reservedCPU = parseInt(document.getElementById('change_bar_cpu_hosts').value); diff --git a/src/sunstone/public/app/tabs/hosts-tab/panels/info/html.hbs b/src/sunstone/public/app/tabs/hosts-tab/panels/info/html.hbs index 7ff53d2194..d9a0ae56d3 100644 --- a/src/sunstone/public/app/tabs/hosts-tab/panels/info/html.hbs +++ b/src/sunstone/public/app/tabs/hosts-tab/panels/info/html.hbs @@ -107,6 +107,9 @@ +
+
{{{templateTableVcenterHTML}}}
+
{{{templateTableHTML}}}
diff --git a/src/sunstone/public/app/tabs/images-tab/form-panels/create-common.js b/src/sunstone/public/app/tabs/images-tab/form-panels/create-common.js index fb2201a1c4..bcad8f2389 100644 --- a/src/sunstone/public/app/tabs/images-tab/form-panels/create-common.js +++ b/src/sunstone/public/app/tabs/images-tab/form-panels/create-common.js @@ -205,8 +205,8 @@ define(function(require) { }); // Custom Adapter Type - var custom_attrs = ["adapter_type", - "disk_type", + var custom_attrs = ["vcenter_adapter_type", + "vcenter_disk_type", "img_dev_prefix", "img_driver"]; @@ -361,10 +361,10 @@ define(function(require) { } document.getElementById( 'percent_progress' ).textContent = 'Completed: ' + (this.progress().toFixed(3)*100).toFixed(1) +'%'; $('div.progressbar', $('div[id="' + fileName + 'progressBar"]')).html( - ProgressBar.html(this.progress(), 1, fileName) ); + ProgressBar.html(this.progress(), 1, fileName) ); }); } - + return false; } @@ -414,12 +414,12 @@ define(function(require) { if (target) img_json["TARGET"] = target; - var adapter_type = WizardFields.retrieveInput($('#adapter_type', context)); - if (adapter_type) { - if (adapter_type == "custom") { - adapter_type = WizardFields.retrieveInput($('#custom_adapter_type', context)); + var vcenter_adapter_type = WizardFields.retrieveInput($('#vcenter_adapter_type', context)); + if (vcenter_adapter_type) { + if (vcenter_adapter_type == "custom") { + vcenter_adapter_type = WizardFields.retrieveInput($('#custom_vcenter_adapter_type', context)); } - img_json["ADAPTER_TYPE"] = adapter_type; + img_json["VCENTER_ADAPTER_TYPE"] = vcenter_adapter_type; } switch ($('#src_path_select input:checked', context).val()){ @@ -431,12 +431,12 @@ define(function(require) { size = WizardFields.retrieveInput($('#img_size', context)); if (size) img_json["SIZE"] = size; - var disk_type = WizardFields.retrieveInput($('#disk_type', context)); - if (disk_type) { - if (disk_type == "custom"){ - disk_type = WizardFields.retrieveInput($('#custom_disk_type', context)); + var vcenter_disk_type = WizardFields.retrieveInput($('#vcenter_disk_type', context)); + if (vcenter_disk_type) { + if (vcenter_disk_type == "custom"){ + vcenter_disk_type = WizardFields.retrieveInput($('#custom_disk_type', context)); } - img_json["DISK_TYPE"] = disk_type; + img_json["VCENTER_DISK_TYPE"] = vcenter_disk_type; } break; diff --git a/src/sunstone/public/app/tabs/images-tab/form-panels/create/wizard.hbs b/src/sunstone/public/app/tabs/images-tab/form-panels/create/wizard.hbs index 37db4780e8..5efe5c43ea 100644 --- a/src/sunstone/public/app/tabs/images-tab/form-panels/create/wizard.hbs +++ b/src/sunstone/public/app/tabs/images-tab/form-panels/create/wizard.hbs @@ -104,10 +104,10 @@
-
@@ -126,10 +126,10 @@
-
diff --git a/src/sunstone/public/app/tabs/images-tab/form-panels/import/html.hbs b/src/sunstone/public/app/tabs/images-tab/form-panels/import/html.hbs index ab8ee9d356..b843babfce 100644 --- a/src/sunstone/public/app/tabs/images-tab/form-panels/import/html.hbs +++ b/src/sunstone/public/app/tabs/images-tab/form-panels/import/html.hbs @@ -31,19 +31,21 @@
-
+
-
- - +
+
+
+ +
{{{vCenterImagesHTML}}}
-
\ No newline at end of file +
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js index 4e9653669b..ed87201e87 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js @@ -165,14 +165,8 @@ define(function(require) { // part of an array, and it is filled in different tabs, the $.extend deep // merge can't work. We define an auxiliary attribute for it. - if (templateJSON["VCENTER_PUBLIC_CLOUD"]) { - if (templateJSON['PUBLIC_CLOUD'] == undefined) { - templateJSON['PUBLIC_CLOUD'] = []; - } - - templateJSON['PUBLIC_CLOUD'].push(templateJSON["VCENTER_PUBLIC_CLOUD"]); - - delete templateJSON["VCENTER_PUBLIC_CLOUD"]; + if (templateJSON['PUBLIC_CLOUD'] == undefined) { + templateJSON['PUBLIC_CLOUD'] = []; } // PCI with TYPE=NIC is not defined in the 'other' tab. Because it is diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/context.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/context.js index d5d1e8240b..7abfb01cda 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/context.js +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/context.js @@ -191,8 +191,8 @@ define(function(require) { var customization = WizardFields.retrieveInput($('input.vcenter_customizations_value', context)); if (customization) { - templateJSON["VCENTER_PUBLIC_CLOUD"] = { - CUSTOMIZATION_SPEC : customization + templateJSON["USER_TEMPLATE"] = { + VCENTER_CUSTOMIZATION_SPEC : customization }; } } else { @@ -259,8 +259,8 @@ define(function(require) { if(this["TYPE"] == "vcenter"){ $("input#context_type_vcenter", context).click(); - if(this["CUSTOMIZATION_SPEC"]){ - WizardFields.fillInput($('input.vcenter_customizations_value', context), this["CUSTOMIZATION_SPEC"]); + if(this["VCENTER_CUSTOMIZATION_SPEC"]){ + WizardFields.fillInput($('input.vcenter_customizations_value', context), this["VCENTER_CUSTOMIZATION_SPEC"]); } else if(userInputsJSON || contextJSON) { $("input#context_type_opennebula", context).click(); } @@ -286,6 +286,7 @@ define(function(require) { } if (contextJSON) { + $("input#context_type_opennebula", context).click(); var file_ds_regexp = /FILE\[IMAGE=(\w+?)\W+IMAGE_UNAME=(\w+?)\]/g; var net_regexp = /^NETWORK$/; var ssh_regexp = /^SSH_PUBLIC_KEY$/; @@ -332,7 +333,7 @@ define(function(require) { that.contextFilesTable.selectResourceTableSelect(selectedResources); } }); - + } else if ("START_SCRIPT_BASE64" == key) { $(".ENCODE_START_SCRIPT", context).prop('checked', 'checked'); $(".START_SCRIPT", context).val(atob(value)); diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general.js index 1800b5784b..702b309b7f 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general.js +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general.js @@ -160,9 +160,13 @@ define(function(require) { $(".only_" + this.value).show(); if (this.value == "vcenter"){ - $("#vcenter_template_uuid", context).attr("required", ""); + $("#vcenter_template_ref", context).attr("required", ""); + $("#vcenter_instance_id", context).attr("required", ""); + $("#vcenter_ccr_ref", context).attr("required", ""); } else { - $("#vcenter_template_uuid", context).removeAttr("required"); + $("#vcenter_template_ref", context).removeAttr("required"); + $("#vcenter_instance_id", context).removeAttr("required"); + $("#vcenter_ccr_ref", context).removeAttr("required"); } // There is another listener in context.js setup }); @@ -187,15 +191,13 @@ define(function(require) { if(templateJSON["MEMORY_UNIT_COST"] == "GB") templateJSON["MEMORY_COST"] = templateJSON["MEMORY_COST"] * 1024; if (templateJSON["HYPERVISOR"] == 'vcenter') { - templateJSON["VCENTER_PUBLIC_CLOUD"] = { - 'TYPE': 'vcenter', - 'VM_TEMPLATE': WizardFields.retrieveInput($("#vcenter_template_uuid", context)) - }; + templateJSON["VCENTER_TEMPLATE_REF"] = WizardFields.retrieveInput($("#vcenter_template_ref", context)); + templateJSON["VCENTER_CCR_REF"] = WizardFields.retrieveInput($("#vcenter_ccr_ref", context)); + templateJSON["VCENTER_INSTANCE_ID"] = WizardFields.retrieveInput($("#vcenter_instance_id", context)); - if (Config.isFeatureEnabled("vcenter_deploy_folder")) { - templateJSON["DEPLOY_FOLDER"] = WizardFields.retrieveInput($("#vcenter_deploy_folder", context)) + if (Config.isFeatureEnabled("vcenter_vm_folder")) { + templateJSON["VCENTER_VM_FOLDER"] = WizardFields.retrieveInput($("#vcenter_vm_folder", context)) } - templateJSON["KEEP_DISKS_ON_DONE"] = $("#KEEP_DISKS", context).is(':checked')?"YES":"NO" } var sunstone_template = {}; @@ -210,27 +212,6 @@ define(function(require) { var userInputs = {}; - // Retrieve Datastore Attribute - var dsInput = $(".vcenter_datastore_input", context); - if (dsInput.length > 0) { - var dsModify = WizardFields.retrieveInput($('.modify_datastore', dsInput)); - var dsInitial = WizardFields.retrieveInput($('.initial_datastore', dsInput)); - var dsParams = WizardFields.retrieveInput($('.available_datastores', dsInput)); - - if (dsModify === 'fixed' && dsInitial !== '') { - templateJSON['VCENTER_DATASTORE'] = dsInitial; - } else if (dsModify === 'list' && dsParams !== '') { - var dsUserInputsStr = UserInputs.marshall({ - type: 'list', - description: Locale.tr("Which datastore you want this VM to run on?"), - initial: dsInitial, - params: dsParams - }); - - userInputs['VCENTER_DATASTORE'] = dsUserInputsStr; - } - } - // Retrieve Resource Pool Attribute var rpInput = $(".vcenter_rp_input", context); if (rpInput.length > 0) { @@ -239,7 +220,7 @@ define(function(require) { var rpParams = WizardFields.retrieveInput($('.available_rps', rpInput)); if (rpModify === 'fixed' && rpInitial !== '') { - templateJSON['RESOURCE_POOL'] = rpInitial; + templateJSON['VCENTER_RESOURCE_POOL'] = rpInitial; } else if (rpModify === 'list' && rpParams !== '') { var rpUserInputs = UserInputs.marshall({ type: 'list', @@ -248,7 +229,7 @@ define(function(require) { params: WizardFields.retrieveInput($('.available_rps', rpInput)) }); - userInputs['RESOURCE_POOL'] = rpUserInputs; + userInputs['VCENTER_RESOURCE_POOL'] = rpUserInputs; } } @@ -275,24 +256,17 @@ define(function(require) { delete sunstone_template["NETWORK_SELECT"]; } - if (templateJSON["HYPERVISOR"] == 'vcenter' && - templateJSON["KEEP_DISKS_ON_DONE"] && - templateJSON["KEEP_DISKS_ON_DONE"].toLowerCase() == "yes" ) { - $("#KEEP_DISKS", context).attr("checked", "checked"); - } - delete templateJSON["KEEP_DISKS_ON_DONE"]; - - if (Config.isFeatureEnabled("vcenter_deploy_folder")) { + if (Config.isFeatureEnabled("vcenter_vm_folder")) { if (templateJSON["HYPERVISOR"] == 'vcenter' && - templateJSON["DEPLOY_FOLDER"]) { - WizardFields.fillInput($("#vcenter_deploy_folder", context), templateJSON["DEPLOY_FOLDER"]); + templateJSON["VCENTER_VM_FOLDER"]) { + WizardFields.fillInput($("#vcenter_vm_folder", context), templateJSON["VCENTER_VM_FOLDER"]); } } else { - $(".vcenter_deploy_folder_input", context).remove(); + $(".vcenter_vm_folder_input", context).remove(); } - delete templateJSON["DEPLOY_FOLDER"]; + delete templateJSON["VCENTER_VM_FOLDER"]; if (templateJSON["HYPERVISOR"] == 'vcenter') { var publicClouds = templateJSON["PUBLIC_CLOUD"]; @@ -304,7 +278,7 @@ define(function(require) { $.each(publicClouds, function(){ if(this["TYPE"] == "vcenter"){ - WizardFields.fillInput($("#vcenter_template_uuid", context), this["VM_TEMPLATE"]); + WizardFields.fillInput($("#vcenter_template_ref", context), this["VCENTER_TEMPLATE_REF"]); return false; } }); @@ -317,37 +291,38 @@ define(function(require) { } if (templateJSON["USER_INPUTS"]) { - if (templateJSON["USER_INPUTS"]["VCENTER_DATASTORE"]) { - var ds = UserInputs.unmarshall(templateJSON["USER_INPUTS"]["VCENTER_DATASTORE"]); - $('.modify_datastore', context).val('list'); - $('.initial_datastore', context).val(ds.initial); - $('.available_datastores', context).val(ds.params); - delete templateJSON["USER_INPUTS"]["VCENTER_DATASTORE"]; - } - - if (templateJSON["USER_INPUTS"]["RESOURCE_POOL"]) { - var rp = UserInputs.unmarshall(templateJSON["USER_INPUTS"]["RESOURCE_POOL"]); + if (templateJSON["USER_INPUTS"]["VCENTER_RESOURCE_POOL"]) { + var rp = UserInputs.unmarshall(templateJSON["USER_INPUTS"]["VCENTER_RESOURCE_POOL"]); $('.modify_rp', context).val('list'); $('.initial_rp', context).val(rp.initial); $('.available_rps', context).val(rp.params); - delete templateJSON["USER_INPUTS"]["RESOURCE_POOL"]; + delete templateJSON["USER_INPUTS"]["VCENTER_RESOURCE_POOL"]; } } - if (templateJSON["VCENTER_DATASTORE"]) { - $('.modify_datastore', context).val('fixed'); - WizardFields.fillInput($('.initial_datastore', context), templateJSON["VCENTER_DATASTORE"]); - delete templateJSON["VCENTER_DATASTORE"]; + if (templateJSON["VCENTER_RESOURCE_POOL"]) { + $('.modify_rp', context).val('fixed'); + WizardFields.fillInput($('.initial_rp', context), templateJSON["VCENTER_RESOURCE_POOL"]); + + delete templateJSON["VCENTER_RESOURCE_POOL"]; } - if (templateJSON["RESOURCE_POOL"]) { - $('.modify_rp', context).val('fixed'); - WizardFields.fillInput($('.initial_rp', context), templateJSON["RESOURCE_POOL"]); + if(templateJSON["VCENTER_TEMPLATE_REF"]){ + WizardFields.fillInput($("#vcenter_template_ref", context), templateJSON["VCENTER_TEMPLATE_REF"]); + delete templateJSON["VCENTER_TEMPLATE_REF"]; + } - delete templateJSON["RESOURCE_POOL"]; + if(templateJSON["VCENTER_CCR_REF"]){ + WizardFields.fillInput($("#vcenter_ccr_ref", context), templateJSON["VCENTER_CCR_REF"]); + delete templateJSON["VCENTER_CCR_REF"]; + } + + if(templateJSON["VCENTER_INSTANCE_ID"]){ + WizardFields.fillInput($("#vcenter_instance_id", context), templateJSON["VCENTER_INSTANCE_ID"]); + delete templateJSON["VCENTER_INSTANCE_ID"]; } CapacityCreate.fill($("div.capacityCreate", context), templateJSON); diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/html.hbs b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/html.hbs index 02414628ef..1a06c52380 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/html.hbs +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/general/html.hbs @@ -56,77 +56,56 @@ {{tr "vCenter"}} -
-
-
+
{{tr "Override Network Values IPv4"}} diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/html.hbs b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/html.hbs index 479a92e087..8edbec819d 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/html.hbs +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/html.hbs @@ -74,19 +74,25 @@ - +
- +

diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/options.hbs b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/options.hbs index db9f134fee..f4ea7f4fc0 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/options.hbs +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage/disk-tab/options.hbs @@ -1,5 +1,5 @@
-
+
-
+
-
+
@@ -45,6 +45,30 @@
+
+ + +
+
+ + +
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js index 00936d4bff..8001dd35ec 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js @@ -32,7 +32,7 @@ define(function(require) { var DisksResize = require('utils/disks-resize'); var NicsSection = require('utils/nics-section'); var VMGroupSection = require('utils/vmgroup-section'); - var DeployFolder = require('utils/deploy-folder'); + var VcenterVMFolder = require('utils/vcenter-vm-folder'); var CapacityInputs = require('tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs'); var Config = require('sunstone-config'); @@ -214,10 +214,10 @@ define(function(require) { tmp_json.PCI = pcis; } - if (Config.isFeatureEnabled("vcenter_deploy_folder")){ - if(!$.isEmptyObject(original_tmpl.TEMPLATE.PUBLIC_CLOUD.TYPE) && - original_tmpl.TEMPLATE.PUBLIC_CLOUD.TYPE === 'vcenter'){ - $.extend(tmp_json, DeployFolder.retrieveChanges($(".deployFolderContext" + template_id))); + if (Config.isFeatureEnabled("vcenter_vm_folder")){ + if(!$.isEmptyObject(original_tmpl.TEMPLATE.HYPERVISOR) && + original_tmpl.TEMPLATE.HYPERVISOR === 'vcenter'){ + $.extend(tmp_json, VcenterVMFolder.retrieveChanges($(".vcenterVMFolderContext" + template_id))); } } @@ -279,9 +279,9 @@ define(function(require) { VMGroupSection.insert(template_json, $(".vmgroupContext"+ template_json.VMTEMPLATE.ID, context)); - deployFolderContext = $(".deployFolderContext" + template_json.VMTEMPLATE.ID, context); - DeployFolder.setup(deployFolderContext); - DeployFolder.fill(deployFolderContext, template_json.VMTEMPLATE); + vcenterVMFolderContext = $(".vcenterVMFolderContext" + template_json.VMTEMPLATE.ID, context); + VcenterVMFolder.setup(vcenterVMFolderContext); + VcenterVMFolder.fill(vcenterVMFolderContext, template_json.VMTEMPLATE); var inputs_div = $(".template_user_inputs" + template_json.VMTEMPLATE.ID, context); diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate/templateRow.hbs b/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate/templateRow.hbs index cd2aaf2159..4e642263d5 100644 --- a/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate/templateRow.hbs +++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate/templateRow.hbs @@ -68,8 +68,8 @@
-
-
+
+
diff --git a/src/sunstone/public/app/tabs/vms-tab/panels/info.js b/src/sunstone/public/app/tabs/vms-tab/panels/info.js index 2784b5597a..b87f71af57 100644 --- a/src/sunstone/public/app/tabs/vms-tab/panels/info.js +++ b/src/sunstone/public/app/tabs/vms-tab/panels/info.js @@ -91,17 +91,24 @@ define(function(require) { // Get rid of the unwanted (for show) SCHED_* keys var that = this; var strippedTemplate = {}; + var strippedTemplateVcenter = {}; var unshownValues = {}; $.each(that.element.USER_TEMPLATE, function(key, value) { if (key.match(/^SCHED_*/) || key == "USER_INPUTS") { unshownValues[key] = value; - } else { + } + else if (key.match(/^VCENTER_*/)){ + strippedTemplateVcenter[key] = value; + } + else { strippedTemplate[key] = value; } }); - var templateTableHTML = TemplateTable.html(strippedTemplate, RESOURCE, Locale.tr("Attributes")); + var templateTableHTML = TemplateTable.html(strippedTemplate, RESOURCE, Locale.tr("Attributes"), true); + var templateTableVcenterHTML = TemplateTable.html(strippedTemplateVcenter, RESOURCE, Locale.tr("Vcenter information"), false); + var monitoring = $.extend({}, this.element.MONITORING); delete monitoring.CPU; @@ -127,6 +134,7 @@ define(function(require) { 'IP': IP, 'resched': resched, 'permissionsTableHTML': permissionsTableHTML, + 'templateTableVcenterHTML': templateTableVcenterHTML, 'templateTableHTML': templateTableHTML, 'monitoringTableContentHTML': monitoringTableContentHTML, 'vrouterHTML': vrouterHTML @@ -139,14 +147,22 @@ define(function(require) { // Get rid of the unwanted (for show) SCHED_* keys var that = this; var strippedTemplate = {}; + var strippedTemplateVcenter = {}; var unshownValues = {}; - $.each(that.element.USER_TEMPLATE, function(key, value) { - if (!key.match(/^SCHED_*/)) { - strippedTemplate[key] = value; - } else { + $.each(that.element.USER_TEMPLATE, function(key, value) { + if (key.match(/^SCHED_*/) || key == "USER_INPUTS") { unshownValues[key] = value; } - }) + else if (key.match(/^VCENTER_*/)){ + strippedTemplateVcenter[key] = value; + } + else { + strippedTemplate[key] = value; + } + }); + if($.isEmptyObject(strippedTemplateVcenter)){ + $('.vcenter', context).hide(); + } TemplateTable.setup(strippedTemplate, RESOURCE, this.element.ID, context, unshownValues); } diff --git a/src/sunstone/public/app/tabs/vms-tab/panels/info/html.hbs b/src/sunstone/public/app/tabs/vms-tab/panels/info/html.hbs index 05c1921b49..a645619bf4 100644 --- a/src/sunstone/public/app/tabs/vms-tab/panels/info/html.hbs +++ b/src/sunstone/public/app/tabs/vms-tab/panels/info/html.hbs @@ -81,6 +81,9 @@
{{{permissionsTableHTML}}}
+
+
{{{templateTableVcenterHTML}}}
+
{{{templateTableHTML}}}
diff --git a/src/sunstone/public/app/tabs/vms-tab/panels/storage.js b/src/sunstone/public/app/tabs/vms-tab/panels/storage.js index 1eb072c0a9..e7607f0ccd 100644 --- a/src/sunstone/public/app/tabs/vms-tab/panels/storage.js +++ b/src/sunstone/public/app/tabs/vms-tab/panels/storage.js @@ -436,6 +436,10 @@ define(function(require) { context.on('click', '#attach_disk', function() { var dialog = Sunstone.getDialog(ATTACH_DISK_DIALOG_ID); dialog.setElement(that.element); + if(that.element.USER_TEMPLATE.HYPERVISOR && that.element.USER_TEMPLATE.HYPERVISOR == 'vcenter'){ + $('.hypervisor.only_kvm').hide(); + $('.hypervisor.only_vcenter').show(); + } dialog.show(); return false; }); @@ -445,7 +449,6 @@ define(function(require) { context.off('click', '.detachdisk'); context.on('click', '.detachdisk', function() { var disk_id = $(this).parents('tr').attr('disk_id'); - Sunstone.getDialog(CONFIRM_DIALOG_ID).setParams({ //header : headerTabId: TAB_ID, @@ -596,7 +599,7 @@ define(function(require) { return false; }); } - + Tree.setup(context); } diff --git a/src/sunstone/public/app/tabs/vnets-tab/form-panels/create.js b/src/sunstone/public/app/tabs/vnets-tab/form-panels/create.js index 797ea28a27..a97eafdaee 100644 --- a/src/sunstone/public/app/tabs/vnets-tab/form-panels/create.js +++ b/src/sunstone/public/app/tabs/vnets-tab/form-panels/create.js @@ -126,7 +126,8 @@ define(function(require) { $("div.mode_param [wizard_field]", context).prop('wizard_field_disabled', true); $('input#vn_mad', context).removeAttr('required'); - + $('input#vn_mad', context).removeAttr('value'); + $('#vcenter_switch_name', context).removeAttr('required'); switch ($(this).val()) { case "dummy": $("div.mode_param.dummy", context).show(); @@ -164,6 +165,16 @@ define(function(require) { $('input#bridge', context).attr('required', ''); break; + case "vcenter": + $("div.mode_param.vcenter", context).show(); + $("div.mode_param.vcenter [wizard_field]", context).prop('wizard_field_disabled', false); + $('input#bridge', context).attr('value', $('#name', context).val()); + $('#vcenter_switch_name', context).attr('required', ''); + $('input#vn_mad', context).attr('required', ''); + $('input#vn_mad', context).attr('value', 'vcenter'); + + $('#div_vn_mad', context).hide(); + break; case "custom": $("div.mode_param.custom", context).show(); $("div.mode_param.custom [wizard_field]", context).prop('wizard_field_disabled', false); diff --git a/src/sunstone/public/app/tabs/vnets-tab/form-panels/create/wizard.hbs b/src/sunstone/public/app/tabs/vnets-tab/form-panels/create/wizard.hbs index a4a35bcfd8..9cee4289d6 100644 --- a/src/sunstone/public/app/tabs/vnets-tab/form-panels/create/wizard.hbs +++ b/src/sunstone/public/app/tabs/vnets-tab/form-panels/create/wizard.hbs @@ -87,10 +87,11 @@ +
-
+
@@ -115,6 +116,9 @@
{{tr "Open vSwitch, restrict network access with Open vSwitch Virtual Switch. Security Groups are not applied."}}
+
+ {{tr "vSphere standard switches or distributed switches with port groups. Security Groups are not applied."}} +
{{tr "Custom, use a custom virtual network driver."}}
@@ -139,7 +143,7 @@
-
+
-
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ +
+
diff --git a/src/sunstone/public/app/tabs/vnets-tab/panels/info.js b/src/sunstone/public/app/tabs/vnets-tab/panels/info.js index 0774481ef9..8bdca05a30 100644 --- a/src/sunstone/public/app/tabs/vnets-tab/panels/info.js +++ b/src/sunstone/public/app/tabs/vnets-tab/panels/info.js @@ -78,14 +78,22 @@ define(function(require) { "OUTBOUND_PEAK_BW", "OUTBOUND_PEAK_KB" ]; - var strippedTemplate = $.extend({}, this.element.TEMPLATE); - - $.each(hiddenKeys, function(i, key){ - delete strippedTemplate[key]; + var strippedTemplate = {}; + var strippedTemplateVcenter = {}; + $.each(this.element.TEMPLATE, function(key, value) { + if (!$.inArray(key, hiddenKeys) > -1) { + if (key.match(/^VCENTER_*/)){ + strippedTemplateVcenter[key] = value; + } + else { + strippedTemplate[key] = value; + } + } }); - var templateTableHTML = TemplateTable.html(strippedTemplate, RESOURCE, Locale.tr("Attributes")); + var templateTableVcenterHTML = TemplateTable.html(strippedTemplateVcenter, RESOURCE, + Locale.tr("Vcenter information"), false); //==== // TODO: move to util? @@ -114,7 +122,8 @@ define(function(require) { 'renameTrHTML': renameTrHTML, 'reservationTrHTML': reservationTrHTML, 'permissionsTableHTML': permissionsTableHTML, - 'templateTableHTML': templateTableHTML + 'templateTableHTML': templateTableHTML, + 'templateTableVcenterHTML': templateTableVcenterHTML }); } @@ -134,20 +143,25 @@ define(function(require) { "OUTBOUND_PEAK_BW", "OUTBOUND_PEAK_KB" ]; - var strippedTemplate = $.extend({}, this.element.TEMPLATE); - - $.each(hiddenKeys, function(i, key){ - delete strippedTemplate[key]; - }); - var hiddenValues = {}; - - $.each(hiddenKeys, function(i, key){ - if (that.element.TEMPLATE[key] != undefined){ - hiddenValues[key] = that.element.TEMPLATE[key]; + var strippedTemplate = {}; + var strippedTemplateVcenter = {}; + $.each(that.element.TEMPLATE, function(key, value) { + if ($.inArray(key, hiddenKeys) > -1) { + hiddenValues[key] = value; } + if (key.match(/^VCENTER_*/)){ + strippedTemplateVcenter[key] = value; + } + else { + strippedTemplate[key] = value; + } }); + if($.isEmptyObject(strippedTemplateVcenter)){ + $('.vcenter', context).hide(); + } + TemplateTable.setup(strippedTemplate, RESOURCE, this.element.ID, context, hiddenValues); //=== diff --git a/src/sunstone/public/app/tabs/vnets-tab/panels/info/html.hbs b/src/sunstone/public/app/tabs/vnets-tab/panels/info/html.hbs index 837d3d87a0..26a067264e 100644 --- a/src/sunstone/public/app/tabs/vnets-tab/panels/info/html.hbs +++ b/src/sunstone/public/app/tabs/vnets-tab/panels/info/html.hbs @@ -96,6 +96,11 @@
+
+
+ {{{templateTableVcenterHTML}}} +
+
{{{templateTableHTML}}} diff --git a/src/sunstone/public/app/utils/panel/template-table.js b/src/sunstone/public/app/utils/panel/template-table.js index e78f21e69f..116ca1599f 100644 --- a/src/sunstone/public/app/utils/panel/template-table.js +++ b/src/sunstone/public/app/utils/panel/template-table.js @@ -31,7 +31,7 @@ define(function(require) { @param {String} tableName Header of the table (i.e: Locale.tr("Attributes")) @returns {String} HTML table */ - function _html(templateJSON, resourceType, tableName) { + function _html(templateJSON, resourceType, tableName, modify=true) { var str = '\ \ @@ -41,13 +41,15 @@ define(function(require) { '\ \ ' + - fromJSONtoHTMLTable(templateJSON, resourceType) + - '\ + fromJSONtoHTMLTable(templateJSON, resourceType, undefined, undefined,modify); + if (modify) { + str += '\ \ \ \ - \ -
\
' + '; + } + str += '' return str; } @@ -359,7 +361,7 @@ define(function(require) { } // Returns an HTML string with the json keys and values - function fromJSONtoHTMLTable(templateJSON, resourceType, vectorial, ocurrence) { + function fromJSONtoHTMLTable(templateJSON, resourceType, vectorial, ocurrence, modify) { var str = "" if (!templateJSON) { return "Not defined";} var field = null; @@ -370,14 +372,15 @@ define(function(require) { templateJSON[field], resourceType, vectorial, - ocurrence); + ocurrence, + modify); } return str; } // Helper for fromJSONtoHTMLTable function - function fromJSONtoHTMLRow(field, value, resourceType, vectorial_key, ocurrence) { + function fromJSONtoHTMLRow(field, value, resourceType, vectorial_key, ocurrence, modify) { var str = ""; // value can be an array @@ -391,28 +394,32 @@ define(function(require) { if (typeof current_value == 'object') { str += '\ ' + Locale.tr(field) + '\ - \ - \ - \ - \ -  \ - \ - \ - \ - \ - ' + '; + if (modify) { + str += '\ + \ + \ +  \ + \ + \ + \ + '; + } + str += '' str += fromJSONtoHTMLTable(current_value, resourceType, field, - it); + it, + modify); } else { // if it is a single value, create the row for this occurence of the key str += fromJSONtoHTMLRow(field, current_value, resourceType, false, - it); + it, + modify); } } } else // or value can be a string @@ -425,48 +432,55 @@ define(function(require) { if (vectorial_key) { str += '\   ' + Locale.tr(field) + '\ - ' + TemplateUtils.htmlEncode(value) + '\ - \ - \ - \ -  \ - \ - \ - \ - \ - '; + ' + TemplateUtils.htmlEncode(value) + ''; + if (modify) { + str += '\ + \ + \ +  \ + \ + \ + \ + ' + } + str += ''; } else { // If it is not comming from a vectorial daddy key, it can still vectorial itself if (typeof value == 'object') { str += '\ ' + Locale.tr(field) + '\ - \ - \ - \ - \ -  \ - \ - \ - \ - ' + '; + if (modify) { + str += '\ + \ + \ +  \ + \ + \ + \ + ' + } str += fromJSONtoHTMLTable(value, resourceType, field, - ocurrence); + ocurrence, + modify); } else // or, just a single value { str += '\ ' + Locale.tr(field) + '\ - ' + TemplateUtils.htmlEncode(value) + '\ - \ - \ - \ -  \ - \ - \ - \ - \ - '; + ' + TemplateUtils.htmlEncode(value) + ''; + if (modify) { + str += '\ + \ + \ +  \ + \ + \ + \ + '; + } + str += ''; } } diff --git a/src/sunstone/public/app/utils/deploy-folder.js b/src/sunstone/public/app/utils/vcenter-vm-folder.js similarity index 76% rename from src/sunstone/public/app/utils/deploy-folder.js rename to src/sunstone/public/app/utils/vcenter-vm-folder.js index f021fc2d19..317ff21306 100644 --- a/src/sunstone/public/app/utils/deploy-folder.js +++ b/src/sunstone/public/app/utils/vcenter-vm-folder.js @@ -21,7 +21,7 @@ define(function(require){ var OpenNebulaImage = require('opennebula/image'); var UserInputs = require('utils/user-inputs'); var WizardFields = require('utils/wizard-fields'); - var DeployFolderTemplate = require('hbs!./deploy-folder/html'); + var VcenterVMFolderTemplate = require('hbs!./vcenter-vm-folder/html'); return { 'setup': _setup, @@ -30,27 +30,27 @@ define(function(require){ }; function _setup(context) { - if (!Config.isFeatureEnabled("vcenter_deploy_folder")){ + if (!Config.isFeatureEnabled("vcenter_vm_folder")){ $(context).remove(); } } function _fill(context, element) { - if (Config.isFeatureEnabled("vcenter_deploy_folder")){ - var deployFolderContext = context; - var template_public_cloud_type = element.TEMPLATE.PUBLIC_CLOUD.TYPE + if (Config.isFeatureEnabled("vcenter_vm_folder")){ + var vcenterVMFolderContext = context; + var template_public_cloud_type = element.TEMPLATE.HYPERVISOR if ($.isEmptyObject(template_public_cloud_type)) { - deployFolderContext.html(""); + vcenterVMFolderContext.html(""); } else { if (template_public_cloud_type === 'vcenter') { - var deploy_folder = element.TEMPLATE.DEPLOY_FOLDER - deployFolderContext.html(DeployFolderTemplate()); - $("#deploy_folder_input", deployFolderContext).val(deploy_folder); - $("#deploy_folder_input", deployFolderContext).data("original_value",deploy_folder); + var vcenter_vm_folder = element.TEMPLATE.VCENTER_VM_FOLDER + vcenterVMFolderContext.html(VcenterVMFolderTemplate()); + $("#vcenter_vm_folder_input", vcenterVMFolderContext).val(vcenter_vm_folder); + $("#vcenter_vm_folder_input", vcenterVMFolderContext).data("original_value",vcenter_vm_folder); } else { - deployFolderContext.html(""); + vcenterVMFolderContext.html(""); } } } diff --git a/src/sunstone/public/app/utils/deploy-folder/html.hbs b/src/sunstone/public/app/utils/vcenter-vm-folder/html.hbs similarity index 85% rename from src/sunstone/public/app/utils/deploy-folder/html.hbs rename to src/sunstone/public/app/utils/vcenter-vm-folder/html.hbs index 9bb686bb7e..834488b52f 100644 --- a/src/sunstone/public/app/utils/deploy-folder/html.hbs +++ b/src/sunstone/public/app/utils/vcenter-vm-folder/html.hbs @@ -19,11 +19,11 @@ {{tr "vCenter Deployment"}}
-
diff --git a/src/sunstone/public/app/utils/vcenter/clusters.js b/src/sunstone/public/app/utils/vcenter/clusters.js index 5d36ba4580..fd90b34404 100644 --- a/src/sunstone/public/app/utils/vcenter/clusters.js +++ b/src/sunstone/public/app/utils/vcenter/clusters.js @@ -100,11 +100,19 @@ define(function(require) { var newdiv = $(content).appendTo($(".vcenter_datacenter_list", context)); var tbody = $('#' + tableId + ' tbody', context); - $.each(elements, function(id, cluster_name) { + $.each(elements, function(id, cluster) { + var cluster_name = cluster.cluster_name; + var rp_list = ''; var opts = { name: cluster_name }; var trow = $(RowTemplate(opts)).appendTo(tbody); - $(".check_item", trow).data("cluster_name", cluster_name); + $(".check_item", trow).data("cluster", cluster); }); var elementsTable = new DomDataTable( @@ -165,7 +173,7 @@ define(function(require) { var host_json = { "host": { - "name": $(this).data("cluster_name"), + "name": $(this).data("cluster").cluster_name, "vm_mad": "vcenter", "vnm_mad": "dummy", "im_mad": "vcenter", @@ -173,6 +181,10 @@ define(function(require) { } }; + var cluster_ref = $(this).data("cluster").cluster_ref; + var vcenter_uuid = $(this).data("cluster").vcenter_uuid; + var vcenter_version = $(this).data("cluster").vcenter_version; + OpenNebulaHost.create({ timeout: true, data: host_json, @@ -183,9 +195,12 @@ define(function(require) { }); var template_raw = - "VCENTER_USER=\"" + that.opts.vcenter_user + "\"\n" + - "VCENTER_PASSWORD=\"" + that.opts.vcenter_password + "\"\n" + - "VCENTER_HOST=\"" + that.opts.vcenter_host + "\"\n"; + "VCENTER_USER=\"" + that.opts.vcenter_user + "\"\n" + + "VCENTER_PASSWORD=\"" + that.opts.vcenter_password + "\"\n" + + "VCENTER_HOST=\"" + that.opts.vcenter_host + "\"\n" + + "VCENTER_INSTANCE_ID=\"" + vcenter_uuid + "\"\n" + + "VCENTER_CCR_REF=\"" + cluster_ref + "\"\n" + + "VCENTER_VERSION=\"" + vcenter_version + "\"\n"; Sunstone.runAction("Host.update_template", response.HOST.ID, template_raw); }, diff --git a/src/sunstone/public/app/utils/vcenter/datastores.js b/src/sunstone/public/app/utils/vcenter/datastores.js index e2e801010f..3b5494abeb 100644 --- a/src/sunstone/public/app/utils/vcenter/datastores.js +++ b/src/sunstone/public/app/utils/vcenter/datastores.js @@ -94,7 +94,7 @@ define(function(require) { columns : [ '', Locale.tr("Name"), - Locale.tr("Datacenter"), + Locale.tr("Cluster"), "" ] }); @@ -106,7 +106,7 @@ define(function(require) { var opts = { name: element.name, cluster: element.cluster }; var trow = $(RowTemplate(opts)).appendTo(tbody); - $(".check_item", trow).data("one_template", element.one) + $(".check_item", trow).data("one_template", element.ds) }); var elementsTable = new DomDataTable( @@ -159,29 +159,30 @@ define(function(require) { var row_context = $(this).closest("tr"); VCenterCommon.importLoading({context : row_context}); - - var datastore_json = { - "datastore": { - "datastore_raw": $(this).data("one_template") - }, - "cluster_id" : -1 - }; - - OpenNebulaDatastore.create({ - timeout: true, - data: datastore_json, - success: function(request, response) { - VCenterCommon.importSuccess({ - context : row_context, - message : Locale.tr("Datastore created successfully. ID: %1$s", response.DATASTORE.ID) - }); - }, - error: function (request, error_json) { - VCenterCommon.importFailure({ - context : row_context, - message : (error_json.error.message || Locale.tr("Cannot contact server: is it running and reachable?")) - }); - } + var one_template = $(this).data("one_template"); + $.each(one_template, function(id, element){ + var datastore_json = { + "datastore": { + "datastore_raw": this.one + }, + "cluster_id" : -1 + }; + OpenNebulaDatastore.create({ + timeout: true, + data: datastore_json, + success: function(request, response) { + VCenterCommon.importSuccess({ + context : row_context, + message : Locale.tr("Datastore created successfully. ID: %1$s", response.DATASTORE.ID) + }); + }, + error: function (request, error_json) { + VCenterCommon.importFailure({ + context : row_context, + message : (error_json.error.message || Locale.tr("Cannot contact server: is it running and reachable?")) + }); + } + }); }); }); }); diff --git a/src/sunstone/public/app/utils/vcenter/networks.js b/src/sunstone/public/app/utils/vcenter/networks.js index 41b47ebdf6..b4fcbed187 100644 --- a/src/sunstone/public/app/utils/vcenter/networks.js +++ b/src/sunstone/public/app/utils/vcenter/networks.js @@ -186,6 +186,23 @@ define(function(require) { '' + '
'; break; + case 'IP6_STATIC': + net_form_str = + '
' + + '' + + '
'+'
' + + '' + + '
'+ + '
' + + '' + + '
'; + break; } $('.net_options', row_context).html(net_form_str); @@ -251,6 +268,21 @@ define(function(require) { ar_array.push("ULA_PREFIX=" + ula); } + break; + case 'IP6_STATIC': + var mac = $('.six_mac_net', row_context).val(); + var ip6_static = $('.six_static_net', row_context).val(); + var prefix = $('.six_prefix_net', row_context).val(); + + if (mac) { + ar_array.push("MAC=" + mac); + } + if (ip6_static) { + ar_array.push("IP6=" + ip6_static); + } + if (prefix) { + ar_array.push("PREFIX_LENGTH=" + prefix); + } break; } diff --git a/src/sunstone/public/app/utils/vcenter/networks/row.hbs b/src/sunstone/public/app/utils/vcenter/networks/row.hbs index eae5fae067..974b32bbe7 100644 --- a/src/sunstone/public/app/utils/vcenter/networks/row.hbs +++ b/src/sunstone/public/app/utils/vcenter/networks/row.hbs @@ -45,6 +45,7 @@ +
diff --git a/src/sunstone/public/app/utils/vcenter/templates.js b/src/sunstone/public/app/utils/vcenter/templates.js index 77e1cfbbbf..20b02d567e 100644 --- a/src/sunstone/public/app/utils/vcenter/templates.js +++ b/src/sunstone/public/app/utils/vcenter/templates.js @@ -45,7 +45,6 @@ define(function(require) { /* Retrieve the list of templates from vCenter and fill the container with them - opts = { datacenter: "Datacenter Name", cluster: "Cluster Name", @@ -56,6 +55,7 @@ define(function(require) { } */ function _fillVCenterTemplates(opts) { + this.opts = opts; var path = '/vcenter/templates'; var context = $(".vcenter_import", opts.container); @@ -102,18 +102,25 @@ define(function(require) { $.each(elements, function(id, element) { var opts = {}; - if (element.ds && element.ds !== '') { - opts.datastore = UserInputs.unmarshall(element.ds); - } if (element.rp && element.rp !== '') { opts.resourcePool = UserInputs.unmarshall(element.rp); } opts.data = element; + opts.resourcePool.params = opts.resourcePool.params.split(","); + opts.id = UniqueId.id(); var trow = $(RowTemplate(opts)).appendTo(tbody); - + + $.each(opts.resourcePool.params, function(){ + $("#available_rps_" + opts.id + " [value ='" + this + "']").mousedown(function(e) { + e.preventDefault(); + $(this).prop('selected', !$(this).prop('selected')); + return false; + }); + }); + $('.check_item', trow).data("import_data", element); }); @@ -160,6 +167,7 @@ define(function(require) { } function _import(context) { + that = this; $.each($(".vcenter_import_table", context), function() { $.each($(this).DataTable().$(".check_item:checked"), function() { var row_context = $(this).closest("tr"); @@ -169,45 +177,28 @@ define(function(require) { var attrs = []; var userInputs = []; - // Retrieve Datastore Attribute - var dsInput = $(".vcenter_datastore_input", row_context); - if (dsInput.length > 0) { - var dsModify = $('.modify_datastore', dsInput).val(); - var dsInitial = $('.initial_datastore', dsInput).val(); - var dsParams = $('.available_datastores', dsInput).val(); - - if (dsModify === 'fixed' && dsInitial !== '') { - attrs.push('VCENTER_DATASTORE="' + dsInitial + '"') - } else if (dsModify === 'list' && dsParams !== '') { - var dsUserInputsStr = UserInputs.marshall({ - type: 'list', - description: Locale.tr("Which datastore you want this VM to run on?"), - initial: dsInitial, - params: dsParams - }); - - userInputs.push('VCENTER_DATASTORE="' + dsUserInputsStr + '"'); - } - } - // Retrieve Resource Pool Attribute var rpInput = $(".vcenter_rp_input", row_context); if (rpInput.length > 0) { var rpModify = $('.modify_rp', rpInput).val(); var rpInitial = $('.initial_rp', rpInput).val(); - var rpParams = $('.available_rps', rpInput).val(); + var rpParams = ""; + $.each($('.available_rps option:selected', rpInput), function(){ + rpParams += $(this).val() + ","; + }); + var rpParams = rpParams.slice(0,-1); if (rpModify === 'fixed' && rpInitial !== '') { - attrs.push('RESOURCE_POOL="' + rpInitial + '"'); + attrs.push('VCENTER_RESOURCE_POOL="' + rpInitial + '"'); } else if (rpModify === 'list' && rpParams !== '') { var rpUserInputs = UserInputs.marshall({ type: 'list', description: Locale.tr("Which resource pool you want this VM to run in?"), initial: rpInitial, - params: $('.available_rps', rpInput).val() + params: rpParams }); - userInputs.push('RESOURCE_POOL="' + rpUserInputs + '"'); + userInputs.push('VCENTER_RESOURCE_POOL="' + rpUserInputs + '"'); } } @@ -222,29 +213,80 @@ define(function(require) { template += "\nUSER_INPUTS=[\n" + userInputs.join(",\n") + "]"; } - var template_json = { - "vmtemplate": { - "template_raw": template - } - }; + if($(this).data("import_data").import_disks_and_nics){ + VCenterCommon.importLoading({ + context : row_context, + message : Locale.tr("Importing images and vnets associated to template disks and nics...") + }); + var path = '/vcenter/template/' + $(this).data("import_data").vcenter_ref; + $.ajax({ + url: path, + type: "GET", + data: {timeout: false}, + headers: { + "X-VCENTER-USER": that.opts.vcenter_user, + "X-VCENTER-PASSWORD": that.opts.vcenter_password, + "X-VCENTER-HOST": that.opts.vcenter_host + }, + dataType: "json", + success: function(response){ + template += "\n" + response.one; + var template_json = { + "vmtemplate": { + "template_raw": template + } + }; + OpenNebulaTemplate.create({ + timeout: true, + data: template_json, + success: function(request, response) { + VCenterCommon.importSuccess({ + context : row_context, + message : Locale.tr("Template created successfully. ID: %1$s", response.VMTEMPLATE.ID) + }); + }, + error: function (request, error_json) { + VCenterCommon.importFailure({ + context : row_context, + message : (error_json.error.message || Locale.tr("Cannot contact server: is it running and reachable?")) + }); + } + }); + }, + error: function(response){ + VCenterCommon.importFailure({ + context : row_context, + message : OpenNebulaError(response).error.message + }); + Notifier.onError({}, OpenNebulaError(response)); + } + }); + } + else { + var template_json = { + "vmtemplate": { + "template_raw": template + } + }; - OpenNebulaTemplate.create({ - timeout: true, - data: template_json, - success: function(request, response) { - VCenterCommon.importSuccess({ - context : row_context, - message : Locale.tr("Template created successfully. ID: %1$s", response.VMTEMPLATE.ID) - }); - }, - error: function (request, error_json) { - VCenterCommon.importFailure({ - context : row_context, - message : (error_json.error.message || Locale.tr("Cannot contact server: is it running and reachable?")) - }); - } - }); + OpenNebulaTemplate.create({ + timeout: true, + data: template_json, + success: function(request, response) { + VCenterCommon.importSuccess({ + context : row_context, + message : Locale.tr("Template created successfully. ID: %1$s", response.VMTEMPLATE.ID) + }); + }, + error: function (request, error_json) { + VCenterCommon.importFailure({ + context : row_context, + message : (error_json.error.message || Locale.tr("Cannot contact server: is it running and reachable?")) + }); + } + }); + } }); }); } -}); +}); \ No newline at end of file diff --git a/src/sunstone/public/app/utils/vcenter/templates/row.hbs b/src/sunstone/public/app/utils/vcenter/templates/row.hbs index 27c320d46f..95521054ff 100644 --- a/src/sunstone/public/app/utils/vcenter/templates/row.hbs +++ b/src/sunstone/public/app/utils/vcenter/templates/row.hbs @@ -15,15 +15,15 @@ {{! -------------------------------------------------------------------------- }} - - + +
@@ -31,34 +31,9 @@
-