fog-vsphere 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -4
  3. data/CHANGELOG.md +8 -0
  4. data/CONTRIBUTORS.md +6 -0
  5. data/fog-vsphere.gemspec +1 -1
  6. data/lib/fog/vsphere/compute.rb +47 -3
  7. data/lib/fog/vsphere/models/compute/cdrom.rb +65 -0
  8. data/lib/fog/vsphere/models/compute/cdroms.rb +18 -0
  9. data/lib/fog/vsphere/models/compute/datacenter.rb +4 -0
  10. data/lib/fog/vsphere/models/compute/folder.rb +4 -0
  11. data/lib/fog/vsphere/models/compute/server.rb +8 -0
  12. data/lib/fog/vsphere/models/compute/storage_pod.rb +19 -0
  13. data/lib/fog/vsphere/models/compute/storage_pods.rb +22 -0
  14. data/lib/fog/vsphere/models/compute/volume.rb +1 -0
  15. data/lib/fog/vsphere/requests/compute/create_folder.rb +10 -0
  16. data/lib/fog/vsphere/requests/compute/create_vm.rb +163 -4
  17. data/lib/fog/vsphere/requests/compute/folder_destroy.rb +26 -0
  18. data/lib/fog/vsphere/requests/compute/get_folder.rb +4 -2
  19. data/lib/fog/vsphere/requests/compute/get_storage_pod.rb +31 -0
  20. data/lib/fog/vsphere/requests/compute/list_datacenters.rb +1 -1
  21. data/lib/fog/vsphere/requests/compute/list_datastores.rb +2 -1
  22. data/lib/fog/vsphere/requests/compute/list_networks.rb +2 -1
  23. data/lib/fog/vsphere/requests/compute/list_storage_pods.rb +45 -0
  24. data/lib/fog/vsphere/requests/compute/list_virtual_machines.rb +8 -4
  25. data/lib/fog/vsphere/requests/compute/list_vm_cdroms.rb +30 -0
  26. data/lib/fog/vsphere/requests/compute/list_vm_interfaces.rb +34 -13
  27. data/lib/fog/vsphere/requests/compute/list_vm_snapshots.rb +5 -1
  28. data/lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb +25 -0
  29. data/lib/fog/vsphere/requests/compute/modify_vm_interface.rb +19 -2
  30. data/lib/fog/vsphere/requests/compute/modify_vm_volume.rb +1 -1
  31. data/lib/fog/vsphere/requests/compute/upload_iso.rb +34 -0
  32. data/lib/fog/vsphere/requests/compute/vm_clone.rb +68 -25
  33. data/lib/fog/vsphere/requests/compute/vm_reconfig_cdrom.rb +68 -0
  34. data/lib/fog/vsphere/version.rb +1 -1
  35. data/tests/models/compute/servers_tests.rb +1 -1
  36. data/tests/requests/compute/folder_destroy_tests.rb +21 -0
  37. data/tests/requests/compute/list_storage_pods_test.rb +10 -0
  38. data/tests/requests/compute/list_vm_cdroms_tests.rb +10 -0
  39. data/tests/requests/compute/modify_vm_cdrom_tests.rb +21 -0
  40. data/tests/requests/compute/vm_reconfig_cdrom_tests.rb +15 -0
  41. metadata +28 -6
@@ -0,0 +1,26 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def folder_destroy(path, datacenter_name)
6
+ folder = get_raw_vmfolder(path, datacenter_name)
7
+ raise Fog::Vsphere::Errors::NotFound, "No such folder #{path}" unless folder
8
+ raise Fog::Vsphere::Errors::ServiceError, "Folder #{path} is not empty" if folder.childEntity.size > 0
9
+
10
+ task = folder.Destroy_Task
11
+ task.wait_for_completion
12
+ { 'task_state' => task.info.state }
13
+ end
14
+ end
15
+ class Mock
16
+ def folder_destroy(path, datacenter_name)
17
+ vms = list_virtual_machines(folder: path, datacenter: datacenter_name)
18
+ if vms.length > 0
19
+ raise Fog::Vsphere::Errors::ServiceError, "Folder #{path} is not empty"
20
+ end
21
+ { 'task_state' => 'success' }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -41,7 +41,7 @@ module Fog
41
41
  # VIM::Folder#inventory since that returns _all_ managed objects of
42
42
  # a certain type _and_ their properties.
43
43
  sub = last_returned_folder.find(sub_folder, RbVmomi::VIM::Folder)
44
- raise ArgumentError, "Could not descend into #{sub_folder}. Please check your path. #{path}" unless sub
44
+ raise Fog::Compute::Vsphere::NotFound, "Could not descend into #{sub_folder}. Please check your path. #{path}" unless sub
45
45
  sub
46
46
  end
47
47
  end
@@ -66,7 +66,9 @@ module Fog
66
66
  end
67
67
 
68
68
  class Mock
69
- def get_folder(path, filters = { })
69
+ def get_folder(path, datacenter_name, type = nil)
70
+ self.data[:folders].values.find {|f| f['datacenter'] == datacenter_name and f['path'].end_with? path} or
71
+ raise Fog::Compute::Vsphere::NotFound
70
72
  end
71
73
  end
72
74
  end
@@ -0,0 +1,31 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def get_storage_pod(name, datacenter_name)
6
+ storage_pod = get_raw_storage_pod(name, datacenter_name)
7
+ raise(Fog::Compute::Vsphere::NotFound) unless storage_pod
8
+ storage_pod_attributes(storage_pod, datacenter_name)
9
+ end
10
+
11
+ protected
12
+
13
+ def get_raw_storage_pod(name, datacenter_name)
14
+ dc = find_raw_datacenter(datacenter_name)
15
+
16
+ @connection.serviceContent.viewManager.CreateContainerView({
17
+ :container => dc,
18
+ :type => ["StoragePod"],
19
+ :recursive => true
20
+ }).view.select{|pod| pod.name == name}.first
21
+ end
22
+ end
23
+
24
+ class Mock
25
+ def get_storage_pod(name, datacenter_name)
26
+ list_storage_pods({datacenter: datacenter_name}).select{|h| h[:name] == name }.first
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -45,7 +45,7 @@ module Fog
45
45
 
46
46
  class Mock
47
47
  def list_datacenters filters = {}
48
- [ {:name => "Solutions", :status => "grey"}, {:name => "Solutions2", :status => "green" }]
48
+ self.data[:datacenters].values
49
49
  end
50
50
  end
51
51
  end
@@ -32,7 +32,8 @@ module Fog
32
32
  end
33
33
  class Mock
34
34
  def list_datastores(datacenter_name)
35
- []
35
+ self.data[:datastores].values.select {|d| d['datacenter'] == datacenter_name[:datacenter]} or
36
+ raise Fog::Compute::Vsphere::NotFound
36
37
  end
37
38
  end
38
39
  end
@@ -30,7 +30,8 @@ module Fog
30
30
  end
31
31
  class Mock
32
32
  def list_networks(datacenter_name)
33
- []
33
+ self.data[:networks].values.select {|n| n['datacenter'] == datacenter_name[:datacenter]} or
34
+ raise Fog::Compute::Vsphere::NotFound
34
35
  end
35
36
  end
36
37
  end
@@ -0,0 +1,45 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def list_storage_pods(filters = { })
6
+ datacenter_name = filters[:datacenter]
7
+ raw_storage_pods(datacenter_name).map do |storage_pod|
8
+ storage_pod_attributes(storage_pod, datacenter_name)
9
+ end.compact
10
+ end
11
+
12
+ private
13
+ def raw_storage_pods(datacenter_name)
14
+ dc = find_raw_datacenter(datacenter_name)
15
+
16
+ @connection.serviceContent.viewManager.CreateContainerView({
17
+ :container => dc,
18
+ :type => ["StoragePod"],
19
+ :recursive => true
20
+ }).view
21
+ end
22
+ protected
23
+
24
+ def storage_pod_attributes storage_pod, datacenter
25
+ {
26
+ :id => managed_obj_id(storage_pod),
27
+ :name => storage_pod.name,
28
+ :freespace => storage_pod.summary.freeSpace,
29
+ :capacity => storage_pod.summary.capacity,
30
+ :datacenter => datacenter,
31
+ }
32
+ end
33
+ end
34
+ class Mock
35
+ def list_storage_pods(filters = {})
36
+ if filters.key?(:datacenter)
37
+ self.data[:storage_pods].select{|h| h[:datacenter] == filters[:datacenter] }
38
+ else
39
+ self.data[:storage_pods]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -65,13 +65,17 @@ module Fog
65
65
  end
66
66
 
67
67
  def list_virtual_machines(options = { })
68
- if options['instance_uuid'].nil? and options['mo_ref'].nil?
69
- self.data[:servers].values
70
- elsif !options['instance_uuid'].nil?
68
+ if options['instance_uuid']
71
69
  server = self.data[:servers][options['instance_uuid']]
72
70
  server.nil? ? [] : [server]
73
- else
71
+ elsif options['mo_ref']
74
72
  self.data[:servers].values.select{|vm| vm['mo_ref'] == options['mo_ref']}
73
+ elsif options[:folder] and options[:datacenter]
74
+ self.data[:servers].values.select {|vm| vm['path'] == options[:folder] && vm['datacenter'] == options[:datacenter]}
75
+ else
76
+ options.delete('datacenter') # real code iterates if this is missing
77
+ options.reject! {|k,v| v.nil? } # ignore options with nil value
78
+ self.data[:servers].values.select {|vm| options.all? {|k,v| vm[k.to_s] == v.to_s }}
75
79
  end
76
80
  end
77
81
  end
@@ -0,0 +1,30 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def list_vm_cdroms(vm_id)
6
+ get_vm_ref(vm_id).config.hardware.device.select { |hw| hw.class == RbVmomi::VIM::VirtualCdrom }.map do |cdrom|
7
+ {
8
+ :filename => (cdrom.backing.fileName rescue(nil)),
9
+ :name => cdrom.deviceInfo.label,
10
+ :key => cdrom.key,
11
+ :controller_key => cdrom.controllerKey,
12
+ :unit_number => cdrom.unitNumber,
13
+ :start_connected => cdrom.connectable.startConnected,
14
+ :allow_guest_control => cdrom.connectable.allowGuestControl,
15
+ :connected => cdrom.connectable.connected,
16
+ :instance_uuid => vm_id,
17
+ }
18
+ end
19
+ end
20
+ end
21
+ class Mock
22
+ def list_vm_cdroms(vm_id)
23
+ raise Fog::Compute::Vsphere::NotFound, 'VM not Found' unless self.data[:servers].key?(vm_id)
24
+ return [] unless self.data[:servers][vm_id].key?('cdroms')
25
+ self.data[:servers][vm_id]['cdroms'].map {|h| h.merge({:instance_uuid => vm_id}) }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -29,31 +29,52 @@ module Fog
29
29
  #unitNumber: 7,
30
30
  #
31
31
  def list_vm_interfaces(vm_id, datacenter = nil)
32
- get_vm_ref(vm_id, datacenter).config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).map do |nic|
33
- {
34
- :name => nic.deviceInfo.label,
35
- :mac => nic.macAddress,
36
- :network => nic.backing.respond_to?("network") ? nic.backing.network.name : nic.backing.port.portgroupKey,
37
- :status => nic.connectable.status,
38
- :summary => nic.deviceInfo.summary,
39
- :type => nic.class,
40
- :key => nic.key,
41
- }
42
- end
32
+ get_raw_interfaces(vm_id, datacenter).map {|nic| raw_to_hash nic}
43
33
  end
44
34
 
45
35
  def get_vm_interface(vm_id, options={})
36
+ raw = get_raw_interface(vm_id, options)
37
+ if raw
38
+ raw_to_hash(raw)
39
+ else
40
+ nil
41
+ end
42
+ end
43
+
44
+ def get_raw_interfaces(vm_id, datacenter = nil)
45
+ get_vm_ref(vm_id, datacenter).config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
46
+ end
47
+
48
+ def get_raw_interface(vm_id, options={})
46
49
  raise ArgumentError, "instance id is a required parameter" unless vm_id
47
50
  if options.is_a? Fog::Compute::Vsphere::Interface
48
51
  options
49
52
  else
50
53
  raise ArgumentError, "Either key or name is a required parameter. options: #{options}" unless options.key? :key or options.key? :mac or options.key? :name
51
- list_vm_interfaces(vm_id).find do | nic |
52
- (options.key? :key and nic[:key]==options[:key].to_i) or (options.key? :mac and nic[:mac]==options[:mac]) or (options.key? :name and nic[:name]==options[:name])
54
+ get_raw_interfaces(vm_id).find do |nic|
55
+ (options.key? :key and nic.key==options[:key].to_i) or
56
+ (options.key? :mac and nic.macAddress==options[:mac]) or
57
+ (options.key? :name and nic.deviceInfo.label==options[:name])
53
58
  end
54
59
  end
55
60
  end
61
+
62
+ private
63
+
64
+ def raw_to_hash(nic)
65
+ {
66
+ :name => nic.deviceInfo.label,
67
+ :mac => nic.macAddress,
68
+ :network => nic.backing.respond_to?("network") ? nic.backing.network.name : nic.backing.port.portgroupKey,
69
+ :status => nic.connectable.status,
70
+ :summary => nic.deviceInfo.summary,
71
+ :type => nic.class,
72
+ :key => nic.key,
73
+ }
74
+ end
75
+
56
76
  end
77
+
57
78
  class Mock
58
79
  def list_vm_interfaces(vm_id)
59
80
  end
@@ -3,7 +3,11 @@ module Fog
3
3
  class Vsphere
4
4
  class Real
5
5
  def list_vm_snapshots(vm_id, opts = {})
6
- root_snapshots = get_vm_ref(vm_id).snapshot.rootSnapshotList.map do |snap|
6
+ vm_snapshot_info = get_vm_ref(vm_id).snapshot
7
+
8
+ return [] unless vm_snapshot_info
9
+
10
+ root_snapshots = vm_snapshot_info.rootSnapshotList.map do |snap|
7
11
  item = snapshot_info(snap, vm_id)
8
12
  [
9
13
  item,
@@ -0,0 +1,25 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def add_vm_cdrom(cdrom)
6
+ vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :add)]})
7
+ end
8
+
9
+ def destroy_vm_cdrom(cdrom)
10
+ vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :remove)]})
11
+ end
12
+ end
13
+
14
+ class Mock
15
+ def add_vm_cdrom(cdrom)
16
+ vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :add)]})
17
+ end
18
+
19
+ def destroy_vm_cdrom(cdrom)
20
+ vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :remove)]})
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -19,11 +19,22 @@ module Fog
19
19
  def update_vm_interface(vmid, options = {})
20
20
  raise ArgumentError, "instance id is a required parameter" unless vmid
21
21
 
22
- interface = get_interface_from_options(vmid, options.merge(:server_id => vmid))
23
- vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface, interface.key, :edit)]})
22
+ interface = get_interface_from_options(vmid, options)
23
+ raw_interface = get_raw_interface(vmid, key: interface.key)
24
+ if options[:network]
25
+ interface.network = options[:network]
26
+ backing = create_nic_backing(interface, {})
27
+ raw_interface.backing = backing
28
+ end
29
+ spec = {
30
+ operation: :edit,
31
+ device: raw_interface
32
+ }
33
+ vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[spec]})
24
34
  end
25
35
 
26
36
  private
37
+
27
38
  def get_interface_from_options(vmid, options)
28
39
  if options and options[:interface]
29
40
  options[:interface]
@@ -53,6 +64,12 @@ module Fog
53
64
  raise ArgumentError, "interface is a required parameter" unless options and options[:interface]
54
65
  true
55
66
  end
67
+
68
+ def update_vm_interface(vmid, options = {})
69
+ return unless options[:interface]
70
+ options[:interface].network = options[:network]
71
+ options[:interface].type = options[:type]
72
+ end
56
73
  end
57
74
  end
58
75
  end
@@ -13,7 +13,7 @@ module Fog
13
13
 
14
14
  class Mock
15
15
  def add_vm_volume(volume)
16
- true
16
+ vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_cdrom(volume, volume.unit_number, :add)]})
17
17
  end
18
18
 
19
19
  def destroy_vm_volume(volume)
@@ -0,0 +1,34 @@
1
+ module Fog
2
+ module Compute
3
+ class Vsphere
4
+ class Real
5
+ def upload_iso_check_options(options)
6
+ default_options = {
7
+ 'upload_directory' => 'isos',
8
+ }
9
+ options = default_options.merge(options)
10
+ required_options = %w{ datacenter datastore local_path }
11
+ required_options.each do |param|
12
+ raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param
13
+ end
14
+ raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options["datacenter"]} Doesn't Exist!" unless get_datacenter(options["datacenter"])
15
+ raise Fog::Compute::Vsphere::NotFound, "Datastore #{options["datastore"]} Doesn't Exist!" unless get_raw_datastore(options['datastore'], options['datacenter'])
16
+ options
17
+ end
18
+
19
+ def upload_iso(options = {})
20
+ options = upload_iso_check_options(options)
21
+ datastore = get_raw_datastore(options['datastore'], options['datacenter'])
22
+ datacenter = get_datacenter(options['datacenter'])
23
+ filename = options['filename'] || File.basename(options['local_path'])
24
+ unless datastore.exists? options['upload_directory']+'/'
25
+ @connection.serviceContent.fileManager.MakeDirectory :name => "[#{options['datastore']}] #{options['directory']}",
26
+ :datacenter => datacenter,
27
+ :createParentDirectories => false
28
+ end
29
+ datastore.upload options['upload_directory']+'/'+filename, options['local_path']
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -10,6 +10,7 @@ module Fog
10
10
  'nic_type' => 'VirtualE1000',
11
11
  }
12
12
  options = default_options.merge(options)
13
+ options["storage_pod"] = nil if options["storage_pod"] == ''
13
14
  # Backwards compat for "path" option
14
15
  options["template_path"] ||= options["path"]
15
16
  options["path"] ||= options["template_path"]
@@ -19,6 +20,7 @@ module Fog
19
20
  end
20
21
  raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options["datacenter"]} Doesn't Exist!" unless get_datacenter(options["datacenter"])
21
22
  raise Fog::Compute::Vsphere::NotFound, "Template #{options["template_path"]} Doesn't Exist!" unless get_virtual_machine(options["template_path"], options["datacenter"])
23
+ raise Fog::Compute::Vsphere::NotFound, "Storage Pod #{options["storage_pod"]} Doesn't Exist!" if options.key?('storage_pod') and ! get_storage_pod(options['storage_pod'], options['datacenter'])
22
24
  options
23
25
  end
24
26
  end
@@ -54,6 +56,7 @@ module Fog
54
56
  # Example: ['cluster_name_here','resource_pool_name_here']
55
57
  # * 'datastore'<~String> - The datastore you'd like to use.
56
58
  # (datacenterObj.datastoreFolder.find('name') in API)
59
+ # * 'storage_pod'<~String> - The storage pod / datastore cluster you'd like to use.
57
60
  # * 'transform'<~String> - Not documented - see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html
58
61
  # * 'numCPUs'<~Integer> - the number of Virtual CPUs of the Destination VM
59
62
  # * 'memoryMB'<~Integer> - the size of memory of the Destination VM in MB
@@ -537,6 +540,9 @@ module Fog
537
540
 
538
541
  relocation_spec=nil
539
542
  if ( options['linked_clone'] )
543
+ # Storage DRS does not support vSphere linked clones.
544
+ # http://www.vmware.com/files/pdf/techpaper/vsphere-storage-drs-interoperability.pdf
545
+ raise ArgumentError, "linked clones are not supported on storage pods" unless options.key?('storage_pod')
540
546
  # cribbed heavily from the rbvmomi clone_vm.rb
541
547
  # this chunk of code reconfigures the disk of the clone source to be read only,
542
548
  # and then creates a delta disk on top of that, this is required by the API in order to create
@@ -569,9 +575,11 @@ module Fog
569
575
  :pool => resource_pool,
570
576
  :diskMoveType => :moveChildMostDiskBacking)
571
577
  else
572
- relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => datastore_obj,
573
- :pool => resource_pool,
578
+ relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool,
574
579
  :transform => options['transform'] || 'sparse')
580
+ unless options.key?('storage_pod') and datastore_obj.nil?
581
+ relocation_spec[:datastore] = datastore_obj
582
+ end
575
583
  end
576
584
  # And the clone specification
577
585
  clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => relocation_spec,
@@ -581,31 +589,66 @@ module Fog
581
589
  :template => false)
582
590
 
583
591
  # Perform the actual Clone Task
584
- task = vm_mob_ref.CloneVM_Task(:folder => dest_folder,
592
+ # Clone VM on a storage pod
593
+ if options.key?('storage_pod')
594
+ raise ArgumentError, "need to use at least vsphere revision 5.0 or greater to use storage pods" unless @vsphere_rev.to_f >= 5
595
+ pod_spec = RbVmomi::VIM::StorageDrsPodSelectionSpec.new(
596
+ :storagePod => get_raw_storage_pod(options['storage_pod'], options['datacenter']),
597
+ )
598
+ storage_spec = RbVmomi::VIM::StoragePlacementSpec.new(
599
+ :type => 'clone',
600
+ :folder => dest_folder,
601
+ :resourcePool => resource_pool,
602
+ :podSelectionSpec => pod_spec,
603
+ :cloneSpec => clone_spec,
604
+ :cloneName => options['name'],
605
+ :vm => vm_mob_ref,
606
+ )
607
+ srm = @connection.serviceContent.storageResourceManager
608
+ result = srm.RecommendDatastores(:storageSpec => storage_spec)
609
+
610
+ # if result array contains recommendation, we can apply it
611
+ if key = result.recommendations.first.key
612
+ task = srm.ApplyStorageDrsRecommendation_Task(:key => [key])
613
+ if options.fetch('wait', true) then
614
+ result = task.wait_for_completion
615
+ new_vm = result.vm
616
+ else
617
+ new_vm = nil
618
+ Fog.wait_for(150, 15) {
619
+ begin
620
+ new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine) or raise Fog::Vsphere::Errors::NotFound
621
+ rescue Fog::Vsphere::Errors::NotFound
622
+ new_vm = nil
623
+ end
624
+ }
625
+ raise Fog::Vsphere::Errors::NotFound unless new_vm
626
+ end
627
+ end
628
+ else
629
+ task = vm_mob_ref.CloneVM_Task(:folder => dest_folder,
585
630
  :name => options['name'],
586
631
  :spec => clone_spec)
587
- # Waiting for the VM to complete allows us to get the VirtulMachine
588
- # object of the new machine when it's done. It is HIGHLY recommended
589
- # to set 'wait' => true if your app wants to wait. Otherwise, you're
590
- # going to have to reload the server model over and over which
591
- # generates a lot of time consuming API calls to vmware.
592
- if options.fetch('wait', true) then
593
- # REVISIT: It would be awesome to call a block passed to this
594
- # request to notify the application how far along in the process we
595
- # are. I'm thinking of updating a progress bar, etc...
596
- new_vm = task.wait_for_completion
597
- else
598
- tries = 0
599
- new_vm = begin
600
- # Try and find the new VM (folder.find is quite efficient)
601
- dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine) or raise Fog::Vsphere::Errors::NotFound
602
- rescue Fog::Vsphere::Errors::NotFound
603
- tries += 1
604
- if tries <= 10 then
605
- sleep 15
606
- retry
607
- end
608
- nil
632
+ # Waiting for the VM to complete allows us to get the VirtulMachine
633
+ # object of the new machine when it's done. It is HIGHLY recommended
634
+ # to set 'wait' => true if your app wants to wait. Otherwise, you're
635
+ # going to have to reload the server model over and over which
636
+ # generates a lot of time consuming API calls to vmware.
637
+ if options.fetch('wait', true) then
638
+ # REVISIT: It would be awesome to call a block passed to this
639
+ # request to notify the application how far along in the process we
640
+ # are. I'm thinking of updating a progress bar, etc...
641
+ new_vm = task.wait_for_completion
642
+ else
643
+ new_vm = nil
644
+ Fog.wait_for(150, 15) {
645
+ begin
646
+ new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine) or raise Fog::Vsphere::Errors::NotFound
647
+ rescue Fog::Vsphere::Errors::NotFound
648
+ new_vm = nil
649
+ end
650
+ }
651
+ raise Fog::Vsphere::Errors::NotFound unless new_vm
609
652
  end
610
653
  end
611
654