rbvmomi2 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +19 -0
  3. data/README.md +114 -0
  4. data/exe/rbvmomish +138 -0
  5. data/lib/rbvmomi/basic_types.rb +383 -0
  6. data/lib/rbvmomi/connection.rb +272 -0
  7. data/lib/rbvmomi/deserialization.rb +249 -0
  8. data/lib/rbvmomi/fault.rb +19 -0
  9. data/lib/rbvmomi/optimist.rb +72 -0
  10. data/lib/rbvmomi/pbm.rb +68 -0
  11. data/lib/rbvmomi/sms/SmsStorageManager.rb +10 -0
  12. data/lib/rbvmomi/sms.rb +63 -0
  13. data/lib/rbvmomi/sso.rb +313 -0
  14. data/lib/rbvmomi/trivial_soap.rb +122 -0
  15. data/lib/rbvmomi/type_loader.rb +138 -0
  16. data/lib/rbvmomi/utils/admission_control.rb +401 -0
  17. data/lib/rbvmomi/utils/deploy.rb +318 -0
  18. data/lib/rbvmomi/utils/leases.rb +145 -0
  19. data/lib/rbvmomi/utils/perfdump.rb +631 -0
  20. data/lib/rbvmomi/version.rb +6 -0
  21. data/lib/rbvmomi/vim/ComputeResource.rb +54 -0
  22. data/lib/rbvmomi/vim/Datacenter.rb +25 -0
  23. data/lib/rbvmomi/vim/Datastore.rb +72 -0
  24. data/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb +78 -0
  25. data/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb +23 -0
  26. data/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb +54 -0
  27. data/lib/rbvmomi/vim/Folder.rb +214 -0
  28. data/lib/rbvmomi/vim/HostSystem.rb +177 -0
  29. data/lib/rbvmomi/vim/ManagedEntity.rb +60 -0
  30. data/lib/rbvmomi/vim/ManagedObject.rb +63 -0
  31. data/lib/rbvmomi/vim/ObjectContent.rb +26 -0
  32. data/lib/rbvmomi/vim/ObjectUpdate.rb +26 -0
  33. data/lib/rbvmomi/vim/OvfManager.rb +204 -0
  34. data/lib/rbvmomi/vim/PerfCounterInfo.rb +28 -0
  35. data/lib/rbvmomi/vim/PerformanceManager.rb +113 -0
  36. data/lib/rbvmomi/vim/PropertyCollector.rb +28 -0
  37. data/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb +33 -0
  38. data/lib/rbvmomi/vim/ResourcePool.rb +58 -0
  39. data/lib/rbvmomi/vim/ServiceInstance.rb +58 -0
  40. data/lib/rbvmomi/vim/Task.rb +68 -0
  41. data/lib/rbvmomi/vim/VirtualMachine.rb +75 -0
  42. data/lib/rbvmomi/vim.rb +157 -0
  43. data/lib/rbvmomi.rb +16 -0
  44. data/lib/rbvmomi2.rb +3 -0
  45. data/vmodl.db +0 -0
  46. metadata +214 -0
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ class RbVmomi::VIM::Datacenter
5
+ # Traverse the given inventory +path+ to find a ComputeResource.
6
+ def find_compute_resource path
7
+ hostFolder.traverse path, RbVmomi::VIM::ComputeResource
8
+ end
9
+
10
+ # Find the Datastore with the given +name+.
11
+ def find_datastore name
12
+ datastore.find { |x| x.name == name }
13
+ end
14
+
15
+ # Traverse the given inventory +path+ to find a VirtualMachine.
16
+ def find_vm path
17
+ vmFolder.traverse path, RbVmomi::VIM::VirtualMachine
18
+ end
19
+
20
+ # Traverse the given inventory +path+ to find a Folder.
21
+ def find_folder path
22
+ vmFolder.traverse path, RbVmomi::VIM::Folder
23
+ end
24
+ end
25
+
@@ -0,0 +1,72 @@
1
+ # Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ # @note +download+ and +upload+ require +curl+. If +curl+ is not in your +PATH+
5
+ # then set the +CURL+ environment variable to point to it.
6
+ # @todo Use an HTTP library instead of executing +curl+.
7
+ class RbVmomi::VIM::Datastore
8
+ CURLBIN = ENV['CURL'] || "curl" #@private
9
+
10
+ # Check whether a file exists on this datastore.
11
+ # @param path [String] Path on the datastore.
12
+ def exists? path
13
+ req = Net::HTTP::Head.new mkuripath(path)
14
+ req.initialize_http_header 'cookie' => _connection.cookie
15
+ resp = _connection.http.request req
16
+ case resp
17
+ when Net::HTTPSuccess
18
+ true
19
+ when Net::HTTPNotFound
20
+ false
21
+ else
22
+ fail resp.inspect
23
+ end
24
+ end
25
+
26
+ # Download a file from this datastore.
27
+ # @param remote_path [String] Source path on the datastore.
28
+ # @param local_path [String] Destination path on the local machine.
29
+ # @return [void]
30
+ def download remote_path, local_path
31
+ url = "http#{_connection.http.use_ssl? ? 's' : ''}://#{_connection.http.address}:#{_connection.http.port}#{mkuripath(remote_path)}"
32
+ pid = spawn CURLBIN, "-k", '--noproxy', '*', '-f',
33
+ "-o", local_path,
34
+ "-b", _connection.cookie,
35
+ url,
36
+ :out => '/dev/null'
37
+ Process.waitpid(pid, 0)
38
+ fail "download failed" unless $?.success?
39
+ end
40
+
41
+ # Upload a file to this datastore.
42
+ # @param remote_path [String] Destination path on the datastore.
43
+ # @param local_path [String] Source path on the local machine.
44
+ # @return [void]
45
+ def upload remote_path, local_path
46
+ url = "http#{_connection.http.use_ssl? ? 's' : ''}://#{_connection.http.address}:#{_connection.http.port}#{mkuripath(remote_path)}"
47
+ pid = spawn CURLBIN, "-k", '--noproxy', '*', '-f',
48
+ "-T", local_path,
49
+ "-b", _connection.cookie,
50
+ url,
51
+ :out => '/dev/null'
52
+ Process.waitpid(pid, 0)
53
+ fail "upload failed" unless $?.success?
54
+ end
55
+
56
+ private
57
+
58
+ def datacenter
59
+ return @datacenter if @datacenter
60
+ x = parent
61
+ while not x.is_a? RbVmomi::VIM::Datacenter
62
+ x = x.parent
63
+ end
64
+ fail unless x.is_a? RbVmomi::VIM::Datacenter
65
+ @datacenter = x
66
+ end
67
+
68
+ def mkuripath path
69
+ datacenter_path_str = datacenter.path[1..-1].map{|elem| elem[1]}.join('/')
70
+ "/folder/#{URI.escape path}?dcPath=#{URI.escape datacenter_path_str }&dsName=#{URI.escape name}"
71
+ end
72
+ end
@@ -0,0 +1,78 @@
1
+ # Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ class RbVmomi::VIM::DynamicTypeMgrAllTypeInfo
5
+ def toRbvmomiTypeHash
6
+ id2name = {}
7
+ id2name.merge!({
8
+ 'string' => 'xsd:string',
9
+ 'java.lang.String' => 'xsd:string',
10
+ 'BOOLEAN' => 'xsd:boolean',
11
+ 'BYTE' => 'xsd:byte',
12
+ 'SHORT' => 'xsd:short',
13
+ 'INT' => 'xsd:int',
14
+ 'LONG' => 'xsd:long',
15
+ 'FLOAT' => 'xsd:float',
16
+ 'DOUBLE' => 'xsd:double',
17
+ 'boolean' => 'xsd:boolean',
18
+ 'byte' => 'xsd:byte',
19
+ 'short' => 'xsd:short',
20
+ 'int' => 'xsd:int',
21
+ 'long' => 'xsd:long',
22
+ 'float' => 'xsd:float',
23
+ 'double' => 'xsd:double',
24
+ 'vmodl.DateTime' => 'xsd:dateTime',
25
+ 'vmodl.Binary' => 'xsd:base64Binary',
26
+ 'vmodl.Any' => 'xsd:anyType',
27
+ 'vim.KeyValue' => 'KeyValue',
28
+ 'void' => nil,
29
+ })
30
+
31
+ %w(DataObject ManagedObject MethodFault MethodName DynamicData
32
+ PropertyPath RuntimeFault TypeName).each do |x|
33
+ id2name['vmodl.' + x] = x
34
+ end
35
+
36
+ types = {}
37
+ self.managedTypeInfo.each{|x| types.merge!(x.toRbvmomiTypeHash) }
38
+ self.dataTypeInfo.each{|x| types.merge!(x.toRbvmomiTypeHash) }
39
+
40
+ types.each do |k,t|
41
+ id2name[t['type-id']] = k
42
+ end
43
+
44
+ types = Hash[types.map do |k,t|
45
+ case t['kind']
46
+ when 'data'
47
+ t['wsdl_base'] = t['base-type-id'] ? id2name[t['base-type-id']] : 'DataObject'
48
+ #t.delete 'base-type-id'
49
+ t['props'].each do |x|
50
+ x['wsdl_type'] = id2name[x['type-id-ref']]
51
+ x.delete 'type-id-ref'
52
+ end
53
+ when 'managed'
54
+ t['wsdl_base'] = t['base-type-id'] ? id2name[t['base-type-id']] : 'ManagedObject'
55
+ #t.delete 'base-type-id'
56
+ t['props'].each do |x|
57
+ x['wsdl_type'] = id2name[x['type-id-ref']]
58
+ x.delete 'type-id-ref'
59
+ end
60
+ t['methods'].each do |mName,x|
61
+ if y = x['result']
62
+ y['wsdl_type'] = id2name[y['type-id-ref']]
63
+ #y.delete 'type-id-ref'
64
+ end
65
+ x['params'].each do |r|
66
+ r['wsdl_type'] = id2name[r['type-id-ref']]
67
+ r.delete 'type-id-ref'
68
+ end
69
+ end
70
+ when 'enum'
71
+ else fail
72
+ end
73
+ [k, t]
74
+ end]
75
+
76
+ types
77
+ end
78
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ class RbVmomi::VIM::DynamicTypeMgrDataTypeInfo
5
+ def toRbvmomiTypeHash
6
+ {
7
+ self.wsdlName => {
8
+ 'kind' => 'data',
9
+ 'type-id' => self.name,
10
+ 'base-type-id' => self.base.first,
11
+ 'props' => self.property.map do |prop|
12
+ {
13
+ 'name' => prop.name,
14
+ 'type-id-ref' => prop.type.gsub("[]", ""),
15
+ 'is-array' => (prop.type =~ /\[\]$/) ? true : false,
16
+ 'is-optional' => prop.annotation.find{|a| a.name == "optional"} ? true : false,
17
+ 'version-id-ref' => prop.version,
18
+ }
19
+ end,
20
+ }
21
+ }
22
+ end
23
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ class RbVmomi::VIM::DynamicTypeMgrManagedTypeInfo
5
+ def toRbvmomiTypeHash
6
+ {
7
+ self.wsdlName => {
8
+ 'kind' => 'managed',
9
+ 'type-id' => self.name,
10
+ 'base-type-id' => self.base.first,
11
+ 'props' => self.property.map do |prop|
12
+ {
13
+ 'name' => prop.name,
14
+ 'type-id-ref' => prop.type.gsub("[]", ""),
15
+ 'is-array' => (prop.type =~ /\[\]$/) ? true : false,
16
+ 'is-optional' => prop.annotation.find{|a| a.name == "optional"} ? true : false,
17
+ 'version-id-ref' => prop.version,
18
+ }
19
+ end,
20
+ 'methods' => Hash[
21
+ self.method.map do |method|
22
+ result = method.returnTypeInfo
23
+
24
+ [method.wsdlName,
25
+ {
26
+ 'params' => method.paramTypeInfo.map do |param|
27
+ {
28
+ 'name' => param.name,
29
+ 'type-id-ref' => param.type.gsub("[]", ""),
30
+ 'is-array' => (param.type =~ /\[\]$/) ? true : false,
31
+ 'is-optional' => param.annotation.find{|a| a.name == "optional"} ? true : false,
32
+ 'version-id-ref' => param.version,
33
+ }
34
+ end,
35
+ 'result' => (
36
+ if result.nil? then
37
+ nil
38
+ else
39
+ {
40
+ 'name' => result.name,
41
+ 'type-id-ref' => result.type.gsub("[]", ""),
42
+ 'is-array' => (result.type =~ /\[\]$/) ? true : false,
43
+ 'is-optional' => result.annotation.find{|a| a.name == "optional"} ? true : false,
44
+ 'version-id-ref' => result.version,
45
+ }
46
+ end)
47
+ }
48
+ ]
49
+ end
50
+ ]
51
+ }
52
+ }
53
+ end
54
+ end
@@ -0,0 +1,214 @@
1
+ # Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ class RbVmomi::VIM::Folder
5
+ # Retrieve a child entity
6
+ # @param name [String] Name of the child.
7
+ # @param type [Class] Return nil unless the found entity <tt>is_a? type</tt>.
8
+ # @return [VIM::ManagedEntity]
9
+ def find name, type=Object
10
+ x = _connection.searchIndex.FindChild(:entity => self, :name => name)
11
+ x if x.is_a? type
12
+ end
13
+
14
+ # Retrieve a virtual machine or host by DNS name
15
+ # @param name [String] The fully qualified domain name to find.
16
+ # @param type [Class] Return nil unless the found entity <tt>is_a? type</tt>.
17
+ # @param dc [RbVmomi::VIM::Datacenter] Restricts the query to entities in the given Datacenter.
18
+ # @return [VIM::ManagedEntity]
19
+ def findByDnsName name, type=RbVmomi::VIM::VirtualMachine, dc=nil
20
+ propSpecs = {
21
+ :entity => self, :dnsName => name,
22
+ :vmSearch => type == RbVmomi::VIM::VirtualMachine
23
+ }
24
+ propSpecs[:datacenter] = dc if dc
25
+ x = _connection.searchIndex.FindByDnsName(propSpecs)
26
+ x if x.is_a? type
27
+ end
28
+
29
+ # Retrieve a virtual machine or host by IP address
30
+ # @param ip [String] The IP address is in dot-decimal notation.
31
+ # @param type [Class] Return nil unless the found entity <tt>is_a? type</tt>.
32
+ # @param dc [RbVmomi::VIM::Datacenter] Restricts the query to entities in the given Datacenter.
33
+ # @return [VIM::ManagedEntity]
34
+ def findByIp ip, type=RbVmomi::VIM::VirtualMachine, dc=nil
35
+ propSpecs = {
36
+ :entity => self, :ip => ip,
37
+ :vmSearch => type == RbVmomi::VIM::VirtualMachine
38
+ }
39
+ propSpecs[:datacenter] = dc if dc
40
+ x = _connection.searchIndex.FindByIp(propSpecs)
41
+ x if x.is_a? type
42
+ end
43
+
44
+ # Finds a virtual machine or host by BIOS or instance UUID
45
+ #
46
+ # @param uuid [String] UUID to find
47
+ # @param type [Class] return nil unless found entity <tt>is_a?(type)</tt>
48
+ # @param dc [RbVmomi::VIM::Datacenter] restricts query to specified datacenter
49
+ #
50
+ # @return [VIM::ManagedEntity]
51
+ def findByUuid(uuid, type = RbVmomi::VIM::VirtualMachine, dc = nil, instance_uuid = false)
52
+ prop_specs = {
53
+ :entity => self,
54
+ :instanceUuid => instance_uuid,
55
+ :uuid => uuid,
56
+ :vmSearch => type == RbVmomi::VIM::VirtualMachine
57
+ }
58
+ prop_specs[:datacenter] = dc if dc
59
+ x = _connection.searchIndex.FindByUuid(prop_specs)
60
+ x if x.is_a?(type)
61
+ end
62
+
63
+ # Retrieve a managed entity by inventory path.
64
+ # @param path [String] A path of the form "My Folder/My Datacenter/vm/Discovered VM/VM1"
65
+ # @return [VIM::ManagedEntity]
66
+ def findByInventoryPath path
67
+ propSpecs = {
68
+ :entity => self, :inventoryPath => path
69
+ }
70
+ _connection.searchIndex.FindByInventoryPath(propSpecs)
71
+ end
72
+
73
+ # Alias to <tt>traverse path, type, true</tt>
74
+ # @see #traverse
75
+ def traverse! path, type=Object
76
+ traverse path, type, true
77
+ end
78
+
79
+ # Retrieve a descendant of this Folder.
80
+ # @param path [String] Path delimited by '/', or an array of path elements.
81
+ # @param type (see Folder#find)
82
+ # @param create [Boolean] If set, create folders that don't exist.
83
+ # @return (see Folder#find)
84
+ # @todo Move +create+ functionality into another method.
85
+ def traverse path, type=Object, create=false
86
+ if path.is_a? String
87
+ es = path.split('/').reject(&:empty?)
88
+ elsif path.is_a? Enumerable
89
+ es = path
90
+ else
91
+ fail "unexpected path class #{path.class}"
92
+ end
93
+ return self if es.empty?
94
+ final = es.pop
95
+
96
+ p = es.inject(self) do |f,e|
97
+ f.find(e, RbVmomi::VIM::Folder) || (create && f.CreateFolder(:name => e)) || return
98
+ end
99
+
100
+ if x = p.find(final, type)
101
+ x
102
+ elsif create and type == RbVmomi::VIM::Folder
103
+ p.CreateFolder(:name => final)
104
+ elsif create and type == RbVmomi::VIM::Datacenter
105
+ p.CreateDatacenter(:name => final)
106
+ else
107
+ nil
108
+ end
109
+ end
110
+
111
+ # Alias to +childEntity+.
112
+ def children
113
+ childEntity
114
+ end
115
+
116
+ # Efficiently retrieve properties from descendants of this folder.
117
+ #
118
+ # @param propSpecs [Hash] Specification of which properties to retrieve from
119
+ # which entities. Keys may be symbols, strings, or
120
+ # classes identifying ManagedEntity subtypes to be
121
+ # included in the results. Values are an array of
122
+ # property paths (strings) or the symbol :all.
123
+ #
124
+ # @return [Hash] Hash of ManagedObjects to properties.
125
+ def inventory_flat propSpecs={}
126
+ propSet = [{ :type => 'Folder', :pathSet => ['name', 'parent', 'childEntity'] }]
127
+ propSpecs.each do |k,v|
128
+ case k
129
+ when Class
130
+ fail "key must be a subclass of ManagedEntity" unless k < RbVmomi::VIM::ManagedEntity
131
+ k = k.wsdl_name
132
+ when Symbol, String
133
+ k = k.to_s
134
+ else
135
+ fail "invalid key"
136
+ end
137
+
138
+ h = { :type => k }
139
+ if v == :all
140
+ h[:all] = true
141
+ elsif v.is_a? Array
142
+ h[:pathSet] = v + %w(parent)
143
+ else
144
+ fail "value must be an array of property paths or :all"
145
+ end
146
+ propSet << h
147
+ end
148
+
149
+ filterSpec = RbVmomi::VIM.PropertyFilterSpec(
150
+ :objectSet => [
151
+ :obj => self,
152
+ :selectSet => [
153
+ RbVmomi::VIM.TraversalSpec(
154
+ :name => 'tsFolder',
155
+ :type => 'Folder',
156
+ :path => 'childEntity',
157
+ :skip => false,
158
+ :selectSet => [
159
+ RbVmomi::VIM.SelectionSpec(:name => 'tsFolder')
160
+ ]
161
+ )
162
+ ]
163
+ ],
164
+ :propSet => propSet
165
+ )
166
+
167
+ result = _connection.propertyCollector.RetrieveProperties(:specSet => [filterSpec])
168
+ {}.tap do |h|
169
+ result.each { |r| h[r.obj] = r }
170
+ end
171
+ end
172
+
173
+ # Efficiently retrieve properties from descendants of this folder.
174
+ #
175
+ # @param propSpecs [Hash] Specification of which properties to retrieve from
176
+ # which entities. Keys may be symbols, strings, or
177
+ # classes identifying ManagedEntity subtypes to be
178
+ # included in the results. Values are an array of
179
+ # property paths (strings) or the symbol :all.
180
+ #
181
+ # @return [Hash] Tree of inventory items. Each node is a hash from
182
+ # VIM::ObjectContent to children.
183
+ def inventory_tree propSpecs={}
184
+ inv = inventory_flat propSpecs
185
+ children = inv.values.group_by { |v| v['parent'] }
186
+ rec = lambda { |parent| Hash[(children[parent]||[]).map { |x| [x, rec[x.obj]] }] }
187
+ rec[self]
188
+ end
189
+
190
+ # Efficiently retrieve properties from descendants of this folder.
191
+ #
192
+ # @param propSpecs [Hash] Specification of which properties to retrieve from
193
+ # which entities. Keys may be symbols, strings, or
194
+ # classes identifying ManagedEntity subtypes to be
195
+ # included in the results. Values are an array of
196
+ # property paths (strings) or the symbol :all.
197
+ #
198
+ # @return [Hash] Tree of inventory items. Folders are hashes from child name
199
+ # to child result. Objects are hashes from property path to
200
+ # value.
201
+ #
202
+ # @deprecated
203
+ def inventory propSpecs={}
204
+ inv = inventory_flat propSpecs
205
+ tree = { self => {} }
206
+ inv.each do |obj,x|
207
+ next if obj == self
208
+ h = Hash[x.propSet.map { |y| [y.name, y.val] }]
209
+ tree[h['parent']][h['name']] = [obj, h]
210
+ tree[obj] = {} if obj.is_a? RbVmomi::VIM::Folder
211
+ end
212
+ tree
213
+ end
214
+ end
@@ -0,0 +1,177 @@
1
+ # Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ module RbVmomi
5
+
6
+ class VIM::HostSystem
7
+ def esxcli
8
+ @cached_esxcli ||= VIM::EsxcliNamespace.root(self)
9
+ end
10
+
11
+ def dtm
12
+ @cached_dtm ||= begin
13
+ RetrieveDynamicTypeManager()
14
+ rescue VIM::MethodNotFound
15
+ if summary.config.product.version >= '4.1.0'
16
+ if summary.config.product.version < '5.0.0' and direct?
17
+ VIM::InternalDynamicTypeManager(_connection, 'ha-dynamic-type-manager')
18
+ else
19
+ raise "esxcli not supported through VC before 5.0.0"
20
+ end
21
+ else
22
+ raise "esxcli not supported before 4.1.0"
23
+ end
24
+ end
25
+ end
26
+
27
+ def dti
28
+ @cached_dti ||= dtm.DynamicTypeMgrQueryTypeInfo
29
+ end
30
+
31
+ def create_dynamic_managed_object inst
32
+ wsdlName = dti.managedTypeInfo.find { |x| x.name == inst.moType }.wsdlName
33
+ _connection.type(wsdlName).new(_connection, inst.id)
34
+ end
35
+
36
+ def cli_info_fetcher
37
+ # XXX there can be more than one
38
+ return @cached_cli_info_fetcher if @cached_cli_info_fetcher
39
+ inst = dtm.DynamicTypeMgrQueryMoInstances.find { |x| x.moType == 'vim.CLIInfo' }
40
+ @cached_cli_info_fetcher = create_dynamic_managed_object inst
41
+ end
42
+
43
+ def mme
44
+ @cached_mme ||= RetrieveManagedMethodExecuter()
45
+ end
46
+
47
+ def direct?
48
+ @ref == 'ha-host'
49
+ end
50
+ end
51
+
52
+ class VIM::EsxcliNamespace
53
+ ESXCLI_PREFIX = 'vim.EsxCLI.'
54
+
55
+ attr_reader :name, :parent, :host, :type, :instance, :type_info, :namespaces, :commands
56
+
57
+ def self.root host
58
+ type_hash = host.dti.toRbvmomiTypeHash
59
+ VIM.loader.add_types type_hash
60
+ all_instances = host.dtm.DynamicTypeMgrQueryMoInstances
61
+ instances = Hash[all_instances.select { |x| x.moType.start_with? ESXCLI_PREFIX }.
62
+ map { |x| [x.moType,x.id] }]
63
+ type_infos = Hash[host.dti.managedTypeInfo.map { |x| [x.name,x] }]
64
+ new('root', nil, host).tap do |root|
65
+ instances.each do |type,instance|
66
+ path = type.split('.')[2..-1]
67
+ ns = path.inject(root) { |b,v| b.namespaces[v] }
68
+ ns.realize type, instance, type_infos[type]
69
+ end
70
+ end
71
+ end
72
+
73
+ def initialize name, parent, host
74
+ @name = name
75
+ @parent = parent
76
+ @host = host
77
+ @type = nil
78
+ @instance = nil
79
+ @type_info = nil
80
+ @namespaces = Hash.new { |h,k| h[k] = self.class.new k, self, host }
81
+ @commands = {}
82
+ @cached_cli_info = nil
83
+ end
84
+
85
+ def realize type, instance, type_info
86
+ fail if @type or @instance
87
+ @type = type
88
+ @instance = instance
89
+ @type_info = type_info
90
+ @type_info.method.each do |method_type_info|
91
+ name = method_type_info.name
92
+ @commands[name] = VIM::EsxcliCommand.new self, method_type_info
93
+ end
94
+ end
95
+
96
+ def type_name
97
+ if @type then @type
98
+ elsif @parent then "#{@parent.type_name}.#{@name}"
99
+ else 'vim.EsxCLI'
100
+ end
101
+ end
102
+
103
+ def cli_info
104
+ @cached_cli_info ||=
105
+ if @host.direct?
106
+ @host.cli_info_fetcher.VimCLIInfoFetchCLIInfo(:typeName => type_name)
107
+ else
108
+ @host.mme.execute(@host.cli_info_fetcher._ref,
109
+ "vim.CLIInfo.FetchCLIInfo", :typeName => type_name)
110
+ end
111
+ end
112
+
113
+ def obj
114
+ conn = @host._connection
115
+ conn.type(@type_info.wsdlName).new(conn, @instance)
116
+ end
117
+
118
+ def method_missing(name, *args)
119
+ name = name.to_s
120
+ if @namespaces.member? name and args.empty?
121
+ @namespaces[name]
122
+ elsif @commands.member? name
123
+ @commands[name].call(*args)
124
+ else
125
+ raise NoMethodError
126
+ end
127
+ end
128
+
129
+ def pretty_print q
130
+ q.text @name
131
+ q.text ' '
132
+ q.group 2 do
133
+ q.text '{'
134
+ q.breakable
135
+ items = (@namespaces.values+@commands.values).sort_by(&:name)
136
+ q.seplist items, nil, :each do |v|
137
+ if v.is_a? VIM::EsxcliNamespace
138
+ q.pp v
139
+ else
140
+ q.text v.name
141
+ end
142
+ end
143
+ end
144
+ q.breakable
145
+ q.text '}'
146
+ end
147
+ end
148
+
149
+ class VIM::EsxcliCommand
150
+ attr_reader :ns, :type_info, :cli_info
151
+
152
+ def initialize ns, type_info
153
+ @ns = ns
154
+ @type_info = type_info
155
+ @cached_cli_info = nil
156
+ end
157
+
158
+ def name
159
+ @type_info.name
160
+ end
161
+
162
+ def cli_info
163
+ @cached_cli_info ||= @ns.cli_info.method.find { |x| x.name == @type_info.name }
164
+ end
165
+
166
+ def call args={}
167
+ if @ns.host.direct?
168
+ @ns.obj._call @type_info.wsdlName, args
169
+ else
170
+ real_args = Set.new(type_info.paramTypeInfo.map(&:name))
171
+ args = args.reject { |k,v| !real_args.member?(k.to_s) }
172
+ @ns.host.mme.execute(@ns.obj._ref, "#{@ns.type_name}.#{@type_info.name}", args)
173
+ end
174
+ end
175
+ end
176
+
177
+ end