vagrant-rbvmomi 1.8.1

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +6 -0
  3. data/LICENSE +19 -0
  4. data/README.rdoc +78 -0
  5. data/Rakefile +31 -0
  6. data/VERSION +1 -0
  7. data/bin/rbvmomish +138 -0
  8. data/devel/analyze-vim-declarations.rb +213 -0
  9. data/devel/analyze-xml.rb +46 -0
  10. data/devel/benchmark.rb +117 -0
  11. data/devel/collisions.rb +18 -0
  12. data/devel/merge-internal-vmodl.rb +59 -0
  13. data/devel/merge-manual-vmodl.rb +32 -0
  14. data/examples/annotate.rb +54 -0
  15. data/examples/cached_ovf_deploy.rb +120 -0
  16. data/examples/clone_vm.rb +84 -0
  17. data/examples/create_vm-1.9.rb +93 -0
  18. data/examples/create_vm.rb +93 -0
  19. data/examples/extraConfig.rb +54 -0
  20. data/examples/lease_tool.rb +102 -0
  21. data/examples/logbundle.rb +63 -0
  22. data/examples/logtail.rb +60 -0
  23. data/examples/nfs_datastore.rb +95 -0
  24. data/examples/power.rb +59 -0
  25. data/examples/readme-1.rb +35 -0
  26. data/examples/readme-2.rb +51 -0
  27. data/examples/run.sh +41 -0
  28. data/examples/screenshot.rb +48 -0
  29. data/examples/vdf.rb +81 -0
  30. data/examples/vm_drs_behavior.rb +76 -0
  31. data/lib/rbvmomi.rb +12 -0
  32. data/lib/rbvmomi/basic_types.rb +375 -0
  33. data/lib/rbvmomi/connection.rb +270 -0
  34. data/lib/rbvmomi/deserialization.rb +248 -0
  35. data/lib/rbvmomi/fault.rb +17 -0
  36. data/lib/rbvmomi/pbm.rb +66 -0
  37. data/lib/rbvmomi/sms.rb +61 -0
  38. data/lib/rbvmomi/sms/SmsStorageManager.rb +7 -0
  39. data/lib/rbvmomi/trivial_soap.rb +114 -0
  40. data/lib/rbvmomi/trollop.rb +70 -0
  41. data/lib/rbvmomi/type_loader.rb +136 -0
  42. data/lib/rbvmomi/utils/admission_control.rb +398 -0
  43. data/lib/rbvmomi/utils/deploy.rb +336 -0
  44. data/lib/rbvmomi/utils/leases.rb +142 -0
  45. data/lib/rbvmomi/utils/perfdump.rb +628 -0
  46. data/lib/rbvmomi/vim.rb +128 -0
  47. data/lib/rbvmomi/vim/ComputeResource.rb +51 -0
  48. data/lib/rbvmomi/vim/Datacenter.rb +17 -0
  49. data/lib/rbvmomi/vim/Datastore.rb +68 -0
  50. data/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb +75 -0
  51. data/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb +20 -0
  52. data/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb +46 -0
  53. data/lib/rbvmomi/vim/Folder.rb +207 -0
  54. data/lib/rbvmomi/vim/HostSystem.rb +174 -0
  55. data/lib/rbvmomi/vim/ManagedEntity.rb +57 -0
  56. data/lib/rbvmomi/vim/ManagedObject.rb +60 -0
  57. data/lib/rbvmomi/vim/ObjectContent.rb +23 -0
  58. data/lib/rbvmomi/vim/ObjectUpdate.rb +23 -0
  59. data/lib/rbvmomi/vim/OvfManager.rb +200 -0
  60. data/lib/rbvmomi/vim/PerfCounterInfo.rb +26 -0
  61. data/lib/rbvmomi/vim/PerformanceManager.rb +110 -0
  62. data/lib/rbvmomi/vim/PropertyCollector.rb +25 -0
  63. data/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb +30 -0
  64. data/lib/rbvmomi/vim/ResourcePool.rb +55 -0
  65. data/lib/rbvmomi/vim/ServiceInstance.rb +55 -0
  66. data/lib/rbvmomi/vim/Task.rb +65 -0
  67. data/lib/rbvmomi/vim/VirtualMachine.rb +74 -0
  68. data/test/test_deserialization.rb +383 -0
  69. data/test/test_emit_request.rb +128 -0
  70. data/test/test_exceptions.rb +14 -0
  71. data/test/test_helper.rb +14 -0
  72. data/test/test_misc.rb +24 -0
  73. data/test/test_parse_response.rb +69 -0
  74. data/test/test_serialization.rb +311 -0
  75. data/vmodl.db +0 -0
  76. 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