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,270 @@
1
+ # Copyright (c) 2010 VMware, Inc. All Rights Reserved.
2
+ require 'time'
3
+ require 'date'
4
+ require 'rbvmomi/trivial_soap'
5
+ require 'rbvmomi/basic_types'
6
+ require 'rbvmomi/fault'
7
+ require 'rbvmomi/type_loader'
8
+ require 'rbvmomi/deserialization'
9
+
10
+ module RbVmomi
11
+
12
+ IS_JRUBY = RUBY_PLATFORM == 'java'
13
+
14
+ class DeserializationFailed < Exception; end
15
+
16
+ class Connection < TrivialSoap
17
+ NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
18
+
19
+ attr_accessor :rev
20
+ attr_reader :profile
21
+ attr_reader :profile_summary
22
+ attr_accessor :profiling
23
+ attr_reader :deserializer
24
+
25
+ def initialize opts
26
+ @ns = opts[:ns] or fail "no namespace specified"
27
+ @rev = opts[:rev] or fail "no revision specified"
28
+ @deserializer = Deserializer.new self
29
+ reset_profiling
30
+ @profiling = false
31
+ super opts
32
+ end
33
+
34
+ def reset_profiling
35
+ @profile = {}
36
+ @profile_summary = {:network_latency => 0, :request_emit => 0, :response_parse => 0, :num_calls => 0}
37
+ end
38
+
39
+ def emit_request xml, method, descs, this, params
40
+ xml.tag! method, :xmlns => @ns do
41
+ obj2xml xml, '_this', 'ManagedObject', false, this
42
+ descs.each do |d|
43
+ k = d['name']
44
+ k = k.to_sym if !params.member?(k) && params.member?(k.to_sym)
45
+ v = params[k]
46
+ if not v == nil
47
+ obj2xml xml, d['name'], d['wsdl_type'], d['is-array'], v
48
+ else
49
+ fail "missing required parameter #{d['name']}" unless d['is-optional']
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def parse_response resp, desc
56
+ if resp.at('faultcode')
57
+ detail = resp.at('detail')
58
+ fault = detail && @deserializer.deserialize(detail.children.first, 'MethodFault')
59
+ msg = resp.at('faultstring').text
60
+ if fault
61
+ raise RbVmomi::Fault.new(msg, fault)
62
+ else
63
+ fail "#{resp.at('faultcode').text}: #{msg}"
64
+ end
65
+ else
66
+ if desc
67
+ type = desc['is-task'] ? 'Task' : desc['wsdl_type']
68
+ returnvals = resp.children.select(&:element?).map { |c| @deserializer.deserialize c, type }
69
+ (desc['is-array'] && !desc['is-task']) ? returnvals : returnvals.first
70
+ else
71
+ nil
72
+ end
73
+ end
74
+ end
75
+
76
+ def call method, desc, this, params
77
+ fail "this is not a managed object" unless this.is_a? BasicTypes::ManagedObject
78
+ fail "parameters must be passed as a hash" unless params.is_a? Hash
79
+ fail unless desc.is_a? Hash
80
+
81
+ t1 = Time.now
82
+ body = soap_envelope do |xml|
83
+ emit_request xml, method, desc['params'], this, params
84
+ end.target!
85
+
86
+ t2 = Time.now
87
+ resp, resp_size = request "#{@ns}/#{@rev}", body
88
+
89
+ t3 = Time.now
90
+ out = parse_response resp, desc['result']
91
+
92
+ if @profiling
93
+ t4 = Time.now
94
+ @profile[method] ||= []
95
+ profile_info = {
96
+ :network_latency => (t3 - t2),
97
+ :request_emit => t2 - t1,
98
+ :response_parse => t4 - t3,
99
+ :params => params,
100
+ :obj => this,
101
+ :backtrace => caller,
102
+ :request_size => body.length,
103
+ :response_size => resp_size,
104
+ }
105
+ @profile[method] << profile_info
106
+ @profile_summary[:network_latency] += profile_info[:network_latency]
107
+ @profile_summary[:response_parse] += profile_info[:response_parse]
108
+ @profile_summary[:request_emit] += profile_info[:request_emit]
109
+ @profile_summary[:num_calls] += 1
110
+ end
111
+
112
+ out
113
+ end
114
+
115
+ # hic sunt dracones
116
+ def obj2xml xml, name, type, is_array, o, attrs={}
117
+ expected = type(type)
118
+ fail "expected array for '#{name}', got #{o.class.wsdl_name}" if is_array and not (o.is_a? Array or (o.is_a? Hash and expected == BasicTypes::KeyValue))
119
+ case o
120
+ when Array, BasicTypes::KeyValue
121
+ if o.is_a? BasicTypes::KeyValue and expected != BasicTypes::KeyValue
122
+ fail "expected #{expected.wsdl_name} for '#{name}', got KeyValue"
123
+ elsif expected == BasicTypes::KeyValue and not is_array
124
+ xml.tag! name, attrs do
125
+ xml.tag! 'key', o[0].to_s
126
+ xml.tag! 'value', o[1].to_s
127
+ end
128
+ else
129
+ fail "expected #{expected.wsdl_name} for '#{name}', got array" unless is_array
130
+ o.each do |e|
131
+ obj2xml xml, name, expected.wsdl_name, false, e, attrs
132
+ end
133
+ end
134
+ when BasicTypes::ManagedObject
135
+ fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class and not expected == BasicTypes::AnyType
136
+ xml.tag! name, o._ref, :type => o.class.wsdl_name
137
+ when BasicTypes::DataObject
138
+ if expected and not expected >= o.class and not expected == BasicTypes::AnyType
139
+ fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}"
140
+ end
141
+ xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
142
+ o.class.full_props_desc.each do |desc|
143
+ if o.props.member? desc['name'].to_sym
144
+ v = o.props[desc['name'].to_sym]
145
+ next if v.nil?
146
+ obj2xml xml, desc['name'], desc['wsdl_type'], desc['is-array'], v
147
+ end
148
+ end
149
+ end
150
+ when BasicTypes::Enum
151
+ xml.tag! name, o.value.to_s, attrs
152
+ when Hash
153
+ if expected == BasicTypes::KeyValue and is_array
154
+ obj2xml xml, name, type, is_array, o.to_a, attrs
155
+ else
156
+ fail "expected #{expected.wsdl_name} for '#{name}', got a hash" unless expected <= BasicTypes::DataObject
157
+ obj2xml xml, name, type, false, expected.new(o), attrs
158
+ end
159
+ when true, false
160
+ fail "expected #{expected.wsdl_name} for '#{name}', got a boolean" unless [BasicTypes::Boolean, BasicTypes::AnyType].member? expected
161
+ attrs['xsi:type'] = 'xsd:boolean' if expected == BasicTypes::AnyType
162
+ xml.tag! name, (o ? '1' : '0'), attrs
163
+ when Symbol, String
164
+ if expected == BasicTypes::Binary
165
+ attrs['xsi:type'] = 'xsd:base64Binary' if expected == BasicTypes::AnyType
166
+ xml.tag! name, [o].pack('m').chomp.gsub("\n", ""), attrs
167
+ else
168
+ attrs['xsi:type'] = 'xsd:string' if expected == BasicTypes::AnyType
169
+ xml.tag! name, o.to_s, attrs
170
+ end
171
+ when Integer
172
+ attrs['xsi:type'] = 'xsd:long' if expected == BasicTypes::AnyType
173
+ xml.tag! name, o.to_s, attrs
174
+ when Float
175
+ attrs['xsi:type'] = 'xsd:double' if expected == BasicTypes::AnyType
176
+ xml.tag! name, o.to_s, attrs
177
+ when DateTime
178
+ attrs['xsi:type'] = 'xsd:dateTime' if expected == BasicTypes::AnyType
179
+ xml.tag! name, o.strftime('%FT%T%:z'), attrs
180
+ when Time
181
+ attrs['xsi:type'] = 'xsd:dateTime' if expected == BasicTypes::AnyType
182
+ xml.tag! name, o.iso8601, attrs
183
+ when BasicTypes::Int
184
+ attrs['xsi:type'] = 'xsd:int'
185
+ xml.tag! name, o.to_s, attrs
186
+ else fail "unexpected object class #{o.class} for '#{name}'"
187
+ end
188
+ xml
189
+ rescue
190
+ $stderr.puts "#{$!.class} while serializing #{name} (#{type}):"
191
+ PP.pp o, $stderr
192
+ raise
193
+ end
194
+
195
+ def self.type name
196
+ fail unless name and (name.is_a? String or name.is_a? Symbol)
197
+ name = $' if name.to_s =~ /^xsd:/
198
+ case name.to_sym
199
+ when :anyType then BasicTypes::AnyType
200
+ when :boolean then BasicTypes::Boolean
201
+ when :string then String
202
+ when :int, :long, :short, :byte then Integer
203
+ when :float, :double then Float
204
+ when :dateTime then Time
205
+ when :base64Binary then BasicTypes::Binary
206
+ when :KeyValue then BasicTypes::KeyValue
207
+ else
208
+ first_char = name[0].chr
209
+ if first_char.downcase == first_char
210
+ name = "%s%s" % [first_char.upcase, name[1..-1]]
211
+ end
212
+
213
+ if @loader.has? name
214
+ const_get(name)
215
+ else
216
+ fail "no such type #{name.inspect}"
217
+ end
218
+ end
219
+ end
220
+
221
+ def type name
222
+ self.class.type name
223
+ end
224
+
225
+ def instanceUuid
226
+ nil
227
+ end
228
+
229
+ def self.extension_dirs
230
+ @extension_dirs ||= []
231
+ end
232
+
233
+ def self.add_extension_dir dir
234
+ extension_dirs << dir
235
+ @loader.reload_extensions_dir dir if @loader
236
+ end
237
+
238
+ def self.reload_extensions
239
+ @loader.reload_extensions
240
+ end
241
+
242
+ def self.loader; @loader; end
243
+
244
+ protected
245
+
246
+ def self.const_missing sym
247
+ name = sym.to_s
248
+ if @loader and @loader.has? name
249
+ @loader.get(name)
250
+ else
251
+ super
252
+ end
253
+ end
254
+
255
+ def self.method_missing sym, *a
256
+ name = sym.to_s
257
+ if @loader and @loader.has? name
258
+ @loader.get(name).new(*a)
259
+ else
260
+ super
261
+ end
262
+ end
263
+
264
+ def self.load_vmodl fn
265
+ @loader = RbVmomi::TypeLoader.new fn, extension_dirs, self
266
+ nil
267
+ end
268
+ end
269
+
270
+ end
@@ -0,0 +1,248 @@
1
+ # Copyright (c) 2011 VMware, Inc. All Rights Reserved.
2
+ require 'time'
3
+
4
+ module RbVmomi
5
+
6
+ class NewDeserializer
7
+ NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
8
+
9
+ DEMANGLED_ARRAY_TYPES = {
10
+ 'AnyType' => 'xsd:anyType',
11
+ 'DateTime' => 'xsd:dateTime',
12
+ }
13
+ %w(Boolean String Byte Short Int Long Float Double).each do |x|
14
+ DEMANGLED_ARRAY_TYPES[x] = "xsd:#{x.downcase}"
15
+ end
16
+
17
+ BUILTIN_TYPE_ACTIONS = {
18
+ 'xsd:string' => :string,
19
+ 'xsd:boolean' => :boolean,
20
+ 'xsd:byte' => :int,
21
+ 'xsd:short' => :int,
22
+ 'xsd:int' => :int,
23
+ 'xsd:long' => :int,
24
+ 'xsd:float' => :float,
25
+ 'xsd:dateTime' => :date,
26
+ 'PropertyPath' => :string,
27
+ 'MethodName' => :string,
28
+ 'TypeName' => :string,
29
+ 'xsd:base64Binary' => :binary,
30
+ 'KeyValue' => :keyvalue,
31
+ }
32
+
33
+ BUILTIN_TYPE_ACTIONS.dup.each do |k,v|
34
+ if k =~ /^xsd:/
35
+ BUILTIN_TYPE_ACTIONS[$'] = v
36
+ end
37
+ end
38
+
39
+ def initialize conn
40
+ @conn = conn
41
+ @loader = conn.class.loader
42
+ end
43
+
44
+ def deserialize node, type=nil
45
+ type_attr = node['type']
46
+
47
+ # Work around for 1.5.x which doesn't populate node['type']
48
+ # XXX what changed
49
+ if node.attributes['type'] and not type_attr
50
+ type_attr = node.attributes['type'].value
51
+ end
52
+
53
+ type = type_attr if type_attr
54
+
55
+ if action = BUILTIN_TYPE_ACTIONS[type]
56
+ case action
57
+ when :string
58
+ node.content
59
+ when :boolean
60
+ node.content == '1' || node.content == 'true'
61
+ when :int
62
+ node.content.to_i
63
+ when :float
64
+ node.content.to_f
65
+ when :date
66
+ leaf_date node
67
+ when :binary
68
+ leaf_binary node
69
+ when :keyvalue
70
+ leaf_keyvalue node
71
+ else fail
72
+ end
73
+ else
74
+ if type =~ /:/
75
+ type = type.split(":", 2)[1]
76
+ end
77
+ if type =~ /^ArrayOf/
78
+ type = DEMANGLED_ARRAY_TYPES[$'] || $'
79
+ return node.children.select(&:element?).map { |c| deserialize c, type }
80
+ end
81
+ if type =~ /:/
82
+ type = type.split(":", 2)[1]
83
+ end
84
+
85
+ klass = @loader.get(type) or fail "no such type '#{type}'"
86
+ case klass.kind
87
+ when :data
88
+ traverse_data node, klass
89
+ when :enum
90
+ node.content
91
+ when :managed
92
+ leaf_managed node, klass
93
+ else fail
94
+ end
95
+ end
96
+ end
97
+
98
+ def traverse_data node, klass
99
+ obj = klass.new nil
100
+ props = obj.props
101
+ children = node.children.select(&:element?)
102
+ n = children.size
103
+ i = 0
104
+
105
+ klass.full_props_desc.each do |desc|
106
+ name = desc['name']
107
+ child_type = desc['wsdl_type']
108
+
109
+ # Ignore unknown fields
110
+ while child = children[i] and not klass.full_props_set.member? child.name
111
+ i += 1
112
+ end
113
+
114
+ if desc['is-array']
115
+ a = []
116
+ while ((child = children[i]) && (child.name == name))
117
+ child = children[i]
118
+ a << deserialize(child, child_type)
119
+ i += 1
120
+ end
121
+ props[name.to_sym] = a
122
+ elsif ((child = children[i]) && (child.name == name))
123
+ props[name.to_sym] = deserialize(child, child_type)
124
+ i += 1
125
+ end
126
+ end
127
+
128
+ obj
129
+ end
130
+
131
+ def leaf_managed node, klass
132
+ type_attr = node['type']
133
+ klass = @loader.get(type_attr) if type_attr
134
+ klass.new(@conn, node.content)
135
+ end
136
+
137
+ def leaf_date node
138
+ Time.parse node.content
139
+ end
140
+
141
+ def leaf_binary node
142
+ node.content.unpack('m')[0]
143
+ end
144
+
145
+ # XXX does the value need to be deserialized?
146
+ def leaf_keyvalue node
147
+ h = {}
148
+ node.children.each do |child|
149
+ next unless child.element?
150
+ h[child.name] = child.content
151
+ end
152
+ [h['key'], h['value']]
153
+ end
154
+ end
155
+
156
+ class OldDeserializer
157
+ NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
158
+
159
+ def initialize conn
160
+ @conn = conn
161
+ end
162
+
163
+ def deserialize xml, typename=nil
164
+ if IS_JRUBY
165
+ type_attr = xml.attribute_nodes.find { |a| a.name == 'type' &&
166
+ a.namespace &&
167
+ a.namespace.prefix == 'xsi' }
168
+ else
169
+ type_attr = xml.attribute_with_ns('type', NS_XSI)
170
+ end
171
+ typename = (type_attr || typename).to_s
172
+
173
+ if typename =~ /^ArrayOf/
174
+ typename = demangle_array_type $'
175
+ return xml.children.select(&:element?).map { |c| deserialize c, typename }
176
+ end
177
+
178
+ t = @conn.type typename
179
+ if t <= BasicTypes::DataObject
180
+ props_desc = t.full_props_desc
181
+ h = {}
182
+ props_desc.select { |d| d['is-array'] }.each { |d| h[d['name'].to_sym] = [] }
183
+ xml.children.each do |c|
184
+ next unless c.element?
185
+ field = c.name.to_sym
186
+ d = t.find_prop_desc(field.to_s) or next
187
+ o = deserialize c, d['wsdl_type']
188
+ if h[field].is_a? Array
189
+ h[field] << o
190
+ else
191
+ h[field] = o
192
+ end
193
+ end
194
+ t.new h
195
+ elsif t == BasicTypes::ManagedObjectReference
196
+ @conn.type(xml['type']).new @conn, xml.text
197
+ elsif t <= BasicTypes::ManagedObject
198
+ @conn.type(xml['type'] || t.wsdl_name).new @conn, xml.text
199
+ elsif t <= BasicTypes::Enum
200
+ xml.text
201
+ elsif t <= BasicTypes::KeyValue
202
+ h = {}
203
+ xml.children.each do |c|
204
+ next unless c.element?
205
+ h[c.name] = c.text
206
+ end
207
+ [h['key'], h['value']]
208
+ elsif t <= String
209
+ xml.text
210
+ elsif t <= Symbol
211
+ xml.text.to_sym
212
+ elsif t <= Integer
213
+ xml.text.to_i
214
+ elsif t <= Float
215
+ xml.text.to_f
216
+ elsif t <= Time
217
+ Time.parse xml.text
218
+ elsif t == BasicTypes::Boolean
219
+ xml.text == 'true' || xml.text == '1'
220
+ elsif t == BasicTypes::Binary
221
+ xml.text.unpack('m')[0]
222
+ elsif t == BasicTypes::AnyType
223
+ fail "attempted to deserialize an AnyType"
224
+ else fail "unexpected type #{t.inspect} (#{t.ancestors * '/'})"
225
+ end
226
+ rescue
227
+ $stderr.puts "#{$!.class} while deserializing #{xml.name} (#{typename}):"
228
+ $stderr.puts xml.to_s
229
+ raise
230
+ end
231
+
232
+ def demangle_array_type x
233
+ case x
234
+ when 'AnyType' then 'anyType'
235
+ when 'DateTime' then 'dateTime'
236
+ when 'Boolean', 'String', 'Byte', 'Short', 'Int', 'Long', 'Float', 'Double' then x.downcase
237
+ else x
238
+ end
239
+ end
240
+ end
241
+
242
+ if ENV['RBVMOMI_NEW_DESERIALIZER'] == '1' || true # Always use new one now
243
+ Deserializer = NewDeserializer
244
+ else
245
+ Deserializer = OldDeserializer
246
+ end
247
+
248
+ end