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.
- 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,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
|