vagrant-rbvmomi 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +6 -0
- data/LICENSE +19 -0
- data/README.rdoc +78 -0
- data/Rakefile +31 -0
- data/VERSION +1 -0
- data/bin/rbvmomish +138 -0
- data/devel/analyze-vim-declarations.rb +213 -0
- data/devel/analyze-xml.rb +46 -0
- data/devel/benchmark.rb +117 -0
- data/devel/collisions.rb +18 -0
- data/devel/merge-internal-vmodl.rb +59 -0
- data/devel/merge-manual-vmodl.rb +32 -0
- data/examples/annotate.rb +54 -0
- data/examples/cached_ovf_deploy.rb +120 -0
- data/examples/clone_vm.rb +84 -0
- data/examples/create_vm-1.9.rb +93 -0
- data/examples/create_vm.rb +93 -0
- data/examples/extraConfig.rb +54 -0
- data/examples/lease_tool.rb +102 -0
- data/examples/logbundle.rb +63 -0
- data/examples/logtail.rb +60 -0
- data/examples/nfs_datastore.rb +95 -0
- data/examples/power.rb +59 -0
- data/examples/readme-1.rb +35 -0
- data/examples/readme-2.rb +51 -0
- data/examples/run.sh +41 -0
- data/examples/screenshot.rb +48 -0
- data/examples/vdf.rb +81 -0
- data/examples/vm_drs_behavior.rb +76 -0
- data/lib/rbvmomi.rb +12 -0
- data/lib/rbvmomi/basic_types.rb +375 -0
- data/lib/rbvmomi/connection.rb +270 -0
- data/lib/rbvmomi/deserialization.rb +248 -0
- data/lib/rbvmomi/fault.rb +17 -0
- data/lib/rbvmomi/pbm.rb +66 -0
- data/lib/rbvmomi/sms.rb +61 -0
- data/lib/rbvmomi/sms/SmsStorageManager.rb +7 -0
- data/lib/rbvmomi/trivial_soap.rb +114 -0
- data/lib/rbvmomi/trollop.rb +70 -0
- data/lib/rbvmomi/type_loader.rb +136 -0
- data/lib/rbvmomi/utils/admission_control.rb +398 -0
- data/lib/rbvmomi/utils/deploy.rb +336 -0
- data/lib/rbvmomi/utils/leases.rb +142 -0
- data/lib/rbvmomi/utils/perfdump.rb +628 -0
- data/lib/rbvmomi/vim.rb +128 -0
- data/lib/rbvmomi/vim/ComputeResource.rb +51 -0
- data/lib/rbvmomi/vim/Datacenter.rb +17 -0
- data/lib/rbvmomi/vim/Datastore.rb +68 -0
- data/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb +75 -0
- data/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb +20 -0
- data/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb +46 -0
- data/lib/rbvmomi/vim/Folder.rb +207 -0
- data/lib/rbvmomi/vim/HostSystem.rb +174 -0
- data/lib/rbvmomi/vim/ManagedEntity.rb +57 -0
- data/lib/rbvmomi/vim/ManagedObject.rb +60 -0
- data/lib/rbvmomi/vim/ObjectContent.rb +23 -0
- data/lib/rbvmomi/vim/ObjectUpdate.rb +23 -0
- data/lib/rbvmomi/vim/OvfManager.rb +200 -0
- data/lib/rbvmomi/vim/PerfCounterInfo.rb +26 -0
- data/lib/rbvmomi/vim/PerformanceManager.rb +110 -0
- data/lib/rbvmomi/vim/PropertyCollector.rb +25 -0
- data/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb +30 -0
- data/lib/rbvmomi/vim/ResourcePool.rb +55 -0
- data/lib/rbvmomi/vim/ServiceInstance.rb +55 -0
- data/lib/rbvmomi/vim/Task.rb +65 -0
- data/lib/rbvmomi/vim/VirtualMachine.rb +74 -0
- data/test/test_deserialization.rb +383 -0
- data/test/test_emit_request.rb +128 -0
- data/test/test_exceptions.rb +14 -0
- data/test/test_helper.rb +14 -0
- data/test/test_misc.rb +24 -0
- data/test/test_parse_response.rb +69 -0
- data/test/test_serialization.rb +311 -0
- data/vmodl.db +0 -0
- metadata +163 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright (c) 2011 VMware, Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
class RbVmomi::VIM::PerfCounterInfo
|
22
|
+
def name
|
23
|
+
"#{groupInfo.key}.#{nameInfo.key}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class Time
|
4
|
+
def to_datetime
|
5
|
+
# Convert seconds + microseconds into a fractional number of seconds
|
6
|
+
seconds = sec + Rational(usec, 10**6)
|
7
|
+
|
8
|
+
# Convert a UTC offset measured in minutes to one measured in a
|
9
|
+
# fraction of a day.
|
10
|
+
offset = Rational(utc_offset, 60 * 60 * 24)
|
11
|
+
DateTime.new(year, month, day, hour, min, seconds, offset)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
RbVmomi::VIM::PerformanceManager
|
16
|
+
class RbVmomi::VIM::PerformanceManager
|
17
|
+
def perfcounter_cached
|
18
|
+
@perfcounter ||= perfCounter
|
19
|
+
end
|
20
|
+
|
21
|
+
def perfcounter_hash
|
22
|
+
@perfcounter_hash ||= Hash[perfcounter_cached.map{|x| [x.name, x]}]
|
23
|
+
end
|
24
|
+
|
25
|
+
def perfcounter_idhash
|
26
|
+
@perfcounter_idhash ||= Hash[perfcounter_cached.map{|x| [x.key, x]}]
|
27
|
+
end
|
28
|
+
|
29
|
+
def provider_summary obj
|
30
|
+
@provider_summary ||= {}
|
31
|
+
@provider_summary[obj.class] ||= QueryPerfProviderSummary(:entity => obj)
|
32
|
+
end
|
33
|
+
|
34
|
+
def retrieve_stats objects, metrics, opts = {}
|
35
|
+
opts = opts.dup
|
36
|
+
max_samples = opts[:max_samples] || 1
|
37
|
+
realtime = false
|
38
|
+
if not opts[:interval]
|
39
|
+
provider = provider_summary objects.first
|
40
|
+
opts[:interval] = provider.refreshRate
|
41
|
+
realtime = true
|
42
|
+
else
|
43
|
+
provider = provider_summary objects.first
|
44
|
+
if opts[:interval] == provider.refreshRate
|
45
|
+
realtime = true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
instances = opts[:instance] || '*'
|
50
|
+
if !instances.is_a?(Array)
|
51
|
+
instances = [instances]
|
52
|
+
end
|
53
|
+
metric_ids = []
|
54
|
+
metrics.each do |x|
|
55
|
+
counter = perfcounter_hash[x]
|
56
|
+
if !counter
|
57
|
+
pp perfcounter_hash.keys
|
58
|
+
fail "Counter for #{x} couldn't be found"
|
59
|
+
end
|
60
|
+
instances.each do |instance|
|
61
|
+
metric_ids << RbVmomi::VIM::PerfMetricId(:counterId => counter.key,
|
62
|
+
:instance => instance)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
query_specs = objects.map do |obj|
|
66
|
+
RbVmomi::VIM::PerfQuerySpec({
|
67
|
+
:maxSample => max_samples,
|
68
|
+
:entity => obj,
|
69
|
+
:metricId => metric_ids,
|
70
|
+
:intervalId => opts[:interval],
|
71
|
+
:startTime => (realtime == false ? opts[:start_time].to_datetime : nil),
|
72
|
+
})
|
73
|
+
end
|
74
|
+
stats = QueryPerf(:querySpec => query_specs)
|
75
|
+
|
76
|
+
if !opts[:multi_instance]
|
77
|
+
Hash[stats.map do |res|
|
78
|
+
[
|
79
|
+
res.entity,
|
80
|
+
{
|
81
|
+
:sampleInfo => res.sampleInfo,
|
82
|
+
:metrics => Hash[res.value.map do |metric|
|
83
|
+
metric_name = perfcounter_idhash[metric.id.counterId].name
|
84
|
+
[metric_name, metric.value]
|
85
|
+
end]
|
86
|
+
}
|
87
|
+
]
|
88
|
+
end]
|
89
|
+
else
|
90
|
+
Hash[stats.map do |res|
|
91
|
+
[
|
92
|
+
res.entity,
|
93
|
+
{
|
94
|
+
:sampleInfo => res.sampleInfo,
|
95
|
+
:metrics => Hash[res.value.map do |metric|
|
96
|
+
metric_name = perfcounter_idhash[metric.id.counterId].name
|
97
|
+
[[metric_name, metric.id.instance], metric.value]
|
98
|
+
end]
|
99
|
+
}
|
100
|
+
]
|
101
|
+
end]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def active_intervals
|
107
|
+
intervals = historicalInterval
|
108
|
+
Hash[(1..4).map { |level| [level, intervals.select { |x| x.enabled && x.level >= level }] }]
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class RbVmomi::VIM::PropertyCollector
|
2
|
+
def collectMultiple objs, *pathSet
|
3
|
+
return {} if objs.empty?
|
4
|
+
|
5
|
+
klasses = objs.map{|x| x.class}.uniq
|
6
|
+
klass = if klasses.length > 1
|
7
|
+
# common superclass
|
8
|
+
klasses.map(&:ancestors).inject(&:&)[0]
|
9
|
+
else
|
10
|
+
klasses.first
|
11
|
+
end
|
12
|
+
|
13
|
+
spec = {
|
14
|
+
:objectSet => objs.map{|x| { :obj => x }},
|
15
|
+
:propSet => [{
|
16
|
+
:pathSet => pathSet,
|
17
|
+
:type => klass.wsdl_name
|
18
|
+
}]
|
19
|
+
}
|
20
|
+
res = RetrieveProperties(:specSet => [spec])
|
21
|
+
Hash[res.map do |x|
|
22
|
+
[x.obj, x.to_hash]
|
23
|
+
end]
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RbVmomi
|
2
|
+
|
3
|
+
class VIM::ReflectManagedMethodExecuter
|
4
|
+
def fetch moid, prop
|
5
|
+
result = FetchSoap(:moid => moid, :version => 'urn:vim25/5.0', :prop => prop)
|
6
|
+
xml = Nokogiri(result.response)
|
7
|
+
_connection.deserializer.deserialize xml.root, nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute moid, method, args
|
11
|
+
soap_args = args.map do |k,v|
|
12
|
+
VIM::ReflectManagedMethodExecuterSoapArgument.new.tap do |soap_arg|
|
13
|
+
soap_arg.name = k
|
14
|
+
xml = Builder::XmlMarkup.new :indent => 0
|
15
|
+
_connection.obj2xml xml, k, :anyType, false, v
|
16
|
+
soap_arg.val = xml.target!
|
17
|
+
end
|
18
|
+
end
|
19
|
+
result = ExecuteSoap(:moid => moid, :version => 'urn:vim25/5.0',
|
20
|
+
:method => method, :argument => soap_args)
|
21
|
+
if result
|
22
|
+
_connection.deserializer.deserialize Nokogiri(result.response).root, nil
|
23
|
+
else
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class RbVmomi::VIM::ResourcePool
|
2
|
+
# Retrieve a child ResourcePool.
|
3
|
+
# @param name [String] Name of the child.
|
4
|
+
# @return [VIM::ResourcePool]
|
5
|
+
def find name
|
6
|
+
_connection.searchIndex.FindChild(:entity => self, :name => name)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Retrieve a descendant of this ResourcePool.
|
10
|
+
# @param path [String] Path delimited by '/'.
|
11
|
+
# @return [VIM::ResourcePool]
|
12
|
+
def traverse path
|
13
|
+
es = path.split('/').reject(&:empty?)
|
14
|
+
es.inject(self) do |f,e|
|
15
|
+
f.find(e) || return
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def resourcePoolSubTree fields = []
|
20
|
+
self.class.resourcePoolSubTree [self], fields
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.resourcePoolSubTree objs, fields = []
|
24
|
+
fields = (fields + ['name', 'resourcePool']).uniq
|
25
|
+
filterSpec = RbVmomi::VIM.PropertyFilterSpec(
|
26
|
+
:objectSet => objs.map do |obj|
|
27
|
+
RbVmomi::VIM.ObjectSpec(
|
28
|
+
:obj => obj,
|
29
|
+
:selectSet => [
|
30
|
+
RbVmomi::VIM.TraversalSpec(
|
31
|
+
:name => "tsRP",
|
32
|
+
:type => 'ResourcePool',
|
33
|
+
:path => 'resourcePool',
|
34
|
+
:skip => false,
|
35
|
+
:selectSet => [
|
36
|
+
RbVmomi::VIM.SelectionSpec(:name => "tsRP")
|
37
|
+
]
|
38
|
+
)
|
39
|
+
]
|
40
|
+
)
|
41
|
+
end,
|
42
|
+
:propSet => [{
|
43
|
+
:pathSet => fields,
|
44
|
+
:type => 'ResourcePool'
|
45
|
+
}]
|
46
|
+
)
|
47
|
+
|
48
|
+
propCollector = objs.first._connection.propertyCollector
|
49
|
+
result = propCollector.RetrieveProperties(:specSet => [filterSpec])
|
50
|
+
|
51
|
+
Hash[result.map do |x|
|
52
|
+
[x.obj, x.to_hash]
|
53
|
+
end]
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class RbVmomi::VIM::ServiceInstance
|
2
|
+
# Retrieve a Datacenter.
|
3
|
+
# If no path is given the first datacenter will be returned.
|
4
|
+
# @param path (see Folder#traverse)
|
5
|
+
# @return [Datacenter]
|
6
|
+
def find_datacenter path=nil
|
7
|
+
if path
|
8
|
+
content.rootFolder.traverse path, RbVmomi::VIM::Datacenter
|
9
|
+
else
|
10
|
+
content.rootFolder.childEntity.grep(RbVmomi::VIM::Datacenter).first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Wait for several tasks to complete.
|
15
|
+
# @param interested [Array] Property paths to watch for updates.
|
16
|
+
# @param tasks [Array] Tasks to wait on.
|
17
|
+
# @yield [Hash] Called when a property is updated on a task.
|
18
|
+
# The parameter is a hash from tasks to hashes from
|
19
|
+
# property path to value.
|
20
|
+
# @return [void]
|
21
|
+
def wait_for_multiple_tasks interested, tasks
|
22
|
+
version = ''
|
23
|
+
interested = (interested + ['info.state']).uniq
|
24
|
+
task_props = Hash.new { |h,k| h[k] = {} }
|
25
|
+
|
26
|
+
filter = _connection.propertyCollector.CreateFilter :spec => {
|
27
|
+
:propSet => [{ :type => 'Task', :all => false, :pathSet => interested }],
|
28
|
+
:objectSet => tasks.map { |x| { :obj => x } },
|
29
|
+
}, :partialUpdates => false
|
30
|
+
|
31
|
+
begin
|
32
|
+
until task_props.size == tasks.size and task_props.all? { |k,h| %w(success error).member? h['info.state'] }
|
33
|
+
result = _connection.propertyCollector.WaitForUpdates(:version => version)
|
34
|
+
version = result.version
|
35
|
+
os = result.filterSet[0].objectSet
|
36
|
+
|
37
|
+
os.each do |o|
|
38
|
+
changes = Hash[o.changeSet.map { |x| [x.name, x.val] }]
|
39
|
+
|
40
|
+
interested.each do |k|
|
41
|
+
task = tasks.find { |x| x._ref == o.obj._ref }
|
42
|
+
task_props[task][k] = changes[k] if changes.member? k
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
yield task_props if block_given?
|
47
|
+
end
|
48
|
+
ensure
|
49
|
+
_connection.propertyCollector.CancelWaitForUpdates
|
50
|
+
filter.DestroyPropertyFilter
|
51
|
+
end
|
52
|
+
|
53
|
+
task_props
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class RbVmomi::VIM::Task
|
2
|
+
# Wait for a task to finish.
|
3
|
+
# @return +info.result+ on success.
|
4
|
+
# @raise +info.error+ on error.
|
5
|
+
def wait_for_completion
|
6
|
+
wait_until('info.state') { %w(success error).member? info.state }
|
7
|
+
case info.state
|
8
|
+
when 'success'
|
9
|
+
info.result
|
10
|
+
when 'error'
|
11
|
+
raise info.error
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Wait for all child tasks to finish. If any one child task failed,
|
16
|
+
# the exception of the first failing task is thrown.
|
17
|
+
# @return [Hash] Map of tasks to their +info.result+ on success.
|
18
|
+
# @raise +info.error+ on error.
|
19
|
+
def wait_for_childtask_completion
|
20
|
+
si = _connection.serviceInstance
|
21
|
+
tasks_props = si.wait_for_multiple_tasks(
|
22
|
+
['info.state', 'info.result', 'info.error'],
|
23
|
+
self.child_tasks
|
24
|
+
)
|
25
|
+
Hash[tasks_props.map do |task, props|
|
26
|
+
case props['info.state']
|
27
|
+
when 'success'
|
28
|
+
[task, props['info.result']]
|
29
|
+
when 'error'
|
30
|
+
raise props['info.error']
|
31
|
+
end
|
32
|
+
end]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Wait for a task to finish, with progress notifications.
|
36
|
+
# @return (see #wait_for_completion)
|
37
|
+
# @raise (see #wait_for_completion)
|
38
|
+
# @yield [info.progress]
|
39
|
+
def wait_for_progress
|
40
|
+
wait_until('info.state', 'info.progress') do
|
41
|
+
yield info.progress if block_given?
|
42
|
+
%w(success error).member? info.state
|
43
|
+
end
|
44
|
+
case info.state
|
45
|
+
when 'success'
|
46
|
+
info.result
|
47
|
+
when 'error'
|
48
|
+
raise info.error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get child tasks of this task.
|
53
|
+
# @return [Array] List of VIM::Task objects
|
54
|
+
def child_tasks
|
55
|
+
tm = _connection.serviceContent.taskManager
|
56
|
+
col = tm.CreateCollectorForTasks(:filter => {
|
57
|
+
:rootTaskKey => [self.info.key],
|
58
|
+
})
|
59
|
+
# XXX: Likely this is not enough and we need to collect pages other
|
60
|
+
# than the latest.
|
61
|
+
tasks = col.latestPage.map{|x| x.task}
|
62
|
+
col.DestroyCollector()
|
63
|
+
tasks
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class RbVmomi::VIM::VirtualMachine
|
2
|
+
# Retrieve the MAC addresses for all virtual NICs.
|
3
|
+
# @return [Hash] Keyed by device label.
|
4
|
+
def macs
|
5
|
+
Hash[self.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).map { |x| [x.deviceInfo.label, x.macAddress] }]
|
6
|
+
end
|
7
|
+
|
8
|
+
# Retrieve all virtual disk devices.
|
9
|
+
# @return [Array] Array of virtual disk devices.
|
10
|
+
def disks
|
11
|
+
self.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Get the IP of the guest, but only if it is not stale
|
15
|
+
# @return [String] Current IP reported (as per VMware Tools) or nil
|
16
|
+
def guest_ip
|
17
|
+
g = self.guest
|
18
|
+
if g.ipAddress && (g.toolsStatus == "toolsOk" || g.toolsStatus == "toolsOld")
|
19
|
+
g.ipAddress
|
20
|
+
else
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Add a layer of delta disks (redo logs) in front of every disk on the VM.
|
26
|
+
# This is similar to taking a snapshot and makes the VM a valid target for
|
27
|
+
# creating a linked clone.
|
28
|
+
#
|
29
|
+
# Background: The API for linked clones is quite strange. We can't create
|
30
|
+
# a linked straight from any VM. The disks of the VM for which we can create a
|
31
|
+
# linked clone need to be read-only and thus VC demands that the VM we
|
32
|
+
# are cloning from uses delta-disks. Only then it will allow us to
|
33
|
+
# share the base disk.
|
34
|
+
def add_delta_disk_layer_on_all_disks
|
35
|
+
devices, = self.collect 'config.hardware.device'
|
36
|
+
disks = devices.grep(RbVmomi::VIM::VirtualDisk)
|
37
|
+
spec = update_spec_add_delta_disk_layer_on_all_disks
|
38
|
+
self.ReconfigVM_Task(:spec => spec).wait_for_completion
|
39
|
+
end
|
40
|
+
|
41
|
+
# Updates a passed in spec to perform the task of adding a delta disk layer
|
42
|
+
# on top of all disks. Does the same as add_delta_disk_layer_on_all_disks
|
43
|
+
# but instead of issuing the ReconfigVM_Task, it just constructs the
|
44
|
+
# spec, so that the caller can batch a couple of updates into one
|
45
|
+
# ReconfigVM_Task.
|
46
|
+
def update_spec_add_delta_disk_layer_on_all_disks spec = {}
|
47
|
+
devices, = self.collect 'config.hardware.device'
|
48
|
+
disks = devices.grep(RbVmomi::VIM::VirtualDisk)
|
49
|
+
device_change = []
|
50
|
+
disks.each do |disk|
|
51
|
+
device_change << {
|
52
|
+
:operation => :remove,
|
53
|
+
:device => disk
|
54
|
+
}
|
55
|
+
device_change << {
|
56
|
+
:operation => :add,
|
57
|
+
:fileOperation => :create,
|
58
|
+
:device => disk.dup.tap { |x|
|
59
|
+
x.backing = x.backing.dup
|
60
|
+
x.backing.fileName = "[#{disk.backing.datastore.name}]"
|
61
|
+
x.backing.parent = disk.backing
|
62
|
+
},
|
63
|
+
}
|
64
|
+
end
|
65
|
+
if spec.is_a?(RbVmomi::VIM::VirtualMachineConfigSpec)
|
66
|
+
spec.deviceChange ||= []
|
67
|
+
spec.deviceChange += device_change
|
68
|
+
else
|
69
|
+
spec[:deviceChange] ||= []
|
70
|
+
spec[:deviceChange] += device_change
|
71
|
+
end
|
72
|
+
spec
|
73
|
+
end
|
74
|
+
end
|