fog-vsphere 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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