def vm_clone(options = {})
options = vm_clone_check_options(options)
template_path = options['path'] || options['template_path']
options['wait'] = true
template_path = options['path'] || options['template_path']
vm_mob_ref = get_vm_ref(template_path, options['datacenter'])
dest_folder = get_raw_vmfolder(options['dest_folder'], options['datacenter']) if options.has_key?('dest_folder')
dest_folder ||= vm_mob_ref.parent
if ( options.has_key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 )
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 )
esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host']
resource_pool = esx_host.parent.resourcePool
end
resource_pool ||= vm_mob_ref.resourcePool.nil? ? esx_host.parent.resourcePool : vm_mob_ref.resourcePool
datastore_obj = get_raw_datastore(options['datastore'], options['datacenter']) if options.has_key?('datastore')
datastore_obj ||= nil
if ( options.has_key?('network_label') )
config_spec_operation = RbVmomi::VIM::VirtualDeviceConfigSpecOperation('edit')
nic_backing_info = RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(:deviceName => options['network_label'])
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
if ( options.has_key?('customization_spec') )
cust_options = options['customization_spec']
if cust_options.has_key?("ipsettings")
raise ArgumentError, "ip and subnetMask is required for static ip" unless cust_options["ipsettings"].has_key?("ip") and
cust_options["ipsettings"].has_key?("subnetMask")
end
raise ArgumentError, "domain is required" unless cust_options.has_key?("domain")
cust_domain = cust_options['domain']
cust_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(cust_options["ipsettings"]) if cust_options.has_key?("ipsettings")
cust_ip_settings.ip = RbVmomi::VIM::CustomizationFixedIp("ipAddress" => cust_options["ipsettings"]["ip"]) if cust_options.has_key?("ipsettings")
cust_ip_settings ||= RbVmomi::VIM::CustomizationIPSettings.new("ip" => RbVmomi::VIM::CustomizationDhcpIpGenerator.new())
cust_ip_settings.dnsDomain = cust_domain
cust_global_ip_settings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
cust_global_ip_settings.dnsServerList = cust_ip_settings.dnsServerList
cust_global_ip_settings.dnsSuffixList = [cust_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']
cust_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
:domain => cust_domain,
:hostName => cust_hostname,
:hwClockUTC => cust_hwclockutc,
:timeZone => cust_timezone)
cust_adapter_mapping = [RbVmomi::VIM::CustomizationAdapterMapping.new("adapter" => cust_ip_settings)]
customization_spec = RbVmomi::VIM::CustomizationSpec.new(
:identity => cust_prep,
:globalIPSettings => cust_global_ip_settings,
:nicSettingMap => cust_adapter_mapping)
end
customization_spec ||= nil
relocation_spec=nil
if ( options['linked_clone'] )
disks = vm_mob_ref.config.hardware.device.select do |vm_device|
vm_device.class == RbVmomi::VIM::VirtualDisk
end
disks.select{|vm_device| vm_device.backing.parent == nil}.each do |disk|
disk_spec = {
:deviceChange => [
{
:operation => :remove,
:device => disk
},
{
:operation => :add,
:fileOperation => :create,
:device => disk.dup.tap{|disk_backing|
disk_backing.backing = disk_backing.backing.dup;
disk_backing.backing.fileName = "[#{disk.backing.datastore.name}]";
disk_backing.backing.parent = disk.backing
}
},
]
}
vm_mob_ref.ReconfigVM_Task(:spec => disk_spec).wait_for_completion
end
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => datastore_obj,
:pool => resource_pool,
:diskMoveType => :moveChildMostDiskBacking)
else
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => datastore_obj,
:pool => resource_pool,
:transform => options['transform'] || 'sparse')
end
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,
:template => false)
task = vm_mob_ref.CloneVM_Task(:folder => dest_folder,
:name => options['name'],
:spec => clone_spec)
if options['wait'] then
new_vm = task.wait_for_completion
else
tries = 0
new_vm = begin
folder.find(options['name'], RbVmomi::VIM::VirtualMachine) or raise Fog::Vsphere::Errors::NotFound
rescue Fog::Vsphere::Errors::NotFound
tries += 1
if tries <= 10 then
sleep 15
retry
end
nil
end
end
{
'vm_ref' => new_vm ? new_vm._ref : nil,
'new_vm' => new_vm ? get_virtual_machine("#{options['dest_folder']}/#{options['name']}", options['datacenter']) : nil,
'task_ref' => task._ref
}
end