mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Updated the save method in Fog::Rackspace::BlockStorage::Volume and Fog::Rackspace::BlockStorage::Snapshot to throw an exception if the identity attribute is set per geemus; rebased code to latest master
This commit is contained in:
commit
611870f787
14 changed files with 188 additions and 85 deletions
7
Rakefile
7
Rakefile
|
@ -52,10 +52,9 @@ require "tasks/test_task"
|
||||||
Fog::Rake::TestTask.new
|
Fog::Rake::TestTask.new
|
||||||
|
|
||||||
namespace :test do
|
namespace :test do
|
||||||
task :dynect do
|
task :vsphere do
|
||||||
[false].each do |mock|
|
[true].each do |mock|
|
||||||
sh("export FOG_MOCK=#{mock} && bundle exec shindont tests/dns/requests/dynect")
|
sh("export FOG_MOCK=#{mock} && bundle exec shindont tests/vsphere")
|
||||||
#sh("export FOG_MOCK=#{mock} && bundle exec shindont tests/dns/models/")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -110,6 +110,18 @@ module Fog
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# @param [Hash] options
|
||||||
|
# @option options [String] acl sets x-amz-acl HTTP header. Valid values include, private | public-read | public-read-write | authenticated-read | bucket-owner-read | bucket-owner-full-control
|
||||||
|
# @option options [String] cache_controle sets Cache-Control header. For example, 'No-cache'
|
||||||
|
# @option options [String] content_disposition sets Content-Disposition HTTP header. For exampple, 'attachment; filename=testing.txt'
|
||||||
|
# @option options [String] content_encoding sets Content-Encoding HTTP header. For example, 'x-gzip'
|
||||||
|
# @option options [String] content_md5 sets Content-MD5. For example, '79054025255fb1a26e4bc422aef54eb4'
|
||||||
|
# @option options [String] content_type Content-Type. For example, 'text/plain'
|
||||||
|
# @option options [String] expires sets Expires HTTP header. For example, 'Thu, 01 Dec 1994 16:00:00 GMT'
|
||||||
|
# @option options [String] storage_class sets x-amz-storage-class HTTP header. Defaults to 'STANDARD'. Or, 'REDUCED_REDUNDANCY'
|
||||||
|
# @option options [String] encryption sets HTTP encryption header. Set to 'AES256' to encrypt files at rest on S3
|
||||||
|
#
|
||||||
def save(options = {})
|
def save(options = {})
|
||||||
requires :body, :directory, :key
|
requires :body, :directory, :key
|
||||||
if options != {}
|
if options != {}
|
||||||
|
|
|
@ -4,6 +4,7 @@ module Fog
|
||||||
module Rackspace
|
module Rackspace
|
||||||
class BlockStorage < Fog::Service
|
class BlockStorage < Fog::Service
|
||||||
|
|
||||||
|
class IdentifierTaken < Fog::Errors::Error; end
|
||||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||||
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
||||||
|
|
|
@ -26,7 +26,7 @@ module Fog
|
||||||
|
|
||||||
def save(force = false)
|
def save(force = false)
|
||||||
requires :volume_id
|
requires :volume_id
|
||||||
return true if identity
|
raise IdentifierTaken.new('Resaving may cause a duplicate snapshot to be created') if identity
|
||||||
data = connection.create_snapshot(volume_id, {
|
data = connection.create_snapshot(volume_id, {
|
||||||
:display_name => display_name,
|
:display_name => display_name,
|
||||||
:display_description => display_description,
|
:display_description => display_description,
|
||||||
|
|
|
@ -35,9 +35,14 @@ module Fog
|
||||||
connection.snapshots.select { |s| s.volume_id == identity }
|
connection.snapshots.select { |s| s.volume_id == identity }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_snapshot(options={})
|
||||||
|
requires :identity
|
||||||
|
connection.snapshots.create(options.merge(:volume_id => identity))
|
||||||
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
requires :size
|
requires :size
|
||||||
return true if identity
|
raise IdentifierTaken.new('Resaving may cause a duplicate volume to be created') if identity
|
||||||
data = connection.create_volume(size, {
|
data = connection.create_volume(size, {
|
||||||
:display_name => display_name,
|
:display_name => display_name,
|
||||||
:display_description => display_description,
|
:display_description => display_description,
|
||||||
|
|
|
@ -123,7 +123,9 @@ module Fog
|
||||||
# This inline rescue catches any standard error. While a VM is
|
# This inline rescue catches any standard error. While a VM is
|
||||||
# cloning, a call to the macs method will throw and NoMethodError
|
# cloning, a call to the macs method will throw and NoMethodError
|
||||||
attrs['mac_addresses'] = vm_mob_ref.macs rescue nil
|
attrs['mac_addresses'] = vm_mob_ref.macs rescue nil
|
||||||
attrs['path'] = get_folder_path(vm_mob_ref.parent)
|
# Rescue nil to catch testing while vm_mob_ref isn't reaL??
|
||||||
|
attrs['path'] = "/"+vm_mob_ref.parent.path.map(&:last).join('/') rescue nil
|
||||||
|
attrs['relative_path'] = (attrs['path'].split('/').reject {|e| e.empty?} - ["Datacenters", attrs['datacenter'], "vm"]).join("/") rescue nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,10 @@ module Fog
|
||||||
connection.folders({ :datacenter => name, :type => :vm }.merge(filters))
|
connection.folders({ :datacenter => name, :type => :vm }.merge(filters))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def virtual_machines filters = {}
|
||||||
|
connection.servers({ :datacenter => name }.merge(filters))
|
||||||
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,6 +31,7 @@ module Fog
|
||||||
attribute :connection_state
|
attribute :connection_state
|
||||||
attribute :mo_ref
|
attribute :mo_ref
|
||||||
attribute :path
|
attribute :path
|
||||||
|
attribute :relative_path
|
||||||
attribute :memory_mb
|
attribute :memory_mb
|
||||||
attribute :cpus
|
attribute :cpus
|
||||||
attribute :interfaces
|
attribute :interfaces
|
||||||
|
@ -93,16 +94,24 @@ module Fog
|
||||||
connection.vm_migrate('instance_uuid' => instance_uuid, 'priority' => options[:priority])
|
connection.vm_migrate('instance_uuid' => instance_uuid, 'priority' => options[:priority])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Clone from a server object
|
||||||
|
#
|
||||||
|
# ==== Parameters
|
||||||
|
# *<~Hash>:
|
||||||
|
# * 'name'<~String> - *REQUIRED* Name of the _new_ VirtualMachine
|
||||||
|
# * See more options in vm_clone request/compute/vm_clone.rb
|
||||||
|
#
|
||||||
def clone(options = {})
|
def clone(options = {})
|
||||||
requires :name, :datacenter
|
requires :name, :datacenter, :relative_path
|
||||||
# Convert symbols to strings
|
# Convert symbols to strings
|
||||||
req_options = options.inject({}) { |hsh, (k,v)| hsh[k.to_s] = v; hsh }
|
req_options = options.inject({}) { |hsh, (k,v)| hsh[k.to_s] = v; hsh }
|
||||||
# Give our path to the request
|
# Give our path to the request
|
||||||
req_options['path'] ="#{path}/#{name}"
|
req_options['template_path'] ="#{relative_path}/#{name}"
|
||||||
|
req_options['datacenter'] = "#{datacenter}"
|
||||||
# Perform the actual clone
|
# Perform the actual clone
|
||||||
clone_results = connection.vm_clone(req_options)
|
clone_results = connection.vm_clone(req_options)
|
||||||
# Create the new VM model.
|
# Create the new VM model. TODO This only works when "wait=true"
|
||||||
new_vm = self.class.new(clone_results['vm_attributes'])
|
new_vm = self.class.new(clone_results['new_vm'])
|
||||||
# We need to assign the collection and the connection otherwise we
|
# We need to assign the collection and the connection otherwise we
|
||||||
# cannot reload the model.
|
# cannot reload the model.
|
||||||
new_vm.collection = self.collection
|
new_vm.collection = self.collection
|
||||||
|
|
|
@ -51,7 +51,7 @@ module Fog
|
||||||
:parent => folder.parent.name,
|
:parent => folder.parent.name,
|
||||||
:datacenter => datacenter_name,
|
:datacenter => datacenter_name,
|
||||||
:type => folder_type(folder),
|
:type => folder_type(folder),
|
||||||
:path => folder.path.map(&:last).join('/'),
|
:path => "/"+folder.path.map(&:last).join('/'),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ module Fog
|
||||||
else
|
else
|
||||||
# try to find based on VM name
|
# try to find based on VM name
|
||||||
if dc
|
if dc
|
||||||
get_datacenter(dc).find_vm(id)
|
get_raw_datacenter(dc).find_vm(id)
|
||||||
else
|
else
|
||||||
raw_datacenters.map { |d| d.find_vm(id) }.compact.first
|
raw_datacenters.map { |d| d.find_vm(id) }.compact.first
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,19 +10,17 @@ module Fog
|
||||||
'linked_clone' => false,
|
'linked_clone' => false,
|
||||||
}
|
}
|
||||||
options = default_options.merge(options)
|
options = default_options.merge(options)
|
||||||
required_options = %w{ path name }
|
# Backwards compat for "path" option
|
||||||
|
options["template_path"] ||= options["path"]
|
||||||
|
options["path"] ||= options["template_path"]
|
||||||
|
required_options = %w{ datacenter template_path name }
|
||||||
required_options.each do |param|
|
required_options.each do |param|
|
||||||
raise ArgumentError, "#{required_options.join(', ')} are required" unless options.has_key? param
|
raise ArgumentError, "#{required_options.join(', ')} are required" unless options.has_key? param
|
||||||
end
|
end
|
||||||
# The tap removes the leading empty string
|
# TODO This is ugly and needs to rethink mocks
|
||||||
path_elements = options['path'].split('/').tap { |o| o.shift }
|
unless ENV['FOG_MOCK']
|
||||||
first_folder = path_elements.shift
|
raise ArgumentError, "#{options["datacenter"]} Doesn't Exist!" unless get_datacenter(options["datacenter"])
|
||||||
if first_folder != 'Datacenters' then
|
raise ArgumentError, "#{options["template_path"]} Doesn't Exist!" unless get_virtual_machine(options["template_path"], options["datacenter"])
|
||||||
raise ArgumentError, "vm_clone path option must start with /Datacenters. Got: #{options['path']}"
|
|
||||||
end
|
|
||||||
dc_name = path_elements.shift
|
|
||||||
if not datacenters.get dc_name then
|
|
||||||
raise ArgumentError, "Datacenter #{dc_name} does not exist, only datacenters #{datacenters.all.map(:name).join(",")} are accessible."
|
|
||||||
end
|
end
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
|
@ -36,22 +34,41 @@ module Fog
|
||||||
#
|
#
|
||||||
# ==== Parameters
|
# ==== Parameters
|
||||||
# * options<~Hash>:
|
# * options<~Hash>:
|
||||||
|
# * 'datacenter'<~String> - *REQUIRED* Datacenter name your cloning
|
||||||
|
# in. Make sure this datacenter exists, should if you're using
|
||||||
|
# the clone function in server.rb model.
|
||||||
# * 'template_path'<~String> - *REQUIRED* The path to the machine you
|
# * 'template_path'<~String> - *REQUIRED* The path to the machine you
|
||||||
# want to clone FROM. (Example:
|
# want to clone FROM. Relative to Datacenter (Example:
|
||||||
# "/Datacenter/DataCenterNameHere/FolderNameHere/VMNameHere")
|
# "FolderNameHere/VMNameHere")
|
||||||
# * 'name'<~String> - *REQUIRED* The VMName of the Destination
|
# * 'name'<~String> - *REQUIRED* The VMName of the Destination
|
||||||
# * 'resource_pool'<~String> - The resource pool on your datacenter
|
|
||||||
# cluster you want to use.
|
|
||||||
# * 'dest_folder'<~String> - Destination Folder of where 'name' will
|
# * 'dest_folder'<~String> - Destination Folder of where 'name' will
|
||||||
# be placed on your cluster. *NOT TESTED OR VALIDATED*
|
# be placed on your cluster. Relative Path to Datacenter E.G.
|
||||||
|
# "FolderPlaceHere/anotherSub Folder/onemore"
|
||||||
# * 'power_on'<~Boolean> - Whether to power on machine after clone.
|
# * 'power_on'<~Boolean> - Whether to power on machine after clone.
|
||||||
# Defaults to true.
|
# Defaults to true.
|
||||||
# * 'wait'<~Boolean> - Whether the method should wait for the virtual
|
# * 'wait'<~Boolean> - Whether the method should wait for the virtual
|
||||||
# machine to close finish cloning before returning information from
|
# machine to finish cloning before returning information from
|
||||||
# vSphere. Returns the value of the machine if it finishes cloning
|
# vSphere. Broken right now as you cannot return a model of a serer
|
||||||
# in 150 seconds (1m30s) else it returns nil. 'wait' Defaults to nil.
|
# that isn't finished cloning. Defaults to True
|
||||||
# Saves a little time.
|
# * 'resource_pool'<~Array> - The resource pool on your datacenter
|
||||||
|
# cluster you want to use. Only works with clusters within same
|
||||||
|
# same datacenter as where you're cloning from. Datacenter grabbed
|
||||||
|
# from template_path option.
|
||||||
|
# Example: ['cluster_name_here','resource_pool_name_here']
|
||||||
|
# * 'datastore'<~String> - The datastore you'd like to use.
|
||||||
|
# (datacenterObj.datastoreFolder.find('name') in API)
|
||||||
# * 'transform'<~String> - Not documented - see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html
|
# * 'transform'<~String> - Not documented - see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html
|
||||||
|
# * customization_spec<~Hash>: Options are marked as required if you
|
||||||
|
# use this customization_spec. Static IP Settings not configured.
|
||||||
|
# This only support cloning and setting DHCP on the first interface
|
||||||
|
# * 'domain'<~String> - *REQUIRED* This is put into
|
||||||
|
# /etc/resolve.conf (we hope)
|
||||||
|
# * 'hostname'<~String> - Hostname of the Guest Os - default is
|
||||||
|
# options['name']
|
||||||
|
# * 'hw_utc_clock'<~Boolean> - *REQUIRED* Is hardware clock UTC?
|
||||||
|
# Default true
|
||||||
|
# * 'time_zone'<~String> - *REQUIRED* Only valid linux options
|
||||||
|
# are valid - example: 'America/Denver'
|
||||||
#
|
#
|
||||||
def vm_clone(options = {})
|
def vm_clone(options = {})
|
||||||
# Option handling
|
# Option handling
|
||||||
|
@ -60,54 +77,100 @@ module Fog
|
||||||
# Added for people still using options['path']
|
# Added for people still using options['path']
|
||||||
template_path = options['path'] || options['template_path']
|
template_path = options['path'] || options['template_path']
|
||||||
|
|
||||||
notfound = lambda { raise Fog::Compute::Vsphere::NotFound, "Could not find VM template" }
|
# Default wait enabled
|
||||||
|
options['wait'] = true
|
||||||
# Find the template in the folder. This is more efficient than
|
|
||||||
# searching ALL VM's looking for the template.
|
|
||||||
# Tap gets rid of the leading empty string and "Datacenters" element
|
|
||||||
# and returns the array.
|
|
||||||
path_elements = template_path.split('/').tap { |ary| ary.shift 2 }
|
|
||||||
# The DC name itself.
|
|
||||||
template_dc = path_elements.shift
|
|
||||||
# If the first path element contains "vm" this denotes the vmFolder
|
|
||||||
# and needs to be shifted out
|
|
||||||
path_elements.shift if path_elements[0] == 'vm'
|
|
||||||
# The template name. The remaining elements are the folders in the
|
|
||||||
# datacenter.
|
|
||||||
template_name = path_elements.pop
|
|
||||||
|
|
||||||
dc = find_raw_datacenter(template_dc)
|
|
||||||
# Get the VM Folder (Group) efficiently
|
|
||||||
vm_folder = dc.vmFolder
|
|
||||||
# Walk the tree resetting the folder pointer as we go
|
|
||||||
folder = path_elements.inject(vm_folder) do |current_folder, sub_folder_name|
|
|
||||||
# JJM VIM::Folder#find appears to be quite efficient as it uses the
|
|
||||||
# searchIndex It certainly appears to be faster than
|
|
||||||
# VIM::Folder#inventory since that returns _all_ managed objects of
|
|
||||||
# a certain type _and_ their properties.
|
|
||||||
sub_folder = current_folder.find(sub_folder_name, RbVmomi::VIM::Folder)
|
|
||||||
raise ArgumentError, "Could not descend into #{sub_folder_name}. Please check your path." unless sub_folder
|
|
||||||
sub_folder
|
|
||||||
end
|
|
||||||
|
|
||||||
|
# Options['template_path']<~String>
|
||||||
|
# Added for people still using options['path']
|
||||||
|
template_path = options['path'] || options['template_path']
|
||||||
# Now find the template itself using the efficient find method
|
# Now find the template itself using the efficient find method
|
||||||
vm_mob_ref = folder.find(template_name, RbVmomi::VIM::VirtualMachine)
|
vm_mob_ref = get_vm_ref(template_path, options['datacenter'])
|
||||||
|
|
||||||
|
# Options['dest_folder']<~String>
|
||||||
|
# Grab the destination folder object if it exists else use cloned mach
|
||||||
|
dest_folder = get_raw_vmfolder(options['dest_folder'], options['datacenter']) if options.has_key?('dest_folder')
|
||||||
|
dest_folder ||= vm_mob_ref.parent
|
||||||
|
|
||||||
|
# Options['resource_pool']<~Array>
|
||||||
# Now find _a_ resource pool to use for the clone if one is not specified
|
# Now find _a_ resource pool to use for the clone if one is not specified
|
||||||
if ( options.has_key?('resource_pool') )
|
if ( options.has_key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 )
|
||||||
resource_pool = options['resource_pool']
|
cluster_name = options['resource_pool'][0]
|
||||||
|
pool_name = options['resource_pool'][1]
|
||||||
|
resource_pool = get_raw_resource_pool(pool_name, cluster_name, options['datacenter'])
|
||||||
elsif ( vm_mob_ref.resourcePool == nil )
|
elsif ( vm_mob_ref.resourcePool == nil )
|
||||||
# If the template is really a template then there is no associated resource pool,
|
# If the template is really a template then there is no associated resource pool,
|
||||||
# so we need to find one using the template's parent host or cluster
|
# so we need to find one using the template's parent host or cluster
|
||||||
esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host']
|
esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host']
|
||||||
# The parent of the ESX host itself is a ComputeResource which has a resourcePool
|
# The parent of the ESX host itself is a ComputeResource which has a resourcePool
|
||||||
resource_pool = esx_host.parent.resourcePool
|
resource_pool = esx_host.parent.resourcePool
|
||||||
else
|
|
||||||
# If the vm given did return a valid resource pool, default to using it for the clone.
|
|
||||||
# Even if specific pools aren't implemented in this environment, we will still get back
|
|
||||||
# at least the cluster or host we can pass on to the clone task
|
|
||||||
resource_pool = vm_mob_ref.resourcePool
|
|
||||||
end
|
end
|
||||||
|
# If the vm given did return a valid resource pool, default to using it for the clone.
|
||||||
|
# Even if specific pools aren't implemented in this environment, we will still get back
|
||||||
|
# at least the cluster or host we can pass on to the clone task
|
||||||
|
# This catches if resource_pool option is set but comes back nil and if resourcePool is
|
||||||
|
# already set.
|
||||||
|
resource_pool ||= vm_mob_ref.resourcePool.nil? ? esx_host.parent.resourcePool : vm_mob_ref.resourcePool
|
||||||
|
|
||||||
|
# Options['datastore']<~String>
|
||||||
|
# Grab the datastore object if option is set
|
||||||
|
datastore_obj = get_raw_datastore(options['datastore'], options['datacenter']) if options.has_key?('datastore')
|
||||||
|
# confirm nil if nil or option is not set
|
||||||
|
datastore_obj ||= nil
|
||||||
|
|
||||||
|
# Options['network']
|
||||||
|
# Build up the config spec
|
||||||
|
if ( options.has_key?('network_label') )
|
||||||
|
#network_obj = datacenter_obj.networkFolder.find(options['network_label'])
|
||||||
|
config_spec_operation = RbVmomi::VIM::VirtualDeviceConfigSpecOperation('edit')
|
||||||
|
nic_backing_info = RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(:deviceName => options['network_label'])
|
||||||
|
#:deviceName => "Network adapter 1",
|
||||||
|
#:network => network_obj)
|
||||||
|
connectable = RbVmomi::VIM::VirtualDeviceConnectInfo(
|
||||||
|
:allowGuestControl => true,
|
||||||
|
:connected => true,
|
||||||
|
:startConnected => true)
|
||||||
|
device = RbVmomi::VIM::VirtualE1000(
|
||||||
|
:backing => nic_backing_info,
|
||||||
|
:deviceInfo => RbVmomi::VIM::Description(:label => "Network adapter 1", :summary => options['network_label']),
|
||||||
|
:key => options['network_adapter_device_key'],
|
||||||
|
:connectable => connectable)
|
||||||
|
device_spec = RbVmomi::VIM::VirtualDeviceConfigSpec(
|
||||||
|
:operation => config_spec_operation,
|
||||||
|
:device => device)
|
||||||
|
virtual_machine_config_spec = RbVmomi::VIM::VirtualMachineConfigSpec(
|
||||||
|
:deviceChange => [device_spec])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Options['customization_spec']
|
||||||
|
# Build up all the crappy tiered objects like the perl method
|
||||||
|
# Collect your variables ifset (writing at 11pm revist me)
|
||||||
|
if ( options.has_key?('customization_spec') )
|
||||||
|
cust_options = options['customization_spec']
|
||||||
|
cust_domain = cust_options['domain']
|
||||||
|
cust_hostname = RbVmomi::VIM::CustomizationFixedName.new(:name => cust_options['hostname']) if cust_options.has_key?('hostname')
|
||||||
|
cust_hostname ||= RbVmomi::VIM::CustomizationFixedName.new(:name => options['name'])
|
||||||
|
cust_hwclockutc = cust_options['hw_clock_utc']
|
||||||
|
cust_timezone = cust_options['time_zone']
|
||||||
|
# Start Building objects
|
||||||
|
# Build the CustomizationLinuxPrep Object
|
||||||
|
cust_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
|
||||||
|
:domain => cust_domain,
|
||||||
|
:hostName => cust_hostname,
|
||||||
|
:hwClockUTC => cust_hwclockutc,
|
||||||
|
:timeZone => cust_timezone)
|
||||||
|
# Build the Dhcp Generator Object
|
||||||
|
cust_fixed_ip = RbVmomi::VIM::CustomizationDhcpIpGenerator.new()
|
||||||
|
# Build the custom_ip_settings Object
|
||||||
|
cust_ip_setting = RbVmomi::VIM::CustomizationIPSettings.new(:ip => cust_fixed_ip)
|
||||||
|
# Build the Custom Adapter Mapping Supports only one eth right now
|
||||||
|
cust_adapter_mapping = [RbVmomi::VIM::CustomizationAdapterMapping.new(:adapter => cust_ip_setting)]
|
||||||
|
# Build the customization Spec
|
||||||
|
customization_spec = RbVmomi::VIM::CustomizationSpec.new(
|
||||||
|
:identity => cust_prep,
|
||||||
|
:globalIPSettings => RbVmomi::VIM::CustomizationGlobalIPSettings.new(),
|
||||||
|
:nicSettingMap => cust_adapter_mapping)
|
||||||
|
end
|
||||||
|
customization_spec ||= nil
|
||||||
|
|
||||||
relocation_spec=nil
|
relocation_spec=nil
|
||||||
if ( options['linked_clone'] )
|
if ( options['linked_clone'] )
|
||||||
|
@ -139,17 +202,23 @@ module Fog
|
||||||
vm_mob_ref.ReconfigVM_Task(:spec => disk_spec).wait_for_completion
|
vm_mob_ref.ReconfigVM_Task(:spec => disk_spec).wait_for_completion
|
||||||
end
|
end
|
||||||
# Next, create a Relocation Spec instance
|
# Next, create a Relocation Spec instance
|
||||||
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool,
|
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => datastore_obj,
|
||||||
|
:pool => resource_pool,
|
||||||
:diskMoveType => :moveChildMostDiskBacking)
|
:diskMoveType => :moveChildMostDiskBacking)
|
||||||
else
|
else
|
||||||
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool,
|
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => datastore_obj,
|
||||||
|
:pool => resource_pool,
|
||||||
:transform => options['transform'] || 'sparse')
|
:transform => options['transform'] || 'sparse')
|
||||||
end
|
end
|
||||||
# And the clone specification
|
# And the clone specification
|
||||||
clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec,
|
clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec,
|
||||||
|
:config => virtual_machine_config_spec,
|
||||||
|
:customization => customization_spec,
|
||||||
:powerOn => options.has_key?('power_on') ? options['power_on'] : true,
|
:powerOn => options.has_key?('power_on') ? options['power_on'] : true,
|
||||||
:template => false)
|
:template => false)
|
||||||
task = vm_mob_ref.CloneVM_Task(:folder => options.has_key?('dest_folder') ? options['dest_folder'] : vm_mob_ref.parent,
|
|
||||||
|
# Perform the actual Clone Task
|
||||||
|
task = vm_mob_ref.CloneVM_Task(:folder => dest_folder,
|
||||||
:name => options['name'],
|
:name => options['name'],
|
||||||
:spec => clone_spec)
|
:spec => clone_spec)
|
||||||
# Waiting for the VM to complete allows us to get the VirtulMachine
|
# Waiting for the VM to complete allows us to get the VirtulMachine
|
||||||
|
@ -180,7 +249,7 @@ module Fog
|
||||||
# Return hash
|
# Return hash
|
||||||
{
|
{
|
||||||
'vm_ref' => new_vm ? new_vm._ref : nil,
|
'vm_ref' => new_vm ? new_vm._ref : nil,
|
||||||
'vm_attributes' => new_vm ? convert_vm_mob_ref_to_attr_hash(new_vm) : {},
|
'new_vm' => new_vm ? get_virtual_machine("#{options['dest_folder']}/#{options['name']}", options['datacenter']) : nil,
|
||||||
'task_ref' => task._ref
|
'task_ref' => task._ref
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -190,11 +259,11 @@ module Fog
|
||||||
class Mock
|
class Mock
|
||||||
include Shared
|
include Shared
|
||||||
def vm_clone(options = {})
|
def vm_clone(options = {})
|
||||||
# Option handling
|
# Option handling TODO Needs better method of checking
|
||||||
options = vm_clone_check_options(options)
|
options = vm_clone_check_options(options)
|
||||||
notfound = lambda { raise Fog::Compute::Vsphere::NotFound, "Could not find VM template" }
|
notfound = lambda { raise Fog::Compute::Vsphere::NotFound, "Could not find VM template" }
|
||||||
list_virtual_machines.find(notfound) do |vm|
|
list_virtual_machines.find(notfound) do |vm|
|
||||||
vm[:name] == options['path'].split("/")[-1]
|
vm[:name] == options['template_path'].split("/")[-1]
|
||||||
end
|
end
|
||||||
{
|
{
|
||||||
'vm_ref' => 'vm-123',
|
'vm_ref' => 'vm-123',
|
||||||
|
|
|
@ -15,7 +15,7 @@ Shindo.tests('Fog::Rackspace::BlockStorage | snapshot', ['rackspace']) do
|
||||||
model_tests(service.snapshots, options, false) do
|
model_tests(service.snapshots, options, false) do
|
||||||
@instance.wait_for { ready? }
|
@instance.wait_for { ready? }
|
||||||
|
|
||||||
tests('double save').returns(true) do
|
tests('double save').raises(Fog::Rackspace::BlockStorage::IdentifierTaken) do
|
||||||
@instance.save
|
@instance.save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ Shindo.tests('Fog::Rackspace::BlockStorage | volume', ['rackspace']) do
|
||||||
model_tests(service.volumes, options, false) do
|
model_tests(service.volumes, options, false) do
|
||||||
@instance.wait_for(timeout=1200) { ready? }
|
@instance.wait_for(timeout=1200) { ready? }
|
||||||
|
|
||||||
tests('double save').returns(true) do
|
tests('double save').raises(Fog::Rackspace::BlockStorage::IdentifierTaken) do
|
||||||
@instance.save
|
@instance.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ Shindo.tests('Fog::Rackspace::BlockStorage | volume', ['rackspace']) do
|
||||||
|
|
||||||
tests('#snapshots').succeeds do
|
tests('#snapshots').succeeds do
|
||||||
begin
|
begin
|
||||||
snapshot = service.snapshots.create({ :volume_id => @instance.id })
|
snapshot = @instance.create_snapshot
|
||||||
snapshot.wait_for(timeout = 1200) { ready? }
|
snapshot.wait_for(timeout=1200) { ready? }
|
||||||
|
|
||||||
returns(true) { @instance.snapshots.first.id == snapshot.id }
|
returns(true) { @instance.snapshots.first.id == snapshot.id }
|
||||||
ensure
|
ensure
|
||||||
|
|
|
@ -4,18 +4,20 @@ Shindo.tests("Fog::Compute[:vsphere] | vm_clone request", 'vsphere') do
|
||||||
response = nil
|
response = nil
|
||||||
response_linked = nil
|
response_linked = nil
|
||||||
|
|
||||||
template = "/Datacenters/Solutions/vm/rhel64"
|
template = "folder/rhel64"
|
||||||
|
datacenter = "Solutions"
|
||||||
tests("Standard Clone | The return value should") do
|
tests("Standard Clone | The return value should") do
|
||||||
response = compute.vm_clone('path' => template, 'name' => 'cloning_vm', 'wait' => 1)
|
response = compute.vm_clone('datacenter' => datacenter, 'template_path' => template, 'name' => 'cloning_vm', 'wait' => true)
|
||||||
test("be a kind of Hash") { response.kind_of? Hash }
|
test("be a kind of Hash") { response.kind_of? Hash }
|
||||||
%w{ vm_ref task_ref }.each do |key|
|
%w{ vm_ref task_ref }.each do |key|
|
||||||
test("have a #{key} key") { response.has_key? key }
|
test("have a #{key} key") { response.has_key? key }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
template = "/Datacenters/Solutions/vm/rhel64"
|
template = "folder/rhel64"
|
||||||
|
datacenter = "Solutions"
|
||||||
tests("Linked Clone | The return value should") do
|
tests("Linked Clone | The return value should") do
|
||||||
response = compute.vm_clone('path' => template, 'name' => 'cloning_vm_linked', 'wait' => 1, 'linked_clone' => true)
|
response = compute.vm_clone('datacenter' => datacenter, 'template_path' => template, 'name' => 'cloning_vm_linked', 'wait' => 1, 'linked_clone' => true)
|
||||||
test("be a kind of Hash") { response.kind_of? Hash }
|
test("be a kind of Hash") { response.kind_of? Hash }
|
||||||
%w{ vm_ref task_ref }.each do |key|
|
%w{ vm_ref task_ref }.each do |key|
|
||||||
test("have a #{key} key") { response.has_key? key }
|
test("have a #{key} key") { response.has_key? key }
|
||||||
|
|
Loading…
Add table
Reference in a new issue