diff --git a/lib/ruby_vcloud_sdk/catalog.rb b/lib/ruby_vcloud_sdk/catalog.rb index 5ec0e24..06b9753 100644 --- a/lib/ruby_vcloud_sdk/catalog.rb +++ b/lib/ruby_vcloud_sdk/catalog.rb @@ -230,7 +230,7 @@ def ovf_directory(directory) end def admin_xml - admin_catalog_link = "/api/admin/catalog/#{id}" + admin_catalog_link = "/api/compute/api/catalog/#{id}" admin_catalog = connection.get(admin_catalog_link) unless admin_catalog diff --git a/lib/ruby_vcloud_sdk/connection/connection.rb b/lib/ruby_vcloud_sdk/connection/connection.rb index 917b7b8..a362f2d 100644 --- a/lib/ruby_vcloud_sdk/connection/connection.rb +++ b/lib/ruby_vcloud_sdk/connection/connection.rb @@ -31,9 +31,9 @@ def initialize(url, request_timeout = nil, def connect(username, password) login_password = "#{username}:#{password}" - auth_header_value = "Basic #{Base64.encode64(login_password)}" - response = @site[login_url].post( - Authorization: auth_header_value, Accept: ACCEPT) + auth_header_value = "Basic #{Base64.strict_encode64(login_password)}" + response = @site[login_url].post(nil, + {Authorization: auth_header_value, Accept: ACCEPT}) Config.logger.debug(response) @cookies = response.cookies unless @cookies["vcloud-token"].gsub!("+", "%2B").nil? @@ -63,11 +63,13 @@ def post(destination, data, content_type = "*/*") "Warning: content type not specified. Default to '*/*'") end @rest_logger.info("#{__method__.to_s.upcase} data:#{data.to_s}") + response = @site[get_nested_resource(destination)].post(data.to_s, { Accept: ACCEPT, cookies: @cookies, content_type: content_type }) + fail ApiRequestError if http_error?(response) @rest_logger.debug(response) wrap_response(response) diff --git a/lib/ruby_vcloud_sdk/vdc.rb b/lib/ruby_vcloud_sdk/vdc.rb index 4837f12..0d84a3d 100644 --- a/lib/ruby_vcloud_sdk/vdc.rb +++ b/lib/ruby_vcloud_sdk/vdc.rb @@ -17,6 +17,7 @@ class VDC extend Forwardable def_delegators :entity_xml, :name, :upload_link, :upload_media_link, + :instantiate_ovf_link, :instantiate_vapp_template_link public :find_network_by_name, :network_exists? @@ -209,6 +210,101 @@ def storage_profile_xml_node(name) storage_profile end + + def instantiate_ovf_params(vapp_name, vdc) + instantiate_ovf_params = VCloudSdk::Xml::WrapperFactory.create_instance("InstantiateOvfParams").tap do |params| + params.name = vapp_name + end + + connection.post(entity_xml.instantiate_ovf_link, + instantiate_ovf_params, + Xml::MEDIA_TYPE[:INSTANTIATE_OVF_PARAMS]) + end + + + def instantiate_ovf(vapp_name,directory) + if vapp_exists?(vapp_name) + fail CloudError, + "vApp '#{vapp_name}' already exists in vdc #{entity_xml.name}" + end + + Config.logger.info "Uploading vApp #{vapp_name} to #{entity_xml.name}" + vapp = instantiate_ovf_params(vapp_name, entity_xml) + vapp = upload_vapp_files(vapp, ovf_directory(directory)) + + end + + + def ovf_directory(directory) + # if directory behaves like an OVFDirectory, then use it + is_ovf_directory = [:ovf_file, :ovf_file_path, :vmdk_file, :vmdk_file_path] + .reduce(true) do |present, name| + present && directory.respond_to?(name) + end + + if is_ovf_directory + directory + else + OVFDirectory.new(directory) + end + end + + def upload_vapp_files( + vapp_template, + ovf_directory, + tries = @session.retries[:upload_vapp_files]) + tries.times do |try| + current_vapp_template = connection.get(vapp_template) + if !current_vapp_template.files || current_vapp_template.files.empty? + Config.logger.info %Q{ + #{current_vapp_template.name} has tasks in progress... + Waiting until done... + } + current_vapp_template.running_tasks.each do |task| + monitor_task(task, + @session.time_limit[:process_descriptor_vapp_template]) + end + + return current_vapp_template + end + + Config.logger.debug "vapp files left to upload #{current_vapp_template.files}." + Config.logger.debug %Q{ + vapp incomplete files left to upload: + #{current_vapp_template.incomplete_files} + } + + current_vapp_template.incomplete_files.each do |f| + # switch on extension + case f.name.split(".")[-1].downcase + when "ovf" + Config.logger.info %Q{ + Uploading OVF file: + #{ovf_directory.ovf_file_path} for #{vapp_template.name} + } + connection.put(f.upload_link, ovf_directory.ovf_file.read, + Xml::MEDIA_TYPE[:OVF]) + when "vmdk" + Config.logger.info %Q{ + Uploading VMDK file: + #{ovf_directory.vmdk_file_path(f.name)} for #{vapp_template.name} + } + connection.put_file(f.upload_link, + ovf_directory.vmdk_file(f.name)) + end + end + # Repeat + sleep 2**try + end + + fail ApiTimeoutError, + %Q{ + Unable to finish uploading vApp after #{tries} tries. + current_vapp_template.files: + #{current_vapp_template.files} + } + end + private def storage_profile_records @@ -238,5 +334,6 @@ def delete_single_disk(disk) Config.logger.info "Disk deleted successfully" end + end end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb index f5bf51a..83fc173 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb @@ -3,6 +3,7 @@ require "ruby_vcloud_sdk/xml/wrapper_classes/admin_catalog" require "ruby_vcloud_sdk/xml/wrapper_classes/admin_org" require "ruby_vcloud_sdk/xml/wrapper_classes/allocated_ip_addresses" +require "ruby_vcloud_sdk/xml/wrapper_classes/catalog" require "ruby_vcloud_sdk/xml/wrapper_classes/catalog_item" require "ruby_vcloud_sdk/xml/wrapper_classes/disk" require "ruby_vcloud_sdk/xml/wrapper_classes/disk_attach_or_detach_params" @@ -12,6 +13,7 @@ require "ruby_vcloud_sdk/xml/wrapper_classes/file" require "ruby_vcloud_sdk/xml/wrapper_classes/gateway_interface" require "ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper" +require "ruby_vcloud_sdk/xml/wrapper_classes/instantiate_ovf_params" require "ruby_vcloud_sdk/xml/wrapper_classes/instantiate_vapp_template_params" require "ruby_vcloud_sdk/xml/wrapper_classes/ip_address" require "ruby_vcloud_sdk/xml/wrapper_classes/ip_scope" diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog.rb new file mode 100644 index 0000000..c0fc78d --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog.rb @@ -0,0 +1,29 @@ +module VCloudSdk + module Xml + + class Catalog < Wrapper + def description + get_nodes("Description").first + end + + def description=(desc) + description.content = desc + end + + def add_item_link + get_nodes(XML_TYPE[:LINK], + { type: ADMIN_MEDIA_TYPE[:CATALOG_ITEM], + rel: XML_TYPE[:ADD] }).first + end + + def catalog_items(name = nil) + if name + get_nodes(XML_TYPE[:CATALOGITEM], { name: name }) + else + get_nodes(XML_TYPE[:CATALOGITEM]) + end + end + end + + end +end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_ovf_params.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_ovf_params.rb new file mode 100644 index 0000000..9099933 --- /dev/null +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_ovf_params.rb @@ -0,0 +1,9 @@ +module VCloudSdk + module Xml + class UploadVAppTemplateParams < Wrapper + def storage_profile=(storage_profile) + add_child(storage_profile) unless storage_profile.nil? + end + end + end +end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb index a71e5b6..7bc2d33 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb @@ -40,6 +40,15 @@ def vms def vm(name) get_nodes("Vm", name: name).first end + + def files + get_nodes("File") + end + + def incomplete_files + files.find_all {|f| f["size"].to_i < 0 || + (f["size"].to_i > f["bytesTransferred"].to_i)} + end end end diff --git a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb index def4a0e..a3c54bf 100644 --- a/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb +++ b/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb @@ -30,6 +30,12 @@ def upload_link .first end + def instantiate_ovf_link + get_nodes(XML_TYPE[:LINK], + type: MEDIA_TYPE[:INSTANTIATE_OVF_PARAMS]) + .first + end + def upload_media_link get_nodes(XML_TYPE[:LINK], type: MEDIA_TYPE[:MEDIA]) diff --git a/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateOvfParams.xml b/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateOvfParams.xml index bbfb41c..be1e517 100644 --- a/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateOvfParams.xml +++ b/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateOvfParams.xml @@ -1 +1 @@ -false \ No newline at end of file +false