lib/vagrant-vcloud/driver/base.rb in vagrant-vcloud-0.1.2 vs lib/vagrant-vcloud/driver/base.rb in vagrant-vcloud-0.2.0
- old
+ new
@@ -13,17 +13,17 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-require "log4r"
-require "vagrant/util/busy"
-require "vagrant/util/platform"
-require "vagrant/util/retryable"
-require "vagrant/util/subprocess"
+require 'log4r'
+require 'vagrant/util/busy'
+require 'vagrant/util/platform'
+require 'vagrant/util/retryable'
+require 'vagrant/util/subprocess'
+require 'awesome_print'
-
module VagrantPlugins
module VCloud
module Driver
class UnauthorizedAccess < StandardError; end
class WrongAPIVersion < StandardError; end
@@ -35,11 +35,11 @@
# Main class to access vCloud rest APIs
class Base
include Vagrant::Util::Retryable
def initialize
- @logger = Log4r::Logger.new("vagrant::provider::vcloud::base")
+ @logger = Log4r::Logger.new('vagrant::provider::vcloud::base')
end
##
# Authenticate against the specified server
def login
@@ -59,11 +59,10 @@
# friendly helper method to fetch an Organization Id by name
# - name (this isn't case sensitive)
def get_organization_id_by_name(name)
end
-
##
# friendly helper method to fetch an Organization by name
# - name (this isn't case sensitive)
def get_organization_by_name(name)
end
@@ -71,67 +70,67 @@
##
# Fetch details about an organization:
# - catalogs
# - vdcs
# - networks
- def get_organization(orgId)
+ def get_organization(org_id)
end
##
# Fetch details about a given catalog
- def get_catalog(catalogId)
+ def get_catalog(catalog_id)
end
##
# Friendly helper method to fetch an catalog id by name
# - organization hash (from get_organization/get_organization_by_name)
# - catalog name
- def get_catalog_id_by_name(organization, catalogName)
+ def get_catalog_id_by_name(organization, catalog_name)
end
##
# Friendly helper method to fetch an catalog by name
# - organization hash (from get_organization/get_organization_by_name)
# - catalog name
- def get_catalog_by_name(organization, catalogName)
+ def get_catalog_by_name(organization, catalog_name)
end
##
# Fetch details about a given vdc:
# - description
# - vapps
# - networks
- def get_vdc(vdcId)
+ def get_vdc(vdc_id)
end
##
# Friendly helper method to fetch a Organization VDC Id by name
# - Organization object
# - Organization VDC Name
- def get_vdc_id_by_name(organization, vdcName)
+ def get_vdc_id_by_name(organization, vdc_name)
end
##
# Friendly helper method to fetch a Organization VDC by name
# - Organization object
# - Organization VDC Name
- def get_vdc_by_name(organization, vdcName)
+ def get_vdc_by_name(organization, vdc_name)
end
##
# Fetch details about a given catalog item:
# - description
# - vApp templates
- def get_catalog_item(catalogItemId)
+ def get_catalog_item(catalog_item_id)
end
##
# friendly helper method to fetch an catalogItem by name
# - catalogId (use get_catalog_name(org, name))
- # - catalagItemName
- def get_catalog_item_by_name(catalogId, catalogItemName)
- end
+ # - catalagItemName
+ def get_catalog_item_by_name(catalog_id, catalog_item_name)
+ end
##
# Fetch details about a given vapp:
# - name
# - description
@@ -139,162 +138,164 @@
# - IP
# - Children VMs:
# -- IP addresses
# -- status
# -- ID
- def get_vapp(vAppId)
+ def get_vapp(vapp_id)
end
##
# Delete a given vapp
# NOTE: It doesn't verify that the vapp is shutdown
- def delete_vapp(vAppId)
+ def delete_vapp(vapp_id)
end
##
# Suspend a given vapp
- def suspend_vapp(vAppId)
+ def suspend_vapp(vapp_id)
end
##
# reboot a given vapp
# This will basically initial a guest OS reboot, and will only work if
# VMware-tools are installed on the underlying VMs.
# vShield Edge devices are not affected
- def reboot_vapp(vAppId)
+ def reboot_vapp(vapp_id)
end
##
# reset a given vapp
# This will basically reset the VMs within the vApp
# vShield Edge devices are not affected.
- def reset_vapp(vAppId)
+ def reset_vapp(vapp_id)
end
##
# Boot a given vapp
- def poweron_vapp(vAppId)
+ def poweron_vapp(vapp_id)
end
##
# Create a vapp starting from a template
#
# Params:
# - vdc: the associated VDC
# - vapp_name: name of the target vapp
# - vapp_description: description of the target vapp
# - vapp_templateid: ID of the vapp template
- def create_vapp_from_template(vdc, vapp_name, vapp_description, vapp_templateid, poweron=false)
+ def create_vapp_from_template(vdc, vapp_name, vapp_description,
+ vapp_templateid, poweron = false)
end
##
# Compose a vapp using existing virtual machines
#
# Params:
# - vdc: the associated VDC
# - vapp_name: name of the target vapp
# - vapp_description: description of the target vapp
- # - vm_list: hash with IDs of the VMs to be used in the composing process
+ # - vm_list: hash with IDs of the VMs used in the composing process
# - network_config: hash of the network configuration for the vapp
- def compose_vapp_from_vm(vdc, vapp_name, vapp_description, vm_list={}, network_config={})
+ def compose_vapp_from_vm(vdc, vapp_name, vapp_description,
+ vm_list = {}, network_config = {})
end
# Fetch details about a given vapp template:
# - name
# - description
# - Children VMs:
# -- ID
- def get_vapp_template(vAppId)
+ def get_vapp_template(vapp_id)
end
##
# Set vApp port forwarding rules
#
# - vappid: id of the vapp to be modified
# - network_name: name of the vapp network to be modified
- # - config: hash with network configuration specifications, must contain an array inside :nat_rules with the nat rules to be applied.
- def set_vapp_port_forwarding_rules(vappid, network_name, config={})
+ # - config: hash with network configuration specifications, must contain
+ # an array inside :nat_rules with the nat rules to be applied.
+ def set_vapp_port_forwarding_rules(vapp_id, network_name, config = {})
end
##
# Get vApp port forwarding rules
#
# - vappid: id of the vApp
- def get_vapp_port_forwarding_rules(vAppId)
+ def get_vapp_port_forwarding_rules(vapp_id)
end
##
# get vApp edge public IP from the vApp ID
# Only works when:
# - vApp needs to be poweredOn
# - FenceMode is set to "natRouted"
# - NatType" is set to "portForwarding
- # This will be required to know how to connect to VMs behind the Edge device.
- def get_vapp_edge_public_ip(vAppId)
+ # This will be required to know how to connect to VMs behind the Edge.
+ def get_vapp_edge_public_ip(vapp_id)
end
##
# Upload an OVF package
# - vdcId
# - vappName
# - vappDescription
# - ovfFile
# - catalogId
# - uploadOptions {}
- def upload_ovf(vdcId, vappName, vappDescription, ovfFile, catalogId, uploadOptions={})
+ def upload_ovf(vdc_id, vapp_name, vapp_description, ovf_file,
+ catalog_id, upload_options = {})
end
##
# Fetch information for a given task
- def get_task(taskid)
+ def get_task(task_id)
end
##
# Poll a given task until completion
- def wait_task_completion(taskid)
+ def wait_task_completion(task_id)
end
##
# Set vApp Network Config
- def set_vapp_network_config(vappid, network_name, config={})
+ def set_vapp_network_config(vapp_id, network_name, config = {})
end
##
# Set VM Network Config
- def set_vm_network_config(vmid, network_name, config={})
+ def set_vm_network_config(vm_id, network_name, config = {})
end
-
##
# Set VM Guest Customization Config
- def set_vm_guest_customization(vmid, computer_name, config={})
+ def set_vm_guest_customization(vm_id, computer_name, config = {})
end
##
# Fetch details about a given VM
- def get_vm(vmId)
+ def get_vm(vm_Id)
end
private
##
- # Sends a synchronous request to the vCloud API and returns the response as parsed XML + headers using HTTPClient.
- def send_request(params, payload=nil, content_type=nil)
-
+ # Sends a synchronous request to the vCloud API and returns the
+ # response as parsed XML + headers using HTTPClient.
+ def send_request(params, payload = nil, content_type = nil)
# Create a new HTTP client
clnt = HTTPClient.new
# Disable SSL cert verification
- clnt.ssl_config.verify_mode=(OpenSSL::SSL::VERIFY_NONE)
+ clnt.ssl_config.verify_mode = (OpenSSL::SSL::VERIFY_NONE)
# Suppress SSL depth message
- clnt.ssl_config.verify_callback=proc{ |ok, ctx|; true };
-
+ clnt.ssl_config.verify_callback = proc { |ok, ctx|; true }
+
extheader = {}
+ extheader['accept'] = "application/*+xml;version=#{@api_version}"
- extheader["accept"] = "application/*+xml;version=#{@api_version}"
-
if !content_type.nil?
extheader['Content-Type'] = content_type
end
if @auth_key
@@ -303,138 +304,186 @@
clnt.set_auth(nil, "#{@username}@#{@org_name}", @password)
end
url = "#{@api_url}#{params['command']}"
+ # Massive debug when LOG=DEBUG
+ # Using awesome_print to get nice XML output for better readability
+ if @logger.level == 1
+ ap "SEND #{url}"
+ if payload
+ payload_xml = Nokogiri.XML(payload)
+ ap payload_xml
+ end
+ end
+
begin
- response = clnt.request(params['method'], url, nil, payload, extheader)
+ response = clnt.request(
+ params['method'],
+ url,
+ nil,
+ payload,
+ extheader
+ )
+
if !response.ok?
- raise "Warning: unattended code #{response.status} #{response.reason}"
+ raise "Warning: unattended code #{response.status}" +
+ " #{response.reason}"
end
- [Nokogiri.parse(response.body), response.headers]
+ nicexml = Nokogiri.XML(response.body)
+ # Massive debug when LOG=DEBUG
+ # Using awesome_print to get nice XML output for readability
+ if @logger.level == 1
+ ap "RECV #{response.status}"
+ # Just avoid the task spam.
+ if !url.index('/task/')
+ ap nicexml
+ end
+ end
+
+ [Nokogiri.parse(response.body), response.headers]
rescue SocketError
- raise "Impossible to connect, verify endpoint"
+ raise 'Impossible to connect, verify endpoint'
rescue Errno::EADDRNOTAVAIL
- raise "Impossible to connect, verify endpoint"
+ raise 'Impossible to connect, verify endpoint'
end
-
-
end
-
##
- # Upload a large file in configurable chunks, output an optional progressbar
- def upload_file(uploadURL, uploadFile, vAppTemplate, config={})
+ # Upload a large file in configurable chunks, output an optional
+ # progressbar
+ def upload_file(upload_url, upload_file, vapp_template, config = {})
+ # Set chunksize to 1M if not specified otherwise
+ chunk_size = (config[:chunksize] || 1_048_576)
+ @logger.debug("Set chunksize to #{chunk_size} bytes")
- # Set chunksize to 10M if not specified otherwise
- chunkSize = (config[:chunksize] || 10485760)
+ # Set progressbar to default format if not specified otherwise
+ progressbar_format = (
+ config[:progressbar_format] || '%t Progress: %p%% %e'
+ )
- # Set progress bar to default format if not specified otherwise
- progressBarFormat = (config[:progressbar_format] || "%t Progress: %p%% %e")
-
- # Set progress bar length to 120 if not specified otherwise
- progressBarLength = (config[:progressbar_length] || 80)
-
# Open our file for upload
- uploadFileHandle = File.new(uploadFile, "rb" )
- fileName = File.basename(uploadFileHandle)
+ upload_file_handle = File.new(upload_file, 'rb')
+ file_name = File.basename(upload_file_handle)
- progressBarTitle = "Uploading: " + fileName.to_s
+ # FIXME: I removed the filename below because I recall a weird issue
+ # of upload failing because if a too long filename
+ # (tsugliani)
+ progressbar_title = 'Uploading Box...'
# Create a progressbar object if progress bar is enabled
- if config[:progressbar_enable] == true && uploadFileHandle.size.to_i > chunkSize
+ if config[:progressbar_enable] == true &&
+ upload_file_handle.size.to_i > chunk_size
progressbar = ProgressBar.create(
- :title => progressBarTitle,
- :starting_at => 0,
- :total => uploadFileHandle.size.to_i,
- ##:length => progressBarLength,
- :format => progressBarFormat
+ :title => progressbar_title,
+ :starting_at => 0,
+ :total => upload_file_handle.size.to_i,
+ :format => progressbar_format
)
else
- puts progressBarTitle
+ puts progressbar_title
end
# Create a new HTTP client
clnt = HTTPClient.new
# Disable SSL cert verification
- clnt.ssl_config.verify_mode=(OpenSSL::SSL::VERIFY_NONE)
+ clnt.ssl_config.verify_mode = (OpenSSL::SSL::VERIFY_NONE)
# Suppress SSL depth message
- clnt.ssl_config.verify_callback=proc{ |ok, ctx|; true };
+ clnt.ssl_config.verify_callback = proc { |ok, ctx|; true }
# Perform ranged upload until the file reaches its end
- until uploadFileHandle.eof?
+ until upload_file_handle.eof?
# Create ranges for this chunk upload
- rangeStart = uploadFileHandle.pos
- rangeStop = uploadFileHandle.pos.to_i + chunkSize
+ range_start = upload_file_handle.pos
+ range_stop = upload_file_handle.pos.to_i + chunk_size
# Read current chunk
- fileContent = uploadFileHandle.read(chunkSize)
+ file_content = upload_file_handle.read(chunk_size)
# If statement to handle last chunk transfer if is > than filesize
- if rangeStop.to_i > uploadFileHandle.size.to_i
- contentRange = "bytes #{rangeStart.to_s}-#{uploadFileHandle.size.to_s}/#{uploadFileHandle.size.to_s}"
- rangeLen = uploadFileHandle.size.to_i - rangeStart.to_i
+ if range_stop.to_i > upload_file_handle.size.to_i
+ content_range = "bytes #{range_start.to_s}-" +
+ "#{upload_file_handle.size.to_s}/" +
+ "#{upload_file_handle.size.to_s}"
+ range_len = upload_file_handle.size.to_i - range_start.to_i
else
- contentRange = "bytes #{rangeStart.to_s}-#{rangeStop.to_s}/#{uploadFileHandle.size.to_s}"
- rangeLen = rangeStop.to_i - rangeStart.to_i
+ content_range = "bytes #{range_start.to_s}-" +
+ "#{range_stop.to_s}/" +
+ "#{upload_file_handle.size.to_s}"
+ range_len = range_stop.to_i - range_start.to_i
end
# Build headers
extheader = {
- 'x-vcloud-authorization' => @auth_key,
- 'Content-Range' => contentRange,
- 'Content-Length' => rangeLen.to_s
+ 'x-vcloud-authorization' => @auth_key,
+ 'Content-Range' => content_range,
+ 'Content-Length' => range_len.to_s
}
begin
- uploadRequest = "#{@host_url}#{uploadURL}"
- connection = clnt.request('PUT', uploadRequest, nil, fileContent, extheader)
+ upload_request = "#{@host_url}#{upload_url}"
+ # FIXME: Add debug on the return status of "connection"
+ # to enhance troubleshooting for this upload process.
+ # (tsugliani)
+ _connection = clnt.request(
+ 'PUT',
+ upload_request,
+ nil,
+ file_content,
+ extheader
+ )
- if config[:progressbar_enable] == true && uploadFileHandle.size.to_i > chunkSize
+ if config[:progressbar_enable] == true &&
+ upload_file_handle.size.to_i > chunk_size
params = {
- 'method' => :get,
- 'command' => "/vAppTemplate/vappTemplate-#{vAppTemplate}"
+ 'method' => :get,
+ 'command' => "/vAppTemplate/vappTemplate-#{vapp_template}"
}
- response, headers = send_request(params)
+ response, _headers = send_request(params)
- response.css("Files File [name='#{fileName}']").each do |file|
- progressbar.progress=file[:bytesTransferred].to_i
+ response.css(
+ "Files File [name='#{file_name}']"
+ ).each do |file|
+ progressbar.progress = file[:bytesTransferred].to_i
end
end
- rescue # FIXME: HUGE FIXME!!!! DO SOMETHING WITH THIS, IT'S JUST STUPID AS IT IS NOW!!!
- retryTime = (config[:retry_time] || 5)
- puts "Range #{contentRange} failed to upload, retrying the chunk in #{retryTime.to_s} seconds, to stop the action press CTRL+C."
- sleep retryTime.to_i
+
+ rescue
+ # FIXME: HUGE FIXME!!!!
+ # DO SOMETHING WITH THIS, IT'S JUST STUPID AS IT IS NOW!!!
+ retry_time = (config[:retry_time] || 5)
+ puts "Range #{content_range} failed to upload, " +
+ "retrying the chunk in #{retry_time.to_s} seconds, " +
+ 'to stop this task press CTRL+C.'
+ sleep retry_time.to_i
retry
end
end
- uploadFileHandle.close
+ upload_file_handle.close
end
-
##
# Convert vApp status codes into human readable description
def convert_vapp_status(status_code)
case status_code.to_i
- when 0
- 'suspended'
- when 3
- 'paused'
- when 4
- 'running'
- when 8
- 'stopped'
- when 10
- 'mixed'
- else
- "Unknown #{status_code}"
+ when 0
+ 'suspended'
+ when 3
+ 'paused'
+ when 4
+ 'running'
+ when 8
+ 'stopped'
+ when 10
+ 'mixed'
+ else
+ "Unknown #{status_code}"
end
end
-
end # class
end
end
end
\ No newline at end of file