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.
- checksums.yaml +4 -4
- data/.travis.yml +0 -4
- data/CHANGELOG.md +8 -0
- data/CONTRIBUTORS.md +6 -0
- data/fog-vsphere.gemspec +1 -1
- data/lib/fog/vsphere/compute.rb +47 -3
- data/lib/fog/vsphere/models/compute/cdrom.rb +65 -0
- data/lib/fog/vsphere/models/compute/cdroms.rb +18 -0
- data/lib/fog/vsphere/models/compute/datacenter.rb +4 -0
- data/lib/fog/vsphere/models/compute/folder.rb +4 -0
- data/lib/fog/vsphere/models/compute/server.rb +8 -0
- data/lib/fog/vsphere/models/compute/storage_pod.rb +19 -0
- data/lib/fog/vsphere/models/compute/storage_pods.rb +22 -0
- data/lib/fog/vsphere/models/compute/volume.rb +1 -0
- data/lib/fog/vsphere/requests/compute/create_folder.rb +10 -0
- data/lib/fog/vsphere/requests/compute/create_vm.rb +163 -4
- data/lib/fog/vsphere/requests/compute/folder_destroy.rb +26 -0
- data/lib/fog/vsphere/requests/compute/get_folder.rb +4 -2
- data/lib/fog/vsphere/requests/compute/get_storage_pod.rb +31 -0
- data/lib/fog/vsphere/requests/compute/list_datacenters.rb +1 -1
- data/lib/fog/vsphere/requests/compute/list_datastores.rb +2 -1
- data/lib/fog/vsphere/requests/compute/list_networks.rb +2 -1
- data/lib/fog/vsphere/requests/compute/list_storage_pods.rb +45 -0
- data/lib/fog/vsphere/requests/compute/list_virtual_machines.rb +8 -4
- data/lib/fog/vsphere/requests/compute/list_vm_cdroms.rb +30 -0
- data/lib/fog/vsphere/requests/compute/list_vm_interfaces.rb +34 -13
- data/lib/fog/vsphere/requests/compute/list_vm_snapshots.rb +5 -1
- data/lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb +25 -0
- data/lib/fog/vsphere/requests/compute/modify_vm_interface.rb +19 -2
- data/lib/fog/vsphere/requests/compute/modify_vm_volume.rb +1 -1
- data/lib/fog/vsphere/requests/compute/upload_iso.rb +34 -0
- data/lib/fog/vsphere/requests/compute/vm_clone.rb +68 -25
- data/lib/fog/vsphere/requests/compute/vm_reconfig_cdrom.rb +68 -0
- data/lib/fog/vsphere/version.rb +1 -1
- data/tests/models/compute/servers_tests.rb +1 -1
- data/tests/requests/compute/folder_destroy_tests.rb +21 -0
- data/tests/requests/compute/list_storage_pods_test.rb +10 -0
- data/tests/requests/compute/list_vm_cdroms_tests.rb +10 -0
- data/tests/requests/compute/modify_vm_cdrom_tests.rb +21 -0
- data/tests/requests/compute/vm_reconfig_cdrom_tests.rb +15 -0
- 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
|
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,
|
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
|
@@ -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']
|
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
|
-
|
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
|
-
|
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
|
-
|
52
|
-
(options.key? :key and nic
|
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
|
-
|
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
|
23
|
-
|
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
|
@@ -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(:
|
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
|
-
|
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
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
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
|
|