diff --git a/src/onedb/vcenter_one54_pre.rb b/src/onedb/vcenter_one54_pre.rb index 3af62719a3..533bc1d46b 100644 --- a/src/onedb/vcenter_one54_pre.rb +++ b/src/onedb/vcenter_one54_pre.rb @@ -32,13 +32,16 @@ $: << RUBY_LIB_LOCATION $: << RUBY_LIB_LOCATION+"/cli" $: << REMOTES_LOCATION+"vmm/vcenter/" +require 'fileutils' + require 'command_parser' require 'one_helper/onehost_helper' require 'one_helper/onecluster_helper' require 'vcenter_driver' require 'opennebula' -TEMP_DIR="/tmp" +TEMP_DIR="/var/tmp/vcenter_one54" +FileUtils.mkdir_p TEMP_DIR def banner(msg, header=false, extended=nil) STDOUT.puts @@ -65,9 +68,6 @@ def logo_banner(msg, header=false) STDOUT.puts "="*80 end - - - ################################################################################ # Monkey patch XMLElement with retrieve_xmlelements ################################################################################ @@ -89,8 +89,8 @@ class OpenNebula::XMLElement end def get_image_size(ds, img_str) - ds_name = ds.name + img_path = File.dirname img_str img_name = File.basename img_str @@ -109,7 +109,6 @@ def get_image_size(ds, img_str) :fileType => true, :modification => true) - spec.matchPattern = img_name.nil? ? [] : [img_name] datastore_path = "[#{ds_name}]" @@ -483,11 +482,22 @@ def vm_unmanaged_discover(devices, xml_doc, template_xml, else template_disk = template_xml.xpath("VMTEMPLATE/TEMPLATE/DISK")[unmanaged_disk_index] rescue nil raise "Cannot find unmanaged disk inside template" if !template_disk + image_id = template_disk.xpath("IMAGE_ID").text raise "Cannot find image id for unmanaged disk" if image_id.empty? + one_image = OpenNebula::Image.new_with_id(image_id, one_client) - rc = one_image.info - raise "\n ERROR! Could not get image info for unmanged disk. Reason #{rc.message}" if OpenNebula.is_error?(rc) + rc = one_image.info + raise "\n ERROR! Could not get image info for unmanaged disk. image_id '#{image_id}'. Reason #{rc.message}" if OpenNebula.is_error?(rc) + + ds_id = one_image['DATASTORE_ID'] + ds = OpenNebula::Datastore.new_with_id(ds_id, one_client) + rc = ds.info + raise "\n ERROR! Could not get ds info. Reason #{rc.message}" if OpenNebula.is_error?(rc) + + ds_ref = ds["TEMPLATE/VCENTER_DS_REF"] + ds_name = ds["NAME"] + STDOUT.puts "--- Image #{one_image["NAME"]} with ID #{one_image["ID"]} already exists" end @@ -1198,7 +1208,7 @@ def select_cluster(vc_clusters, ccr_name, vi_client) end loop do - STDOUT.print("\nFrom the list above, please \e[95mpick up one number\e[39m in order to specify the cluster: ") + STDOUT.print("\nFrom the list above, please \e[95mpick a number\e[39m in order to specify the cluster: ") cluster_index = STDIN.gets.strip.to_i next if cluster_index == 0 || cluster_index - 1 < 0 || cluster_index - 1 > ccr_refs.size ccr_ref = ccr_refs[cluster_index-1] rescue nil @@ -1286,7 +1296,6 @@ def create_new_clusters(vc_clusters, hpool, cpool, one_client) # Get all hosts from pool with VN_MAD="vcenter" hosts = hpool.retrieve_xmlelements("HOST[VM_MAD=\"vcenter\"]") - hosts.each do |host| begin @@ -1322,6 +1331,13 @@ def create_new_clusters(vc_clusters, hpool, cpool, one_client) # We inform that the Cluster has been created STDOUT.puts "OpenNebula Cluster named #{ccr_name} \e[92mhas been created.\e[39m" STDOUT.puts + + # Fetch the cluster info + rc = one_cluster.info + if OpenNebula.is_error?(rc) + STDOUT.puts " Error Getting information from cluster '#{ccr_name}'. Reason: #{rc.message}\n" + next + end else STDOUT.puts "OpenNebula Cluster #{ccr_name} \e[92malready exists.\e[39m" STDOUT.puts @@ -1403,6 +1419,7 @@ def inspect_datastores(vc_datastores, vc_clusters, one_clusters, dspool, hpool, one_ds.delete end end + STDOUT.puts # Refresh dspool and retrieve datastores again @@ -1420,7 +1437,7 @@ def inspect_datastores(vc_datastores, vc_clusters, one_clusters, dspool, hpool, raise rc.message if OpenNebula.is_error?(rc) ds_name = one_ds["NAME"] ccr_name = one_ds["TEMPLATE/VCENTER_CLUSTER"] - next if !ccr_name #If VCENTER_CLUSTER doesn't exist it's not usable + next if !ccr_name # If VCENTER_CLUSTER doesn't exist it's not usable # Get cluster's host from its name stored in VCENTER_CLUSTER hosts = hpool.retrieve_xmlelements("HOST[NAME=\"#{ccr_name}\"]") @@ -1460,7 +1477,6 @@ def inspect_datastores(vc_datastores, vc_clusters, one_clusters, dspool, hpool, # otherwise the administrator should select one from the list # We need to extract the datacenter ref and name as they are now # required attributes. - if datastores_with_name.size == 1 vc_datastores[vcenter_uuid].each do |ref, ds| if ds["name"] == ds_name @@ -1525,7 +1541,7 @@ def inspect_datastores(vc_datastores, vc_clusters, one_clusters, dspool, hpool, # Loop until the admin user chooses the right datastore loop do - STDOUT.print("\nFrom the list above, please \e[95mpick up one number\e[39m in order to specify the datastore: ") + STDOUT.print("\nFrom the list above, please \e[95mpick one number\e[39m in order to specify the datastore: ") ds_index = STDIN.gets.strip.to_i next if ds_index == 0 || ds_index - 1 < 0 || ds_index - 1 > ds_info.size ds_ref = ds_info[ds_index-1][:ref] rescue nil @@ -1563,14 +1579,14 @@ def inspect_datastores(vc_datastores, vc_clusters, one_clusters, dspool, hpool, # Inform what attributes have been added STDOUT.puts "Datastore \e[96m#{ds_name}\e[39m got new attributes:\n" STDOUT.puts - STDOUT.puts "--- VCENTER_DS_REF=#{ds_ref}\n" - STDOUT.puts "--- VCENTER_DS_NAME=#{ds_name}\n" - STDOUT.puts "--- VCENTER_DC_REF=#{dc_ref}\n" - STDOUT.puts "--- VCENTER_DC_NAME=#{dc_name}\n" - STDOUT.puts "--- VCENTER_HOST=#{vcenter_host}\"\n" - STDOUT.puts "--- VCENTER_USER=#{vcenter_user}\"\n" - STDOUT.puts "--- VCENTER_PASSWORD=#{vcenter_pass}\"\n" - STDOUT.puts "--- VCENTER_INSTANCE_ID=#{vcenter_uuid}\n" + STDOUT.puts "--- VCENTER_DS_REF=\"#{ds_ref}\"\n" + STDOUT.puts "--- VCENTER_DS_NAME=\"#{ds_name}\"\n" + STDOUT.puts "--- VCENTER_DC_REF=\"#{dc_ref}\"\n" + STDOUT.puts "--- VCENTER_DC_NAME=\"#{dc_name}\"\n" + STDOUT.puts "--- VCENTER_HOST=\"#{vcenter_host}\"\n" + STDOUT.puts "--- VCENTER_USER=\"#{vcenter_user}\"\n" + STDOUT.puts "--- VCENTER_PASSWORD=\"#{vcenter_pass}\"\n" + STDOUT.puts "--- VCENTER_INSTANCE_ID=\"#{vcenter_uuid}\"\n" STDOUT.puts @@ -1690,7 +1706,7 @@ def inspect_networks(vc_networks, vc_clusters, one_clusters, vnpool, hpool, one_ STDOUT.puts("#{ccr_names.size+1}: None of the above.") loop do - STDOUT.print("\nFrom the list above, please pick up one number in order to specify the cluster: ") + STDOUT.print("\nFrom the list above, please pick one number in order to specify the cluster: ") cluster_index = STDIN.gets.strip.to_i next if cluster_index == 0 || cluster_index - 1 < 0 || cluster_index - 1 > ccr_names.size+1 ccr_name = ccr_names[cluster_index-1] rescue nil @@ -1758,7 +1774,7 @@ def inspect_networks(vc_networks, vc_clusters, one_clusters, vnpool, hpool, one_ # Loop until the administrator selects a vnet loop do - STDOUT.print("\nFrom the list above, please \e[95mpick up one number\e[39m in order to specify the vnet: ") + STDOUT.print("\nFrom the list above, please \e[95mpick one number\e[39m in order to specify the vnet: ") vnet_index = STDIN.gets.strip.to_i next if vnet_index == 0 || vnet_index - 1 < 0 || vnet_index - 1 > vnet_refs.size vnet_ref = vnet_refs[vnet_index-1] rescue nil @@ -1854,7 +1870,13 @@ def add_new_image_attrs(ipool, one_client, vcenter_ids) imported_images.each do |image| one_image = OpenNebula::Image.new_with_id(image["ID"], one_client) one_image.delete + + loop do + rc = one_image.info + break if OpenNebula.is_error?(rc) + end end + STDOUT.puts # Refresh pool @@ -1962,13 +1984,10 @@ end ################################################################################ def inspect_templates(vc_templates, vc_clusters, one_clusters, tpool, ipool, vnpool, dspool, hpool, one_client, vcenter_ids) - - # Retrieve all OpenNebula templates associated with PUBLIC_CLOUD=vcenter templates = tpool.retrieve_xmlelements("VMTEMPLATE[TEMPLATE/PUBLIC_CLOUD/TYPE=\"vcenter\"]") templates.each do |template| - begin # Refresh pools rc = vnpool.info_all @@ -1979,9 +1998,10 @@ def inspect_templates(vc_templates, vc_clusters, one_clusters, tpool, ipool, vnp raise "\n ERROR! Could not update dspool. Reason #{rc.message}" if OpenNebula.is_error?(rc) # Get some variables - ccr_ref = nil + ccr_ref = nil vcenter_uuid = nil - host_id = nil + host_id = nil + template_name = template["NAME"] template_uuid = template["TEMPLATE/PUBLIC_CLOUD/VM_TEMPLATE"] template_ref = template["TEMPLATE/PUBLIC_CLOUD/VCENTER_REF"] @@ -2001,6 +2021,10 @@ def inspect_templates(vc_templates, vc_clusters, one_clusters, tpool, ipool, vnp ccr_ref = hosts.first["TEMPLATE/VCENTER_CCR_REF"] vcenter_uuid = hosts.first["TEMPLATE/VCENTER_INSTANCE_ID"] host_id = hosts.first["ID"] + vcenter_user = hosts.first["TEMPLATE/VCENTER_USER"] + vcenter_pass = hosts.first["TEMPLATE/VCENTER_PASSWORD"] + vcenter_host = hosts.first["TEMPLATE/VCENTER_HOST"] + template_cluster = nil if !ccr_ref || !vcenter_uuid end end @@ -2008,30 +2032,36 @@ def inspect_templates(vc_templates, vc_clusters, one_clusters, tpool, ipool, vnp # As we don't know which vCenter cluster is associated with the template # The administrator must select one from a list if !template_cluster - STDOUT.puts("\n\e[93mWARNING: Manual intervention required!\e[39m") - STDOUT.puts("\nWhich vCenter cluster is associated with OpenNebula \e[96mtemplate #{template_name}?\n\e[39m") - STDOUT.puts + hpool_vcenter = hpool.select{|h| h["VM_MAD"] == "vcenter"} - ccr_names = [] - hpool.each_with_index do |host, index| - STDOUT.puts("#{index+1}: #{host["NAME"]} in #{host["TEMPLATE/VCENTER_HOST"]}") - ccr_names << host["NAME"] + if hpool_vcenter.count == 1 + template_cluster = hpool_vcenter.first["NAME"] + else + STDOUT.puts("\n\e[93mWARNING: Manual intervention required!\e[39m") + STDOUT.puts("\nWhich vCenter cluster is associated with OpenNebula \e[96mtemplate #{template_name}?\n\e[39m") + STDOUT.puts + + ccr_names = [] + hpool_vcenter.each_with_index do |host, index| + STDOUT.puts("#{index+1}: #{host["NAME"]} in #{host["TEMPLATE/VCENTER_HOST"]}") + ccr_names << host["NAME"] + end + + STDOUT.puts("#{ccr_names.size+1}: None of the above.") + + loop do + STDOUT.print("\nFrom the list above, please \e[95mpick one number\e[39m in order to specify the cluster: ") + cluster_index = STDIN.gets.strip.to_i + next if cluster_index == 0 || cluster_index - 1 < 0 || cluster_index > ccr_names.size+1 + template_cluster = ccr_names[cluster_index-1] rescue nil + break + end + + STDOUT.puts + STDOUT.puts "-" * 80 + STDOUT.puts end - STDOUT.puts("#{ccr_names.size+1}: None of the above.") - - loop do - STDOUT.print("\nFrom the list above, please \e[95mpick up one number\e[39m in order to specify the cluster: ") - cluster_index = STDIN.gets.strip.to_i - next if cluster_index == 0 || cluster_index - 1 < 0 || cluster_index > ccr_names.size+1 - template_cluster = ccr_names[cluster_index-1] rescue nil - break - end - - STDOUT.puts - STDOUT.puts "-" * 80 - STDOUT.puts - if !template_cluster raise "We could not find the host name associated to template #{template_name}\n"\ "You may have to import the OpenNebula host first using onevcenter tool." @@ -2040,20 +2070,18 @@ def inspect_templates(vc_templates, vc_clusters, one_clusters, tpool, ipool, vnp # Get host attributes from the name of the cluster associated # to the template hosts = hpool.retrieve_xmlelements("HOST[NAME=\"#{template_cluster}\"]") + ccr_ref = hosts.first["TEMPLATE/VCENTER_CCR_REF"] vcenter_uuid = hosts.first["TEMPLATE/VCENTER_INSTANCE_ID"] host_id = hosts.first["ID"] vcenter_user = hosts.first["TEMPLATE/VCENTER_USER"] vcenter_pass = hosts.first["TEMPLATE/VCENTER_PASSWORD"] vcenter_host = hosts.first["TEMPLATE/VCENTER_HOST"] - - if ccr_ref.nil? || vcenter_uuid.nil? - raise "Template #{template_name} could not be updated, cannot find cluster's MOREF or vcenter uuid" - end end - if !ccr_ref - raise "Template #{template_name} could not be updated, cannot find cluster's MOREF" + if ccr_ref.nil? || vcenter_uuid.nil? + raise "Template #{template_name} could not be updated, cannot find cluster's MOREF: '#{ccr_ref}'" \ + ", or vcenter uuid: '#{vcenter_uuid}'. " end # Create Rbvmomi connection @@ -2126,7 +2154,7 @@ def inspect_templates(vc_templates, vc_clusters, one_clusters, tpool, ipool, vnp STDOUT.puts("#{template_refs.size+1}: None of the above.") loop do - STDOUT.print("\nFrom the list above, please \e[95mpick up one number\e[39m in order to specify the template: ") + STDOUT.print("\nFrom the list above, please \e[95mpick a number\e[39m in order to specify the template: ") template_index = STDIN.gets.strip.to_i next if template_index == 0 || template_index - 1 < 0 || template_index > template_refs.size + 1 template_ref = template_refs[template_index-1] rescue nil @@ -2341,7 +2369,6 @@ def inspect_vms(vc_vmachines, vc_templates, vc_clusters, one_clusters, vmpool, i next if !vm["DEPLOY_ID"] # Ignore undeployed vms begin - # Refresh pools rc = vnpool.info_all raise "\n ERROR! Could not update vnpool. Reason #{rc.message}" if OpenNebula.is_error?(rc) @@ -2542,8 +2569,9 @@ def inspect_vms(vc_vmachines, vc_templates, vc_clusters, one_clusters, vmpool, i dc_ref = dc._ref # Get xml template from tmp with unmanaged disks and nics and new attributes - template_id = vm["TEMPLATE/TEMPLATE_ID"] - template_xml = nil + template_id = vm["TEMPLATE/TEMPLATE_ID"] + template_xml = nil + if !vm_wild template_filename = "#{TEMP_DIR}/one_migrate_template_#{template_id}" if File.exist?("#{template_filename}") @@ -2665,17 +2693,18 @@ CommandParser::CmdParser.new(ARGV) do hpool = OpenNebula::HostPool.new(one_client) rc = hpool.info + raise "Error contacting OpenNebula #{rc.message}" if OpenNebula.is_error?(rc) cpool = OpenNebula::ClusterPool.new(one_client) rc = cpool.info raise "Error contacting OpenNebula #{rc.message}" if OpenNebula.is_error?(rc) - vc_clusters = {} + vc_clusters = {} vc_datastores = {} - vc_networks = {} - vc_vmachines = {} - vc_templates = {} + vc_networks = {} + vc_vmachines = {} + vc_templates = {} banner " PHASE 0 - Before running the script please read the following notes", true @@ -2685,9 +2714,10 @@ CommandParser::CmdParser.new(ARGV) do " restarted your OpenNebula services to apply the new configuration before\n"\ " launching the script.") STDOUT.puts - STDOUT.puts("- Don't forget to edit the file \e[92m/var/lib/one/remotes/datastore/vcenter/rm\e[39m\n"\ - " and replace the following line:\n\n"\ - " \e[96mvi_client.delete_virtual_disk(img_src,ds_name)\e[39m \n\n"\ + STDOUT.puts("- Edit the file \e[92m/var/lib/one/remotes/datastore/vcenter/rm\e[39m and replace the\n"\ + " following lines:\n\n"\ + " \e[96mvi_client.delete_virtual_disk(img_src,\n"\ + " ds_name)\e[39m \n\n"\ " with the following lines:\n\n"\ " \e[96mif drv_action[\"/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/VCENTER_IMPORTED\"] != \"YES\"\n"\ " vi_client.delete_virtual_disk(img_src,ds_name) \n"\ @@ -2711,9 +2741,10 @@ CommandParser::CmdParser.new(ARGV) do STDOUT.puts("- This script can be executed as many times as you wish. It will update previous\n"\ " results and XML template will be always overwritten.") STDOUT.puts - + STDOUT.puts("\e[93mDon't forget to restart OpenNebula if you have made changes!\e[39m") STDOUT.print("\nDo you want to continue? ([y]/n): ") + exit! if STDIN.gets.strip.downcase == 'n' banner " PHASE 1 - Retrieve objects from vCenter instances", true @@ -2736,11 +2767,13 @@ CommandParser::CmdParser.new(ARGV) do next end vcenter_instances << vcenter_uuid + # Retrieve vCenter Managed Objects vc_clusters[vcenter_uuid] = retrieve_vcenter_clusters(vi_client) vc_datastores[vcenter_uuid] = retrieve_vcenter_datastores(vi_client) vc_networks[vcenter_uuid] = retrieve_vcenter_networks(vi_client) - vc_vmachines[vcenter_uuid], vc_templates[vcenter_uuid] = retrieve_vcenter_vms(vi_client) + vc_vmachines[vcenter_uuid], vc_templates[vcenter_uuid] = retrieve_vcenter_vms(vi_client) + STDOUT.puts "--- #{host["TEMPLATE/VCENTER_HOST"]} \e[92mobjects have been retrieved\e[39m" end @@ -2759,25 +2792,28 @@ CommandParser::CmdParser.new(ARGV) do banner " PHASE 3 - Create OpenNebula clusters if needed", true STDOUT.puts + one_clusters = create_new_clusters(vc_clusters, hpool, cpool, one_client) dspool = OpenNebula::DatastorePool.new(one_client) rc = dspool.info raise "Error contacting OpenNebula #{rc.message}" if OpenNebula.is_error?(rc) - rc = hpool.info #Update host pool to get new attributes + rc = hpool.info # Update host pool to get new attributes raise "Error contacting OpenNebula #{rc.message}" if OpenNebula.is_error?(rc) - rc = cpool.info #Update cluster pool to get new clusters + rc = cpool.info # Update cluster pool to get new clusters raise "Error contacting OpenNebula #{rc.message}" if OpenNebula.is_error?(rc) extended_message = " - Add new attributes to datastores\n"\ " - Create SYSTEM datastores if needed\n"\ " - Assign datastores to OpenNebula Clusters" + banner " PHASE 4 - Inspect existing datatores ", true, extended_message + inspect_datastores(vc_datastores, vc_clusters, one_clusters, dspool, hpool, one_client, vcenter_ids) - rc = dspool.info #Refresh datastore pool + rc = dspool.info # Refresh datastore pool raise "Error contacting OpenNebula #{rc.message}" if OpenNebula.is_error?(rc) vnpool = OpenNebula::VirtualNetworkPool.new(one_client)