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.
- data/.yardopts +5 -0
- data/README.rdoc +71 -0
- data/Rakefile +11 -0
- data/VERSION +1 -1
- data/devel/analyze-xml.rb +29 -29
- data/{test/test.rb → examples/create_vm.rb} +40 -15
- data/examples/extraConfig.rb +54 -0
- data/examples/power.rb +57 -0
- data/examples/readme-1.rb +35 -0
- data/examples/readme-2.rb +51 -0
- data/lib/rbvmomi.rb +3 -282
- data/lib/rbvmomi/{types.rb → basic_types.rb} +37 -97
- data/lib/rbvmomi/connection.rb +239 -0
- data/lib/rbvmomi/fault.rb +17 -0
- data/lib/{trivial_soap.rb → rbvmomi/trivial_soap.rb} +31 -13
- data/lib/rbvmomi/trollop.rb +6 -2
- data/lib/rbvmomi/type_loader.rb +72 -0
- data/lib/rbvmomi/vim.rb +76 -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/Folder.rb +112 -0
- data/lib/rbvmomi/vim/ManagedEntity.rb +46 -0
- data/lib/rbvmomi/vim/ManagedObject.rb +55 -0
- data/lib/rbvmomi/vim/ObjectContent.rb +23 -0
- data/lib/rbvmomi/vim/ObjectUpdate.rb +23 -0
- data/lib/rbvmomi/vim/OvfManager.rb +93 -0
- data/lib/rbvmomi/vim/ResourcePool.rb +18 -0
- data/lib/rbvmomi/vim/ServiceInstance.rb +53 -0
- data/lib/rbvmomi/vim/Task.rb +31 -0
- data/lib/rbvmomi/vim/VirtualMachine.rb +7 -0
- data/test/test_deserialization.rb +11 -55
- data/test/test_emit_request.rb +13 -10
- data/test/test_exceptions.rb +16 -0
- data/test/test_parse_response.rb +2 -10
- data/test/test_serialization.rb +14 -11
- metadata +41 -25
- data/.gitignore +0 -4
- data/README.md +0 -12
- data/lib/rbvmomi/extensions.rb +0 -491
- data/lib/rbvmomi/profile.rb +0 -22
- data/test/runner.rb +0 -3
@@ -0,0 +1,239 @@
|
|
1
|
+
# Copyright (c) 2010 VMware, Inc. All Rights Reserved.
|
2
|
+
require 'time'
|
3
|
+
require 'rbvmomi/trivial_soap'
|
4
|
+
require 'rbvmomi/basic_types'
|
5
|
+
require 'rbvmomi/fault'
|
6
|
+
require 'rbvmomi/type_loader'
|
7
|
+
|
8
|
+
module RbVmomi
|
9
|
+
|
10
|
+
class DeserializationFailed < Exception; end
|
11
|
+
|
12
|
+
class Connection < TrivialSoap
|
13
|
+
NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
|
14
|
+
|
15
|
+
attr_accessor :rev
|
16
|
+
|
17
|
+
def initialize opts
|
18
|
+
@ns = opts[:ns] or fail "no namespace specified"
|
19
|
+
@rev = opts[:rev] or fail "no revision specified"
|
20
|
+
super opts
|
21
|
+
end
|
22
|
+
|
23
|
+
def emit_request xml, method, descs, this, params
|
24
|
+
xml.tag! method, :xmlns => @ns do
|
25
|
+
obj2xml xml, '_this', 'ManagedObject', false, this
|
26
|
+
descs.each do |d|
|
27
|
+
k = d['name'].to_sym
|
28
|
+
if params.member? k or params.member? k.to_s
|
29
|
+
v = params.member?(k) ? params[k] : params[k.to_s]
|
30
|
+
obj2xml xml, d['name'], d['wsdl_type'], d['is-array'], v
|
31
|
+
else
|
32
|
+
fail "missing required parameter #{d['name']}" unless d['is-optional']
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_response resp, desc
|
39
|
+
if resp.at('faultcode')
|
40
|
+
detail = resp.at('detail')
|
41
|
+
fault = detail && xml2obj(detail.children.first, 'MethodFault')
|
42
|
+
msg = resp.at('faultstring').text
|
43
|
+
if fault
|
44
|
+
raise RbVmomi::Fault.new(msg, fault)
|
45
|
+
else
|
46
|
+
fail "#{resp.at('faultcode').text}: #{msg}"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
if desc
|
50
|
+
type = desc['is-task'] ? 'Task' : desc['wsdl_type']
|
51
|
+
returnvals = resp.children.select(&:element?).map { |c| xml2obj c, type }
|
52
|
+
desc['is-array'] ? returnvals : returnvals.first
|
53
|
+
else
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def call method, desc, this, params
|
60
|
+
fail "this is not a managed object" unless this.is_a? BasicTypes::ManagedObject
|
61
|
+
fail "parameters must be passed as a hash" unless params.is_a? Hash
|
62
|
+
fail unless desc.is_a? Hash
|
63
|
+
|
64
|
+
resp = request "#{@ns}/#{@rev}" do |xml|
|
65
|
+
emit_request xml, method, desc['params'], this, params
|
66
|
+
end
|
67
|
+
|
68
|
+
parse_response resp, desc['result']
|
69
|
+
end
|
70
|
+
|
71
|
+
def demangle_array_type x
|
72
|
+
case x
|
73
|
+
when 'AnyType' then 'anyType'
|
74
|
+
when 'DateTime' then 'dateTime'
|
75
|
+
when 'Boolean', 'String', 'Byte', 'Short', 'Int', 'Long', 'Float', 'Double' then x.downcase
|
76
|
+
else x
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def xml2obj xml, typename
|
81
|
+
typename = (xml.attribute_with_ns('type', NS_XSI) || typename).to_s
|
82
|
+
|
83
|
+
if typename =~ /^ArrayOf/
|
84
|
+
typename = demangle_array_type $'
|
85
|
+
return xml.children.select(&:element?).map { |c| xml2obj c, typename }
|
86
|
+
end
|
87
|
+
|
88
|
+
t = type typename
|
89
|
+
if t <= BasicTypes::DataObject
|
90
|
+
props_desc = t.full_props_desc
|
91
|
+
h = {}
|
92
|
+
props_desc.select { |d| d['is-array'] }.each { |d| h[d['name'].to_sym] = [] }
|
93
|
+
xml.children.each do |c|
|
94
|
+
next unless c.element?
|
95
|
+
field = c.name.to_sym
|
96
|
+
d = t.find_prop_desc(field.to_s) or next
|
97
|
+
o = xml2obj c, d['wsdl_type']
|
98
|
+
if h[field].is_a? Array
|
99
|
+
h[field] << o
|
100
|
+
else
|
101
|
+
h[field] = o
|
102
|
+
end
|
103
|
+
end
|
104
|
+
t.new h
|
105
|
+
elsif t == BasicTypes::ManagedObjectReference
|
106
|
+
type(xml['type']).new self, xml.text
|
107
|
+
elsif t <= BasicTypes::ManagedObject
|
108
|
+
type(xml['type'] || t.wsdl_name).new self, xml.text
|
109
|
+
elsif t <= BasicTypes::Enum
|
110
|
+
xml.text
|
111
|
+
elsif t <= String
|
112
|
+
xml.text
|
113
|
+
elsif t <= Symbol
|
114
|
+
xml.text.to_sym
|
115
|
+
elsif t <= Integer
|
116
|
+
xml.text.to_i
|
117
|
+
elsif t <= Float
|
118
|
+
xml.text.to_f
|
119
|
+
elsif t <= Time
|
120
|
+
Time.parse xml.text
|
121
|
+
elsif t == BasicTypes::Boolean
|
122
|
+
xml.text == 'true' || xml.text == '1'
|
123
|
+
elsif t == BasicTypes::Binary
|
124
|
+
xml.text.unpack('m')[0]
|
125
|
+
elsif t == BasicTypes::AnyType
|
126
|
+
fail "attempted to deserialize an AnyType"
|
127
|
+
else fail "unexpected type #{t.inspect}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# hic sunt dracones
|
132
|
+
def obj2xml xml, name, type, is_array, o, attrs={}
|
133
|
+
expected = type(type)
|
134
|
+
fail "expected array, got #{o.class.wsdl_name}" if is_array and not o.is_a? Array
|
135
|
+
case o
|
136
|
+
when Array
|
137
|
+
fail "expected #{expected.wsdl_name}, got array" unless is_array
|
138
|
+
o.each do |e|
|
139
|
+
obj2xml xml, name, expected.wsdl_name, false, e, attrs
|
140
|
+
end
|
141
|
+
when BasicTypes::ManagedObject
|
142
|
+
fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class
|
143
|
+
xml.tag! name, o._ref, :type => o.class.wsdl_name
|
144
|
+
when BasicTypes::DataObject
|
145
|
+
fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class
|
146
|
+
xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
|
147
|
+
o.class.full_props_desc.each do |desc|
|
148
|
+
if o.props.member? desc['name'].to_sym
|
149
|
+
v = o.props[desc['name'].to_sym]
|
150
|
+
next if v.nil?
|
151
|
+
obj2xml xml, desc['name'], desc['wsdl_type'], desc['is-array'], v
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
when BasicTypes::Enum
|
156
|
+
xml.tag! name, o.value.to_s, attrs
|
157
|
+
when Hash
|
158
|
+
fail "expected #{expected.wsdl_name}, got a hash" unless expected <= BasicTypes::DataObject
|
159
|
+
obj2xml xml, name, type, false, expected.new(o), attrs
|
160
|
+
when true, false
|
161
|
+
fail "expected #{expected.wsdl_name}, got a boolean" unless expected == BasicTypes::Boolean
|
162
|
+
attrs['xsi:type'] = 'xsd:boolean' if expected == BasicTypes::AnyType
|
163
|
+
xml.tag! name, (o ? '1' : '0'), attrs
|
164
|
+
when Symbol, String
|
165
|
+
if expected == BasicTypes::Binary
|
166
|
+
attrs['xsi:type'] = 'xsd:base64Binary' if expected == BasicTypes::AnyType
|
167
|
+
xml.tag! name, [o].pack('m').chomp, attrs
|
168
|
+
else
|
169
|
+
attrs['xsi:type'] = 'xsd:string' if expected == BasicTypes::AnyType
|
170
|
+
xml.tag! name, o.to_s, attrs
|
171
|
+
end
|
172
|
+
when Integer
|
173
|
+
attrs['xsi:type'] = 'xsd:long' if expected == BasicTypes::AnyType
|
174
|
+
xml.tag! name, o.to_s, attrs
|
175
|
+
when Float
|
176
|
+
attrs['xsi:type'] = 'xsd:double' if expected == BasicTypes::AnyType
|
177
|
+
xml.tag! name, o.to_s, attrs
|
178
|
+
when DateTime
|
179
|
+
attrs['xsi:type'] = 'xsd:dateTime' if expected == BasicTypes::AnyType
|
180
|
+
xml.tag! name, o.to_s, attrs
|
181
|
+
else fail "unexpected object class #{o.class}"
|
182
|
+
end
|
183
|
+
xml
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.type name
|
187
|
+
fail unless name and (name.is_a? String or name.is_a? Symbol)
|
188
|
+
name = $' if name.to_s =~ /^xsd:/
|
189
|
+
case name.to_sym
|
190
|
+
when :anyType then BasicTypes::AnyType
|
191
|
+
when :boolean then BasicTypes::Boolean
|
192
|
+
when :string then String
|
193
|
+
when :int, :long, :short, :byte then Integer
|
194
|
+
when :float, :double then Float
|
195
|
+
when :dateTime then Time
|
196
|
+
when :base64Binary then BasicTypes::Binary
|
197
|
+
else
|
198
|
+
if @loader.has_type? name
|
199
|
+
const_get(name)
|
200
|
+
else
|
201
|
+
fail "no such type #{name.inspect}"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def type name
|
207
|
+
self.class.type name
|
208
|
+
end
|
209
|
+
|
210
|
+
def self.extension_path
|
211
|
+
fail "must be implemented in subclass"
|
212
|
+
end
|
213
|
+
|
214
|
+
protected
|
215
|
+
|
216
|
+
def self.const_missing sym
|
217
|
+
name = sym.to_s
|
218
|
+
if @loader and @loader.has_type? name
|
219
|
+
@loader.load_type name
|
220
|
+
const_get sym
|
221
|
+
else
|
222
|
+
super
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def self.method_missing sym, *a
|
227
|
+
if @loader and @loader.has_type? sym.to_s
|
228
|
+
const_get(sym).new(*a)
|
229
|
+
else
|
230
|
+
super
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def self.load_vmodl fn
|
235
|
+
@loader = RbVmomi::TypeLoader.new self, fn
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright (c) 2010 VMware, Inc. All Rights Reserved.
|
2
|
+
module RbVmomi
|
3
|
+
|
4
|
+
class Fault < StandardError
|
5
|
+
attr_reader :fault
|
6
|
+
|
7
|
+
def initialize msg, fault
|
8
|
+
super "#{fault.class.wsdl_name}: #{msg}"
|
9
|
+
@fault = fault
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing *a
|
13
|
+
@fault.send(*a)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -4,18 +4,19 @@ require 'builder'
|
|
4
4
|
require 'nokogiri'
|
5
5
|
require 'net/http'
|
6
6
|
require 'pp'
|
7
|
-
require 'rbvmomi/profile'
|
8
7
|
|
9
|
-
|
10
|
-
|
8
|
+
module Net
|
9
|
+
class HTTPGenericRequest
|
10
|
+
alias old_exec exec
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def exec sock, ver, path
|
13
|
+
old_exec sock, ver, path
|
14
|
+
sock.io.flush
|
15
|
+
end
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
|
-
class TrivialSoap
|
19
|
+
class RbVmomi::TrivialSoap
|
19
20
|
attr_accessor :debug, :cookie
|
20
21
|
attr_reader :http
|
21
22
|
|
@@ -23,21 +24,31 @@ class TrivialSoap
|
|
23
24
|
fail unless opts.is_a? Hash
|
24
25
|
@opts = opts
|
25
26
|
return unless @opts[:host] # for testcases
|
27
|
+
@debug = @opts[:debug]
|
28
|
+
@cookie = nil
|
29
|
+
@lock = Mutex.new
|
30
|
+
@http = nil
|
31
|
+
restart_http
|
32
|
+
end
|
33
|
+
|
34
|
+
def restart_http
|
35
|
+
@http.finish if @http
|
26
36
|
@http = Net::HTTP.new(@opts[:host], @opts[:port], @opts[:proxyHost], @opts[:proxyPort])
|
27
37
|
if @opts[:ssl]
|
28
38
|
require 'net/https'
|
29
39
|
@http.use_ssl = true
|
30
|
-
@
|
40
|
+
if @opts[:insecure]
|
41
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
42
|
+
else
|
43
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
44
|
+
end
|
31
45
|
@http.cert = OpenSSL::X509::Certificate.new(@opts[:cert]) if @opts[:cert]
|
32
46
|
@http.key = OpenSSL::PKey::RSA.new(@opts[:key]) if @opts[:key]
|
33
47
|
end
|
34
48
|
@http.set_debug_output(STDERR) if $DEBUG
|
35
|
-
@http.read_timeout =
|
49
|
+
@http.read_timeout = 1000000000
|
36
50
|
@http.open_timeout = 5
|
37
51
|
@http.start
|
38
|
-
@debug = @opts[:debug]
|
39
|
-
@cookie = nil
|
40
|
-
@lock = Mutex.new
|
41
52
|
end
|
42
53
|
|
43
54
|
def soap_envelope
|
@@ -65,7 +76,14 @@ class TrivialSoap
|
|
65
76
|
end
|
66
77
|
|
67
78
|
start_time = Time.now
|
68
|
-
response = @lock.synchronize
|
79
|
+
response = @lock.synchronize do
|
80
|
+
begin
|
81
|
+
@http.request_post(@opts[:path], body, headers)
|
82
|
+
rescue Exception
|
83
|
+
restart_http
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
end
|
69
87
|
end_time = Time.now
|
70
88
|
|
71
89
|
@cookie = response['set-cookie'] if response.key? 'set-cookie'
|
data/lib/rbvmomi/trollop.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
+
# Copyright (c) 2011 VMware, Inc. All Rights Reserved.
|
1
2
|
require 'trollop'
|
2
3
|
|
3
|
-
|
4
|
+
module Trollop
|
5
|
+
class Parser
|
4
6
|
def rbvmomi_connection_opts
|
5
7
|
opt :host, "host", type: :string, short: 'o', default: ENV['RBVMOMI_HOST']
|
6
8
|
opt :port, "port", type: :int, short: :none, default: (ENV.member?('RBVMOMI_PORT') ? ENV['RBVMOMI_PORT'].to_i : 443)
|
7
9
|
opt :"no-ssl", "don't use ssl", short: :none, default: (ENV['RBVMOMI_SSL'] == '0')
|
10
|
+
opt :insecure, "don't verify ssl certificate", short: 'k', default: (ENV['RBVMOMI_INSECURE'] == '1')
|
8
11
|
opt :user, "username", short: 'u', default: (ENV['RBVMOMI_USER'] || 'root')
|
9
12
|
opt :password, "password", short: 'p', default: (ENV['RBVMOMI_PASSWORD'] || '')
|
10
13
|
opt :path, "SOAP endpoint path", short: :none, default: (ENV['RBVMOMI_PATH'] || '/sdk')
|
@@ -12,7 +15,7 @@ class Trollop::Parser
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def rbvmomi_datacenter_opt
|
15
|
-
opt :datacenter, "datacenter", type: :string, short: "D", default: (ENV['RBVMOMI_DATACENTER'])
|
18
|
+
opt :datacenter, "datacenter", type: :string, short: "D", default: (ENV['RBVMOMI_DATACENTER'] || 'ha-datacenter')
|
16
19
|
end
|
17
20
|
|
18
21
|
def rbvmomi_folder_opt
|
@@ -27,3 +30,4 @@ class Trollop::Parser
|
|
27
30
|
opt :datastore, "Datastore", short: 's', default: (ENV['RBVMOMI_DATASTORE'] || 'datastore1')
|
28
31
|
end
|
29
32
|
end
|
33
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Copyright (c) 2010 VMware, Inc. All Rights Reserved.
|
2
|
+
require 'cdb'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module RbVmomi
|
6
|
+
|
7
|
+
class TypeLoader
|
8
|
+
def initialize target, fn
|
9
|
+
@target = target
|
10
|
+
@db = CDB.new fn
|
11
|
+
@vmodl = Hash.new { |h,k| if e = @db[k] then h[k] = Marshal.load(e) end }
|
12
|
+
@typenames = Set.new(Marshal.load(@db['_typenames']) + BasicTypes::BUILTIN)
|
13
|
+
@target.constants.select { |x| has_type? x.to_s }.each { |x| load_type x.to_s }
|
14
|
+
BasicTypes::BUILTIN.each do |x|
|
15
|
+
target.const_set x, BasicTypes.const_get(x)
|
16
|
+
load_extension x
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_type? name
|
21
|
+
fail unless name.is_a? String
|
22
|
+
@typenames.member? name
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_type name
|
26
|
+
fail unless name.is_a? String
|
27
|
+
@target.const_set name, make_type(name)
|
28
|
+
load_extension name
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def load_extension name
|
35
|
+
path = @target.extension_path name
|
36
|
+
load path if File.exists? path
|
37
|
+
end
|
38
|
+
|
39
|
+
def make_type name
|
40
|
+
name = name.to_s
|
41
|
+
fail if BasicTypes::BUILTIN.member? name
|
42
|
+
desc = @vmodl[name] or fail "unknown VMODL type #{name}"
|
43
|
+
case desc['kind']
|
44
|
+
when 'data' then make_data_type name, desc
|
45
|
+
when 'managed' then make_managed_type name, desc
|
46
|
+
when 'enum' then make_enum_type name, desc
|
47
|
+
else fail desc.inspect
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def make_data_type name, desc
|
52
|
+
superclass = @target.const_get desc['wsdl_base']
|
53
|
+
Class.new(superclass).tap do |klass|
|
54
|
+
klass.init name, desc['props']
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def make_managed_type name, desc
|
59
|
+
superclass = @target.const_get desc['wsdl_base']
|
60
|
+
Class.new(superclass).tap do |klass|
|
61
|
+
klass.init name, desc['props'], desc['methods']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def make_enum_type name, desc
|
66
|
+
Class.new(BasicTypes::Enum).tap do |klass|
|
67
|
+
klass.init name, desc['values']
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/lib/rbvmomi/vim.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Copyright (c) 2011 VMware, Inc. All Rights Reserved.
|
2
|
+
require 'rbvmomi'
|
3
|
+
|
4
|
+
module RbVmomi
|
5
|
+
|
6
|
+
# A connection to one vSphere SDK endpoint.
|
7
|
+
# @see #serviceInstance
|
8
|
+
class VIM < Connection
|
9
|
+
# Connect to a vSphere SDK endpoint
|
10
|
+
#
|
11
|
+
# @param [Hash] opts The options hash.
|
12
|
+
# @option opts [String] :host Host to connect to.
|
13
|
+
# @option opts [Numeric] :port (443) Port to connect to.
|
14
|
+
# @option opts [Boolean] :ssl (true) Whether to use SSL.
|
15
|
+
# @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
|
16
|
+
# @option opts [String] :user (root) Username.
|
17
|
+
# @option opts [String] :password Password.
|
18
|
+
# @option opts [String] :path (/sdk) SDK endpoint path.
|
19
|
+
# @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
|
20
|
+
def self.connect opts
|
21
|
+
fail unless opts.is_a? Hash
|
22
|
+
fail "host option required" unless opts[:host]
|
23
|
+
opts[:user] ||= 'root'
|
24
|
+
opts[:password] ||= ''
|
25
|
+
opts[:ssl] = true unless opts.member? :ssl
|
26
|
+
opts[:insecure] ||= false
|
27
|
+
opts[:port] ||= (opts[:ssl] ? 443 : 80)
|
28
|
+
opts[:path] ||= '/sdk'
|
29
|
+
opts[:ns] ||= 'urn:vim25'
|
30
|
+
opts[:rev] = '4.1'
|
31
|
+
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
|
32
|
+
|
33
|
+
new(opts).tap do |vim|
|
34
|
+
vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return the ServiceInstance
|
39
|
+
#
|
40
|
+
# The ServiceInstance is the root of the vSphere inventory.
|
41
|
+
# @see http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.ServiceInstance.html
|
42
|
+
def serviceInstance
|
43
|
+
VIM::ServiceInstance self, 'ServiceInstance'
|
44
|
+
end
|
45
|
+
|
46
|
+
# Alias to serviceInstance.RetrieveServiceContent
|
47
|
+
def serviceContent
|
48
|
+
@serviceContent ||= serviceInstance.RetrieveServiceContent
|
49
|
+
end
|
50
|
+
|
51
|
+
# Alias to serviceContent.rootFolder
|
52
|
+
def rootFolder
|
53
|
+
serviceContent.rootFolder
|
54
|
+
end
|
55
|
+
|
56
|
+
alias root rootFolder
|
57
|
+
|
58
|
+
# Alias to serviceContent.propertyCollector
|
59
|
+
def propertyCollector
|
60
|
+
serviceContent.propertyCollector
|
61
|
+
end
|
62
|
+
|
63
|
+
# Alias to serviceContent.searchIndex
|
64
|
+
def searchIndex
|
65
|
+
serviceContent.searchIndex
|
66
|
+
end
|
67
|
+
|
68
|
+
# @private
|
69
|
+
def self.extension_path name
|
70
|
+
File.join(File.dirname(__FILE__), "vim", "#{name}.rb")
|
71
|
+
end
|
72
|
+
|
73
|
+
load_vmodl(ENV['VMODL'] || File.join(File.dirname(__FILE__), "../../vmodl.cdb"))
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|