rubywbem 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ #
2
+ # Copyright 2006, Red Hat, Inc
3
+ # Scott Seago <sseago@redhat.com>
4
+ #
5
+ # derived from pywbem, written by Tim Potter <tpot@hp.com>, Martin Pool <mbp@hp.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, write to the Free Software
14
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+ #
16
+ require "wbem/cim_constants"
17
+ require "wbem/cim_http"
18
+ require "wbem/cim_obj"
19
+ require "wbem/cim_types"
20
+ require "wbem/cim_operations"
21
+ require "wbem/cim_xml"
22
+ require "wbem/tupleparse"
23
+ require "wbem/tupletree"
@@ -0,0 +1,50 @@
1
+ #
2
+ # Copyright 2006, Red Hat, Inc
3
+ # Scott Seago <sseago@redhat.com>
4
+ #
5
+ # derived from pywbem, written by Tim Potter <tpot@hp.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, write to the Free Software
14
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+ #
16
+ #"""Useful CIM constants."""
17
+
18
+ module WBEM
19
+
20
+ # CIMError error code constants
21
+
22
+ CIM_ERR_FAILED = 1 # A general error occurred
23
+ CIM_ERR_ACCESS_DENIED = 2 # Resource not available
24
+ CIM_ERR_INVALID_NAMESPACE = 3 # The target namespace does not exist
25
+ CIM_ERR_INVALID_PARAMETER = 4 # Parameter value(s) invalid
26
+ CIM_ERR_INVALID_CLASS = 5 # The specified Class does not exist
27
+ CIM_ERR_NOT_FOUND = 6 # Requested object could not be found
28
+ CIM_ERR_NOT_SUPPORTED = 7 # Operation not supported
29
+ CIM_ERR_CLASS_HAS_CHILDREN = 8 # Class has subclasses
30
+ CIM_ERR_CLASS_HAS_INSTANCES = 9 # Class has instances
31
+ CIM_ERR_INVALID_SUPERCLASS = 10 # Superclass does not exist
32
+ CIM_ERR_ALREADY_EXISTS = 11 # Object already exists
33
+ CIM_ERR_NO_SUCH_PROPERTY = 12 # Property does not exist
34
+ CIM_ERR_TYPE_MISMATCH = 13 # Value incompatible with type
35
+ CIM_ERR_QUERY_LANGUAGE_NOT_SUPPORTED = 14 # Query language not supported
36
+ CIM_ERR_INVALID_QUERY = 15 # Query not valid
37
+ CIM_ERR_METHOD_NOT_AVAILABLE = 16 # Extrinsic method not executed
38
+ CIM_ERR_METHOD_NOT_FOUND = 17 # Extrinsic method does not exist
39
+
40
+ # Provider types
41
+
42
+ PROVIDERTYPE_CLASS = 1
43
+ PROVIDERTYPE_INSTANCE = 2
44
+ PROVIDERTYPE_ASSOCIATION = 3
45
+ PROVIDERTYPE_INDICATION = 4
46
+ PROVIDERTYPE_METHOD = 5
47
+ PROVIDERTYPE_CONSUMER = 6 # Indication consumer
48
+ PROVIDERTYPE_QUERY = 7
49
+
50
+ end
@@ -0,0 +1,137 @@
1
+ #
2
+ # Copyright 2006, Red Hat, Inc
3
+ # Scott Seago <sseago@redhat.com>
4
+ #
5
+ # derived from pywbem, written by Tim Potter <tpot@hp.com>, Martin Pool <mbp@hp.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, write to the Free Software
14
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+ #
16
+
17
+ #'''
18
+ #This module implements CIM operations over HTTP.
19
+ #
20
+ #This module should not know anything about the fact that the data
21
+ #being transferred is XML. It is up to the caller to format the input
22
+ #data and interpret the result.
23
+ #'''
24
+
25
+ require "wbem/cim_obj"
26
+ require "net/https"
27
+
28
+ module WBEM
29
+ class CIMHttpError < Exception
30
+ # """This exception is raised when a transport error occurs."""
31
+ end
32
+ class AuthError < StandardError
33
+ #"""This exception is raised when an authentication error (401) occurs."""
34
+ end
35
+
36
+ def WBEM.parse_url(url)
37
+ #"""Return an array of (host, port, ssl, credentials) from the URL parameter.
38
+ #The returned port defaults to 5988 if not specified. SSL supports
39
+ #defaults to False if not specified. Credentials are optional
40
+ #as they may be specified as a separate parameter to
41
+ #wbem_request. """
42
+
43
+ host = url.sub(%r{^https?://}, "") # Eat protocol name
44
+ port = 5988
45
+ ssl = false
46
+
47
+ if /^https/.match(url) # Set SSL if specified
48
+ ssl = true
49
+ port = 5989
50
+ end
51
+
52
+ s = host.split("@") # parse creds if specified
53
+ if (s.length > 1 )
54
+ creds = s[0].split(":")
55
+ host = s[1]
56
+ end
57
+ s = host.split(":") # Set port number
58
+ if (s.length > 1 )
59
+ host = s[0]
60
+ port = s[1].to_i
61
+ end
62
+ # STDOUT << "host: #{host}, port: #{port}, ssl: #{ssl}, creds: #{creds}\n"
63
+ return host, port, ssl, creds
64
+ end
65
+
66
+ def WBEM.wbem_request(url, data, creds, headers = [], debug = 0, x509 = nil)
67
+ #"""Send XML data over HTTP to the specified url. Return the
68
+ #response in XML. Uses Python's build-in httplib. x509 may be a
69
+ #dictionary containing the location of the SSL certificate and key
70
+ #files."""
71
+
72
+ host, port, ssl, urlcreds = WBEM.parse_url(url)
73
+ creds = urlcreds unless creds
74
+ h = Net::HTTP.new(host, port)
75
+ if (ssl)
76
+ if x509
77
+ cert_file = x509.get("cert_file")
78
+ key_file = x509.get("key_file", cert_file)
79
+ else
80
+ cert_file = nil
81
+ key_file = nil
82
+ end
83
+ h.use_ssl = true
84
+ # key_file, cert_file ???
85
+ end
86
+ data = "<?xml version='1.0' encoding='utf-8' ?>\n" + data
87
+ response = nil
88
+ h.start do |http|
89
+ request = Net::HTTP::Post.new("/cimom")
90
+ request.basic_auth creds[0], creds[1]
91
+ request.content_type = "application/xml"
92
+ request.content_length = data.length
93
+ headers.each do |header|
94
+ s = header.split(":", 2).collect { |x| x.strip }
95
+ request.add_field(URI.escape(s[0]), URI.escape(s[1]))
96
+ end
97
+ # STDOUT << "request: #{data}\n"
98
+ response = http.request(request, data)
99
+ # STDOUT << "response: #{response.body}\n"
100
+ end
101
+ unless response.kind_of?(Net::HTTPSuccess)
102
+ if (response.kind_of?(NET::HTTPUnauthorized))
103
+ raise AuthError, response.reason
104
+ elsif (response.fetch("CIMError", []) or response.fetch("PGErrorDetail", []))
105
+ raise CIMHttpError, "CIMError: #{response.fetch('CIMError',[])}: #{response.fetch('PGErrorDetail',[])}"
106
+ end
107
+ raise CIMHttpError, "HTTP error: #{response.reason}"
108
+ end
109
+ # TODO: do we need more error checking here?
110
+
111
+ response.body
112
+ end
113
+
114
+ def WBEM.get_object_header(obj)
115
+ #"""Return the HTTP header required to make a CIM operation request
116
+ #using the given object. Return None if the object does not need
117
+ #to have a header."""
118
+
119
+ # Local namespacepath
120
+
121
+ if obj.kind_of?(String)
122
+ return "CIMObject: #{obj}"
123
+ end
124
+
125
+ # CIMLocalClassPath
126
+
127
+ if obj.kind_of?(CIMLocalClassPath)
128
+ return "CIMObject: #{obj.localnamespacepath}:#{obj.classname}"
129
+ end
130
+ # CIMInstanceName with namespace
131
+
132
+ if obj.kind_of?(CIMInstanceName) && !obj.namespace.nil?
133
+ return 'CIMObject: %s' % obj
134
+ end
135
+ raise CIMHttpError, "Don\'t know how to generate HTTP headers for #{obj}"
136
+ end
137
+ end
@@ -0,0 +1,1148 @@
1
+ #
2
+ # Copyright 2006, Red Hat, Inc
3
+ # Scott Seago <sseago@redhat.com>
4
+ #
5
+ # derived from pywbem, written by Tim Potter <tpot@hp.com>, Martin Pool <mbp@hp.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, write to the Free Software
14
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+ #
16
+
17
+ require "wbem/cim_types"
18
+ require "wbem/cim_xml"
19
+ require "date"
20
+
21
+ #"""
22
+ #Representations of CIM Objects.
23
+ #
24
+ #In general we try to map CIM objects directly into standard Ruby types,
25
+ #except when that is not possible or would be ambiguous. For example,
26
+ #CIM Class names are simply strings, but a ClassPath is
27
+ #represented as a special object.
28
+ #
29
+ #These objects can also be mapped back into XML, by the toxml() method
30
+ #which returns a string.
31
+ #"""
32
+
33
+ #
34
+ # Base objects
35
+ #
36
+
37
+ module WBEM
38
+
39
+ class NocaseHash < Hash
40
+
41
+ def initialize(initial_values = {})
42
+ super()
43
+ initial_values = initial_values.to_a if initial_values.is_a?(Hash)
44
+ if initial_values.is_a?(Array)
45
+ initial_values.each do |item|
46
+ self[item[0]] = item[1] if item.is_a?(Array)
47
+ end
48
+ end
49
+ end
50
+
51
+ def get_key(key)
52
+ key.is_a?(String) ? key.downcase : key
53
+ end
54
+ def [](key)
55
+ v = super(get_key(key))
56
+ v[1] unless v.nil?
57
+ end
58
+ def []=(key, value)
59
+ unless key.is_a?(String)
60
+ raise IndexError, "Key must be a String"
61
+ end
62
+ super(get_key(key),[key, value])
63
+ end
64
+ alias rawkeys keys
65
+ alias rawvalues values
66
+ alias rawarray to_a
67
+ def keys
68
+ rawvalues.collect { |v| v[0] }
69
+ end
70
+ def values
71
+ super.collect { |v| v[1] }
72
+ end
73
+ def to_a
74
+ super.collect { |k,v| [v[0], v[1]] }
75
+ end
76
+ def each(&block)
77
+ to_a.each(&block)
78
+ end
79
+ def sort
80
+ rawarray.sort.collect { |k,v| [v[0], v[1]] }
81
+ end
82
+ def ==(other)
83
+ self.each do |key, value|
84
+ return false unless (other.include?(key) and other[key] == value)
85
+ end
86
+ return self.length == other.length
87
+ end
88
+
89
+ def delete(key)
90
+ super(get_key(key))
91
+ end
92
+ def fetch(key)
93
+ super(get_key(key))[1]
94
+ end
95
+ def has_key?(key)
96
+ super(get_key(key))
97
+ end
98
+ def include?(key)
99
+ super(get_key(key))
100
+ end
101
+ def update(otherHash)
102
+ otherHash.to_a.each { |key, value| self[key] = value }
103
+ end
104
+ def clone
105
+ return NocaseHash.new(self)
106
+ end
107
+ alias copy clone
108
+ end
109
+
110
+ class XMLObject
111
+ #"""Base class for objects that produce cim_xml document fragments."""
112
+
113
+ def toxml
114
+ #"""Return the XML string representation of ourselves."""
115
+ ret = ""
116
+ self.tocimxml().write(ret)
117
+ return ret
118
+ end
119
+ def hash
120
+ self.toxml().hash
121
+ end
122
+ # probably not the best equality method, as trivial
123
+ # differences such as attribute order will affect the results,
124
+ # but better than the default eql? method defined in object --
125
+ # subclasses can define this in a better way
126
+ def eql?(other)
127
+ (self.toxml == other.toxml)
128
+ end
129
+
130
+ def nilcmp(obj1, obj2)
131
+ cmpname(obj1, obj2, false)
132
+ end
133
+
134
+ def cmpname(name1, name2, downcase_strings = true)
135
+ #"""Compare to CIM names. The comparison is done
136
+ #case-insensitvely, and one or both of the names may be None."""
137
+
138
+ if name1.nil? and name2.nil?
139
+ return 0
140
+ end
141
+ unless (name1 || name2)
142
+ return 0
143
+ end
144
+
145
+ if name1.nil?
146
+ return -1
147
+ end
148
+
149
+ if name2.nil?
150
+ return 1
151
+ end
152
+ if (downcase_strings)
153
+ name1.downcase <=> name2.downcase
154
+ elsif (name2.is_a?(Boolean))
155
+ (name2 <=> name1)*-1
156
+ elsif (!name1.methods.include?("<=>"))
157
+ (name1 == name2) ? 0 : 1
158
+ elsif ((name1.nil? || name1 == false) &&
159
+ (name2.nil? || name2 == false))
160
+ return 0
161
+ else
162
+ name1 <=> name2
163
+ end
164
+ end
165
+ end
166
+
167
+ #
168
+ # Object location classes
169
+ #
170
+
171
+ #
172
+ # It turns out that most of the object location elements can be
173
+ # represented easily using one base class which roughly corresponds to
174
+ # the OBJECTPATH element.
175
+ #
176
+ # Element Name (host, namespace, classname, instancename)
177
+ # ---------------------------------------------------------------------------
178
+ # CLASSNAME (None, None, 'CIM_Foo', None)
179
+ # LOCALNAMESPACEPATH (None, 'root/cimv2', None, None)
180
+ # NAMESPACEPATH ('leonardo', 'root/cimv2', None, None)
181
+ # LOCALCLASSPATH (None, 'root/cimv2', 'CIM_Foo', None)
182
+ # CLASSPATH ('leonardo', 'root/cimv2', 'CIM_Foo', None)
183
+ # LOCALINSTANCEPATH (None, 'root/cimv2', None, InstanceName)
184
+ # INSTANCEPATH ('leonardo', 'root/cimv2', None, InstanceName)
185
+ #
186
+ # These guys also have string representations similar to the output
187
+ # produced by the Pegasus::CIMObjectPath.toString() method:
188
+ #
189
+ # Element Name Python Class String representation
190
+ # ---------------------------------------------------------------------------
191
+ # CLASSNAME CIMClassName CIM_Foo
192
+ # LOCALNAMESPACEPATH String root/cimv2:
193
+ # NAMESPACEPATH CIMNamespacePath //leo/root/cimv2:
194
+ # LOCALCLASSPATH CIMLocalClassPath root/cimv2:CIM_Foo
195
+ # CLASSPATH CIMClassPath //leo/root/cimv2:CIM_Foo
196
+ # INSTANCENAME CIMInstanceName CIM_Foo.Foo="Bar"
197
+ # LOCALINSTANCEPATH CIMLocalInstancePath root/cimv2:CIM_Foo.Foo="Bar"
198
+ # INSTANCEPATH CIMInstancePath //leo/root/cimv2:CIM_Foo.Foo="Bar"
199
+ #
200
+
201
+ class CIMObjectLocation < XMLObject
202
+ include Comparable
203
+ #"""A base class that can name any CIM object."""
204
+
205
+ attr_writer :host, :localnamespacepath, :classname, :instancename
206
+ attr_reader :host, :localnamespacepath, :classname, :instancename
207
+
208
+ def initialize(host = nil, localnamespacepath = nil,
209
+ classname = nil, instancename = nil)
210
+ @host = host
211
+ @localnamespacepath = localnamespacepath
212
+ @classname = classname
213
+ @instancename = instancename
214
+ end
215
+
216
+ def HOST
217
+ HOST.new(@host)
218
+ end
219
+
220
+ def CLASSNAME
221
+ CLASSNAME.new(@classname)
222
+ end
223
+
224
+ def LOCALNAMESPACEPATH
225
+ nsArray = @localnamespacepath.split("/").collect { |name| NAMESPACE.new(name) }
226
+ LOCALNAMESPACEPATH.new(nsArray)
227
+ end
228
+
229
+ def NAMESPACEPATH
230
+ NAMESPACEPATH.new(self.HOST, self.LOCALNAMESPACEPATH)
231
+ end
232
+
233
+ def eql?(other)
234
+ (self <=> other) == 0
235
+ end
236
+ def hash
237
+ self.host.hash + self.localnamespacepath.hash + self.classname.hash + self.instancename.hash
238
+ end
239
+ def <=>(other)
240
+ if equal?(other)
241
+ return 0
242
+ elsif (!other.kind_of?(CIMObjectLocation))
243
+ return 1
244
+ end
245
+ ret_val = cmpname(self.host, other.host)
246
+ ret_val = nilcmp(self.localnamespacepath, other.localnamespacepath) if (ret_val == 0)
247
+ ret_val = cmpname(lclassname, lOclassname) if (ret_val == 0)
248
+ ret_val = nilcmp(self.instancename, other.instancename) if (ret_val == 0)
249
+ ret_val
250
+ end
251
+ end
252
+
253
+ class CIMClassName < CIMObjectLocation
254
+ def initialize(classname)
255
+ unless classname.kind_of?(String)
256
+ raise TypeError, "classname argument must be a string"
257
+ end
258
+
259
+ # TODO: There are some odd restrictions on what a CIM
260
+ # classname can look like (i.e must start with a
261
+ # non-underscore and only one underscore per classname).
262
+ super()
263
+ self.classname=classname
264
+ end
265
+
266
+ def tocimxml
267
+ self.CLASSNAME
268
+ end
269
+
270
+ def to_s
271
+ self.classname
272
+ end
273
+
274
+ end
275
+
276
+ class CIMNamespacePath < CIMObjectLocation
277
+ def initialize(host, localnamespacepath)
278
+ unless host.kind_of?(String)
279
+ raise TypeError, "host argument must be a string"
280
+ end
281
+ unless localnamespacepath.kind_of?(String)
282
+ raise TypeError, "localnamespacepath argument must be a string"
283
+ end
284
+
285
+ super()
286
+ self.host=host
287
+ self.localnamespacepath=localnamespacepath
288
+ end
289
+
290
+ def tocimxml
291
+ self.NAMESPACEPATH
292
+ end
293
+
294
+ def to_s
295
+ "//#{self.host}/#{self.localnamespacepath}"
296
+ end
297
+ end
298
+
299
+ class CIMLocalClassPath < CIMObjectLocation
300
+ def initialize(localnamespacepath, classname)
301
+ unless localnamespacepath.kind_of?(String)
302
+ raise TypeError, "localnamespacepath argument must be a string"
303
+ end
304
+ unless classname.kind_of?(String)
305
+ raise TypeError, "classname argument must be a string"
306
+ end
307
+
308
+ super()
309
+ self.classname=classname
310
+ self.localnamespacepath=localnamespacepath
311
+ end
312
+
313
+ def tocimxml
314
+ LOCALCLASSPATH.new(self.LOCALNAMESPACEPATH, self.CLASSNAME)
315
+ end
316
+
317
+ def to_s
318
+ "#{self.localnamespacepath}:#{self.classname}"
319
+ end
320
+ end
321
+
322
+ class CIMClassPath < CIMObjectLocation
323
+ def initialize(localnamespacepath, classname)
324
+ unless host.kind_of?(String)
325
+ raise TypeError, "host argument must be a string"
326
+ end
327
+ unless localnamespacepath.kind_of?(String)
328
+ raise TypeError, "localnamespacepath argument must be a string"
329
+ end
330
+ unless classname.kind_of?(String)
331
+ raise TypeError, "classname argument must be a string"
332
+ end
333
+
334
+ super()
335
+ self.host=host
336
+ self.classname=classname
337
+ self.localnamespacepath=localnamespacepath
338
+ end
339
+
340
+ def tocimxml
341
+ CLASSPATH.new(self.NAMESPACEPATH, self.CLASSNAME)
342
+ end
343
+
344
+ def to_s
345
+ "//#{self.host}/#{self.localnamespacepath}:#{self.classname}"
346
+ end
347
+ end
348
+
349
+ # Object value elements
350
+
351
+ class CIMProperty < XMLObject
352
+ include Comparable
353
+ #"""A property of a CIMInstance.
354
+
355
+ #Property objects represent both properties on particular instances,
356
+ #and the property defined in a class. In the first case, the property
357
+ #will have a Value and in the second it will not.
358
+
359
+ #The property may hold an array value, in which case it is encoded
360
+ #in XML to PROPERTY.ARRAY containing VALUE.ARRAY.
361
+
362
+ #Properties holding references are handled specially as
363
+ #CIMPropertyReference."""
364
+
365
+ attr_writer :name, :prop_type, :class_origin, :propagated, :value, :is_array, :reference_class, :array_size
366
+ attr_reader :name, :prop_type, :class_origin, :propagated, :value, :is_array, :qualifiers, :reference_class, :array_size
367
+
368
+ def initialize(name, value, type=nil, class_origin=nil, propagated=nil,
369
+ is_array = false, qualifiers = {},
370
+ reference_class = nil, array_size = nil)
371
+ #"""Construct a new CIMProperty
372
+ #Either the type or the value must be given. If the value is not
373
+ #given, it is left as nil. If the type is not given, it is implied
374
+ #from the value."""
375
+ unless name.kind_of?(String)
376
+ raise TypeError, "name argument must be a string"
377
+ end
378
+ unless (class_origin.nil? or class_origin.kind_of?(String))
379
+ raise TypeError, "class_origin argument must be a string"
380
+ end
381
+
382
+ @name = name
383
+ @value = value
384
+ @prop_type = type
385
+ @class_origin = class_origin
386
+ @propagated = propagated
387
+ @qualifiers = NocaseHash.new(qualifiers)
388
+ @is_array = is_array
389
+ @array_size = array_size
390
+ @reference_class = reference_class
391
+
392
+ if type.nil?
393
+ if (value.nil?)
394
+ raise TypeError, "value argument must not be nil if type is missing"
395
+ end
396
+ if (value.is_a?(Array))
397
+ if (value.empty?)
398
+ raise TypeError, "Empty property array #{name} must have a type"
399
+ end
400
+ @is_array = true
401
+ @prop_type = WBEM.cimtype(value[0])
402
+ else
403
+ @prop_type = WBEM.cimtype(value)
404
+ end
405
+ else
406
+ @is_array = true if (value.is_a?(Array))
407
+ @prop_type = type
408
+ end
409
+ @value = value
410
+ end
411
+
412
+ def qualifiers=(qualifiers)
413
+ @qualifiers = NocaseHash.new(qualifiers)
414
+ end
415
+
416
+ def clone
417
+ return CIMProperty.new(self.name,
418
+ self.value,
419
+ self.prop_type,
420
+ self.class_origin,
421
+ self.propagated,
422
+ self.is_array,
423
+ self.qualifiers,
424
+ self.reference_class,
425
+ self.array_size)
426
+ end
427
+
428
+ def to_s
429
+ r = "#{self.class}(name=#{self.name}, type=#{self.prop_type}"
430
+ r += ", class_origin=#{self.class_origin}" if self.class_origin
431
+ r += ", propagated=#{self.propagated}" if self.propagated
432
+ r += ", value=#{self.value}" if self.value
433
+ r += ", qualifiers=#{self.qualifiers}" if self.qualifiers
434
+ r += ", is_array=#{self.is_array}"
435
+ r += ")"
436
+ end
437
+
438
+ def <=>(other)
439
+ if equal?(other)
440
+ ret_val = 0
441
+ elsif (!other.kind_of?(CIMProperty ))
442
+ ret_val = 1
443
+ else
444
+ ret_val = cmpname(self.name, other.name)
445
+ ret_val = nilcmp(self.value, other.value) if (ret_val == 0)
446
+ ret_val = nilcmp(self.prop_type, other.prop_type) if (ret_val == 0)
447
+ ret_val = nilcmp(self.class_origin, other.class_origin) if (ret_val == 0)
448
+ ret_val = nilcmp(self.propagated, other.propagated) if (ret_val == 0)
449
+ ret_val = nilcmp(self.qualifiers, other.qualifiers) if (ret_val == 0)
450
+ ret_val = nilcmp(self.is_array, other.is_array) if (ret_val == 0)
451
+ ret_val = cmpname(self.reference_class, other.reference_class) if (ret_val == 0)
452
+ end
453
+ ret_val
454
+ end
455
+
456
+ def tocimxml
457
+ if self.is_array
458
+ return PROPERTY_ARRAY.new(self.name,
459
+ self.prop_type,
460
+ WBEM.tocimxml(self.value),
461
+ self.array_size,
462
+ self.class_origin,
463
+ self.propagated,
464
+ self.qualifiers.values.collect { |q| q.tocimxml})
465
+ elsif self.prop_type == 'reference'
466
+ return PROPERTY_REFERENCE.new(self.name,
467
+ WBEM.tocimxml(self.value, true),
468
+ self.reference_class,
469
+ self.class_origin,
470
+ self.propagated,
471
+ self.qualifiers.values.collect { |q| q.tocimxml})
472
+ else
473
+ return PROPERTY.new(self.name,
474
+ self.prop_type,
475
+ WBEM.tocimxml(self.value),
476
+ self.class_origin,
477
+ self.propagated,
478
+ self.qualifiers.values.collect { |q| q.tocimxml})
479
+ end
480
+ end
481
+ end
482
+
483
+ class CIMInstanceName < XMLObject
484
+ include Comparable
485
+ #"""Name (keys) identifying an instance.
486
+
487
+ #This may be treated as a hash to retrieve the keys."""
488
+ # qualifiers removed?
489
+ attr_reader :classname, :keybindings, :host, :namespace
490
+ attr_writer :classname, :keybindings, :host, :namespace
491
+ def initialize(classname, keybindings = {}, host = nil, namespace = nil)
492
+ @classname = classname
493
+ @keybindings = NocaseHash.new(keybindings)
494
+ @host = host
495
+ @namespace = namespace
496
+ end
497
+
498
+ def clone
499
+ CIMInstanceName.new(@classname, @keybindings, @host, @namespace)
500
+ end
501
+
502
+ def <=>(other)
503
+ if equal?(other)
504
+ ret_val = 0
505
+ elsif (!other.kind_of?(CIMInstanceName ))
506
+ ret_val = 1
507
+ else
508
+ ## TODO: Allow for the type to be null as long as the values
509
+ ## are the same and non-null?
510
+ ret_val = cmpname(self.classname, other.classname)
511
+ ret_val = nilcmp(self.keybindings, other.keybindings) if (ret_val == 0)
512
+ ret_val = cmpname(self.host, other.host) if (ret_val == 0)
513
+ ret_val = cmpname(self.namespace, other.namespace) if (ret_val == 0)
514
+ end
515
+ ret_val
516
+ end
517
+
518
+ def keybindings=(keybindings)
519
+ @keybindings = NocaseHash.new(keybindings)
520
+ end
521
+
522
+ def to_s
523
+ s = ''
524
+
525
+ unless self.host.nil?
526
+ s += '//%s/' % self.host
527
+ end
528
+ unless self.namespace.nil?
529
+ s += '%s:' % self.namespace
530
+ end
531
+ s += '%s.' % self.classname
532
+
533
+ self.keybindings.to_a.each do |key, value|
534
+
535
+ s += "#{key}="
536
+
537
+ if value.kind_of?(Integer)
538
+ s += value.to_s
539
+ else
540
+ s += '"%s"' % value
541
+ end
542
+ s += ","
543
+ end
544
+ return s[0..-2]
545
+ end
546
+ # A whole bunch of dictionary methods that map to the equivalent
547
+ # operation on self.keybindings.
548
+
549
+ def fetch(key)
550
+ return self.keybindings.fetch(key)
551
+ end
552
+ def [](key)
553
+ return self.keybindings[key]
554
+ end
555
+ def []=(key, value)
556
+ return self.keybindings[key] = value
557
+ end
558
+ def delete(key)
559
+ self.keybindings.delete(key)
560
+ end
561
+ def length
562
+ return self.keybindings.length
563
+ end
564
+ def has_key?(key)
565
+ return self.keybindings.has_key?(key)
566
+ end
567
+ def keys
568
+ return self.keybindings.keys()
569
+ end
570
+ def values
571
+ return self.keybindings.values()
572
+ end
573
+ def to_a
574
+ return self.keybindings.to_a()
575
+ end
576
+
577
+ def tocimxml
578
+ # Generate an XML representation of the instance classname and
579
+ # keybindings.
580
+
581
+ if (self.keybindings.kind_of?(String))
582
+ # Class with single key string property
583
+ instancename_xml = INSTANCENAME.new(self.classname,
584
+ KEYVALUE.new(self.keybindings, "string"))
585
+
586
+ elsif (self.keybindings.kind_of?(Integer))
587
+ # Class with single key numeric property
588
+ instancename_xml = INSTANCENAME.new(self.classname,
589
+ KEYVALUE.new(self.keybindings.to_s, "numeric"))
590
+
591
+ elsif (self.keybindings.kind_of?(NocaseHash))
592
+ # Dictionary of keybindings
593
+ kbs = []
594
+ self.keybindings.to_a.each do |kb|
595
+ # Keybindings can be integers, booleans, strings or
596
+ # value references.
597
+ if (kb[1].methods.include?("tocimxml"))
598
+ kbs << KEYBINDING.new(kb[0], VALUE_REFERENCE.new(kb[1].tocimxml()))
599
+ next
600
+ end
601
+
602
+ if (kb[1].kind_of?(Integer) or kb[1].kind_of?(CIMInt))
603
+ _type = "numeric"
604
+ value = kb[1].to_s
605
+ elsif (kb[1] == true or kb[1] == false)
606
+ _type = "boolean"
607
+ if kb[1]
608
+ value = "TRUE"
609
+ else
610
+ value = "FALSE"
611
+ end
612
+ elsif (kb[1].kind_of?(String )) # unicode?
613
+ _type = "string"
614
+ value = kb[1]
615
+ else
616
+ raise TypeError, "Invalid keybinding type #{kb[1]}(#{kb[1].class}) for keybinding #{kb[0]}"
617
+ end
618
+
619
+ kbs << KEYBINDING.new(kb[0], KEYVALUE.new(value, _type))
620
+
621
+ end
622
+ instancename_xml = INSTANCENAME.new(self.classname, kbs)
623
+
624
+ else
625
+ # Value reference
626
+
627
+ return instancename_xml = INSTANCENAME.new(self.classname, self.keybindings.nil? ? nil : VALUE_REFERENCE.new(self.keybindings.tocimxml()))
628
+ end
629
+ # Instance name plus namespace = LOCALINSTANCEPATH
630
+
631
+ if (self.host.nil? && !self.namespace.nil?)
632
+ return LOCALINSTANCEPATH.new(
633
+ LOCALNAMESPACEPATH.new(
634
+ self.namespace.split('/').collect { |ns| NAMESPACE.new(ns)}),
635
+ instancename_xml)
636
+ end
637
+
638
+ # Instance name plus host and namespace = INSTANCEPATH
639
+ if (!self.host.nil? && !self.namespace.nil?)
640
+ return INSTANCEPATH.new(
641
+ NAMESPACEPATH.new(
642
+ HOST.new(self.host),
643
+ LOCALNAMESPACEPATH.new(
644
+ self.namespace.split('/').collect { |ns| NAMESPACE.new(ns)})),
645
+ instancename_xml)
646
+ end
647
+
648
+ # Just a regular INSTANCENAME
649
+ return instancename_xml
650
+ end
651
+ end
652
+
653
+ class CIMInstance < XMLObject
654
+ include Comparable
655
+ #"""Instance of a CIM Object.
656
+
657
+ #Has a classname (string), and named arrays of properties and qualifiers.
658
+
659
+ #The properties is indexed by name and points to CIMProperty
660
+ #instances."""
661
+
662
+ attr_reader :classname, :properties, :qualifiers, :path
663
+ attr_writer :classname, :path
664
+ def initialize(classname, properties = {}, qualifiers = {},
665
+ path = nil)
666
+ #"""Create CIMInstance.
667
+
668
+ @classname = classname
669
+ @qualifiers = NocaseHash.new(qualifiers)
670
+ @path = path
671
+ @properties = NocaseHash.new
672
+ properties.each do |k, v|
673
+ self[k]=v
674
+ end
675
+ end
676
+
677
+ def clone
678
+ CIMInstance.new(@classname, @properties, @qualifiers, @path)
679
+ end
680
+
681
+ def properties=(properties)
682
+ @properties = NocaseHash.new
683
+ properties.each do |k, v|
684
+ self[k]=v
685
+ end
686
+ end
687
+
688
+ def qualifiers=(qualifiers)
689
+ @qualifiers = NocaseHash.new(qualifiers)
690
+ end
691
+
692
+ def <=>(other)
693
+ if equal?(other)
694
+ return 0
695
+ elsif (!other.kind_of?(CIMInstance))
696
+ return 1
697
+ end
698
+ ## TODO: Allow for the type to be null as long as the values
699
+ ## are the same and non-null?
700
+ ret_val = cmpname(self.classname, other.classname)
701
+ ret_val = nilcmp(self.path, other.path) if (ret_val == 0)
702
+ ret_val = nilcmp(self.properties, other.properties) if (ret_val == 0)
703
+ ret_val = nilcmp(self.qualifiers, other.qualifiers) if (ret_val == 0)
704
+ ret_val
705
+ end
706
+
707
+ def to_s
708
+ # Don't show all the properties and qualifiers because they're
709
+ # just too big
710
+ "#{self.class}(classname=#{self.classname} ...)"
711
+ end
712
+
713
+ # A whole bunch of dictionary methods that map to the equivalent
714
+ # operation on self.properties.
715
+
716
+ def fetch(key)
717
+ return self.properties.fetch(key)
718
+ end
719
+ def [](key)
720
+ ret = self.properties[key]
721
+ ret = ret.value unless ret.nil?
722
+ end
723
+ def delete(key)
724
+ self.properties.delete(key)
725
+ end
726
+ def length
727
+ self.properties.length
728
+ end
729
+ def has_key?(key)
730
+ self.properties.has_key?(key)
731
+ end
732
+ def keys
733
+ self.properties.keys()
734
+ end
735
+ def values
736
+ self.properties.values.collect { |v| v.value }
737
+ end
738
+ def to_a
739
+ self.properties.to_a.collect { |k, v| [k, v.value] }
740
+ end
741
+ #def iterkeys(self): return self.properties.iterkeys()
742
+ #def itervalues(self): return self.properties.itervalues()
743
+ #def iteritems(self): return self.properties.iteritems()
744
+
745
+ def []=(key, value)
746
+
747
+ # Don't let anyone set integer or float values. You must use
748
+ # a subclass from the cim_type module.
749
+
750
+ unless (value.is_a?(CIMProperty))
751
+ unless WBEM.valid_cimtype?(value)
752
+ raise TypeError, "Must use a CIM type assigning numeric values."
753
+ end
754
+ value = CIMProperty.new(key, value)
755
+ end
756
+ self.properties[key] = value
757
+ end
758
+
759
+ def tocimxml
760
+ props = []
761
+ self.properties.each do |key, prop|
762
+ if (prop.is_a?(CIMProperty))
763
+ props << prop
764
+ else
765
+ props << CIMProperty.new(key, prop)
766
+ end
767
+ end
768
+ instance_xml = INSTANCE.new(self.classname,
769
+ props.collect { |p| p.tocimxml},
770
+ self.qualifiers.values.collect { |q| q.tocimxml})
771
+ if self.path.nil?
772
+ return instance_xml
773
+ end
774
+ return VALUE_NAMEDINSTANCE.new(self.path.tocimxml,
775
+ instance_xml)
776
+ end
777
+ end
778
+
779
+ class CIMClass < XMLObject
780
+ #"""Class, including a description of properties, methods and qualifiers.
781
+ #superclass may be None."""
782
+ include Comparable
783
+ attr_reader :classname, :properties, :qualifiers, :cim_methods, :superclass
784
+ attr_writer :classname, :superclass
785
+ def initialize(classname, properties = {}, qualifiers = {},
786
+ methods = {}, superclass = nil)
787
+ unless (classname.kind_of?(String))
788
+ raise TypeError, "classname must be a String"
789
+ end
790
+ @classname = classname
791
+ @properties = NocaseHash.new
792
+ unless properties.nil?
793
+ properties.each do |k, v|
794
+ @properties[k]=v
795
+ end
796
+ end
797
+ @qualifiers = NocaseHash.new(qualifiers)
798
+ @cim_methods = NocaseHash.new(methods)
799
+ @superclass = superclass
800
+ end
801
+
802
+ def clone
803
+ return CIMClass.new(@classname, @properties, @qualifiers,
804
+ @cim_methods, @superclass)
805
+ end
806
+
807
+ def properties=(properties)
808
+ @properties = NocaseHash.new
809
+ unless properties.nil?
810
+ properties.each do |k, v|
811
+ @properties[k]=v
812
+ end
813
+ end
814
+ end
815
+
816
+ def qualifiers=(qualifiers)
817
+ @qualifiers = NocaseHash.new(qualifiers)
818
+ end
819
+
820
+ def cim_methods=(cim_methods)
821
+ @cim_methods = NocaseHash.new(cim_methods)
822
+ end
823
+
824
+ def to_s
825
+ "#{self.class}(#{self.classname}, ...)"
826
+ end
827
+
828
+ def <=>(other)
829
+ if equal?(other)
830
+ return 0
831
+ elsif (!other.kind_of?(CIMClass))
832
+ return 1
833
+ end
834
+ ret_val = cmpname(self.classname, other.classname)
835
+ ret_val = cmpname(self.superclass, other.superclass) if (ret_val == 0)
836
+ ret_val = nilcmp(self.properties, other.properties) if (ret_val == 0)
837
+ ret_val = nilcmp(self.qualifiers, other.qualifiers) if (ret_val == 0)
838
+ ret_val = nilcmp(self.cim_methods, other.cim_methods) if (ret_val == 0)
839
+ ret_val
840
+ end
841
+
842
+ def tocimxml
843
+ return CLASS.new(self.classname,
844
+ self.properties.values.collect {|p| p.tocimxml()},
845
+ self.cim_methods.values.collect {|m| m.tocimxml()},
846
+ self.qualifiers.values.collect {|q| q.tocimxml()},
847
+ self.superclass)
848
+ end
849
+ end
850
+
851
+ class CIMMethod < XMLObject
852
+ include Comparable
853
+
854
+ attr_reader :name, :parameters, :qualifiers, :class_origin, :return_type, :propagated
855
+ attr_writer :name, :class_origin, :return_type, :propagated
856
+ def initialize(methodname, return_type = nil, parameters = {}, class_origin = nil, propagated = false, qualifiers = {} )
857
+ @name = methodname
858
+ @return_type = return_type
859
+ @parameters = NocaseHash.new(parameters)
860
+ @class_origin = class_origin
861
+ @propagated = propagated
862
+ @qualifiers = NocaseHash.new(qualifiers)
863
+ end
864
+
865
+ def clone
866
+ return CIMMethod.new(@name, @return_type, @parameters,
867
+ @class_origin, @propagated, @qualifiers)
868
+ end
869
+
870
+ def parameters=(parameters)
871
+ @parameters = NocaseHash.new(parameters)
872
+ end
873
+
874
+ def qualifiers=(qualifiers)
875
+ @qualifiers = NocaseHash.new(qualifiers)
876
+ end
877
+
878
+ def tocimxml
879
+ METHOD.new(self.name,
880
+ self.parameters.values.collect {|p| p.tocimxml()},
881
+ self.return_type,
882
+ self.class_origin,
883
+ self.propagated,
884
+ self.qualifiers.values.collect {|q| q.tocimxml()})
885
+ end
886
+
887
+ def <=>(other)
888
+ ret_val = 0
889
+ if equal?(other)
890
+ return 0
891
+ elsif (!other.kind_of?(CIMMethod))
892
+ return 1
893
+ end
894
+ ret_val = cmpname(self.name, other.name)
895
+ ret_val = nilcmp(self.parameters, other.parameters) if (ret_val == 0)
896
+ ret_val = nilcmp(self.qualifiers, other.qualifiers) if (ret_val == 0)
897
+ ret_val = nilcmp(self.class_origin, other.class_origin) if (ret_val == 0)
898
+ ret_val = nilcmp(self.propagated, other.propagated) if (ret_val == 0)
899
+ ret_val = nilcmp(self.return_type, other.return_type) if (ret_val == 0)
900
+ ret_val
901
+ end
902
+
903
+ def to_s
904
+ "#{self.class}(name=#{self.name}, return_type=#{self.return_type}...)"
905
+ end
906
+ end
907
+
908
+ class CIMParameter < XMLObject
909
+ include Comparable
910
+
911
+ attr_writer :name, :param_type, :is_array, :reference_class, :array_size
912
+ attr_reader :name, :param_type, :is_array, :qualifiers, :reference_class, :array_size
913
+
914
+ def initialize(name, type, reference_class=nil, is_array = nil,
915
+ array_size = nil, qualifiers = {})
916
+ @name = name
917
+ @param_type = type
918
+ @reference_class = reference_class
919
+ @is_array = is_array
920
+ @array_size = array_size
921
+ @qualifiers = NocaseHash.new(qualifiers)
922
+ end
923
+
924
+ def clone
925
+ return CIMParameter.new(@name, @param_type, @reference_class,
926
+ @is_array, @array_size, @qualifiers)
927
+ end
928
+
929
+ def qualifiers=(qualifiers)
930
+ @qualifiers = NocaseHash.new(qualifiers)
931
+ end
932
+
933
+ def to_s
934
+ "#{self.class}(name=#{self.name}, type=#{self.param_type}, is_array=#{self.is_array})"
935
+ end
936
+
937
+ def <=>(other)
938
+ if equal?(other)
939
+ return 0
940
+ elsif (!other.kind_of?(CIMParameter ))
941
+ return 1
942
+ end
943
+ ret_val = cmpname(self.name, other.name)
944
+ ret_val = nilcmp(self.param_type, other.param_type) if (ret_val == 0)
945
+ ret_val = cmpname(self.reference_class, other.reference_class) if (ret_val == 0)
946
+ ret_val = nilcmp(self.is_array, other.is_array) if (ret_val == 0)
947
+ ret_val = nilcmp(self.array_size, other.array_size) if (ret_val == 0)
948
+ ret_val = nilcmp(self.qualifiers, other.qualifiers) if (ret_val == 0)
949
+ ret_val
950
+ end
951
+
952
+ def tocimxml
953
+ if self.param_type == 'reference'
954
+ if self.is_array
955
+ return PARAMETER_REFARRAY.new(self.name,
956
+ self.reference_class,
957
+ array_size.nil? ? nil : self.array_size.to_s,
958
+ self.qualifiers.values.collect {|q| q.tocimxml()})
959
+ else
960
+ return PARAMETER_REFERENCE.new(self.name,
961
+ self.reference_class,
962
+ self.qualifiers.values.collect {|q| q.tocimxml()})
963
+ end
964
+ elsif self.is_array
965
+ return PARAMETER_ARRAY.new(self.name,
966
+ self.param_type,
967
+ array_size.nil? ? nil : self.array_size.to_s,
968
+ self.qualifiers.values.collect { |q| q.tocimxml})
969
+ else
970
+ return PARAMETER.new(self.name,
971
+ self.param_type,
972
+ self.qualifiers.values.collect { |q| q.tocimxml})
973
+ end
974
+ end
975
+ end
976
+
977
+ class CIMQualifier < XMLObject
978
+ include Comparable
979
+ #"""Represents static annotations of a class, method, property, etc.
980
+
981
+ #Includes information such as a documentation string and whether a property
982
+ #is a key."""
983
+
984
+ attr_reader :name, :qual_type, :value, :overridable, :propagated, :toinstance, :tosubclass, :translatable
985
+ attr_writer :name, :qual_type, :value, :overridable, :propagated, :toinstance, :tosubclass, :translatable
986
+ def initialize(name, value, propagated=nil, overridable=nil,
987
+ tosubclass=nil, toinstance=nil, translatable=nil)
988
+ @name = name
989
+ @value = value
990
+ @overridable = overridable
991
+ @propagated = propagated
992
+ @toinstance = toinstance
993
+ @tosubclass = tosubclass
994
+ @translatable = translatable
995
+ @qual_type = WBEM.cimtype(value)
996
+ end
997
+
998
+ def clone
999
+ CIMQualifier.new(@name, @value, @propagated, @overridable,
1000
+ @tosubclass, @toinstance, @translatable)
1001
+ end
1002
+
1003
+ def to_s
1004
+ "#{self.class}(#{self.name}, #{self.value}, ...)"
1005
+ end
1006
+
1007
+ def <=>(other)
1008
+ ret_val = 0
1009
+ if equal?(other)
1010
+ return 0
1011
+ elsif (!other.kind_of?(CIMQualifier))
1012
+ return 1
1013
+ end
1014
+ ret_val = cmpname(self.name, other.name)
1015
+ ret_val = nilcmp(self.value, other.value) if (ret_val == 0)
1016
+ ret_val = nilcmp(self.propagated, other.propagated) if (ret_val == 0)
1017
+ ret_val = nilcmp(self.overridable, other.overridable) if (ret_val == 0)
1018
+ ret_val = nilcmp(self.tosubclass, other.tosubclass) if (ret_val == 0)
1019
+ ret_val = nilcmp(self.toinstance, other.toinstance) if (ret_val == 0)
1020
+ ret_val = nilcmp(self.translatable, other.translatable) if (ret_val == 0)
1021
+ ret_val
1022
+ end
1023
+ def tocimxml
1024
+ QUALIFIER.new(self.name,
1025
+ self.qual_type,
1026
+ WBEM.tocimxml(self.value),
1027
+ self.propagated,
1028
+ self.overridable,
1029
+ self.tosubclass,
1030
+ self.toinstance,
1031
+ self.translatable)
1032
+ end
1033
+ end
1034
+
1035
+ def WBEM.tocimxml(value, wrap_references = false)
1036
+ #"""Convert an arbitrary object to CIM xml. Works with cim_obj
1037
+ #objects and builtin types."""
1038
+
1039
+
1040
+ # CIMType or builtin type
1041
+
1042
+ if ([CIMType, String, Integer, DateTime, TimeDelta, TrueClass, FalseClass].any? do |item|
1043
+ value.is_a?(item)
1044
+ end)
1045
+ return VALUE.new(WBEM.atomic_to_cim_xml(value))
1046
+ elsif (wrap_references and (value.is_a?(CIMInstanceName) or
1047
+ value.is_a?(CIMClassName) or
1048
+ value.is_a?(CIMLocalClassPath)))
1049
+ return VALUE_REFERENCE.new(WBEM.atomic_to_cim_xml(value))
1050
+ elsif (value.methods.include?("tocimxml"))
1051
+ return value.tocimxml()
1052
+ elsif (value.is_a?(Array))
1053
+ if (wrap_references and (value[0].is_a?(CIMInstanceName) or
1054
+ value[0].is_a?(CIMClassName) or
1055
+ value.is_a?(CIMLocalClassPath)))
1056
+ return VALUE_REFARRAY.new(value.collect {|val| WBEM.tocimxml(val, wrap_references)})
1057
+ else
1058
+ return VALUE_ARRAY.new(value.collect {|val| WBEM.tocimxml(val, wrap_references)})
1059
+ end
1060
+ elsif (value.nil?)
1061
+ return value
1062
+ end
1063
+ raise TypeError, "Can't convert #{value} (#{value.class}) to CIM XML"
1064
+ end
1065
+
1066
+ def WBEM.tocimobj(_type, value)
1067
+ #"""Convert a CIM type and a string value into an appropriate
1068
+ #builtin type."""
1069
+
1070
+ # Lists of values
1071
+
1072
+ if value.is_a?(Array)
1073
+ return value.collect { |val| WBEM.tocimobj(_type, val) }
1074
+ end
1075
+
1076
+ case _type
1077
+ # Boolean type
1078
+ when "boolean"
1079
+ return Boolean.new(value)
1080
+ # String type
1081
+ when "string"
1082
+ return value
1083
+ # Integer types
1084
+ when "uint8"
1085
+ return Uint8.new(value)
1086
+ when "sint8"
1087
+ return Sint8.new(value)
1088
+ when "uint16"
1089
+ return Uint16.new(value)
1090
+ when "sint16"
1091
+ return Sint16.new(value)
1092
+ when "uint32"
1093
+ return Uint32.new(value)
1094
+ when "sint32"
1095
+ return Sint32.new(value)
1096
+ when "uint64"
1097
+ return Uint64.new(value)
1098
+ when "sint64"
1099
+ return Sint64.new(value)
1100
+ # Real types
1101
+ when "real32"
1102
+ return Real32.new(value)
1103
+ when "real64"
1104
+ return Real64.new(value)
1105
+ # Char16
1106
+ when "char16"
1107
+ raise TypeError, "CIMType char16 not handled"
1108
+ # Datetime
1109
+ when "datetime"
1110
+ if (value.nil?)
1111
+ return nil
1112
+ end
1113
+ tv_pattern = /^(\d{8})(\d{2})(\d{2})(\d{2})\.(\d{6})(:)(\d{3})/
1114
+ date_pattern = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d{6})([+|-])(\d{3})/
1115
+ s = tv_pattern.match(value)
1116
+ if (s.nil?)
1117
+ if ((s = date_pattern.match(value)).nil?)
1118
+ raise TypeError, "Invalid Datetime format #{value}"
1119
+ end
1120
+ return DateTime.new(s[1].to_i,s[2].to_i,s[3].to_i,s[4].to_i,s[5].to_i,s[6].to_i+Rational(s[7].to_i,1000000))
1121
+ else
1122
+ # returning a rational num for the #days rather than a python timedelta
1123
+ return TimeDelta.new(s[1].to_i, s[2].to_i, s[3].to_i, s[4].to_i, s[5].to_i)
1124
+ end
1125
+ return value
1126
+ else
1127
+ return nil if _type.nil?
1128
+ raise TypeError, "Invalid CIM type #{_type}"
1129
+ end
1130
+ end
1131
+ def WBEM.byname(nlist)
1132
+ #"""Convert a list of named objects into a map indexed by name"""
1133
+ hash = Hash.new
1134
+ nlist.each { |x| hash[x.name] = x }
1135
+ return hash
1136
+ end
1137
+ class TimeDelta
1138
+ attr_reader :days, :hours, :minutes, :seconds, :microseconds
1139
+ attr_writer :days, :hours, :minutes, :seconds, :microseconds
1140
+ def initialize(days=0, hours=0, minutes=0, seconds=0, microseconds=0)
1141
+ @days = days
1142
+ @hours = hours
1143
+ @minutes = minutes
1144
+ @seconds = seconds
1145
+ @microseconds = microseconds
1146
+ end
1147
+ end
1148
+ end