rbvmomi2 3.1.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: []