rbvmomi2 3.1.0 → 3.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf4824d3bb1f25494502cc88370980ae16122a1b57d23b973ba90ad02257450c
4
- data.tar.gz: 924e4c79fe11d3c940b3cc02a75b626209bfb8e899cf3d080afdead2383988c6
3
+ metadata.gz: ca23adf85e7f9aa7fc531ed9c16e45a07c4ed9aedc6725afed17b94aa978c45b
4
+ data.tar.gz: 3b2be36f622eb5ac2311315ce3a39e75245e91684fb22a3fb7574e58fc33375f
5
5
  SHA512:
6
- metadata.gz: dd87f32ab50ec52e75f226048e518717e59d9558948d8d58d3e538e9fab15b4138de8dfed5d9c0501ab30474eb71a643e51033282da6b01151b23b1fca7d7691
7
- data.tar.gz: 2faf225fb094a42118d22ed0be970e136223beb9bf9d62fd49703e0163d7d06f59c54fe9f04c72a1c78d8ec521f0c1e75991af7b757f164716c2702609b2404f
6
+ metadata.gz: 429eb97268d0b4be01876bb6b19371726e7177589418fe7fcae34729b77fc333e19e0d897fbcb6fd3aa5d988b4ed9b36c396e2f2ffb990bd20921dd93052eb52
7
+ data.tar.gz: 037b902b0da661ddc142c2a5eb27df979ac9b91db18c778ec40f102bc094ef16fd9b0f575d290d15299dbe7361ec1cbadbc43f921795615b5acddcc29c20f3ae
@@ -195,8 +195,7 @@ module RbVmomi
195
195
  end
196
196
  xml
197
197
  rescue
198
- $stderr.puts "#{$!.class} while serializing #{name} (#{type}):"
199
- PP.pp o, $stderr
198
+ RbVmomi.logger.error("#{$!.class} while serializing #{name} (#{type})\n#{o.pretty_inspect}")
200
199
  raise
201
200
  end
202
201
 
@@ -221,8 +221,7 @@ module RbVmomi
221
221
  else raise "unexpected type #{t.inspect} (#{t.ancestors * '/'})"
222
222
  end
223
223
  rescue
224
- $stderr.puts "#{$!.class} while deserializing #{xml.name} (#{typename}):"
225
- $stderr.puts xml.to_s
224
+ RbVmomi.logger.error("#{$!.class} while deserializing #{xml.name} (#{typename}):\n#{xml.to_s}")
226
225
  raise
227
226
  end
228
227
 
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RbVmomi
4
+ class << self
5
+ attr_writer :logger
6
+ end
7
+
8
+ def self.logger
9
+ @logger ||= begin
10
+ require 'logger'
11
+ Logger.new($stderr)
12
+ end
13
+ end
14
+ end
data/lib/rbvmomi/pbm.rb CHANGED
@@ -18,7 +18,7 @@ module RbVmomi
18
18
  # @option opts [Boolean] :ssl (true) Whether to use SSL.
19
19
  # @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
20
20
  # @option opts [String] :path (/pbm/sdk) SDK endpoint path.
21
- # @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
21
+ # @option opts [Boolean] :debug (false) If true, print SOAP traffic to RbVmomi.logger.debug.
22
22
  def self.connect vim, opts = {}
23
23
  raise unless opts.is_a? Hash
24
24
 
data/lib/rbvmomi/sms.rb CHANGED
@@ -17,7 +17,7 @@ module RbVmomi
17
17
  # @option opts [Boolean] :ssl (true) Whether to use SSL.
18
18
  # @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
19
19
  # @option opts [String] :path (/sms/sdk) SDK endpoint path.
20
- # @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
20
+ # @option opts [Boolean] :debug (false) If true, print SOAP traffic to RbVmomi.logger.debug.
21
21
  def self.connect vim, opts = {}
22
22
  raise unless opts.is_a? Hash
23
23
 
@@ -84,11 +84,7 @@ class RbVmomi::TrivialSoap
84
84
  headers = { 'content-type' => 'text/xml; charset=utf-8', 'SOAPAction' => action }
85
85
  headers['cookie'] = @cookie if @cookie
86
86
 
87
- if @debug
88
- $stderr.puts 'Request:'
89
- $stderr.puts body
90
- $stderr.puts
91
- end
87
+ RbVmomi.logger.debug("Request:\n#{body}") if @debug
92
88
 
93
89
  if @cookie.nil? && @sso
94
90
  @sso.request_token unless @sso.assertion_id
@@ -112,11 +108,7 @@ class RbVmomi::TrivialSoap
112
108
 
113
109
  nk = Nokogiri(response.body)
114
110
 
115
- if @debug
116
- $stderr.puts "Response (in #{'%.3f' % (end_time - start_time)} s)"
117
- $stderr.puts nk
118
- $stderr.puts
119
- end
111
+ RbVmomi.logger.debug("Response (in #{'%.3f' % (end_time - start_time)} s)\n#{nk}") if @debug
120
112
 
121
113
  [nk.xpath('//soapenv:Body/*').select(&:element?).first, response.body.size]
122
114
  end
@@ -3,5 +3,5 @@
3
3
  # SPDX-License-Identifier: MIT
4
4
 
5
5
  module RbVmomi
6
- VERSION = '3.1.0'.freeze
6
+ VERSION = '3.4.0'.freeze
7
7
  end
data/lib/rbvmomi/vim.rb CHANGED
@@ -18,7 +18,7 @@ module RbVmomi
18
18
  # @option opts [String] :user (root) Username.
19
19
  # @option opts [String] :password Password.
20
20
  # @option opts [String] :path (/sdk) SDK endpoint path.
21
- # @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
21
+ # @option opts [Boolean] :debug (false) If true, print SOAP traffic to RbVmomi.logger.debug.
22
22
  # @option opts [String] :operation_id If set, use for operationID
23
23
  # @option opts [Boolean] :close_on_exit (true) If true, will close connection with at_exit
24
24
  # @option opts [RbVmomi::SSO] :sso (nil) Use SSO token to login if set
@@ -56,7 +56,7 @@ module RbVmomi
56
56
  def close
57
57
  serviceContent.sessionManager.Logout
58
58
  rescue RbVmomi::Fault => e
59
- $stderr.puts(e.message) if debug
59
+ RbVmomi.logger.error(e.message) if debug
60
60
  ensure
61
61
  self.cookie = nil
62
62
  super
data/lib/rbvmomi.rb CHANGED
@@ -12,6 +12,7 @@ module RbVmomi
12
12
  end
13
13
 
14
14
  require_relative 'rbvmomi/connection'
15
+ require_relative 'rbvmomi/logging'
15
16
  require_relative 'rbvmomi/sso'
16
17
  require_relative 'rbvmomi/version'
17
18
  require_relative 'rbvmomi/vim'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './vmodl_helper'
4
+
5
+ namespace :vmodl do
6
+ desc 'Verify vmodl.db'
7
+ task :verify do
8
+ VmodlHelper.verify!
9
+ end
10
+
11
+ desc 'Generate vmodl.db'
12
+ task :generate do
13
+ VmodlHelper.generate!
14
+ end
15
+ end
@@ -0,0 +1,278 @@
1
+ # frozen_string_literal: true
2
+ require 'active_support/core_ext/enumerable'
3
+ require 'active_support/inflector'
4
+ require 'optimist'
5
+ require 'pathname'
6
+ require 'wsdl/parser'
7
+ require 'rbvmomi'
8
+ require 'rbvmomi/pbm'
9
+ require 'rbvmomi/sms'
10
+
11
+ class VmodlHelper
12
+ class << self
13
+ def verify!
14
+ run!('verify')
15
+ end
16
+
17
+ def generate!
18
+ run!('generate')
19
+ end
20
+
21
+ private
22
+
23
+ def run!(mode)
24
+ vmodl, wsdl = options(mode).values_at(:vmodl, :wsdl)
25
+ new(vmodl_path: vmodl, wsdl_path: wsdl).send("#{mode}!")
26
+ end
27
+
28
+ def options(rake_task)
29
+ argv = ARGV.slice_after('--').to_a.last
30
+ Optimist.options(argv) do
31
+ educate_on_error
32
+ opt :wsdl, 'Path to the vsphere-ws wsdl file', type: :string, required: true
33
+ opt :vmodl, 'Path to the vmodl.db', type: :string, default: 'vmodl.db'
34
+ banner <<~EOS
35
+ Usage:
36
+ rake vmodl:#{rake_task} -- --wsdl=path/to/wsdl
37
+ EOS
38
+ end
39
+ end
40
+ end
41
+
42
+ def initialize(vmodl_path:, wsdl_path:)
43
+ @vmodl_path = Pathname.new(vmodl_path)
44
+ @wsdl_path = Pathname.new(wsdl_path)
45
+
46
+ @vmodl = load_vmodl(@vmodl_path)
47
+ @wsdl = load_wsdl(@wsdl_path)
48
+ end
49
+
50
+ def verify!
51
+ # Loop through the ComplexTypes in the WSDL and compare their types
52
+ # to the types which are defined in the vmodl.db
53
+ wsdl_classes_by_name.each_value do |type|
54
+ type_name = type.name.name
55
+ vmodl_data = @vmodl[type_name]
56
+
57
+ # If a type exists in the WSDL but not in the vmodl.db this usually
58
+ # indicates that it was added in a newer version than the current
59
+ # vmodl.db supports.
60
+ #
61
+ # Print a warning that the type is missing and skip it.
62
+ if vmodl_data.nil?
63
+ puts " class #{type_name} is missing"
64
+ next
65
+ end
66
+
67
+ # Index the properties by name to make it simpler to find later
68
+ elements_by_name = type.elements.index_by { |e| e.name.name }
69
+
70
+ # Loop through the properties defined in the vmodl.db for this type and
71
+ # compare the type to that property as defined in the wsdl.
72
+ vmodl_data['props'].each do |vmodl_prop|
73
+ wsdl_prop = elements_by_name[vmodl_prop['name']]
74
+ next if wsdl_prop.nil?
75
+
76
+ vmodl_klass = wsdl_constantize(vmodl_prop['wsdl_type'])
77
+ wsdl_klass = wsdl_constantize(wsdl_prop.type.source)
78
+
79
+ # The vmodl class should be equal to or a subclass of the one in the wsdl.
80
+ # Example of a subclass is e.g. VirtualMachine.host is defined as a HostSystem
81
+ # in the vmodl.db but it is a ManagedObjectReference in the wsdl.
82
+ puts "#{type_name}.#{vmodl_prop["name"]} #{wsdl_klass.wsdl_name} doesn't match #{vmodl_klass.wsdl_name}" unless vmodl_klass <= wsdl_klass
83
+ end
84
+ end
85
+
86
+ # Loop through the SimpleTypes (enums) in the WSDL
87
+ wsdl_enums_by_name.each_value do |enum|
88
+ enum_name = enum.name.name
89
+ vmodl_data = @vmodl[enum_name]
90
+
91
+ if vmodl_data.nil?
92
+ puts " enum #{enum_name} is missing"
93
+ next
94
+ end
95
+ end
96
+ end
97
+
98
+ def generate!
99
+ wsdl_classes_by_name.each_value do |type|
100
+ type_name = type.name.name
101
+
102
+ # Update the existing vmodl object if it exists otherwise instantiate a
103
+ # new one.
104
+ vmodl_data = @vmodl[type_name] || build_wsdl_class!(type)
105
+ props_by_name = vmodl_data['props'].index_by { |prop| prop['name'] }
106
+
107
+ vmodl_data['props'] = wsdl_properties(type).map do |element|
108
+ # NOTE we should prioritize the existing property hash over building a
109
+ # new one because the generic ManagedObjectReferences are manually
110
+ # replaced with their specific counterparts (e.g. Datastore) which
111
+ # cannot be computed programmatically.
112
+ props_by_name[element.name.name] || build_vmodl_property(element)
113
+ end
114
+
115
+ # Some types (e.g. ManagedObjectReference) have extra properties which are
116
+ # not present in the WSDL but are required for proper function of RbVmomi.
117
+ vmodl_data['props'] += extra_props_for_type(type_name)
118
+ end
119
+
120
+ wsdl_enums_by_name.each_value do |enum|
121
+ enum_name = enum.name.name
122
+
123
+ vmodl_data = @vmodl[enum_name] || build_wsdl_enum(enum)
124
+ vmodl_data['values'] = enum.restriction.enumeration
125
+ end
126
+
127
+ wsdl_classes_by_name.each_value do |type|
128
+ type_name = type.name.name
129
+ vmodl_data = @vmodl[type_name]
130
+
131
+ elements_by_name = type.elements.index_by { |e| e.name.name }
132
+
133
+ # Loop through the properties defined in the vmodl.db for this type and
134
+ # compare the type to that property as defined in the wsdl.
135
+ vmodl_data['props'].each do |vmodl_prop|
136
+ wsdl_prop = elements_by_name[vmodl_prop['name']]
137
+ next if wsdl_prop.nil?
138
+
139
+ vmodl_klass = wsdl_constantize(vmodl_prop['wsdl_type'])
140
+ wsdl_klass = wsdl_constantize(wsdl_prop.type.source)
141
+
142
+ vmodl_prop['wsdl_type'] = wsdl_klass.wsdl_name unless vmodl_klass <= wsdl_klass
143
+ end
144
+ end
145
+
146
+ dump_vmodl!
147
+ end
148
+
149
+ protected
150
+
151
+ def load_wsdl(path)
152
+ # WSDL includes have to resolve in the local directory so we have to
153
+ # change working directories to where the wsdl is
154
+ Dir.chdir(path.dirname) do
155
+ WSDL::Parser.new.parse(path.read)
156
+ end
157
+ end
158
+
159
+ def load_vmodl(path)
160
+ Marshal.load(path.read)
161
+ end
162
+
163
+ def dump_vmodl!
164
+ File.write(@vmodl_path, Marshal.dump(@vmodl))
165
+ end
166
+
167
+ private
168
+
169
+ def build_wsdl_class!(type)
170
+ type_name = type.name.name
171
+
172
+ puts "Adding class #{type_name} to vmodl"
173
+
174
+ vmodl_obj = {'kind' => 'data', 'props' => [], 'wsdl_base' => type.complexcontent.extension.base.name}
175
+
176
+ @vmodl[type_name] = vmodl_obj
177
+ @vmodl['_typenames']['_typenames'] << type_name
178
+
179
+ wsdl_to_rbvmomi_namespace(type).loader.add_types(type_name => vmodl_obj)
180
+
181
+ vmodl_obj
182
+ end
183
+
184
+ def build_wsdl_enum(enum)
185
+ enum_name = enum.name.name
186
+
187
+ puts "Adding enum #{enum_name} to vmodl"
188
+
189
+ vmodl_obj = {'kind' => 'enum', 'values' => []}
190
+
191
+ @vmodl[enum_name] = vmodl_obj
192
+ @vmodl['_typenames']['_typenames'] << enum_name
193
+
194
+ wsdl_to_rbvmomi_namespace(enum).loader.add_types(enum_name => vmodl_obj)
195
+
196
+ vmodl_obj
197
+ end
198
+
199
+ def build_vmodl_property(element)
200
+ {
201
+ 'name' => element.name.name,
202
+ 'is-optional' => element.minoccurs == 0,
203
+ 'is-array' => element.maxoccurs != 1,
204
+ 'version-id-ref' => nil,
205
+ 'wsdl_type' => wsdl_to_vmodl_type(element.type)
206
+ }
207
+ end
208
+
209
+ def wsdl_properties(type)
210
+ base_class = wsdl_classes_by_name[type.complexcontent&.extension&.base&.name]
211
+ if base_class
212
+ inherited_properties = base_class.elements.map { |element| element.name.name }
213
+ type.elements.reject { |e| inherited_properties.include?(e.name.name) }
214
+ else
215
+ type.elements
216
+ end
217
+ end
218
+
219
+ def extra_props_for_type(type)
220
+ @extra_props_for_type ||= {
221
+ 'ManagedObjectReference' => [
222
+ {'name' => 'type', 'is-optional' => false, 'is-array' => false, 'version-id-ref' => nil, 'wsdl_type' => 'xsd:string'},
223
+ {'name' => 'value', 'is-optional' => false, 'is-array' => false, 'version-id-ref' => nil, 'wsdl_type' => 'xsd:string'}
224
+ ]
225
+ }
226
+
227
+ @extra_props_for_type[type] || []
228
+ end
229
+
230
+ def wsdl_classes_by_name
231
+ @wsdl_classes_by_name ||= @wsdl.collect_complextypes
232
+ .reject { |type| type.name.name.match?(/^ArrayOf|RequestType$/) }
233
+ .index_by { |type| type.name.name }
234
+ end
235
+
236
+ def wsdl_enums_by_name
237
+ @wsdl_enums_by_name ||= @wsdl.collect_simpletypes.index_by { |type| type.name.name }
238
+ end
239
+
240
+ def wsdl_to_vmodl_type(type)
241
+ case type.source
242
+ when /vim25:/, /pbm:/, /sms:/
243
+ vmodl_type = type.name == 'ManagedObjectReference' ? 'ManagedObject' : type.name
244
+ when /xsd:/
245
+ vmodl_type = type.source
246
+ else
247
+ raise ArgumentError, "Unrecognized wsdl type: [#{type}]"
248
+ end
249
+
250
+ vmodl_type
251
+ end
252
+
253
+ def wsdl_to_rbvmomi_namespace(type)
254
+ case type.targetnamespace
255
+ when 'urn:vim25'
256
+ RbVmomi::VIM
257
+ when 'urn:pbm'
258
+ RbVmomi::PBM
259
+ when 'urn:sms'
260
+ RbVmomi::SMS
261
+ else
262
+ raise ArgumentError, "Unrecognized namespace [#{type}]"
263
+ end
264
+ end
265
+
266
+ # Normalize the type, some of these don't have RbVmomi equivalents such as xsd:long
267
+ # and RbVmomi uses ManagedObjects not ManagedObjectReferences as parameters
268
+ def wsdl_constantize(type)
269
+ type = type.split(':').last
270
+ type = 'int' if %w[long short byte].include?(type)
271
+ type = 'float' if type == 'double'
272
+ type = 'binary' if type == 'base64Binary'
273
+ type = 'ManagedObject' if type == 'ManagedObjectReference'
274
+
275
+ type = type.camelcase
276
+ type.safe_constantize || "RbVmomi::BasicTypes::#{type}".safe_constantize || "#{wsdl_to_rbvmomi_namespace(@wsdl)}::#{type}".safe_constantize
277
+ end
278
+ end
data/vmodl.db CHANGED
Binary file
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbvmomi2
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Grare
8
8
  - Jason Frey
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-09-23 00:00:00.000000000 Z
12
+ date: 2022-09-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: builder
@@ -43,16 +43,22 @@ dependencies:
43
43
  name: nokogiri
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 1.12.5
46
49
  - - "~>"
47
50
  - !ruby/object:Gem::Version
48
- version: '1.10'
51
+ version: '1.12'
49
52
  type: :runtime
50
53
  prerelease: false
51
54
  version_requirements: !ruby/object:Gem::Requirement
52
55
  requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 1.12.5
53
59
  - - "~>"
54
60
  - !ruby/object:Gem::Version
55
- version: '1.10'
61
+ version: '1.12'
56
62
  - !ruby/object:Gem::Dependency
57
63
  name: optimist
58
64
  requirement: !ruby/object:Gem::Requirement
@@ -87,14 +93,14 @@ dependencies:
87
93
  requirements:
88
94
  - - "~>"
89
95
  - !ruby/object:Gem::Version
90
- version: 0.13.1
96
+ version: 0.14.1
91
97
  type: :development
92
98
  prerelease: false
93
99
  version_requirements: !ruby/object:Gem::Requirement
94
100
  requirements:
95
101
  - - "~>"
96
102
  - !ruby/object:Gem::Version
97
- version: 0.13.1
103
+ version: 0.14.1
98
104
  - !ruby/object:Gem::Dependency
99
105
  name: rake
100
106
  requirement: !ruby/object:Gem::Requirement
@@ -179,7 +185,7 @@ dependencies:
179
185
  - - "~>"
180
186
  - !ruby/object:Gem::Version
181
187
  version: 0.9.25
182
- description:
188
+ description:
183
189
  email:
184
190
  - adam@grare.com
185
191
  - fryguy9@gmail.com
@@ -196,6 +202,7 @@ files:
196
202
  - lib/rbvmomi/connection.rb
197
203
  - lib/rbvmomi/deserialization.rb
198
204
  - lib/rbvmomi/fault.rb
205
+ - lib/rbvmomi/logging.rb
199
206
  - lib/rbvmomi/optimist.rb
200
207
  - lib/rbvmomi/pbm.rb
201
208
  - lib/rbvmomi/sms.rb
@@ -231,12 +238,14 @@ files:
231
238
  - lib/rbvmomi/vim/Task.rb
232
239
  - lib/rbvmomi/vim/VirtualMachine.rb
233
240
  - lib/rbvmomi2.rb
241
+ - lib/tasks/vmodl.rake
242
+ - lib/tasks/vmodl_helper.rb
234
243
  - vmodl.db
235
244
  homepage: https://github.com/ManageIQ/rbvmomi2
236
245
  licenses:
237
246
  - MIT
238
247
  metadata: {}
239
- post_install_message:
248
+ post_install_message:
240
249
  rdoc_options: []
241
250
  require_paths:
242
251
  - lib
@@ -251,8 +260,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
251
260
  - !ruby/object:Gem::Version
252
261
  version: '0'
253
262
  requirements: []
254
- rubygems_version: 3.2.5
255
- signing_key:
263
+ rubygems_version: 3.3.15
264
+ signing_key:
256
265
  specification_version: 4
257
266
  summary: Ruby interface to the VMware vSphere API
258
267
  test_files: []