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.
- 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
|
|