This repository has been archived by the owner on Jul 1, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 176
/
verify-vim-wsdl.rb
executable file
·100 lines (79 loc) · 3.32 KB
/
verify-vim-wsdl.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'active_support/core_ext/enumerable'
require 'active_support/inflector'
require 'optimist'
require 'pathname'
require 'rbvmomi'
require 'wsdl/parser'
def parse_args(args)
opts = Optimist.options do
usage <<~HELP
Usage:
verify-vim-wsdl.rb [path to wsdl] [path to vmodl.db]
HELP
opt :fix, 'Optionally fix the wsdl types in the vmodl.db', type: :boolean, default: false
end
Optimist.die('You must provide a wsdl file and a vmodl file') if args.count < 2
wsdl_path = Pathname.new(args.shift).expand_path
Optimist.die('You must pass a path to a wsdl file') if !wsdl_path.exist?
vmodl_path = Pathname.new(args.shift).expand_path
Optimist.die('You must pass a path to the vmodl.db file') if !vmodl_path.exist?
return wsdl_path, vmodl_path, opts
end
def load_wsdl(path)
# WSDL includes have to resolve in the local directory so we have to
# change working directories to where the wsdl is
Dir.chdir(path.dirname) do
WSDL::Parser.new.parse(path.read)
end
end
def load_vmodl(path)
Marshal.load(path.read)
end
def dump_vmodl(vmodl, path)
File.write(path, Marshal.dump(vmodl))
end
# Normalize the type, some of these don't have RbVmomi equivalents such as xsd:long
# and RbVmomi uses ManagedObjects not ManagedObjectReferences as parameters
def wsdl_constantize(type)
type = type.split(':').last
type = 'int' if %w[long short byte].include?(type)
type = 'float' if type == 'double'
type = 'binary' if type == 'base64Binary'
type = 'ManagedObject' if type == 'ManagedObjectReference'
type = type.camelcase
type.safe_constantize || "RbVmomi::BasicTypes::#{type}".safe_constantize || "RbVmomi::VIM::#{type}".safe_constantize
end
wsdl_path, vmodl_path, options = parse_args(ARGV)
vim = load_wsdl(wsdl_path)
vmodl = load_vmodl(vmodl_path)
# Loop through the ComplexTypes in the WSDL and compare their types
# to the types which are defined in the vmodl.db
vim.collect_complextypes.each do |type|
type_name = type.name.name
vmodl_data = vmodl[type_name]
# If a type exists in the WSDL but not in the vmodl.db just skip it, this
# can be for a few reasons including:
# 1. ArrayOf... types are not needed in the vmodl
# 2. A newer wsdl might have some types which haven't been added yet
next if vmodl_data.nil?
# Index the properties by name to make it simpler to find later
elements_by_name = type.elements.index_by { |e| e.name.name }
# Loop through the properties defined in the vmodl.db for this type and
# compare the type to that property as defined in the wsdl.
vmodl_data['props'].each do |vmodl_prop|
wsdl_prop = elements_by_name[vmodl_prop['name']]
next if wsdl_prop.nil?
vmodl_klass = wsdl_constantize(vmodl_prop['wsdl_type'])
wsdl_klass = wsdl_constantize(wsdl_prop.type.source)
# The vmodl class should be equal to or a subclass of the one in the wsdl.
# Example of a subclass is e.g. VirtualMachine.host is defined as a HostSystem
# in the vmodl.db but it is a ManagedObjectReference in the wsdl.
unless vmodl_klass <= wsdl_klass
puts "#{type_name}.#{vmodl_prop["name"]} #{wsdl_klass.wsdl_name} doesn't match #{vmodl_klass.wsdl_name}"
vmodl_prop['wsdl_type'] = wsdl_klass.wsdl_name if options[:fix]
end
end
end
dump_vmodl(vmodl, vmodl_path) if options[:fix]