2011-09-06 19:46:42 -04:00
|
|
|
module Fog
|
|
|
|
module Compute
|
|
|
|
class Vsphere
|
|
|
|
class Real
|
|
|
|
|
|
|
|
def vm_clone(params = {})
|
2011-09-06 23:09:57 -04:00
|
|
|
params = { :force => false }.merge(params)
|
|
|
|
required_params = %w{ instance_uuid name }
|
|
|
|
required_params.each do |param|
|
|
|
|
raise ArgumentError, "#{required_params.join(', ')} are required" unless params.has_key? param.to_sym
|
|
|
|
end
|
|
|
|
# First, figure out if there's already a VM of the same name.
|
|
|
|
if not params[:force] and list_virtual_machines.detect { |vm| vm.name == params[:name] } then
|
|
|
|
raise Fog::Vsphere::Errors::ServiceError, "A VM already exists with name #{params[:name]}"
|
|
|
|
end
|
|
|
|
# Find the Managed Object reference of the template VM
|
2011-09-06 19:46:42 -04:00
|
|
|
vm = find_template_by_instance_uuid(params[:instance_uuid])
|
|
|
|
# We need to locate the datacenter object to find the
|
|
|
|
# default resource pool.
|
|
|
|
container = vm.parent
|
|
|
|
until container.kind_of? RbVmomi::VIM::Datacenter
|
|
|
|
container = container.parent
|
|
|
|
end
|
|
|
|
dc = container
|
|
|
|
# With the Datacenter Object we can obtain the resource pool
|
|
|
|
resource_pool = dc.hostFolder.children.first.resourcePool
|
|
|
|
# Next, create a Relocation Spec instance
|
|
|
|
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool,
|
|
|
|
:transform => 'sparse')
|
|
|
|
# And the clone specification
|
|
|
|
clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec,
|
|
|
|
:powerOn => true,
|
|
|
|
:template => false)
|
|
|
|
task = vm.CloneVM_Task(:folder => vm.parent, :name => params[:name], :spec => clone_spec)
|
2011-09-06 23:09:57 -04:00
|
|
|
# REVISIT: The task object contains a reference to the template but does
|
|
|
|
# not appear to contain a reference to the newly created VM.
|
|
|
|
# This is a really naive way to find the managed object reference
|
|
|
|
# of the newly created VM.
|
|
|
|
tries = 0
|
|
|
|
new_vm = begin
|
|
|
|
list_virtual_machines.detect(lambda { raise Fog::Vsphere::Errors::NotFound }) do |vm|
|
|
|
|
next false if vm.name != params[:name]
|
|
|
|
begin
|
|
|
|
vm.config ? true : false
|
|
|
|
rescue RuntimeError
|
|
|
|
# This rescue is here because we want to make sure we find
|
|
|
|
# a VM _without_ a config, which indicates the VM is still cloning.
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
rescue Fog::Vsphere::Errors::NotFound
|
|
|
|
tries += 1
|
|
|
|
if tries <= 10 then
|
|
|
|
sleep 2
|
|
|
|
retry
|
|
|
|
end
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
# Taking a hint from wait_for we return a hash to indicate this is a
|
|
|
|
# managed object reference
|
|
|
|
{
|
|
|
|
:vm_ref => new_vm ? new_vm._ref : nil,
|
|
|
|
:task_ref => task._ref
|
|
|
|
}
|
2011-09-06 19:46:42 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
class Mock
|
|
|
|
|
|
|
|
def vm_clone(params = {})
|
2011-09-06 23:09:57 -04:00
|
|
|
{
|
|
|
|
:vm_ref => 'vm-123',
|
|
|
|
:task_ref => 'task-1234'
|
|
|
|
}
|
2011-09-06 19:46:42 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|