rbvmomi 1.0.2 → 1.1.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.
Files changed (42) hide show
  1. data/.yardopts +5 -0
  2. data/README.rdoc +71 -0
  3. data/Rakefile +11 -0
  4. data/VERSION +1 -1
  5. data/devel/analyze-xml.rb +29 -29
  6. data/{test/test.rb → examples/create_vm.rb} +40 -15
  7. data/examples/extraConfig.rb +54 -0
  8. data/examples/power.rb +57 -0
  9. data/examples/readme-1.rb +35 -0
  10. data/examples/readme-2.rb +51 -0
  11. data/lib/rbvmomi.rb +3 -282
  12. data/lib/rbvmomi/{types.rb → basic_types.rb} +37 -97
  13. data/lib/rbvmomi/connection.rb +239 -0
  14. data/lib/rbvmomi/fault.rb +17 -0
  15. data/lib/{trivial_soap.rb → rbvmomi/trivial_soap.rb} +31 -13
  16. data/lib/rbvmomi/trollop.rb +6 -2
  17. data/lib/rbvmomi/type_loader.rb +72 -0
  18. data/lib/rbvmomi/vim.rb +76 -0
  19. data/lib/rbvmomi/vim/ComputeResource.rb +51 -0
  20. data/lib/rbvmomi/vim/Datacenter.rb +17 -0
  21. data/lib/rbvmomi/vim/Datastore.rb +68 -0
  22. data/lib/rbvmomi/vim/Folder.rb +112 -0
  23. data/lib/rbvmomi/vim/ManagedEntity.rb +46 -0
  24. data/lib/rbvmomi/vim/ManagedObject.rb +55 -0
  25. data/lib/rbvmomi/vim/ObjectContent.rb +23 -0
  26. data/lib/rbvmomi/vim/ObjectUpdate.rb +23 -0
  27. data/lib/rbvmomi/vim/OvfManager.rb +93 -0
  28. data/lib/rbvmomi/vim/ResourcePool.rb +18 -0
  29. data/lib/rbvmomi/vim/ServiceInstance.rb +53 -0
  30. data/lib/rbvmomi/vim/Task.rb +31 -0
  31. data/lib/rbvmomi/vim/VirtualMachine.rb +7 -0
  32. data/test/test_deserialization.rb +11 -55
  33. data/test/test_emit_request.rb +13 -10
  34. data/test/test_exceptions.rb +16 -0
  35. data/test/test_parse_response.rb +2 -10
  36. data/test/test_serialization.rb +14 -11
  37. metadata +41 -25
  38. data/.gitignore +0 -4
  39. data/README.md +0 -12
  40. data/lib/rbvmomi/extensions.rb +0 -491
  41. data/lib/rbvmomi/profile.rb +0 -22
  42. data/test/runner.rb +0 -3
@@ -1,283 +1,4 @@
1
1
  # Copyright (c) 2010 VMware, Inc. All Rights Reserved.
2
- require 'trivial_soap'
3
- require 'time'
4
-
5
- module RbVmomi
6
-
7
- class Boolean; def self.wsdl_name; 'xsd:boolean' end end
8
- class AnyType; def self.wsdl_name; 'xsd:anyType' end end
9
- class Binary; def self.wsdl_name; 'xsd:base64Binary' end end
10
-
11
- def self.type name
12
- fail unless name and (name.is_a? String or name.is_a? Symbol)
13
- name = $' if name.to_s =~ /^xsd:/
14
- case name.to_sym
15
- when :anyType then AnyType
16
- when :boolean then Boolean
17
- when :string then String
18
- when :int, :long, :short, :byte then Integer
19
- when :float, :double then Float
20
- when :dateTime then Time
21
- when :base64Binary then Binary
22
- else
23
- if VIM.has_type? name
24
- VIM.type name
25
- else
26
- fail "no such type #{name.inspect}"
27
- end
28
- end
29
- end
30
-
31
- class DeserializationFailed < Exception; end
32
-
33
- class Soap < TrivialSoap
34
- NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
35
-
36
- def initialize opts
37
- @vim_debug = opts[:vim_debug]
38
- super opts
39
- @ns = @opts[:ns] or fail "no namespace specified"
40
- if @opts[:rev]
41
- @rev = @opts[:rev]
42
- elsif @opts[:host]
43
- @rev = '4.0'
44
- @rev = serviceContent.about.apiVersion
45
- else
46
- fail "no revision specified"
47
- end
48
- end
49
-
50
- def serviceInstance
51
- VIM::ServiceInstance self, 'ServiceInstance'
52
- end
53
-
54
- def serviceContent
55
- @serviceContent ||= serviceInstance.RetrieveServiceContent
56
- end
57
-
58
- %w(rootFolder propertyCollector searchIndex).map(&:to_sym).each do |s|
59
- define_method(s) { serviceContent.send s }
60
- end
61
-
62
- alias root rootFolder
63
-
64
- def emit_request xml, method, descs, this, params
65
- xml.tag! method, :xmlns => @ns do
66
- obj2xml xml, '_this', 'ManagedObject', false, this
67
- descs.each do |d|
68
- k = d['name'].to_sym
69
- if params.member? k or params.member? k.to_s
70
- v = params.member?(k) ? params[k] : params[k.to_s]
71
- obj2xml xml, d['name'], d['wsdl_type'], d['is-array'], v
72
- else
73
- fail "missing required parameter #{d['name']}" unless d['is-optional']
74
- end
75
- end
76
- end
77
- end
78
-
79
- def parse_response resp, desc
80
- if resp.at('faultcode')
81
- detail = resp.at('detail')
82
- fault = detail && xml2obj(detail.children.first, 'MethodFault')
83
- msg = resp.at('faultstring').text
84
- if fault
85
- raise RbVmomi.fault msg, fault
86
- else
87
- fail "#{resp.at('faultcode').text}: #{msg}"
88
- end
89
- else
90
- if desc
91
- type = desc['is-task'] ? 'Task' : desc['wsdl_type']
92
- returnvals = resp.children.select(&:element?).map { |c| xml2obj c, type }
93
- desc['is-array'] ? returnvals : returnvals.first
94
- else
95
- nil
96
- end
97
- end
98
- end
99
-
100
- def call method, desc, this, params
101
- fail "this is not a managed object" unless this.is_a? RbVmomi::VIM::ManagedObject
102
- fail "parameters must be passed as a hash" unless params.is_a? Hash
103
- fail unless desc.is_a? Hash
104
-
105
- if @vim_debug
106
- $stderr.puts "Request #{method}:"
107
- PP.pp({ _this: this }.merge(params), $stderr)
108
- $stderr.puts
109
- start_time = Time.now
110
- end
111
-
112
- resp = request "#{@ns}/#{@rev}" do |xml|
113
- emit_request xml, method, desc['params'], this, params
114
- end
115
-
116
- ret = parse_response resp, desc['result']
117
-
118
- if @vim_debug
119
- end_time = Time.now
120
- $stderr.puts "Response (in #{'%.3f' % (end_time - start_time)} s)"
121
- PP.pp ret, $stderr
122
- $stderr.puts
123
- end
124
-
125
- ret
126
- end
127
-
128
- def demangle_array_type x
129
- case x
130
- when 'AnyType' then 'anyType'
131
- when 'DateTime' then 'dateTime'
132
- when 'Boolean', 'String', 'Byte', 'Short', 'Int', 'Long', 'Float', 'Double' then x.downcase
133
- else x
134
- end
135
- end
136
-
137
- def xml2obj xml, type
138
- type = (xml.attribute_with_ns('type', NS_XSI) || type).to_s
139
-
140
- if type =~ /^ArrayOf/
141
- type = demangle_array_type $'
142
- return xml.children.select(&:element?).map { |c| xml2obj c, type }
143
- end
144
-
145
- t = RbVmomi.type type
146
- if t <= VIM::DataObject
147
- #puts "deserializing data object #{t} from #{xml.name}"
148
- props_desc = t.full_props_desc
149
- h = {}
150
- props_desc.select { |d| d['is-array'] }.each { |d| h[d['name'].to_sym] = [] }
151
- xml.children.each do |c|
152
- next unless c.element?
153
- field = c.name.to_sym
154
- #puts "field #{field.to_s}: #{t.find_prop_desc(field.to_s).inspect}"
155
- d = t.find_prop_desc(field.to_s) or next
156
- o = xml2obj c, d['wsdl_type']
157
- if h[field].is_a? Array
158
- h[field] << o
159
- else
160
- h[field] = o
161
- end
162
- end
163
- t.new h
164
- elsif t == VIM::ManagedObjectReference
165
- RbVmomi.type(xml['type']).new self, xml.text
166
- elsif t <= VIM::ManagedObject
167
- RbVmomi.type(xml['type'] || t.wsdl_name).new self, xml.text
168
- elsif t <= VIM::Enum
169
- xml.text
170
- elsif t <= String
171
- xml.text
172
- elsif t <= Symbol
173
- xml.text.to_sym
174
- elsif t <= Integer
175
- xml.text.to_i
176
- elsif t <= Float
177
- xml.text.to_f
178
- elsif t <= Time
179
- Time.parse xml.text
180
- elsif t == Boolean
181
- xml.text == 'true' || xml.text == '1'
182
- elsif t == Binary
183
- xml.text.unpack('m')[0]
184
- elsif t == AnyType
185
- fail "attempted to deserialize an AnyType"
186
- else fail "unexpected type #{t.inspect}"
187
- end
188
- end
189
-
190
- def obj2xml xml, name, type, is_array, o, attrs={}
191
- expected = RbVmomi.type(type)
192
- fail "expected array, got #{o.class.wsdl_name}" if is_array and not o.is_a? Array
193
- case o
194
- when Array
195
- fail "expected #{expected.wsdl_name}, got array" unless is_array
196
- o.each do |e|
197
- obj2xml xml, name, expected.wsdl_name, false, e, attrs
198
- end
199
- when VIM::ManagedObject
200
- fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class
201
- xml.tag! name, o._ref, :type => o.class.wsdl_name
202
- when VIM::DataObject
203
- fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class
204
- xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
205
- o.class.full_props_desc.each do |desc|
206
- if o.props.member? desc['name'].to_sym
207
- v = o.props[desc['name'].to_sym]
208
- next if v.nil?
209
- obj2xml xml, desc['name'], desc['wsdl_type'], desc['is-array'], v
210
- end
211
- end
212
- end
213
- when VIM::Enum
214
- xml.tag! name, o.value.to_s, attrs
215
- when Hash
216
- fail "expected #{expected.wsdl_name}, got a hash" unless expected <= VIM::DataObject
217
- obj2xml xml, name, type, false, expected.new(o), attrs
218
- when true, false
219
- fail "expected #{expected.wsdl_name}, got a boolean" unless expected == Boolean
220
- attrs['xsi:type'] = 'xsd:boolean' if expected == AnyType
221
- xml.tag! name, (o ? '1' : '0'), attrs
222
- when Symbol, String
223
- if expected == Binary
224
- attrs['xsi:type'] = 'xsd:base64Binary' if expected == AnyType
225
- xml.tag! name, [o].pack('m').chomp, attrs
226
- else
227
- attrs['xsi:type'] = 'xsd:string' if expected == AnyType
228
- xml.tag! name, o.to_s, attrs
229
- end
230
- when Integer
231
- attrs['xsi:type'] = 'xsd:long' if expected == AnyType
232
- xml.tag! name, o.to_s, attrs
233
- when Float
234
- attrs['xsi:type'] = 'xsd:double' if expected == AnyType
235
- xml.tag! name, o.to_s, attrs
236
- when DateTime
237
- attrs['xsi:type'] = 'xsd:dateTime' if expected == AnyType
238
- xml.tag! name, o.to_s, attrs
239
- else fail "unexpected object class #{o.class}"
240
- end
241
- xml
242
- end
243
- end
244
-
245
- # XXX fault class hierarchy
246
- class Fault < StandardError
247
- attr_reader :fault
248
-
249
- def initialize msg, fault
250
- super "#{fault.class.wsdl_name}: #{msg}"
251
- @fault = fault
252
- end
253
- end
254
-
255
- def self.fault msg, fault
256
- Fault.new(msg, fault)
257
- end
258
-
259
- # host, port, ssl, user, password, path, debug
260
- def self.connect opts
261
- fail unless opts.is_a? Hash
262
- fail "host option required" unless opts[:host]
263
- opts[:user] ||= 'root'
264
- opts[:password] ||= ''
265
- opts[:ssl] = true unless opts.member? :ssl
266
- opts[:port] ||= (opts[:ssl] ? 443 : 80)
267
- opts[:path] ||= '/sdk'
268
- opts[:ns] ||= 'urn:vim25'
269
- opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
270
- opts[:vim_debug] = (!ENV['RBVMOMI_VIM_DEBUG'].empty? rescue false) unless opts.member? :vim_debug
271
-
272
- Soap.new(opts).tap do |vim|
273
- vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
274
- end
275
- end
276
-
277
- end
278
-
279
- require 'rbvmomi/types'
280
- vmodl_fn = ENV['VMODL'] || File.join(File.dirname(__FILE__), "../vmodl.cdb")
281
- RbVmomi::VIM.load vmodl_fn
282
-
283
- require 'rbvmomi/extensions'
2
+ module RbVmomi; end
3
+ require 'rbvmomi/connection'
4
+ require 'rbvmomi/vim'
@@ -1,95 +1,16 @@
1
1
  # Copyright (c) 2010 VMware, Inc. All Rights Reserved.
2
- require 'cdb'
3
2
  require 'pp'
4
- require 'set'
5
-
6
- class Class
7
- def wsdl_name
8
- self.class.name
9
- end
10
- end
11
3
 
12
4
  module RbVmomi
5
+ module BasicTypes
13
6
 
14
- module VIM
15
-
16
- BUILTIN_TYPES = %w(ManagedObject TypeName PropertyPath ManagedObjectReference MethodName MethodFault LocalizedMethodFault)
17
-
18
- def self.load fn
19
- @db = CDB.new fn
20
- @vmodl = Hash.new { |h,k| if e = @db[k] then h[k] = Marshal.load(e) end }
21
- @typenames = Marshal.load(@db['_typenames']) + BUILTIN_TYPES
22
- Object.constants.select { |x| @typenames.member? x.to_s }.each { |x| load_type x }
23
- end
24
-
25
- def self.has_type? name
26
- @typenames.member? name.to_s
27
- end
28
-
29
- def self.type name
30
- if has_type? name
31
- const_get(name.to_sym)
32
- else
33
- fail "no such type #{name.inspect}"
34
- end
35
- end
36
-
37
- def self.const_missing sym
38
- if @typenames.member? sym.to_s
39
- load_type sym
40
- else
41
- super
42
- end
43
- end
44
-
45
- def self.method_missing sym, *a
46
- if @typenames.member? sym.to_s
47
- const_get(sym).new *a
48
- else
49
- super
50
- end
51
- end
52
-
53
- def self.load_type sym
54
- const_set sym, make_type(sym)
55
- end
56
-
57
- def self.make_type name
58
- name = name.to_s
59
- desc = @vmodl[name] or fail "unknown VIM type #{name}"
60
- case desc['kind']
61
- when 'data' then make_data_type name, desc
62
- when 'managed' then make_managed_type name, desc
63
- when 'enum' then make_enum_type name, desc
64
- else fail desc.inspect
65
- end
66
- end
67
-
68
- def self.make_data_type name, desc
69
- superclass = const_get(desc['wsdl_base'].to_sym)
70
- Class.new(superclass).tap do |klass|
71
- klass.initialize name, desc['props']
72
- end
73
- end
74
-
75
- def self.make_managed_type name, desc
76
- superclass = const_get(desc['wsdl_base'].to_sym)
77
- Class.new(superclass).tap do |klass|
78
- klass.initialize name, desc['props'], desc['methods']
79
- end
80
- end
81
-
82
- def self.make_enum_type name, desc
83
- Class.new(Enum).tap do |klass|
84
- klass.initialize name, desc['values']
85
- end
86
- end
7
+ BUILTIN = %w(ManagedObject DataObject TypeName PropertyPath ManagedObjectReference MethodName MethodFault LocalizedMethodFault)
87
8
 
88
9
  class Base
89
10
  class << self
90
11
  attr_reader :wsdl_name
91
12
 
92
- def initialize wsdl_name=self.name
13
+ def init wsdl_name=self.name
93
14
  @wsdl_name = wsdl_name
94
15
  end
95
16
 
@@ -98,14 +19,14 @@ class Base
98
19
  end
99
20
  end
100
21
 
101
- initialize
22
+ init
102
23
  end
103
24
 
104
25
  class ObjectWithProperties < Base
105
26
  class << self
106
27
  attr_accessor :props_desc
107
28
 
108
- def initialize name=self.name, props=[]
29
+ def init name=self.name, props=[]
109
30
  super name
110
31
  @props_desc = props
111
32
  @props_desc.each do |d|
@@ -133,14 +54,14 @@ class ObjectWithProperties < Base
133
54
  fail 'unimplemented'
134
55
  end
135
56
 
136
- initialize
57
+ init
137
58
  end
138
59
 
139
60
  class ObjectWithMethods < ObjectWithProperties
140
61
  class << self
141
62
  attr_accessor :methods_desc
142
63
 
143
- def initialize name=self.name, props=[], methods={}
64
+ def init name=self.name, props=[], methods={}
144
65
  super name, props
145
66
  @methods_desc = methods
146
67
 
@@ -157,7 +78,7 @@ class ObjectWithMethods < ObjectWithProperties
157
78
  end
158
79
  end
159
80
 
160
- initialize
81
+ init
161
82
  end
162
83
 
163
84
  class DataObject < ObjectWithProperties
@@ -196,7 +117,7 @@ class DataObject < ObjectWithProperties
196
117
  end
197
118
 
198
119
  def pretty_print q
199
- q.text self.class.name
120
+ q.text self.class.wsdl_name
200
121
  q.group 2 do
201
122
  q.text '('
202
123
  q.breakable
@@ -213,7 +134,7 @@ class DataObject < ObjectWithProperties
213
134
  q.text ')'
214
135
  end
215
136
 
216
- initialize
137
+ init
217
138
  end
218
139
 
219
140
  class ManagedObject < ObjectWithMethods
@@ -273,14 +194,14 @@ class ManagedObject < ObjectWithMethods
273
194
  [self.class, @ref].hash
274
195
  end
275
196
 
276
- initialize 'ManagedObject'
197
+ init 'ManagedObject'
277
198
  end
278
199
 
279
200
  class Enum < Base
280
201
  class << self
281
202
  attr_accessor :values
282
203
 
283
- def initialize name=self.name, values=[]
204
+ def init name=self.name, values=[]
284
205
  super name
285
206
  @values = values
286
207
  end
@@ -292,11 +213,11 @@ class Enum < Base
292
213
  @value = value
293
214
  end
294
215
 
295
- initialize
216
+ init
296
217
  end
297
218
 
298
219
  class MethodFault < DataObject
299
- initialize 'MethodFault', [
220
+ init 'MethodFault', [
300
221
  {
301
222
  'name' => 'faultCause',
302
223
  'wsdl_type' => 'LocalizedMethodFault',
@@ -309,10 +230,14 @@ class MethodFault < DataObject
309
230
  'is-optional' => true,
310
231
  },
311
232
  ]
233
+
234
+ def self.=== exn
235
+ exn.class == RbVmomi::Fault and self <= exn.fault.class
236
+ end
312
237
  end
313
238
 
314
239
  class LocalizedMethodFault < DataObject
315
- initialize 'LocalizedMethodFault', [
240
+ init 'LocalizedMethodFault', [
316
241
  {
317
242
  'name' => 'fault',
318
243
  'wsdl_type' => 'MethodFault',
@@ -327,12 +252,12 @@ class LocalizedMethodFault < DataObject
327
252
  ]
328
253
 
329
254
  def exception
330
- RbVmomi.fault self.localizedMessage, self.fault
255
+ RbVmomi::Fault.new(self.localizedMessage, self.fault)
331
256
  end
332
257
  end
333
258
 
334
259
  class RuntimeFault < MethodFault
335
- initialize
260
+ init
336
261
  end
337
262
 
338
263
  class MethodName < String
@@ -351,6 +276,22 @@ class ManagedObjectReference
351
276
  def self.wsdl_name; 'ManagedObjectReference' end
352
277
  end
353
278
 
279
+ class Boolean
280
+ def self.wsdl_name; 'xsd:boolean' end
281
+ end
282
+
283
+ class AnyType
284
+ def self.wsdl_name; 'xsd:anyType' end
285
+ end
286
+
287
+ class Binary
288
+ def self.wsdl_name; 'xsd:base64Binary' end
289
+ end
290
+
291
+ class ::Class
292
+ def wsdl_name; self.class.name end
293
+ end
294
+
354
295
  class ::String
355
296
  def self.wsdl_name; 'xsd:string' end
356
297
  end
@@ -364,5 +305,4 @@ class ::Float
364
305
  end
365
306
 
366
307
  end
367
-
368
308
  end