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