diff --git a/README.md b/README.md index 0e4e82c..ed9abc5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [Vagrant](http://www.vagrantup.com) provider for VMware vCloud Director® ============= -[Version 0.4.0](../../releases/tag/v0.4.0) has been released! +[Version 0.4.1](../../releases/tag/v0.4.1) has been released! ------------- Please note that this software is still Alpha/Beta quality and is not recommended for production usage. @@ -23,6 +23,15 @@ Vagrant will download all the required gems during the installation process. After the install has completed a ```vagrant up --provider=vcloud``` will trigger the newly installed provider. +Upgrade +------------- + +If you already have vagrant-vcloud installed you can update to the latest version available by issuing: + +```vagrant plugin update vagrant-vcloud``` + +Vagrant will take care of the upgrade process. + Configuration ------------- diff --git a/lib/vagrant-vcloud/action.rb b/lib/vagrant-vcloud/action.rb index 75fc58a..430feac 100644 --- a/lib/vagrant-vcloud/action.rb +++ b/lib/vagrant-vcloud/action.rb @@ -21,6 +21,7 @@ def self.action_boot b2.use ForwardPorts end end + b.use WaitForCommunicator, [:starting, :running] b.use Provision b.use SyncFolders end diff --git a/lib/vagrant-vcloud/driver/base.rb b/lib/vagrant-vcloud/driver/base.rb index 8255be6..d883187 100644 --- a/lib/vagrant-vcloud/driver/base.rb +++ b/lib/vagrant-vcloud/driver/base.rb @@ -297,7 +297,7 @@ def send_request(params, payload = nil, content_type = nil) extheader = {} extheader['accept'] = "application/*+xml;version=#{@api_version}" - if !content_type.nil? + unless content_type.nil? extheader['Content-Type'] = content_type end @@ -331,9 +331,16 @@ def send_request(params, payload = nil, content_type = nil) extheader ) - if !response.ok? - raise "Warning: unattended code #{response.status}" + - " #{response.reason}" + unless response.ok? + if response.code == 400 + error_message = Nokogiri.parse(response.body) + error = error_message.css('Error') + fail Errors::InvalidRequestError, + :message => error.first['message'].to_s + else + fail Errors::UnattendedCodeError, + :message => response.status + end end nicexml = Nokogiri.XML(response.body) @@ -343,7 +350,7 @@ def send_request(params, payload = nil, content_type = nil) if @logger.level == 1 ap "[#{Time.now.ctime}] <- RECV #{response.status}" # Just avoid the task spam. - if !url.index('/task/') + unless url.index('/task/') ap 'RECV HEADERS' ap response.headers ap 'RECV BODY' @@ -352,10 +359,8 @@ def send_request(params, payload = nil, content_type = nil) end [Nokogiri.parse(response.body), response.headers] - rescue SocketError - raise 'Impossible to connect, verify endpoint' - rescue Errno::EADDRNOTAVAIL - raise 'Impossible to connect, verify endpoint' + rescue SocketError, Errno::EADDRNOTAVAIL + raise Errors::EndpointUnavailable, :endpoint => @api_url end end @@ -432,8 +437,20 @@ def upload_file(upload_url, upload_file, vapp_template, config = {}) 'Content-Length' => range_len.to_s } + upload_request = "#{@host_url}#{upload_url}" + + # Massive debug when LOG=DEBUG + # Using awesome_print to get nice XML output for better readability + if @logger.level == 1 + ap "[#{Time.now.ctime}] -> SEND PUT #{upload_request}" + ap 'SEND HEADERS' + ap extheader + ap 'SEND BODY' + ap '' + end + begin - upload_request = "#{@host_url}#{upload_url}" + # FIXME: Add debug on the return status of "connection" # to enhance troubleshooting for this upload process. # (tsugliani) diff --git a/lib/vagrant-vcloud/driver/meta.rb b/lib/vagrant-vcloud/driver/meta.rb index d2e98ca..1877de4 100644 --- a/lib/vagrant-vcloud/driver/meta.rb +++ b/lib/vagrant-vcloud/driver/meta.rb @@ -129,13 +129,14 @@ def get_api_version(host_url) # Suppress SSL depth message clnt.ssl_config.verify_callback = proc { |ok, ctx|; true } - url = "#{host_url}/api/versions" + uri = URI(host_url) + url = "#{uri.scheme}://#{uri.host}:#{uri.port}/api/versions" begin response = clnt.request('GET', url, nil, nil, nil) - if !response.ok? - raise "Warning: unattended code #{response.status} " + - "#{response.reason}" + unless response.ok? + fail Errors::UnattendedCodeError, + :message => response.status + ' ' + response.reason end version_info = Nokogiri.parse(response.body) @@ -154,10 +155,9 @@ def get_api_version(host_url) api_version_supported - rescue SocketError - raise Errors::HostNotFound, :message => host_url - rescue Errno::EADDRNOTAVAIL - raise Errors::HostNotFound, :message => host_url + rescue SocketError, Errno::EADDRNOTAVAIL + raise Errors::EndpointUnavailable, + :endpoint => "#{uri.scheme}://#{uri.host}:#{uri.port}/api" end end end diff --git a/lib/vagrant-vcloud/driver/version_5_1.rb b/lib/vagrant-vcloud/driver/version_5_1.rb index b497bee..34282c5 100644 --- a/lib/vagrant-vcloud/driver/version_5_1.rb +++ b/lib/vagrant-vcloud/driver/version_5_1.rb @@ -18,6 +18,7 @@ require 'ruby-progressbar' require 'set' require 'netaddr' +require 'uri' module VagrantPlugins module VCloud @@ -28,17 +29,17 @@ class Version_5_1 < Base ## # Init the driver with the Vagrantfile information - def initialize(host, username, password, org_name) + def initialize(hostname, username, password, org_name) @logger = Log4r::Logger.new('vagrant::provider::vcloud::driver_5_1') - - @host = host - @api_url = "#{host}/api" - @host_url = "#{host}" + uri = URI(hostname) + @api_url = "#{uri.scheme}://#{uri.host}:#{uri.port}/api" + @host_url = "#{uri.scheme}://#{uri.host}:#{uri.port}" @username = username @password = password @org_name = org_name @api_version = '5.1' @id = nil + @cached_vapp_edge_public_ips = {} end @@ -86,7 +87,7 @@ def get_organizations results = {} orgs.each do |org| - results[org['name']] = org['href'].gsub("#{@api_url}/org/", '') + results[org['name']] = URI(org['href']).path.gsub('/api/org/', '') end results end @@ -142,8 +143,8 @@ def get_organization(org_id) response.css( "Link[type='application/vnd.vmware.vcloud.catalog+xml']" ).each do |item| - catalogs[item['name']] = item['href'].gsub( - "#{@api_url}/catalog/", '' + catalogs[item['name']] = URI(item['href']).path.gsub( + '/api/catalog/', '' ) end @@ -151,8 +152,8 @@ def get_organization(org_id) response.css( "Link[type='application/vnd.vmware.vcloud.vdc+xml']" ).each do |item| - vdcs[item['name']] = item['href'].gsub( - "#{@api_url}/vdc/", '' + vdcs[item['name']] = URI(item['href']).path.gsub( + '/api/vdc/', '' ) end @@ -160,8 +161,8 @@ def get_organization(org_id) response.css( "Link[type='application/vnd.vmware.vcloud.orgNetwork+xml']" ).each do |item| - networks[item['name']] = item['href'].gsub( - "#{@api_url}/network/", '' + networks[item['name']] = URI(item['href']).path.gsub( + '/api/network/', '' ) end @@ -169,8 +170,8 @@ def get_organization(org_id) response.css( "Link[type='application/vnd.vmware.vcloud.tasksList+xml']" ).each do |item| - tasklists[item['name']] = item['href'].gsub( - "#{@api_url}/tasksList/", '' + tasklists[item['name']] = URI(item['href']).path.gsub( + '/api/tasksList/', '' ) end @@ -198,8 +199,8 @@ def get_catalog(catalog_id) response.css( "CatalogItem[type='application/vnd.vmware.vcloud.catalogItem+xml']" ).each do |item| - items[item['name']] = item['href'].gsub( - "#{@api_url}/catalogItem/", '' + items[item['name']] = URI(item['href']).path.gsub( + '/api/catalogItem/', '' ) end { :description => description, :items => items } @@ -218,6 +219,34 @@ def get_catalog_id_by_name(organization, catalog_name) end end + if result.nil? + # catalog not found, search in global catalogs as well + # that are not listed in organization directly + params = { + 'method' => :get, + 'command' => '/catalogs/query/', + 'cacheable' => true + } + + response, _headers = send_request(params) + + catalogs = {} + response.css( + 'CatalogRecord' + ).each do |item| + catalogs[item['name']] = URI(item['href']).path.gsub( + '/api/catalog/', '' + ) + end + + catalogs.each do |catalog| + if catalog[0].downcase == catalog_name.downcase + result = catalog[1] + end + end + + end + result end @@ -256,8 +285,8 @@ def get_vdc(vdc_id) response.css( "ResourceEntity[type='application/vnd.vmware.vcloud.vApp+xml']" ).each do |item| - vapps[item['name']] = item['href'].gsub( - "#{@api_url}/vApp/vapp-", '' + vapps[item['name']] = URI(item['href']).path.gsub( + '/api/vApp/vapp-', '' ) end @@ -265,8 +294,8 @@ def get_vdc(vdc_id) response.css( "Network[type='application/vnd.vmware.vcloud.network+xml']" ).each do |item| - networks[item['name']] = item['href'].gsub( - "#{@api_url}/network/", '' + networks[item['name']] = URI(item['href']).path.gsub( + '/api/network/', '' ) end { @@ -324,8 +353,8 @@ def get_catalog_item(catalog_item_id) response.css( "Entity[type='application/vnd.vmware.vcloud.vAppTemplate+xml']" ).each do |item| - items[item['name']] = item['href'].gsub( - "#{@api_url}/vAppTemplate/vappTemplate-", '' + items[item['name']] = URI(item['href']).path.gsub( + '/api/vAppTemplate/vappTemplate-', '' ) end { :description => description, :items => items } @@ -359,7 +388,9 @@ def get_catalog_item_by_name(catalog_id, catalog_item_name) vms_hash = {} response.css('/VAppTemplate/Children/Vm').each do |vm_elem| vm_name = vm_elem['name'] - vm_id = vm_elem['href'].gsub("#{@api_url}/vAppTemplate/vm-", '') + vm_id = URI(vm_elem['href']).path.gsub( + '/api/vAppTemplate/vm-', '' + ) # Add the VM name/id to the VMs Hash vms_hash[vm_name] = { :id => vm_id } @@ -415,7 +446,7 @@ def get_vapp(vapp_id) vms_hash[vm['name'].to_sym] = { :addresses => addresses, :status => convert_vapp_status(vm['status']), - :id => vm['href'].gsub("#{@api_url}/vApp/vm-", ''), + :id => URI(vm['href']).path.gsub('/api/vApp/vm-', ''), :vapp_scoped_local_id => vapp_local_id.text } end @@ -440,7 +471,7 @@ def delete_vapp(vapp_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -463,7 +494,7 @@ def poweroff_vapp(vapp_id) builder.to_xml, 'application/vnd.vmware.vcloud.undeployVAppParams+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -476,7 +507,7 @@ def suspend_vapp(vapp_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -492,7 +523,7 @@ def reboot_vapp(vapp_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -507,7 +538,7 @@ def reset_vapp(vapp_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -520,7 +551,7 @@ def poweron_vapp(vapp_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -535,7 +566,7 @@ def delete_vm(vm_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -560,7 +591,7 @@ def poweroff_vm(vm_id) builder.to_xml, 'application/vnd.vmware.vcloud.undeployVAppParams+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -583,7 +614,7 @@ def suspend_vm(vm_id) builder.to_xml, 'application/vnd.vmware.vcloud.undeployVAppParams+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -599,7 +630,7 @@ def reboot_vm(vm_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -614,7 +645,7 @@ def reset_vm(vm_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -627,7 +658,7 @@ def poweron_vm(vm_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -652,13 +683,13 @@ def create_catalog(org_id, catalog_name, catalog_description) builder.to_xml, 'application/vnd.vmware.admin.catalog+xml' ) - task_id = response.css( - "AdminCatalog Tasks Task[operationName='catalogCreateCatalog']" - ).first[:href].gsub("#{@api_url}/task/", '') + task_id = URI(response.css( + "AdminCatalog Tasks Task[operationName='catalogCreateCatalog']" + ).first[:href]).path.gsub('/api/task/', '') - catalog_id = response.css( - "AdminCatalog Link [type='application/vnd.vmware.vcloud.catalog+xml']" - ).first[:href].gsub("#{@api_url}/catalog/", '') + catalog_id = URI(response.css( + "AdminCatalog Link [type='application/vnd.vmware.vcloud.catalog+xml']" + ).first[:href]).path.gsub('/api/catalog/', '') { :task_id => task_id, :catalog_id => catalog_id } end @@ -697,13 +728,13 @@ def create_vapp_from_template(vdc, vapp_name, vapp_description, vapp_template_id 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml' ) - vapp_id = headers['Location'].gsub("#{@api_url}/vApp/vapp-", '') + vapp_id = URI(headers['Location']).path.gsub('/api/vApp/vapp-', '') task = response.css( "VApp Task[operationName='vdcInstantiateVapp']" ).first - task_id = task['href'].gsub("#{@api_url}/task/", '') + task_id = URI(task['href']).path.gsub("/api/task/", '') { :vapp_id => vapp_id, :task_id => task_id } end @@ -802,10 +833,10 @@ def compose_vapp_from_vm(vdc, vapp_name, vapp_description, vm_list = {}, network 'application/vnd.vmware.vcloud.composeVAppParams+xml' ) - vapp_id = headers['Location'].gsub("#{@api_url}/vApp/vapp-", '') + vapp_id = URI(headers['Location']).path.gsub("/api/vApp/vapp-", '') task = response.css("VApp Task[operationName='vdcComposeVapp']").first - task_id = task['href'].gsub("#{@api_url}/task/", '') + task_id = URI(task['href']).path.gsub('/api/task/', '') { :vapp_id => vapp_id, :task_id => task_id } end @@ -865,10 +896,10 @@ def recompose_vapp_from_vm(vapp_id, vm_list = {}, network_config = {}) 'application/vnd.vmware.vcloud.recomposeVAppParams+xml' ) - vapp_id = headers['Location'].gsub("#{@api_url}/vApp/vapp-", '') + vapp_id = URI(headers['Location']).path.gsub('/api/vApp/vapp-', '') task = response.css("Task [operationName='vdcRecomposeVapp']").first - task_id = task['href'].gsub("#{@api_url}/task/", '') + task_id = URI(task['href']).path.gsub('/api/task/', '') { :vapp_id => vapp_id, :task_id => task_id } end @@ -904,7 +935,7 @@ def get_vapp_template(vapp_id) vms.each do |vm| vms_hash[vm['name']] = { - :id => vm['href'].gsub("#{@api_url}/vAppTemplate/vm-", '') + :id => URI(vm['href']).path.gsub('/api/vAppTemplate/vm-', '') } end @@ -962,7 +993,7 @@ def set_vapp_port_forwarding_rules(vapp_id, network_name, config = {}) 'application/vnd.vmware.vcloud.networkConfigSection+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub("/api/task/", '') task_id end @@ -1029,7 +1060,7 @@ def add_vapp_port_forwarding_rules(vapp_id, network_name, config = {}) 'application/vnd.vmware.vcloud.networkConfigSection+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end ## @@ -1099,8 +1130,8 @@ def find_edge_gateway_id(edge_gateway_name, vdc_id) edge_gateway = response.css('EdgeGatewayRecord').first if edge_gateway - return edge_gateway['href'].gsub( - "#{@api_url}/admin/edgeGateway/", '' + return URI(edge_gateway['href']).path.gsub( + '/api/admin/edgeGateway/', '' ) else return nil @@ -1119,7 +1150,7 @@ def redeploy_edge_gateway(edge_gateway_id) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -1145,8 +1176,8 @@ def find_edge_gateway_network(edge_gateway_name, vdc_id, edge_gateway_ip) edge_gateway = response.css('EdgeGatewayRecord').first if edge_gateway - edge_gateway_id = edge_gateway['href'].gsub( - "#{@api_url}/admin/edgeGateway/", '' + edge_gateway_id = URI(edge_gateway['href']).path.gsub( + '/api/admin/edgeGateway/', '' ) end @@ -1312,7 +1343,7 @@ def remove_edge_gateway_rules(edge_gateway_name, vdc_id, edge_gateway_ip, vapp_i 'application/vnd.vmware.admin.edgeGatewayServiceConfiguration+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -1450,7 +1481,7 @@ def add_edge_gateway_rules(edge_gateway_name, vdc_id, edge_gateway_ip, vapp_id, 'application/vnd.vmware.admin.edgeGatewayServiceConfiguration+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -1545,14 +1576,14 @@ def upload_ovf(vdc_id, vapp_name, vapp_description, ovf_file, catalog_id, upload ) # Get vAppTemplate Link from location - vapp_template = headers['Location'].gsub( - "#{@api_url}/vAppTemplate/vappTemplate-", '' + vapp_template = URI(headers['Location']).path.gsub( + '/api/vAppTemplate/vappTemplate-', '' ) @logger.debug("Getting vAppTemplate ID: #{vapp_template}") - descriptor_upload = response.css( + descriptor_upload = URI(response.css( "Files Link [rel='upload:default']" - ).first[:href].gsub("#{@host_url}/transfer/", '') + ).first[:href]).path.gsub('/transfer/', '') transfer_guid = descriptor_upload.gsub('/descriptor.ovf', '') ovf_file_basename = File.basename(ovf_file, '.ovf') @@ -1581,7 +1612,7 @@ def upload_ovf(vdc_id, vapp_name, vapp_description, ovf_file, catalog_id, upload task = response.css( "VAppTemplate Task[operationName='vdcUploadOvfContents']" ).first - task_id = task['href'].gsub("#{@api_url}/task/", '') + task_id = URI(task['href']).path.gsub('/api/task/', '') # Loop to wait for the upload links to show up in the vAppTemplate # we just created @@ -1616,9 +1647,7 @@ def upload_ovf(vdc_id, vapp_name, vapp_description, ovf_file, catalog_id, upload response.css( "Files File [bytesTransferred='0'] Link [rel='upload:default']" ).each do |file| - file_name = file[:href].gsub( - "#{@host_url}/transfer/#{transfer_guid}/", '' - ) + file_name = URI(file[:href]).path.gsub("/transfer/#{transfer_guid}/", '') upload_filename = "#{ovf_dir}/#{file_name}" upload_url = "/transfer/#{transfer_guid}/#{file_name}" upload_file( @@ -1670,9 +1699,9 @@ def upload_ovf(vdc_id, vapp_name, vapp_description, ovf_file, catalog_id, upload response, _headers = send_request(params) # Cancel Task - cancel_hook = response.css( + cancel_hook = URI(response.css( "Tasks Task Link [rel='task:cancel']" - ).first[:href].gsub("#{@api_url}", '') + ).first[:href]).path.gsub('/api', '') params = { 'method' => :post, @@ -1769,7 +1798,7 @@ def set_vapp_network_config(vapp_id, network_name, config = {}) 'application/vnd.vmware.vcloud.networkConfigSection+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -1805,7 +1834,7 @@ def set_vm_network_config(vm_id, network_name, config = {}) 'application/vnd.vmware.vcloud.networkConnectionSection+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -1834,7 +1863,7 @@ def set_vm_guest_customization(vm_id, computer_name, config = {}) builder.to_xml, 'application/vnd.vmware.vcloud.guestCustomizationSection+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -1847,7 +1876,7 @@ def set_vm_nested_hypervisor(vm_id, enable) } _response, headers = send_request(params) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id end @@ -1898,7 +1927,7 @@ def set_vm_hardware(vm_id, cfg) 'application/vnd.vmware.vcloud.virtualhardwaresection+xml' ) - task_id = headers['Location'].gsub("#{@api_url}/task/", '') + task_id = URI(headers['Location']).path.gsub('/api/task/', '') task_id else return nil diff --git a/lib/vagrant-vcloud/errors.rb b/lib/vagrant-vcloud/errors.rb index 6ba1415..cd03ba8 100644 --- a/lib/vagrant-vcloud/errors.rb +++ b/lib/vagrant-vcloud/errors.rb @@ -9,7 +9,6 @@ class VCloudError < Vagrant::Errors::VagrantError class RsyncError < VCloudError error_key(:rsync_error) end - class MkdirError < VCloudError error_key(:mkdir_error) end @@ -19,12 +18,6 @@ class VCloudOldVersion < VCloudError class CatalogAddError < VCloudError error_key(:catalog_add_error) end - class HostNotFound < VCloudError - error_key(:host_not_found) - end - class HostRedirect < VCloudError - error_key(:host_redirect) - end class UnauthorizedAccess < VCloudError error_key(:unauthorized_access) end @@ -61,6 +54,15 @@ class InvalidConfigError < RestError class InvalidStateError < RestError error_key(:invalid_state_error) end + class InvalidRequestError < RestError + error_key(:invalid_request_error) + end + class UnattendedCodeError < RestError + error_key(:unattended_code_error) + end + class EndpointUnavailable < RestError + error_key(:endpoint_unavailable) + end class SyncError < VCloudError error_key(:sync_error) end diff --git a/lib/vagrant-vcloud/version.rb b/lib/vagrant-vcloud/version.rb index 2931b83..0143b41 100644 --- a/lib/vagrant-vcloud/version.rb +++ b/lib/vagrant-vcloud/version.rb @@ -1,5 +1,5 @@ module VagrantPlugins module VCloud - VERSION = '0.4.0' + VERSION = '0.4.1' end end diff --git a/locales/en.yml b/locales/en.yml index 0cc1ac7..273152c 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -30,8 +30,6 @@ en: missing_resource_pool: "Configured resource pool not found" missing_template: "Configured template VM could not be found" vcloud_old_version: "Sorry, VMware vCloud Director API version %{version} is not supported" - host_not_found: "VMware vCloud Endpoint not found: %{message}" - host_redirect: "VMware vCloud Endpoint not found, received an HTTP 302 message back, are you sure you're using the right protocol? (https)" unauthorized_access: "Access not authorized, please verify the username and password in your Vagrantfile" catalog_add_error: "Impossible to add Box to Catalog, error: %{message}" invalid_network_specification: "Wrong Network specification in the Vagrantfile, make sure you have access to the specified network." @@ -42,6 +40,9 @@ en: object_not_found: "Object not found in vCloud Director" invalid_config_error: "Invalid Guest Customization Specified" invalid_state_error: "Invalid vApp State %{message}" + invalid_request_error: "Invalid request %{message}" + unattended_code_error: "Unattended code received %{message}" + endpoint_unavailable: "Can't connect to the specified endpoint %{endpoint}, please verify connectivity." subnet_errors: invalid_subnet: "The specified subnet is invalid: %{message}" subnet_too_small: "The specified subnet is too small: %{message}, must contain at least 2 usable IPs (/30 or 255.255.255.252)"