rbvmomi2 3.0.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.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +114 -0
- data/exe/rbvmomish +138 -0
- data/lib/rbvmomi/basic_types.rb +383 -0
- data/lib/rbvmomi/connection.rb +272 -0
- data/lib/rbvmomi/deserialization.rb +249 -0
- data/lib/rbvmomi/fault.rb +19 -0
- data/lib/rbvmomi/optimist.rb +72 -0
- data/lib/rbvmomi/pbm.rb +68 -0
- data/lib/rbvmomi/sms/SmsStorageManager.rb +10 -0
- data/lib/rbvmomi/sms.rb +63 -0
- data/lib/rbvmomi/sso.rb +313 -0
- data/lib/rbvmomi/trivial_soap.rb +122 -0
- data/lib/rbvmomi/type_loader.rb +138 -0
- data/lib/rbvmomi/utils/admission_control.rb +401 -0
- data/lib/rbvmomi/utils/deploy.rb +318 -0
- data/lib/rbvmomi/utils/leases.rb +145 -0
- data/lib/rbvmomi/utils/perfdump.rb +631 -0
- data/lib/rbvmomi/version.rb +6 -0
- data/lib/rbvmomi/vim/ComputeResource.rb +54 -0
- data/lib/rbvmomi/vim/Datacenter.rb +25 -0
- data/lib/rbvmomi/vim/Datastore.rb +72 -0
- data/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb +78 -0
- data/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb +23 -0
- data/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb +54 -0
- data/lib/rbvmomi/vim/Folder.rb +214 -0
- data/lib/rbvmomi/vim/HostSystem.rb +177 -0
- data/lib/rbvmomi/vim/ManagedEntity.rb +60 -0
- data/lib/rbvmomi/vim/ManagedObject.rb +63 -0
- data/lib/rbvmomi/vim/ObjectContent.rb +26 -0
- data/lib/rbvmomi/vim/ObjectUpdate.rb +26 -0
- data/lib/rbvmomi/vim/OvfManager.rb +204 -0
- data/lib/rbvmomi/vim/PerfCounterInfo.rb +28 -0
- data/lib/rbvmomi/vim/PerformanceManager.rb +113 -0
- data/lib/rbvmomi/vim/PropertyCollector.rb +28 -0
- data/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb +33 -0
- data/lib/rbvmomi/vim/ResourcePool.rb +58 -0
- data/lib/rbvmomi/vim/ServiceInstance.rb +58 -0
- data/lib/rbvmomi/vim/Task.rb +68 -0
- data/lib/rbvmomi/vim/VirtualMachine.rb +75 -0
- data/lib/rbvmomi/vim.rb +157 -0
- data/lib/rbvmomi.rb +16 -0
- data/lib/rbvmomi2.rb +3 -0
- data/vmodl.db +0 -0
- metadata +214 -0
@@ -0,0 +1,272 @@
|
|
1
|
+
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
|
4
|
+
require 'time'
|
5
|
+
require 'date'
|
6
|
+
require_relative 'trivial_soap'
|
7
|
+
require_relative 'basic_types'
|
8
|
+
require_relative 'fault'
|
9
|
+
require_relative 'type_loader'
|
10
|
+
require_relative 'deserialization'
|
11
|
+
|
12
|
+
module RbVmomi
|
13
|
+
|
14
|
+
IS_JRUBY = RUBY_PLATFORM == 'java'
|
15
|
+
|
16
|
+
class DeserializationFailed < Exception; end
|
17
|
+
|
18
|
+
class Connection < TrivialSoap
|
19
|
+
NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
|
20
|
+
|
21
|
+
attr_accessor :rev
|
22
|
+
attr_reader :profile
|
23
|
+
attr_reader :profile_summary
|
24
|
+
attr_accessor :profiling
|
25
|
+
attr_reader :deserializer
|
26
|
+
|
27
|
+
def initialize opts
|
28
|
+
@ns = opts[:ns] or fail "no namespace specified"
|
29
|
+
@rev = opts[:rev] or fail "no revision specified"
|
30
|
+
@deserializer = Deserializer.new self
|
31
|
+
reset_profiling
|
32
|
+
@profiling = false
|
33
|
+
super opts
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset_profiling
|
37
|
+
@profile = {}
|
38
|
+
@profile_summary = {:network_latency => 0, :request_emit => 0, :response_parse => 0, :num_calls => 0}
|
39
|
+
end
|
40
|
+
|
41
|
+
def emit_request xml, method, descs, this, params
|
42
|
+
xml.tag! method, :xmlns => @ns do
|
43
|
+
obj2xml xml, '_this', 'ManagedObject', false, this
|
44
|
+
descs.each do |d|
|
45
|
+
k = d['name']
|
46
|
+
k = k.to_sym if !params.member?(k) && params.member?(k.to_sym)
|
47
|
+
v = params[k]
|
48
|
+
if not v == nil
|
49
|
+
obj2xml xml, d['name'], d['wsdl_type'], d['is-array'], v
|
50
|
+
else
|
51
|
+
fail "missing required parameter #{d['name']}" unless d['is-optional']
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_response resp, desc
|
58
|
+
if resp.at('faultcode')
|
59
|
+
detail = resp.at('detail')
|
60
|
+
fault = detail && @deserializer.deserialize(detail.children.first, 'MethodFault')
|
61
|
+
msg = resp.at('faultstring').text
|
62
|
+
if fault
|
63
|
+
raise RbVmomi::Fault.new(msg, fault)
|
64
|
+
else
|
65
|
+
fail "#{resp.at('faultcode').text}: #{msg}"
|
66
|
+
end
|
67
|
+
else
|
68
|
+
if desc
|
69
|
+
type = desc['is-task'] ? 'Task' : desc['wsdl_type']
|
70
|
+
returnvals = resp.children.select(&:element?).map { |c| @deserializer.deserialize c, type }
|
71
|
+
(desc['is-array'] && !desc['is-task']) ? returnvals : returnvals.first
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def call method, desc, this, params
|
79
|
+
fail "this is not a managed object" unless this.is_a? BasicTypes::ManagedObject
|
80
|
+
fail "parameters must be passed as a hash" unless params.is_a? Hash
|
81
|
+
fail unless desc.is_a? Hash
|
82
|
+
|
83
|
+
t1 = Time.now
|
84
|
+
body = soap_envelope do |xml|
|
85
|
+
emit_request xml, method, desc['params'], this, params
|
86
|
+
end.target!
|
87
|
+
|
88
|
+
t2 = Time.now
|
89
|
+
resp, resp_size = request "#{@ns}/#{@rev}", body
|
90
|
+
|
91
|
+
t3 = Time.now
|
92
|
+
out = parse_response resp, desc['result']
|
93
|
+
|
94
|
+
if @profiling
|
95
|
+
t4 = Time.now
|
96
|
+
@profile[method] ||= []
|
97
|
+
profile_info = {
|
98
|
+
:network_latency => (t3 - t2),
|
99
|
+
:request_emit => t2 - t1,
|
100
|
+
:response_parse => t4 - t3,
|
101
|
+
:params => params,
|
102
|
+
:obj => this,
|
103
|
+
:backtrace => caller,
|
104
|
+
:request_size => body.length,
|
105
|
+
:response_size => resp_size,
|
106
|
+
}
|
107
|
+
@profile[method] << profile_info
|
108
|
+
@profile_summary[:network_latency] += profile_info[:network_latency]
|
109
|
+
@profile_summary[:response_parse] += profile_info[:response_parse]
|
110
|
+
@profile_summary[:request_emit] += profile_info[:request_emit]
|
111
|
+
@profile_summary[:num_calls] += 1
|
112
|
+
end
|
113
|
+
|
114
|
+
out
|
115
|
+
end
|
116
|
+
|
117
|
+
# hic sunt dracones
|
118
|
+
def obj2xml xml, name, type, is_array, o, attrs={}
|
119
|
+
expected = type(type)
|
120
|
+
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))
|
121
|
+
case o
|
122
|
+
when Array, BasicTypes::KeyValue
|
123
|
+
if o.is_a? BasicTypes::KeyValue and expected != BasicTypes::KeyValue
|
124
|
+
fail "expected #{expected.wsdl_name} for '#{name}', got KeyValue"
|
125
|
+
elsif expected == BasicTypes::KeyValue and not is_array
|
126
|
+
xml.tag! name, attrs do
|
127
|
+
xml.tag! 'key', o[0].to_s
|
128
|
+
xml.tag! 'value', o[1].to_s
|
129
|
+
end
|
130
|
+
else
|
131
|
+
fail "expected #{expected.wsdl_name} for '#{name}', got array" unless is_array
|
132
|
+
o.each do |e|
|
133
|
+
obj2xml xml, name, expected.wsdl_name, false, e, attrs
|
134
|
+
end
|
135
|
+
end
|
136
|
+
when BasicTypes::ManagedObject
|
137
|
+
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
|
138
|
+
xml.tag! name, o._ref, :type => o.class.wsdl_name
|
139
|
+
when BasicTypes::DataObject
|
140
|
+
if expected and not expected >= o.class and not expected == BasicTypes::AnyType
|
141
|
+
fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}"
|
142
|
+
end
|
143
|
+
xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
|
144
|
+
o.class.full_props_desc.each do |desc|
|
145
|
+
if o.props.member? desc['name'].to_sym
|
146
|
+
v = o.props[desc['name'].to_sym]
|
147
|
+
next if v.nil?
|
148
|
+
obj2xml xml, desc['name'], desc['wsdl_type'], desc['is-array'], v
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
when BasicTypes::Enum
|
153
|
+
xml.tag! name, o.value.to_s, attrs
|
154
|
+
when Hash
|
155
|
+
if expected == BasicTypes::KeyValue and is_array
|
156
|
+
obj2xml xml, name, type, is_array, o.to_a, attrs
|
157
|
+
else
|
158
|
+
fail "expected #{expected.wsdl_name} for '#{name}', got a hash" unless expected <= BasicTypes::DataObject
|
159
|
+
obj2xml xml, name, type, false, expected.new(o), attrs
|
160
|
+
end
|
161
|
+
when true, false
|
162
|
+
fail "expected #{expected.wsdl_name} for '#{name}', got a boolean" unless [BasicTypes::Boolean, BasicTypes::AnyType].member? expected
|
163
|
+
attrs['xsi:type'] = 'xsd:boolean' if expected == BasicTypes::AnyType
|
164
|
+
xml.tag! name, (o ? '1' : '0'), attrs
|
165
|
+
when Symbol, String
|
166
|
+
if expected == BasicTypes::Binary
|
167
|
+
attrs['xsi:type'] = 'xsd:base64Binary' if expected == BasicTypes::AnyType
|
168
|
+
xml.tag! name, [o].pack('m').chomp.gsub("\n", ""), attrs
|
169
|
+
else
|
170
|
+
attrs['xsi:type'] = 'xsd:string' if expected == BasicTypes::AnyType
|
171
|
+
xml.tag! name, o.to_s, attrs
|
172
|
+
end
|
173
|
+
when Integer
|
174
|
+
attrs['xsi:type'] = 'xsd:long' if expected == BasicTypes::AnyType
|
175
|
+
xml.tag! name, o.to_s, attrs
|
176
|
+
when Float
|
177
|
+
attrs['xsi:type'] = 'xsd:double' if expected == BasicTypes::AnyType
|
178
|
+
xml.tag! name, o.to_s, attrs
|
179
|
+
when DateTime
|
180
|
+
attrs['xsi:type'] = 'xsd:dateTime' if expected == BasicTypes::AnyType
|
181
|
+
xml.tag! name, o.strftime('%FT%T%:z'), attrs
|
182
|
+
when Time
|
183
|
+
attrs['xsi:type'] = 'xsd:dateTime' if expected == BasicTypes::AnyType
|
184
|
+
xml.tag! name, o.iso8601, attrs
|
185
|
+
when BasicTypes::Int
|
186
|
+
attrs['xsi:type'] = 'xsd:int'
|
187
|
+
xml.tag! name, o.to_s, attrs
|
188
|
+
else fail "unexpected object class #{o.class} for '#{name}'"
|
189
|
+
end
|
190
|
+
xml
|
191
|
+
rescue
|
192
|
+
$stderr.puts "#{$!.class} while serializing #{name} (#{type}):"
|
193
|
+
PP.pp o, $stderr
|
194
|
+
raise
|
195
|
+
end
|
196
|
+
|
197
|
+
def self.type name
|
198
|
+
fail unless name and (name.is_a? String or name.is_a? Symbol)
|
199
|
+
name = $' if name.to_s =~ /^xsd:/
|
200
|
+
case name.to_sym
|
201
|
+
when :anyType then BasicTypes::AnyType
|
202
|
+
when :boolean then BasicTypes::Boolean
|
203
|
+
when :string then String
|
204
|
+
when :int, :long, :short, :byte then Integer
|
205
|
+
when :float, :double then Float
|
206
|
+
when :dateTime then Time
|
207
|
+
when :base64Binary then BasicTypes::Binary
|
208
|
+
when :KeyValue then BasicTypes::KeyValue
|
209
|
+
else
|
210
|
+
first_char = name[0].chr
|
211
|
+
if first_char.downcase == first_char
|
212
|
+
name = "%s%s" % [first_char.upcase, name[1..-1]]
|
213
|
+
end
|
214
|
+
|
215
|
+
if @loader.has? name
|
216
|
+
const_get(name)
|
217
|
+
else
|
218
|
+
fail "no such type #{name.inspect}"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def type name
|
224
|
+
self.class.type name
|
225
|
+
end
|
226
|
+
|
227
|
+
def instanceUuid
|
228
|
+
nil
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.extension_dirs
|
232
|
+
@extension_dirs ||= []
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.add_extension_dir dir
|
236
|
+
extension_dirs << dir
|
237
|
+
@loader.reload_extensions_dir dir if @loader
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.reload_extensions
|
241
|
+
@loader.reload_extensions
|
242
|
+
end
|
243
|
+
|
244
|
+
def self.loader; @loader; end
|
245
|
+
|
246
|
+
protected
|
247
|
+
|
248
|
+
def self.const_missing sym
|
249
|
+
name = sym.to_s
|
250
|
+
if @loader and @loader.has? name
|
251
|
+
@loader.get(name)
|
252
|
+
else
|
253
|
+
super
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def self.method_missing sym, *a
|
258
|
+
name = sym.to_s
|
259
|
+
if @loader and @loader.has? name
|
260
|
+
@loader.get(name).new(*a)
|
261
|
+
else
|
262
|
+
super
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def self.load_vmodl fn
|
267
|
+
@loader = RbVmomi::TypeLoader.new fn, extension_dirs, self
|
268
|
+
nil
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
module RbVmomi
|
7
|
+
|
8
|
+
class NewDeserializer
|
9
|
+
NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
|
10
|
+
|
11
|
+
DEMANGLED_ARRAY_TYPES = {
|
12
|
+
'AnyType' => 'xsd:anyType',
|
13
|
+
'DateTime' => 'xsd:dateTime',
|
14
|
+
}
|
15
|
+
%w(Boolean String Byte Short Int Long Float Double).each do |x|
|
16
|
+
DEMANGLED_ARRAY_TYPES[x] = "xsd:#{x.downcase}"
|
17
|
+
end
|
18
|
+
|
19
|
+
BUILTIN_TYPE_ACTIONS = {
|
20
|
+
'xsd:string' => :string,
|
21
|
+
'xsd:boolean' => :boolean,
|
22
|
+
'xsd:byte' => :int,
|
23
|
+
'xsd:short' => :int,
|
24
|
+
'xsd:int' => :int,
|
25
|
+
'xsd:long' => :int,
|
26
|
+
'xsd:float' => :float,
|
27
|
+
'xsd:dateTime' => :date,
|
28
|
+
'PropertyPath' => :string,
|
29
|
+
'MethodName' => :string,
|
30
|
+
'TypeName' => :string,
|
31
|
+
'xsd:base64Binary' => :binary,
|
32
|
+
'KeyValue' => :keyvalue,
|
33
|
+
}
|
34
|
+
|
35
|
+
BUILTIN_TYPE_ACTIONS.dup.each do |k,v|
|
36
|
+
if k =~ /^xsd:/
|
37
|
+
BUILTIN_TYPE_ACTIONS[$'] = v
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize conn
|
42
|
+
@conn = conn
|
43
|
+
@loader = conn.class.loader
|
44
|
+
end
|
45
|
+
|
46
|
+
def deserialize node, type=nil
|
47
|
+
type_attr = node['type']
|
48
|
+
|
49
|
+
# Work around for 1.5.x which doesn't populate node['type']
|
50
|
+
# XXX what changed
|
51
|
+
if node.attributes['type'] and not type_attr
|
52
|
+
type_attr = node.attributes['type'].value
|
53
|
+
end
|
54
|
+
|
55
|
+
type = type_attr if type_attr
|
56
|
+
|
57
|
+
if action = BUILTIN_TYPE_ACTIONS[type]
|
58
|
+
case action
|
59
|
+
when :string
|
60
|
+
node.content
|
61
|
+
when :boolean
|
62
|
+
node.content == '1' || node.content == 'true'
|
63
|
+
when :int
|
64
|
+
node.content.to_i
|
65
|
+
when :float
|
66
|
+
node.content.to_f
|
67
|
+
when :date
|
68
|
+
leaf_date node
|
69
|
+
when :binary
|
70
|
+
leaf_binary node
|
71
|
+
when :keyvalue
|
72
|
+
leaf_keyvalue node
|
73
|
+
else fail
|
74
|
+
end
|
75
|
+
else
|
76
|
+
if type =~ /:/
|
77
|
+
type = type.split(":", 2)[1]
|
78
|
+
end
|
79
|
+
if type =~ /^ArrayOf/
|
80
|
+
type = DEMANGLED_ARRAY_TYPES[$'] || $'
|
81
|
+
return node.children.select(&:element?).map { |c| deserialize c, type }
|
82
|
+
end
|
83
|
+
if type =~ /:/
|
84
|
+
type = type.split(":", 2)[1]
|
85
|
+
end
|
86
|
+
|
87
|
+
klass = @loader.get(type) or fail "no such type '#{type}'"
|
88
|
+
case klass.kind
|
89
|
+
when :data
|
90
|
+
traverse_data node, klass
|
91
|
+
when :enum
|
92
|
+
node.content
|
93
|
+
when :managed
|
94
|
+
leaf_managed node, klass
|
95
|
+
else fail
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def traverse_data node, klass
|
101
|
+
obj = klass.new nil
|
102
|
+
props = obj.props
|
103
|
+
children = node.children.select(&:element?)
|
104
|
+
i = 0
|
105
|
+
|
106
|
+
klass.full_props_desc.each do |desc|
|
107
|
+
name = desc['name']
|
108
|
+
child_type = desc['wsdl_type']
|
109
|
+
|
110
|
+
# Ignore unknown fields
|
111
|
+
while child = children[i] and not klass.full_props_set.member? child.name
|
112
|
+
i += 1
|
113
|
+
end
|
114
|
+
|
115
|
+
if desc['is-array']
|
116
|
+
a = []
|
117
|
+
while ((child = children[i]) && (child.name == name))
|
118
|
+
child = children[i]
|
119
|
+
a << deserialize(child, child_type)
|
120
|
+
i += 1
|
121
|
+
end
|
122
|
+
props[name.to_sym] = a
|
123
|
+
elsif ((child = children[i]) && (child.name == name))
|
124
|
+
props[name.to_sym] = deserialize(child, child_type)
|
125
|
+
i += 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
obj
|
130
|
+
end
|
131
|
+
|
132
|
+
def leaf_managed node, klass
|
133
|
+
type_attr = node['type']
|
134
|
+
klass = @loader.get(type_attr) if type_attr
|
135
|
+
klass.new(@conn, node.content)
|
136
|
+
end
|
137
|
+
|
138
|
+
def leaf_date node
|
139
|
+
Time.parse node.content
|
140
|
+
end
|
141
|
+
|
142
|
+
def leaf_binary node
|
143
|
+
node.content.unpack('m')[0]
|
144
|
+
end
|
145
|
+
|
146
|
+
# XXX does the value need to be deserialized?
|
147
|
+
def leaf_keyvalue node
|
148
|
+
h = {}
|
149
|
+
node.children.each do |child|
|
150
|
+
next unless child.element?
|
151
|
+
h[child.name] = child.content
|
152
|
+
end
|
153
|
+
[h['key'], h['value']]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class OldDeserializer
|
158
|
+
NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
|
159
|
+
|
160
|
+
def initialize conn
|
161
|
+
@conn = conn
|
162
|
+
end
|
163
|
+
|
164
|
+
def deserialize xml, typename=nil
|
165
|
+
if IS_JRUBY
|
166
|
+
type_attr = xml.attribute_nodes.find { |a| a.name == 'type' &&
|
167
|
+
a.namespace &&
|
168
|
+
a.namespace.prefix == 'xsi' }
|
169
|
+
else
|
170
|
+
type_attr = xml.attribute_with_ns('type', NS_XSI)
|
171
|
+
end
|
172
|
+
typename = (type_attr || typename).to_s
|
173
|
+
|
174
|
+
if typename =~ /^ArrayOf/
|
175
|
+
typename = demangle_array_type $'
|
176
|
+
return xml.children.select(&:element?).map { |c| deserialize c, typename }
|
177
|
+
end
|
178
|
+
|
179
|
+
t = @conn.type typename
|
180
|
+
if t <= BasicTypes::DataObject
|
181
|
+
props_desc = t.full_props_desc
|
182
|
+
h = {}
|
183
|
+
props_desc.select { |d| d['is-array'] }.each { |d| h[d['name'].to_sym] = [] }
|
184
|
+
xml.children.each do |c|
|
185
|
+
next unless c.element?
|
186
|
+
field = c.name.to_sym
|
187
|
+
d = t.find_prop_desc(field.to_s) or next
|
188
|
+
o = deserialize c, d['wsdl_type']
|
189
|
+
if h[field].is_a? Array
|
190
|
+
h[field] << o
|
191
|
+
else
|
192
|
+
h[field] = o
|
193
|
+
end
|
194
|
+
end
|
195
|
+
t.new h
|
196
|
+
elsif t == BasicTypes::ManagedObjectReference
|
197
|
+
@conn.type(xml['type']).new @conn, xml.text
|
198
|
+
elsif t <= BasicTypes::ManagedObject
|
199
|
+
@conn.type(xml['type'] || t.wsdl_name).new @conn, xml.text
|
200
|
+
elsif t <= BasicTypes::Enum
|
201
|
+
xml.text
|
202
|
+
elsif t <= BasicTypes::KeyValue
|
203
|
+
h = {}
|
204
|
+
xml.children.each do |c|
|
205
|
+
next unless c.element?
|
206
|
+
h[c.name] = c.text
|
207
|
+
end
|
208
|
+
[h['key'], h['value']]
|
209
|
+
elsif t <= String
|
210
|
+
xml.text
|
211
|
+
elsif t <= Symbol
|
212
|
+
xml.text.to_sym
|
213
|
+
elsif t <= Integer
|
214
|
+
xml.text.to_i
|
215
|
+
elsif t <= Float
|
216
|
+
xml.text.to_f
|
217
|
+
elsif t <= Time
|
218
|
+
Time.parse xml.text
|
219
|
+
elsif t == BasicTypes::Boolean
|
220
|
+
xml.text == 'true' || xml.text == '1'
|
221
|
+
elsif t == BasicTypes::Binary
|
222
|
+
xml.text.unpack('m')[0]
|
223
|
+
elsif t == BasicTypes::AnyType
|
224
|
+
fail "attempted to deserialize an AnyType"
|
225
|
+
else fail "unexpected type #{t.inspect} (#{t.ancestors * '/'})"
|
226
|
+
end
|
227
|
+
rescue
|
228
|
+
$stderr.puts "#{$!.class} while deserializing #{xml.name} (#{typename}):"
|
229
|
+
$stderr.puts xml.to_s
|
230
|
+
raise
|
231
|
+
end
|
232
|
+
|
233
|
+
def demangle_array_type x
|
234
|
+
case x
|
235
|
+
when 'AnyType' then 'anyType'
|
236
|
+
when 'DateTime' then 'dateTime'
|
237
|
+
when 'Boolean', 'String', 'Byte', 'Short', 'Int', 'Long', 'Float', 'Double' then x.downcase
|
238
|
+
else x
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
if ENV['RBVMOMI_NEW_DESERIALIZER'] == '1' || true # Always use new one now
|
244
|
+
Deserializer = NewDeserializer
|
245
|
+
else
|
246
|
+
Deserializer = OldDeserializer
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
|
4
|
+
module RbVmomi
|
5
|
+
|
6
|
+
class Fault < StandardError
|
7
|
+
attr_reader :fault
|
8
|
+
|
9
|
+
def initialize msg, fault
|
10
|
+
super "#{fault.class.wsdl_name}: #{msg}"
|
11
|
+
@fault = fault
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing *a
|
15
|
+
@fault.send(*a)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Copyright (c) 2010-2017 VMware, Inc. All Rights Reserved.
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
|
4
|
+
require 'optimist'
|
5
|
+
|
6
|
+
# Convenience methods for Optimist, Ruby's premier option parser.
|
7
|
+
# @see http://optimist.rubyforge.org/
|
8
|
+
# @see Optimist::Parser
|
9
|
+
module Optimist
|
10
|
+
|
11
|
+
# Convenience methods for Optimist, Ruby's premier option parser.
|
12
|
+
#
|
13
|
+
# See the examples directory for sample code.
|
14
|
+
# Descriptions are of the form:
|
15
|
+
# <key>: <options> <environment variable> (<default>)
|
16
|
+
# @see http://optimist.rubyforge.org/
|
17
|
+
class Parser
|
18
|
+
# Options used by VIM.connect
|
19
|
+
#
|
20
|
+
# !!!plain
|
21
|
+
# host: -o --host RBVMOMI_HOST
|
22
|
+
# port: --port RBVMOMI_PORT (443)
|
23
|
+
# no-ssl: --no-ssl RBVMOMI_SSL (false)
|
24
|
+
# insecure: -k --insecure RBVMOMI_INSECURE (false)
|
25
|
+
# user: -u --user RBVMOMI_USER (root)
|
26
|
+
# password: -p --password RBVMOMI_PASSWORD ()
|
27
|
+
# path: --path RBVMOMI_PATH (/sdk)
|
28
|
+
# debug: -d --debug RBVMOMI_DEBUG (false)
|
29
|
+
def rbvmomi_connection_opts
|
30
|
+
opt :host, "host", :type => :string, :short => 'o', :default => ENV['RBVMOMI_HOST']
|
31
|
+
opt :port, "port", :type => :int, :short => :none, :default => (ENV.member?('RBVMOMI_PORT') ? ENV['RBVMOMI_PORT'].to_i : 443)
|
32
|
+
opt :"no-ssl", "don't use ssl", :short => :none, :default => (ENV['RBVMOMI_SSL'] == '0')
|
33
|
+
opt :insecure, "don't verify ssl certificate", :short => 'k', :default => (ENV['RBVMOMI_INSECURE'] == '1')
|
34
|
+
opt :user, "username", :short => 'u', :default => (ENV['RBVMOMI_USER'] || 'root')
|
35
|
+
opt :password, "password", :short => 'p', :default => (ENV['RBVMOMI_PASSWORD'] || '')
|
36
|
+
opt :path, "SOAP endpoint path", :short => :none, :default => (ENV['RBVMOMI_PATH'] || '/sdk')
|
37
|
+
opt :debug, "Log SOAP messages", :short => 'd', :default => (ENV['RBVMOMI_DEBUG'] || false)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Select a datacenter
|
41
|
+
#
|
42
|
+
# !!!plain
|
43
|
+
# datacenter: -D --datacenter RBVMOMI_DATACENTER (ha-datacenter)
|
44
|
+
def rbvmomi_datacenter_opt
|
45
|
+
opt :datacenter, "datacenter", :type => :string, :short => "D", :default => (ENV['RBVMOMI_DATACENTER'] || 'ha-datacenter')
|
46
|
+
end
|
47
|
+
|
48
|
+
# Select a folder
|
49
|
+
#
|
50
|
+
# !!!plain
|
51
|
+
# folder: -F --folder RBVMOMI_FOLDER ()
|
52
|
+
def rbvmomi_folder_opt
|
53
|
+
opt :folder, "VM folder", :type => :string, :short => "F", :default => (ENV['RBVMOMI_FOLDER'] || '')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Select a compute resource
|
57
|
+
#
|
58
|
+
# !!!plain
|
59
|
+
# computer: -R --computer RBVMOMI_COMPUTER
|
60
|
+
def rbvmomi_computer_opt
|
61
|
+
opt :computer, "Compute resource", :type => :string, :short => "R", :default => (ENV['RBVMOMI_COMPUTER']||'ha-compute-res')
|
62
|
+
end
|
63
|
+
|
64
|
+
# Select a datastore
|
65
|
+
#
|
66
|
+
# !!!plain
|
67
|
+
# datastore: -s --datastore RBVMOMI_DATASTORE (datastore1)
|
68
|
+
def rbvmomi_datastore_opt
|
69
|
+
opt :datastore, "Datastore", :short => 's', :default => (ENV['RBVMOMI_DATASTORE'] || 'datastore1')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/rbvmomi/pbm.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Copyright (c) 2012-2017 VMware, Inc. All Rights Reserved.
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
|
4
|
+
require_relative '../rbvmomi'
|
5
|
+
|
6
|
+
module RbVmomi
|
7
|
+
|
8
|
+
# A connection to one vSphere ProfileBasedManagement endpoint.
|
9
|
+
# @see #serviceInstance
|
10
|
+
class PBM < Connection
|
11
|
+
# Connect to a vSphere ProfileBasedManagement endpoint
|
12
|
+
#
|
13
|
+
# @param [VIM] Connection to main vSphere API endpoint
|
14
|
+
# @param [Hash] opts The options hash.
|
15
|
+
# @option opts [String] :host Host to connect to.
|
16
|
+
# @option opts [Numeric] :port (443) Port to connect to.
|
17
|
+
# @option opts [Boolean] :ssl (true) Whether to use SSL.
|
18
|
+
# @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
|
19
|
+
# @option opts [String] :path (/pbm/sdk) SDK endpoint path.
|
20
|
+
# @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
|
21
|
+
def self.connect vim, opts = {}
|
22
|
+
fail unless opts.is_a? Hash
|
23
|
+
opts[:host] = vim.host
|
24
|
+
opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
|
25
|
+
opts[:insecure] ||= false
|
26
|
+
opts[:port] ||= (opts[:ssl] ? 443 : 80)
|
27
|
+
opts[:path] ||= '/pbm/sdk'
|
28
|
+
opts[:ns] ||= 'urn:pbm'
|
29
|
+
rev_given = opts[:rev] != nil
|
30
|
+
opts[:rev] = '1.0' unless rev_given
|
31
|
+
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
|
32
|
+
|
33
|
+
new(opts).tap do |pbm|
|
34
|
+
pbm.vcSessionCookie = vim.cookie.split('"')[1]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def vcSessionCookie= cookie
|
39
|
+
@vcSessionCookie = cookie
|
40
|
+
end
|
41
|
+
|
42
|
+
def rev= x
|
43
|
+
super
|
44
|
+
@serviceContent = nil
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return the ServiceInstance
|
48
|
+
#
|
49
|
+
# The ServiceInstance is the root of the vSphere inventory.
|
50
|
+
def serviceInstance
|
51
|
+
@serviceInstance ||= VIM::PbmServiceInstance self, 'ServiceInstance'
|
52
|
+
end
|
53
|
+
|
54
|
+
# Alias to serviceInstance.PbmRetrieveServiceContent
|
55
|
+
def serviceContent
|
56
|
+
@serviceContent ||= serviceInstance.PbmRetrieveServiceContent
|
57
|
+
end
|
58
|
+
|
59
|
+
# @private
|
60
|
+
def pretty_print pp
|
61
|
+
pp.text "PBM(#{@opts[:host]})"
|
62
|
+
end
|
63
|
+
|
64
|
+
add_extension_dir File.join(File.dirname(__FILE__), "pbm")
|
65
|
+
load_vmodl(ENV['VMODL'] || File.join(File.dirname(__FILE__), "../../vmodl.db"))
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|