Class: RbVmomi::Soap

Inherits:
TrivialSoap show all
Defined in:
lib/rbvmomi.rb

Constant Summary collapse

NS_XSI =
'http://www.w3.org/2001/XMLSchema-instance'

Instance Attribute Summary

Attributes inherited from TrivialSoap

#cookie, #debug, #http

Instance Method Summary collapse

Methods inherited from TrivialSoap

#request, #soap_envelope

Constructor Details

#initialize(opts) ⇒ Soap

Returns a new instance of Soap.



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rbvmomi.rb', line 36

def initialize opts
  @vim_debug = opts[:vim_debug]
  super opts
  @ns = @opts[:ns] or fail "no namespace specified"
  if @opts[:rev]
    @rev = @opts[:rev]
  elsif @opts[:host]
    @rev = '4.0'
    @rev = serviceContent.about.apiVersion
  else
    fail "no revision specified"
  end
end

Instance Method Details

#call(method, desc, this, params) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rbvmomi.rb', line 100

def call method, desc, this, params
  fail "this is not a managed object" unless this.is_a? RbVmomi::VIM::ManagedObject
  fail "parameters must be passed as a hash" unless params.is_a? Hash
  fail unless desc.is_a? Hash

  if @vim_debug
    $stderr.puts "Request #{method}:"
    PP.pp({ _this: this }.merge(params), $stderr)
    $stderr.puts
    start_time = Time.now
  end

  resp = request "#{@ns}/#{@rev}" do |xml|
    emit_request xml, method, desc['params'], this, params
  end

  ret = parse_response resp, desc['result']

  if @vim_debug
    end_time = Time.now
    $stderr.puts "Response (in #{'%.3f' % (end_time - start_time)} s)"
    PP.pp ret, $stderr
    $stderr.puts
  end

  ret
end

#demangle_array_type(x) ⇒ Object



128
129
130
131
132
133
134
135
# File 'lib/rbvmomi.rb', line 128

def demangle_array_type x
  case x
  when 'AnyType' then 'anyType'
  when 'DateTime' then 'dateTime'
  when 'Boolean', 'String', 'Byte', 'Short', 'Int', 'Long', 'Float', 'Double' then x.downcase
  else x
  end
end

#emit_request(xml, method, descs, this, params) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rbvmomi.rb', line 64

def emit_request xml, method, descs, this, params
  xml.tag! method, :xmlns => @ns do
    obj2xml xml, '_this', 'ManagedObject', false, this
    descs.each do |d|
      k = d['name'].to_sym
      if params.member? k or params.member? k.to_s
        v = params.member?(k) ? params[k] : params[k.to_s]
        obj2xml xml, d['name'], d['wsdl_type'], d['is-array'], v
      else
        fail "missing required parameter #{d['name']}" unless d['is-optional']
      end
    end
  end
end

#obj2xml(xml, name, type, is_array, o, attrs = {}) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/rbvmomi.rb', line 190

def obj2xml xml, name, type, is_array, o, attrs={}
  expected = RbVmomi.type(type)
  fail "expected array, got #{o.class.wsdl_name}" if is_array and not o.is_a? Array
  case o
  when Array
    fail "expected #{expected.wsdl_name}, got array" unless is_array
    o.each do |e|
      obj2xml xml, name, expected.wsdl_name, false, e, attrs
    end
  when VIM::ManagedObject
    fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class
    xml.tag! name, o._ref, :type => o.class.wsdl_name
  when VIM::DataObject
    fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class
    xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
      o.class.full_props_desc.each do |desc|
        if o.props.member? desc['name'].to_sym
          v = o.props[desc['name'].to_sym]
          next if v.nil?
          obj2xml xml, desc['name'], desc['wsdl_type'], desc['is-array'], v
        end
      end
    end
  when VIM::Enum
    xml.tag! name, o.value.to_s, attrs
  when Hash
    fail "expected #{expected.wsdl_name}, got a hash" unless expected <= VIM::DataObject
    obj2xml xml, name, type, false, expected.new(o), attrs
  when true, false
    fail "expected #{expected.wsdl_name}, got a boolean" unless expected == Boolean
    attrs['xsi:type'] = 'xsd:boolean' if expected == AnyType
    xml.tag! name, (o ? '1' : '0'), attrs
  when Symbol, String
    if expected == Binary
      attrs['xsi:type'] = 'xsd:base64Binary' if expected == AnyType
      xml.tag! name, [o].pack('m').chomp, attrs
    else
      attrs['xsi:type'] = 'xsd:string' if expected == AnyType
      xml.tag! name, o.to_s, attrs
    end
  when Integer
    attrs['xsi:type'] = 'xsd:long' if expected == AnyType
    xml.tag! name, o.to_s, attrs
  when Float
    attrs['xsi:type'] = 'xsd:double' if expected == AnyType
    xml.tag! name, o.to_s, attrs
  when DateTime
    attrs['xsi:type'] = 'xsd:dateTime' if expected == AnyType
    xml.tag! name, o.to_s, attrs
  else fail "unexpected object class #{o.class}"
  end
  xml
end

#parse_response(resp, desc) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rbvmomi.rb', line 79

def parse_response resp, desc
  if resp.at('faultcode')
    detail = resp.at('detail')
    fault = detail && xml2obj(detail.children.first, 'MethodFault')
    msg = resp.at('faultstring').text
    if fault
      raise RbVmomi.fault msg, fault
    else
      fail "#{resp.at('faultcode').text}: #{msg}"
    end
  else
    if desc
      type = desc['is-task'] ? 'Task' : desc['wsdl_type']
      returnvals = resp.children.select(&:element?).map { |c| xml2obj c, type }
      desc['is-array'] ? returnvals : returnvals.first
    else
      nil
    end
  end
end

#serviceContentObject



54
55
56
# File 'lib/rbvmomi.rb', line 54

def serviceContent
  @serviceContent ||= serviceInstance.RetrieveServiceContent
end

#serviceInstanceObject



50
51
52
# File 'lib/rbvmomi.rb', line 50

def serviceInstance
  VIM::ServiceInstance self, 'ServiceInstance'
end

#xml2obj(xml, type) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/rbvmomi.rb', line 137

def xml2obj xml, type
  type = (xml.attribute_with_ns('type', NS_XSI) || type).to_s

  if type =~ /^ArrayOf/
    type = demangle_array_type $'
    return xml.children.select(&:element?).map { |c| xml2obj c, type }
  end

  t = RbVmomi.type type
  if t <= VIM::DataObject
    #puts "deserializing data object #{t} from #{xml.name}"
    props_desc = t.full_props_desc
    h = {}
    props_desc.select { |d| d['is-array'] }.each { |d| h[d['name'].to_sym] = [] }
    xml.children.each do |c|
      next unless c.element?
      field = c.name.to_sym
      #puts "field #{field.to_s}: #{t.find_prop_desc(field.to_s).inspect}"
      d = t.find_prop_desc(field.to_s) or next
      o = xml2obj c, d['wsdl_type']
      if h[field].is_a? Array
        h[field] << o
      else
        h[field] = o
      end
    end
    t.new h
  elsif t == VIM::ManagedObjectReference
    RbVmomi.type(xml['type']).new self, xml.text
  elsif t <= VIM::ManagedObject
    RbVmomi.type(xml['type'] || t.wsdl_name).new self, xml.text
  elsif t <= VIM::Enum
    xml.text
  elsif t <= String
    xml.text
  elsif t <= Symbol
    xml.text.to_sym
  elsif t <= Integer
    xml.text.to_i
  elsif t <= Float
    xml.text.to_f
  elsif t <= Time
    Time.parse xml.text
  elsif t == Boolean
    xml.text == 'true' || xml.text == '1'
  elsif t == Binary
    xml.text.unpack('m')[0]
  elsif t == AnyType
    fail "attempted to deserialize an AnyType"
  else fail "unexpected type #{t.inspect}"
  end
end