rbvmomi 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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