1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 r"""Python CIM Providers (aka "nirvana")
23
24 This module is an abstraction and utility layer between a CIMOM and
25 Python providers. The CIMOM uses this module to load Python providers,
26 and route requests to those providers.
27
28 Python Provider Modules
29
30 Python Providers are implemented as Python modules. By convention
31 these modules are installed into /usr/lib/pycim. However, they can
32 be anywhere. These modules are loaded on demand using load_source()
33 from the imp module. The CIMOM's pycim interface stores the timestamp
34 of the provider modules. If the modules change, the CIMOM reloads the
35 modules. This is very useful while developing providers, since the
36 latest code will always be loaded and used.
37
38 A Python Provider Module will contain functions, attributes, and
39 instances that will be accessed and manipulated by this module.
40
41 Providers are often classified in the following catagories:
42 Instance -- Instrument the retrieval, creation, modification,
43 and deletion of CIM instances.
44 Association -- Instrument CIM associations (CIM classes with the
45 Association qualifier).
46 Method -- Instrument methods as defined on CIM instances or CIM
47 classes.
48 Indication -- Generates indications based on indication
49 subscriptions.
50 Indication Consumer -- "Consumes" (or "Handles") an indication,
51 possibly delivering it through some other means, such as email.
52 Polled -- A polled provider is allowed to run periodically (by
53 calling its poll function). This allows a provider to do some
54 periodic work, without the need to create its own thread.
55
56 An Instance, Association, and/or Method provider is created by defining
57 one or more subclasses of CIMProvider within the provider module, and
58 registering instances of the subclass(es) with CIM class names by way
59 of the get_providers function (described below). Refer to
60 the documentation for CIMProvider in this module.
61
62 Indication, Indication Consumer, and Polled providers are defined by
63 implementing some functions within the provider module.
64
65 Provider module functions:
66 init(env):
67 This module function is optional. It is called immediately
68 after the provider module is imported.
69
70 Arguments:
71 env -- Provider Environment (pycimmb.ProviderEnvironment)
72
73 get_providers(env):
74 Return a dict that maps CIM class names to instances of
75 CIMProvider subclasses. Note that multiple classes can be
76 instrumented by the same instance of a CIMProvider subclass.
77 The CIM class names are case-insensitive, since this dict is
78 converted to a NocaseDict.
79
80 Arguments:
81 env -- Provider Environment (pycimmb.ProviderEnvironment)
82
83 For example, a Python Provider Module may contain the following:
84
85 class Py_FooBarProvider(CIMProvider):
86 ...
87
88 def get_providers(env):
89 _fbp = Py_FooBarProvider()
90 return {'Py_Foo':_fbp, 'Py_Bar':_fbp}
91
92 get_initial_polling_interval(env):
93 Return the number of seconds before the first call to poll.
94
95 If this method returns zero, then the poll method is never called.
96
97 Arguments:
98 env -- Provider Environment (pycimmb.ProviderEnvironment)
99
100 poll(env):
101 Do some work, and return the number of seconds until the next poll.
102
103 A polled provider's poll function will be called periodically by
104 the CIMOM. The polled provider can use this opportunity to do
105 some work, such as checking on some conditions, and generating
106 indications. The poll function returns the number of seconds the
107 CIMOM should wait before calling poll again. A return value of -1
108 indicates to the CIMOM that the previous poll value should be used.
109 A return value of 0 indicates that the poll function should never
110 be called again.
111
112 Arguments:
113 env -- Provider Environment (pycimmb.ProviderEnvironment)
114
115 can_unload(env):
116 Return True if the provider can be unloaded.
117
118 The CIMOM may try to unload a provider after a period of inactivity.
119 Before unloading a provider, the CIMOM asks the provider if it can
120 be unloaded.
121
122 Arguments:
123 env -- Provider Environment (pycimmb.ProviderEnvironment)
124
125 shutdown(env):
126 Perform any cleanup tasks prior to being unloaded.
127
128 The provider will shortly be unloaded, and is given an opportunity
129 to perform any needed cleanup. The provider may be unloaded after
130 a period of inactivity (see the documentation for can_unload), or
131 because the CIMOM is shutting down.
132
133 Arguments:
134 env -- Provider Environment (pycimmb.ProviderEnvironment)
135
136 handle_indication(env, ns, handler_instance, indication_instance):
137 Process an indication.
138
139 Arguments:
140 env -- Provider Environment (pycimmb.ProviderEnvironment)
141 ns -- The namespace where the even occurred
142 handler_instance --
143 indication_instance -- The indication
144
145 activate_filter (env, filter, ns, classes,
146 first_activation):
147 Arguments:
148 env -- Provider Environment (pycimmb.ProviderEnvironment)
149 filter --
150 namespace --
151 classes --
152 first_activation --
153
154 deactivate_filter(env, filter, ns, classes,
155 last_activation):
156 Arguments:
157 env -- Provider Environment (pycimmb.ProviderEnvironment)
158 filter --
159 ns --
160 classes --
161 last_activation --
162
163 Provider Environment
164
165 A pycimmb.ProviderEnvironment is passed to many functions. This is
166 a handle back into the CIMOM. You can use it for logging and for
167 making "up-calls" to the CIMOM. For example:
168
169 logger = env.get_logger()
170 logger.log_debug('Debug Info')
171
172 ch = env.get_cimom_handle()
173 other_inst = ch.GetInstance(inst_path, LocalOnly=False,
174 IncludeQualifiers=False,
175 IncludeClassOrigin=False)
176
177 The API of the pycimmb.CIMOMHandle resembles that of
178 pywbem.WBEMConnection.
179
180 For more information on the ProviderEnvironments, and other features
181 provided by pycimmb, refer to the pycimmb documentation.
182
183 CodeGen
184
185 The codegen function can be used to generate provider stub code for a
186 given CIM class. This is a quick way to get started writing a provider.
187
188 """
189
190 import sys
191 from os.path import dirname
192 from imp import load_source
193 from types import ModuleType
194
195 import pywbem
196
197 __all__ = ['CIMProvider']
198
199
201 """If one object path doesn't inlcude a host, don't include the hosts
202 in the comparison
203
204 """
205
206 if lhs is rhs:
207 return True
208 if lhs.host is not None and rhs.host is not None and lhs.host != rhs.host:
209 return False
210
211 return not (pywbem.cmpname(rhs.classname, lhs.classname) or
212 cmp(rhs.keybindings, lhs.keybindings) or
213 pywbem.cmpname(rhs.namespace, lhs.namespace))
214
215
217 """Base class for CIM Providers.
218
219 A derived class might normally override the following:
220 - enum_instances
221 - get_instance
222 - set_instance
223 - delete_instance
224 - references
225
226 If the provider is a "read-only" instance provider, set_instance and
227 delete_instance need not be overridden.
228
229 Only association providers need to override references.
230
231 A method provider should implement a method of the form:
232 def cim_method_<method_name>(self, env, object_name, method,
233 param_<input_param_1>,
234 param_<input_param_2>,
235 ...):
236 Where <method_name> is the name of the method from the CIM schema.
237 <method_name> needs to be all lowercase, regardless of the case of
238 the method name in the CIM schema (CIM method names are case
239 insensitive).
240
241 Keyword arguments:
242 env -- Provider Environment (pycimmb.ProviderEnvironment)
243 object_name -- A pywbem.CIMInstanceName or pywbem.CIMClassname
244 specifying the object on which the method is to be invoked.
245 method -- A pywbem.CIMMethod, representing the method to execute.
246 param_<param_name> -- Corresponds to the input parameter <param_name>
247 from the CIM schema. <param_name> needs to be all lowercase,
248 regardless of the case of the parameter name in the CIM schema
249 (CIM parameter names are case insensitive).
250
251 The method returns a two-tuple containing the return value of the
252 method, and a dictionary containing the output parameters.
253
254 Example:
255 def cim_method_requeststatechange(self, env, object_name, method,
256 param_requestedstate,
257 param_timeoutperiod):
258 # do stuff.
259 out_params = {'job': pywbem.CIMInstanceName(...)}
260 rval = pywbem.Uint32(0)
261 return (rval, out_params)
262
263 The methods prefixed with "MI_" correspond to the WBEM operations
264 from http://www.dmtf.org/standards/published_documents/DSP200.html
265 The default implementations of these methods call the methods
266 described above. These will not normally be overridden or extended
267 by a subclass.
268
269 """
270
272 """Return an instance.
273
274 Keyword arguments:
275 env -- Provider Environment (pycimmb.ProviderEnvironment)
276 model -- A template of the pywbem.CIMInstance to be returned. The
277 key properties are set on this instance to correspond to the
278 instanceName that was requested. The properties of the model
279 are already filtered according to the PropertyList from the
280 request. Only properties present in the model need to be
281 given values. If you prefer, you can set all of the
282 values, and the instance will be filtered for you.
283 cim_class -- The pywbem.CIMClass
284
285 Possible Errors:
286 CIM_ERR_ACCESS_DENIED
287 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
288 or otherwise incorrect parameters)
289 CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
290 Instance does not exist in the specified namespace)
291 CIM_ERR_FAILED (some other unspecified error occurred)
292
293 """
294 return None
295
297 """Enumerate instances.
298
299 The WBEM operations EnumerateInstances and EnumerateInstanceNames
300 are both mapped to this method.
301 This method is a python generator
302
303 Keyword arguments:
304 env -- Provider Environment (pycimmb.ProviderEnvironment)
305 model -- A template of the pywbem.CIMInstances to be generated.
306 The properties of the model are already filtered according to
307 the PropertyList from the request. Only properties present in
308 the model need to be given values. If you prefer, you can
309 always set all of the values, and the instance will be filtered
310 for you.
311 cim_class -- The pywbem.CIMClass
312 keys_only -- A boolean. True if only the key properties should be
313 set on the generated instances.
314
315 Possible Errors:
316 CIM_ERR_FAILED (some other unspecified error occurred)
317
318 """
319 pass
320
321 - def set_instance(self, env, instance, previous_instance, cim_class):
322 """Return a newly created or modified instance.
323
324 Keyword arguments:
325 env -- Provider Environment (pycimmb.ProviderEnvironment)
326 instance -- The new pywbem.CIMInstance. If modifying an existing
327 instance, the properties on this instance have been filtered by
328 the PropertyList from the request.
329 previous_instance -- The previous pywbem.CIMInstance if modifying
330 an existing instance. None if creating a new instance.
331 cim_class -- The pywbem.CIMClass
332
333 Return the new instance. The keys must be set on the new instance.
334
335 Possible Errors:
336 CIM_ERR_ACCESS_DENIED
337 CIM_ERR_NOT_SUPPORTED
338 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
339 or otherwise incorrect parameters)
340 CIM_ERR_ALREADY_EXISTS (the CIM Instance already exists -- only
341 valid if previous_instance is None, indicating that the operation
342 was CreateInstance)
343 CIM_ERR_NOT_FOUND (the CIM Instance does not exist -- only valid
344 if previous_instance is not None, indicating that the operation
345 was ModifyInstance)
346 CIM_ERR_FAILED (some other unspecified error occurred)
347
348 """
349 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED, "")
350
352 """Delete an instance.
353
354 Keyword arguments:
355 env -- Provider Environment (pycimmb.ProviderEnvironment)
356 instance_name -- A pywbem.CIMInstanceName specifying the instance
357 to delete.
358
359 Possible Errors:
360 CIM_ERR_ACCESS_DENIED
361 CIM_ERR_NOT_SUPPORTED
362 CIM_ERR_INVALID_NAMESPACE
363 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
364 or otherwise incorrect parameters)
365 CIM_ERR_INVALID_CLASS (the CIM Class does not exist in the specified
366 namespace)
367 CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
368 Instance does not exist in the specified namespace)
369 CIM_ERR_FAILED (some other unspecified error occurred)
370
371 """
372 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED, "")
373
374 - def references(self, env, object_name, model, assoc_class,
375 result_class_name, role, result_role, keys_only):
376 """Instrument Associations.
377
378 All four association-related operations (Associators, AssociatorNames,
379 References, ReferenceNames) are mapped to this method.
380 This method is a python generator
381
382 Keyword arguments:
383 env -- Provider Environment (pycimmb.ProviderEnvironment)
384 object_name -- A pywbem.CIMInstanceName that defines the source
385 CIM Object whose associated Objects are to be returned.
386 model -- A template pywbem.CIMInstance to serve as a model
387 of the objects to be returned. Only properties present on this
388 model need to be set.
389 assoc_class -- The pywbem.CIMClass.
390 result_class_name -- If not empty, this string acts as a filter on
391 the returned set of Instances by mandating that each returned
392 Instances MUST represent an association between object_name
393 and an Instance of a Class whose name matches this parameter
394 or a subclass.
395 role -- If not empty, MUST be a valid Property name. It acts as a
396 filter on the returned set of Instances by mandating that each
397 returned Instance MUST refer to object_name via a Property
398 whose name matches the value of this parameter.
399 result_role -- If not empty, MUST be a valid Property name. It acts
400 as a filter on the returned set of Instances by mandating that
401 each returned Instance MUST represent associations of
402 object_name to other Instances, where the other Instances play
403 the specified result_role in the association (i.e. the
404 name of the Property in the Association Class that refers to
405 the Object related to object_name MUST match the value of this
406 parameter).
407 keys_only -- A boolean. True if only the key properties should be
408 set on the generated instances.
409
410 The following diagram may be helpful in understanding the role,
411 result_role, and result_class_name parameters.
412 +------------------------+ +-------------------+
413 | object_name.classname | | result_class_name |
414 | ~~~~~~~~~~~~~~~~~~~~~ | | ~~~~~~~~~~~~~~~~~ |
415 +------------------------+ +-------------------+
416 | +-----------------------------------+ |
417 | | [Association] assoc_class | |
418 | object_name | ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
419 +--------------+ object_name.classname REF role | |
420 (CIMInstanceName) | result_class_name REF result_role +------+
421 | |(CIMInstanceName)
422 +-----------------------------------+
423
424 Possible Errors:
425 CIM_ERR_ACCESS_DENIED
426 CIM_ERR_NOT_SUPPORTED
427 CIM_ERR_INVALID_NAMESPACE
428 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
429 or otherwise incorrect parameters)
430 CIM_ERR_FAILED (some other unspecified error occurred)
431
432 """
433 pass
434
436 self._filter_results = value
438 if hasattr(self, '_filter_results'):
439 return self._filter_results
440 return True
441 filter_results = property(
442 _get_filter_results,
443 _set_filter_results,
444 None,
445 """Determines if the CIMProvider base class should filter results
446
447 If True, the subclass of CIMProvider in the provider module
448 does not need to filter returned results based on property_list,
449 and in the case of association providers, role, result_role, and
450 result_class_name. The results will be filtered by the
451 CIMProvider base class.
452
453 If False, the CIMProvider base class will do no filtering.
454 Therefore the subclass of CIMProvider in the provider module will
455 have to filter based on property_list, and in the case of
456 association providers, role, result_role, and result_class_name.""")
457
462
463 """Return instance names of a given CIM class
464
465 Implements the WBEM operation EnumerateInstanceNames in terms
466 of the enum_instances method. A derived class will not normally
467 override this method.
468
469 """
470
471 logger = env.get_logger()
472 logger.log_debug('CIMProvider MI_enumInstanceNames called...')
473 provClass = False
474 keys = pywbem.NocaseDict()
475 [keys.__setitem__(p.name, p) for p in cimClass.properties.values() \
476 if 'key' in p.qualifiers]
477
478 _strip_quals(keys)
479 path = pywbem.CIMInstanceName(classname=cimClass.classname,
480 namespace=ns)
481 model = pywbem.CIMInstance(classname=cimClass.classname,
482 properties=keys,
483 path=path)
484 gen = self.enum_instances(env=env,
485 model=model,
486 cim_class=cimClass,
487 keys_only=True)
488 try:
489 iter(gen)
490 except TypeError:
491 logger.log_debug('CIMProvider MI_enumInstanceNames returning')
492 return
493
494 for inst in gen:
495 rval = build_instance_name(inst)
496 yield rval
497 logger.log_debug('CIMProvider MI_enumInstanceNames returning')
498
499 - def MI_enumInstances(self,
500 env,
501 ns,
502 propertyList,
503 requestedCimClass,
504 cimClass):
505
506 """Return instances of a given CIM class
507
508 Implements the WBEM operation EnumerateInstances in terms
509 of the enum_instances method. A derived class will not normally
510 override this method.
511
512 """
513 logger = env.get_logger()
514 logger.log_debug('CIMProvider MI_enumInstances called...')
515 keyNames = get_keys_from_class(cimClass)
516 plist = None
517 if propertyList is not None:
518 lkns = [kn.lower() for kn in keyNames]
519 props = pywbem.NocaseDict()
520 plist = [s.lower() for s in propertyList]
521 pklist = plist + lkns
522 [props.__setitem__(p.name, p) for p in cimClass.properties.values()
523 if p.name.lower() in pklist]
524 else:
525 props = cimClass.properties
526 _strip_quals(props)
527 path = pywbem.CIMInstanceName(classname=cimClass.classname,
528 namespace=ns)
529 model = pywbem.CIMInstance(classname=cimClass.classname,
530 properties=props, path=path)
531 gen = self.enum_instances(env=env,
532 model=model,
533 cim_class=cimClass,
534 keys_only=False)
535 try:
536 iter(gen)
537 except TypeError:
538 logger.log_debug('CIMProvider MI_enumInstances returning')
539 return
540 for inst in gen:
541 inst.path = build_instance_name(inst, keyNames)
542 if self.filter_results and plist is not None:
543 inst = inst.copy()
544 filter_instance(inst, plist)
545 yield inst
546 logger.log_debug('CIMProvider MI_enumInstances returning')
547
548 - def MI_getInstance(self,
549 env,
550 instanceName,
551 propertyList,
552 cimClass):
553
554 """Return a specific CIM instance
555
556 Implements the WBEM operation GetInstance in terms
557 of the get_instance method. A derived class will not normally
558 override this method.
559
560 """
561
562 logger = env.get_logger()
563 logger.log_debug('CIMProvider MI_getInstance called...')
564 keyNames = get_keys_from_class(cimClass)
565 plist = None
566 if propertyList is not None:
567 lkns = [kn.lower() for kn in keyNames]
568 props = pywbem.NocaseDict()
569 plist = [s.lower() for s in propertyList]
570 pklist = plist + lkns
571 [props.__setitem__(p.name, p) for p in cimClass.properties.values()
572 if p.name.lower() in pklist]
573 else:
574 props = cimClass.properties
575 _strip_quals(props)
576 model = pywbem.CIMInstance(classname=instanceName.classname,
577 properties=props,
578 path=instanceName)
579 for k, v in instanceName.keybindings.items():
580 type = cimClass.properties[k].type
581
582 if type != 'reference':
583 v = val = pywbem.tocimobj(type, v)
584 model.__setitem__(k, pywbem.CIMProperty(name=k, type=type,
585 value=v))
586
587 rval = self.get_instance(env=env,
588 model=model,
589 cim_class=cimClass)
590 if self.filter_results:
591 filter_instance(rval, plist)
592 logger.log_debug('CIMProvider MI_getInstance returning')
593 if rval is None:
594 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "")
595 return rval
596
600
601 """Create a CIM instance, and return its instance name
602
603 Implements the WBEM operation CreateInstance in terms
604 of the set_instance method. A derived class will not normally
605 override this method.
606
607 """
608
609 logger = env.get_logger()
610 logger.log_debug('CIMProvider MI_createInstance called...')
611 rval = None
612 ch = env.get_cimom_handle()
613 cimClass = ch.GetClass(instance.classname,
614 instance.path.namespace,
615 LocalOnly=False,
616 IncludeQualifiers=True)
617
618
619 rval = self.set_instance(env=env,
620 instance=instance,
621 previous_instance=None,
622 cim_class=cimClass)
623 rval = build_instance_name(rval, cimClass)
624 logger.log_debug('CIMProvider MI_createInstance returning')
625 return rval
626
627 - def MI_modifyInstance(self,
628 env,
629 modifiedInstance,
630 previousInstance,
631 propertyList,
632 cimClass):
633
634 """Modify a CIM instance
635
636 Implements the WBEM operation ModifyInstance in terms
637 of the set_instance method. A derived class will not normally
638 override this method.
639
640 """
641
642 logger = env.get_logger()
643 logger.log_debug('CIMProvider MI_modifyInstance called...')
644 if propertyList is not None:
645 plist = [p.lower() for p in propertyList]
646 filter_instance(modifiedInstance, plist)
647 modifiedInstance.update(modifiedInstance.path)
648 self.set_instance(env=env,
649 instance=modifiedInstance,
650 previous_instance=previousInstance,
651 cim_class=cimClass)
652 logger.log_debug('CIMProvider MI_modifyInstance returning')
653
657
658 """Delete a CIM instance
659
660 Implements the WBEM operation DeleteInstance in terms
661 of the delete_instance method. A derived class will not normally
662 override this method.
663
664 """
665
666 logger = env.get_logger()
667 logger.log_debug('CIMProvider MI_deleteInstance called...')
668 self.delete_instance(env=env, instance_name=instanceName)
669 logger.log_debug('CIMProvider MI_deleteInstance returning')
670
671
672 - def MI_associators(self,
673 env,
674 objectName,
675 assocClassName,
676 resultClassName,
677 role,
678 resultRole,
679 propertyList):
680
681 """Return instances associated to a given object.
682
683 Implements the WBEM operation Associators in terms
684 of the references method. A derived class will not normally
685 override this method.
686
687 """
688
689
690
691 logger = env.get_logger()
692 logger.log_debug('CIMProvider MI_associators called. ' \
693 'assocClass: %s' % (assocClassName))
694 ch = env.get_cimom_handle()
695 if not assocClassName:
696 raise pywbem.CIMError(
697 pywbem.CIM_ERR_FAILED,
698 "Empty assocClassName passed to Associators")
699 assocClass = ch.GetClass(assocClassName, objectName.namespace,
700 LocalOnly=False,
701 IncludeQualifiers=True)
702 plist = pywbem.NocaseDict()
703 [plist.__setitem__(p.name, p) for p in assocClass.properties.values()
704 if 'key' in p.qualifiers or p.type == 'reference']
705 _strip_quals(plist)
706 model = pywbem.CIMInstance(classname=assocClass.classname,
707 properties=plist)
708 model.path = pywbem.CIMInstanceName(classname=assocClass.classname,
709 namespace=objectName.namespace)
710 for inst in self.references(env=env,
711 object_name=objectName,
712 model=model,
713 assoc_class=assocClass,
714 result_class_name=resultClassName,
715 role=role,
716 result_role=None,
717 keys_only=False):
718 for prop in inst.properties.values():
719 lpname = prop.name.lower()
720 if prop.type != 'reference':
721 continue
722 if role and role.lower() == lpname:
723 continue
724 if resultRole and resultRole.lower() != lpname:
725 continue
726 if _path_equals_ignore_host(prop.value, objectName):
727 continue
728 if resultClassName and self.filter_results and \
729 not pywbem.is_subclass(ch, objectName.namespace,
730 sub=prop.value.classname,
731 super=resultClassName):
732 continue
733 try:
734 if prop.value.namespace is None:
735 prop.value.namespace = objectName.namespace
736 inst = ch.GetInstance(prop.value,
737 IncludeQualifiers=True,
738 IncludeClassOrigin=True,
739 PropertyList=propertyList)
740 except pywbem.CIMError, (num, msg):
741 if num == pywbem.CIM_ERR_NOT_FOUND:
742 continue
743 else:
744 raise
745 if inst.path is None:
746 inst.path = prop.value
747 yield inst
748 logger.log_debug('CIMProvider MI_associators returning')
749
750 - def MI_associatorNames(self,
751 env,
752 objectName,
753 assocClassName,
754 resultClassName,
755 role,
756 resultRole):
757
758 """Return instances names associated to a given object.
759
760 Implements the WBEM operation AssociatorNames in terms
761 of the references method. A derived class will not normally
762 override this method.
763
764 """
765
766 logger = env.get_logger()
767 logger.log_debug('CIMProvider MI_associatorNames called. ' \
768 'assocClass: %s' % (assocClassName))
769 ch = env.get_cimom_handle()
770 if not assocClassName:
771 raise pywbem.CIMError(
772 pywbem.CIM_ERR_FAILED,
773 "Empty assocClassName passed to AssociatorNames")
774 assocClass = ch.GetClass(assocClassName, objectName.namespace,
775 LocalOnly=False,
776 IncludeQualifiers=True)
777 keys = pywbem.NocaseDict()
778 [keys.__setitem__(p.name, p) for p in assocClass.properties.values()
779 if 'key' in p.qualifiers or p.type == 'reference']
780 _strip_quals(keys)
781 model = pywbem.CIMInstance(classname=assocClass.classname,
782 properties=keys)
783 model.path = pywbem.CIMInstanceName(classname=assocClass.classname,
784 namespace=objectName.namespace)
785 for inst in self.references(env=env,
786 object_name=objectName,
787 model=model,
788 assoc_class=assocClass,
789 result_class_name=resultClassName,
790 role=role,
791 result_role=None,
792 keys_only=False):
793 for prop in inst.properties.values():
794 lpname = prop.name.lower()
795 if prop.type != 'reference':
796 continue
797 if role and role.lower() == lpname:
798 continue
799 if resultRole and resultRole.lower() != lpname:
800 continue
801 if _path_equals_ignore_host(prop.value, objectName):
802 continue
803 if resultClassName and self.filter_results and \
804 not pywbem.is_subclass(ch, objectName.namespace,
805 sub=prop.value.classname,
806 super=resultClassName):
807 continue
808 if prop.value.namespace is None:
809 prop.value.namespace = objectName.namespace
810 yield prop.value
811 logger.log_debug('CIMProvider MI_associatorNames returning')
812
813 - def MI_references(self,
814 env,
815 objectName,
816 resultClassName,
817 role,
818 propertyList):
819
820 """Return instances of an association class.
821
822 Implements the WBEM operation References in terms
823 of the references method. A derived class will not normally
824 override this method.
825
826 """
827
828 logger = env.get_logger()
829 logger.log_debug('CIMProvider MI_references called. resultClass: %s' % \
830 (resultClassName))
831 ch = env.get_cimom_handle()
832 if not resultClassName:
833 raise pywbem.CIMError(
834 pywbem.CIM_ERR_FAILED,
835 "Empty resultClassName passed to References")
836 assocClass = ch.GetClass(resultClassName, objectName.namespace,
837 LocalOnly=False,
838 IncludeQualifiers=True)
839 keyNames = get_keys_from_class(assocClass)
840 plist = None
841 if propertyList is not None:
842 lkns = [kn.lower() for kn in keyNames]
843 props = pywbem.NocaseDict()
844 plist = [s.lower() for s in propertyList]
845 pklist = plist + lkns
846 [props.__setitem__(p.name, p) for p in \
847 assocClass.properties.values() \
848 if p.name.lower() in pklist]
849 else:
850 props = assocClass.properties
851 _strip_quals(props)
852 model = pywbem.CIMInstance(classname=assocClass.classname,
853 properties=props)
854 model.path = pywbem.CIMInstanceName(classname=assocClass.classname,
855 namespace=objectName.namespace)
856
857
858
859 if role:
860 if role not in model.properties:
861 raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
862 "** this shouldn't happen")
863 model[role] = objectName
864
865 for inst in self.references(env=env,
866 object_name=objectName,
867 model=model,
868 assoc_class=assocClass,
869 result_class_name='',
870 role=role,
871 result_role=None,
872 keys_only=False):
873 inst.path = build_instance_name(inst, keyNames)
874 if self.filter_results and plist is not None:
875 inst = inst.copy()
876 filter_instance(inst, plist)
877 for prop in inst.properties.values():
878 if hasattr(prop.value, 'namespace') and \
879 prop.value.namespace is None:
880 prop.value.namespace = objectName.namespace
881 yield inst
882 logger.log_debug('CIMProvider MI_references returning')
883
884 - def MI_referenceNames(self,
885 env,
886 objectName,
887 resultClassName,
888 role):
889
890 """Return instance names of an association class.
891
892 Implements the WBEM operation ReferenceNames in terms
893 of the references method. A derived class will not normally
894 override this method.
895
896 """
897
898 logger = env.get_logger()
899 logger.log_debug('CIMProvider MI_referenceNames <2> called. ' \
900 'resultClass: %s' % (resultClassName))
901 ch = env.get_cimom_handle()
902 if not resultClassName:
903 raise pywbem.CIMError(
904 pywbem.CIM_ERR_FAILED,
905 "Empty resultClassName passed to ReferenceNames")
906
907 assocClass = ch.GetClass(resultClassName, objectName.namespace,
908 LocalOnly=False,
909 IncludeQualifiers=True)
910 keys = pywbem.NocaseDict()
911 keyNames = [p.name for p in assocClass.properties.values()
912 if 'key' in p.qualifiers]
913 for keyName in keyNames:
914 p = assocClass.properties[keyName]
915 keys.__setitem__(p.name, p)
916 _strip_quals(keys)
917 model = pywbem.CIMInstance(classname=assocClass.classname,
918 properties=keys)
919 model.path = pywbem.CIMInstanceName(classname=assocClass.classname,
920 namespace=objectName.namespace)
921
922
923
924 if role:
925 if role not in model.properties:
926 raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
927 "** this shouldn't happen")
928 model[role] = objectName
929 for inst in self.references(env=env,
930 object_name=objectName,
931 model=model,
932 assoc_class=assocClass,
933 result_class_name='',
934 role=role,
935 result_role=None,
936 keys_only=True):
937 for prop in inst.properties.values():
938 if hasattr(prop.value, 'namespace') and \
939 prop.value.namespace is None:
940 prop.value.namespace = objectName.namespace
941 yield build_instance_name(inst, keyNames)
942 logger.log_debug('CIMProvider MI_referenceNames returning')
943
945
946 """Invoke an extrinsic method.
947
948 Implements the InvokeMethod WBEM operation by calling the
949 method on a derived class called cim_method_<method_name>,
950 where <method_name> is the name of the CIM method, in all
951 lower case.
952
953 Arguments:
954 env -- Provider Environment (pycimmb.ProviderEnvironment)
955 objectName -- The InstanceName or ClassName of the object on
956 which the method is invoked.
957 metaMethod -- The CIMMethod representing the method to be
958 invoked.
959 inputParams -- A Dictionary where the key is the parameter name
960 and the value is the parameter value.
961
962 The return value for invokeMethod must be a tuple of size 2
963 where:
964 element 0 is a tuple of size 2 where element 0 is the return
965 data type name and element 1 is the actual data value.
966 element 1 is a dictionary where the key is the output
967 parameter name and the value is a tuple of size 2 where
968 element 0 is the data type name for the output parameter
969 and element 1 is the actual value of the output parameter.
970
971 A derived class will not normally override this method.
972
973 """
974
975 logger = env.get_logger()
976 logger.log_debug('CIMProvider MI_invokeMethod called. method: %s:%s' \
977 % (objectName.classname, metaMethod.name))
978 lmethName = "cim_method_%s" % metaMethod.name.lower()
979 if hasattr(self, lmethName):
980 method = getattr(self, lmethName)
981 new_inputs = dict([('param_%s' % k.lower(), v) \
982 for k, v in inputParams.items()])
983 (rval, outs) = method(env=env, object_name=objectName,
984 method=metaMethod, **new_inputs)
985
986 def add_type(v, _tp):
987 lv = v
988 if type(v) == list and len(v) > 0:
989 lv = v[0]
990 if isinstance(lv, pywbem.CIMClass):
991 tp = 'class'
992 elif isinstance(lv, pywbem.CIMInstance):
993 tp = 'instance'
994 elif isinstance(lv, pywbem.CIMInstanceName):
995 tp = 'reference'
996 elif v is None or (type(v) == list and len(v) == 0):
997 tp = _tp
998 else:
999 tp = pywbem.cimtype(v)
1000 return (tp, v)
1001
1002 for k, v in outs.items():
1003 if hasattr(v, 'namespace') and v.namespace is None:
1004 v.namespace = objectName.namespace
1005 outs[k] = add_type(v, metaMethod.parameters[k].type)
1006 rval = add_type(rval, metaMethod.return_type)
1007 rval = (rval, outs)
1008 else:
1009 raise pywbem.CIMError(
1010 pywbem.CIM_ERR_METHOD_NOT_FOUND,
1011 "%s:%s"%(objectName.classname, metaMethod.name))
1012 logger.log_debug('CIMProvider MI_invokeMethod returning')
1013 return rval
1014
1016 """Remove properties from an instance that aren't in the PropertyList
1017
1018 inst -- The CIMInstance
1019 plist -- The property List, or None. The list items must be all
1020 lowercase.
1021
1022 """
1023
1024 if plist is not None:
1025 for pname in inst.properties.keys():
1026 if pname.lower() not in plist:
1027 del inst.properties[pname]
1028
1030 """Return list of the key property names for a class """
1031 return [prop.name for prop in cc.properties.values() \
1032 if 'key' in prop.qualifiers]
1033
1035 """Return an instance name from an instance, and set instance.path """
1036 if obj is None:
1037 for _ in inst.properties.values():
1038 inst.path.keybindings.__setitem__(_.name, _.value)
1039 return inst.path
1040 if not isinstance(obj, list):
1041 return build_instance_name(inst, get_keys_from_class(obj))
1042 keys = {}
1043 for _ in obj:
1044 if _ not in inst.properties:
1045 raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
1046 "Instance of %s is missing key property %s" \
1047 %(inst.classname, _))
1048 keys[_] = inst[_]
1049 inst.path = pywbem.CIMInstanceName(classname=inst.classname,
1050 keybindings=keys,
1051 namespace=inst.path.namespace,
1052 host=inst.path.host)
1053 return inst.path
1054
1055
1063
1064
1066 """Generate a Python Provider template.
1067
1068 Parameters:
1069 cc - A CIMClass to generate code for.
1070
1071 Returns a two-tuple containing the Python provider code stubs, and
1072 the provider registration MOF.
1073
1074 """
1075
1076 import inspect
1077
1078 def format_desc(obj, indent):
1079 linelen = 75 - indent
1080 if isinstance(obj, basestring):
1081 raw = obj
1082 else:
1083 try:
1084 raw = obj.qualifiers['description'].value
1085 except KeyError:
1086 return ''
1087 txt = ''
1088 beg = 0
1089 end = 0
1090 while beg < len(raw):
1091 beg = end
1092 end += linelen
1093 while beg < len(raw) and raw[beg].isspace():
1094 beg = beg+1
1095 while end < len(raw) and end > beg and not raw[end].isspace():
1096 end = end-1
1097 if beg == end:
1098 while end < len(raw) and not raw[end].isspace():
1099 end += 1
1100 line = raw[beg:end]
1101 line = line.replace('\n', ' ')
1102 line = line.replace('\r', '')
1103 txt += '\n%s%s'% (''.ljust(indent), line)
1104 return txt
1105
1106
1107 def map_value(obj, val):
1108 rv = str(val)
1109 if 'ValueMap' not in obj.qualifiers:
1110 return rv
1111 if 'Values' not in obj.qualifiers:
1112 return rv
1113 vals = [str(x) for x in obj.qualifiers['Values'].value]
1114 maps = [str(x) for x in obj.qualifiers['ValueMap'].value]
1115 d = dict(zip(maps, vals))
1116 try:
1117 tmp = d[str(val)]
1118 rv = ''
1119 for ch in tmp:
1120 rv += ch.isalnum() and ch or '_'
1121 except KeyError:
1122 pass
1123 return rv
1124
1125
1126 def type_hint(obj, method_name=None):
1127 if hasattr(obj, 'type'):
1128 tx = obj.type
1129 if 'embeddedinstance' in obj.qualifiers:
1130 tx = "pywbem.CIMInstance(classname='%s', ...)" % \
1131 obj.qualifiers['embeddedinstance'].value
1132 elif tx == 'reference':
1133 tx = "pywbem.CIMInstanceName(classname='%s', ...)" % \
1134 obj.reference_class
1135 else:
1136 tx = obj.return_type
1137 if hasattr(obj, 'value') and obj.value is not None:
1138 defval = str(obj.value)
1139 else:
1140 defval = ''
1141 if not tx.startswith('pywbem.'):
1142 if tx == 'boolean':
1143 tx = 'bool(%s)' % defval
1144 elif tx == 'datetime':
1145 tx = 'pywbem.CIMDateTime()'
1146 elif tx == 'string':
1147 tx = "''"
1148 else:
1149 tx = 'pywbem.%s(%s)' % (tx.capitalize(), defval)
1150 if 'valuemap' in obj.qualifiers:
1151 if defval:
1152 defval = map_value(obj, defval)
1153 else:
1154 defval = '<VAL>'
1155 tx = 'self.Values.%s%s.%s' % \
1156 (method_name and '%s.'%method_name or '',
1157 obj.name, defval)
1158 if hasattr(obj, 'is_array') and obj.is_array:
1159 tx = '[%s,]' % tx
1160 return tx
1161
1162 def type_str(obj, method_name=None):
1163 if hasattr(obj, 'type'):
1164 tx = obj.type
1165 if 'embeddedinstance' in obj.qualifiers:
1166 return "pywbem.CIMInstance(classname='%s', ...)" % \
1167 obj.qualifiers['embeddedinstance'].value
1168 elif tx == 'reference':
1169 return "REF (pywbem.CIMInstanceName(classname='%s', ...)" % \
1170 obj.reference_class
1171 else:
1172 tx = obj.return_type
1173 if tx == 'boolean':
1174 tx = 'bool'
1175 elif tx == 'datetime':
1176 tx = 'pywbem.CIMDateTime'
1177 elif tx == 'string':
1178 tx = 'unicode'
1179 else:
1180 tx = 'pywbem.%s' % tx.capitalize()
1181 if hasattr(obj, 'is_array') and obj.is_array:
1182 tx = '[%s,]' % tx
1183 if 'valuemap' in obj.qualifiers:
1184 tx += ' self.Values.%s%s' % \
1185 (method_name and '%s.' % method_name or '', obj.name)
1186 return tx
1187
1188 def is_required(obj):
1189 if 'required' in obj.qualifiers and obj.qualifiers['required'].value:
1190 return '(Required)'
1191 return ''
1192
1193 def build_val_map(obj):
1194 vm = obj.qualifiers['valuemap'].value
1195 if 'values' in obj.qualifiers:
1196 vals = obj.qualifiers['values'].value
1197 else:
1198 vals = vm
1199 tmap = zip(vals, vm)
1200 map = []
1201 for t in tmap:
1202 nname = ''
1203 for ch in t[0]:
1204 if ch.isalnum():
1205 nname += ch
1206 else:
1207 nname += '_'
1208 if hasattr(obj, 'return_type'):
1209 tp = obj.return_type
1210 else:
1211 tp = obj.type
1212 if tp == 'string':
1213 val = "'%s'" % t[1]
1214 else:
1215 try:
1216 int(t[1])
1217 val = 'pywbem.%s(%s)' % (tp.capitalize(), t[1])
1218 except ValueError:
1219 val = t[1]
1220 nname = "# "+nname
1221 map.append((nname, val))
1222 return map
1223
1224 valuemaps = {}
1225
1226 for obj in cc.properties.values() + cc.methods.values():
1227 if 'valuemap' in obj.qualifiers:
1228 valuemaps[obj.name] = {'<vms>':build_val_map(obj)}
1229
1230 for meth in cc.methods.values():
1231 for parm in meth.parameters.values():
1232 if 'valuemap' in parm.qualifiers:
1233 if meth.name not in valuemaps:
1234 valuemaps[meth.name] = {}
1235 valuemaps[meth.name][parm.name] = build_val_map(parm)
1236
1237 mappings = {'classname':cc.classname,
1238 'classname_l':cc.classname.lower()}
1239 isAssoc = 'association' in cc.qualifiers
1240
1241 code = '''"""Python Provider for %(classname)s
1242
1243 Instruments the CIM class %(classname)s
1244
1245 """
1246
1247 import pywbem
1248
1249 class %(classname)sProvider(pywbem.CIMProvider):
1250 """Instrument the CIM class %(classname)s \n''' % mappings
1251 code += format_desc(cc, 4)
1252 code += '''
1253 """'''
1254
1255
1256 args = inspect.getargspec(CIMProvider.get_instance)[0]
1257 args = ', '.join(args)
1258 code += '''
1259
1260 def __init__ (self, env):
1261 logger = env.get_logger()
1262 logger.log_debug('Initializing provider %%s from %%s' \\
1263 %% (self.__class__.__name__, __file__))
1264 # If you will be filtering instances yourself according to
1265 # property_list, role, result_role, and result_class_name
1266 # parameters, set self.filter_results to False
1267 # self.filter_results = False
1268
1269 def get_instance(%s):
1270 """%s"""
1271
1272 logger = env.get_logger()
1273 logger.log_debug('Entering %%s.get_instance()' \\
1274 %% self.__class__.__name__)
1275 ''' % (args, CIMProvider.get_instance.__doc__)
1276 keyProps = [p for p in cc.properties.values() \
1277 if 'key' in p.qualifiers]
1278 code += '''
1279 ux = model.update_existing
1280
1281 # TODO fetch system resource matching the following keys:'''
1282 for kp in keyProps:
1283 code += '''
1284 # model['%s']''' % kp.name
1285 code += '\n'
1286 props = cc.properties.values()
1287 props.sort()
1288 for prop in props:
1289 if 'key' in prop.qualifiers:
1290 continue
1291
1292
1293 line = "#ux(%s=%s) # TODO %s" % \
1294 (prop.name, type_hint(prop), is_required(prop))
1295 code += '''
1296 %s''' % line
1297
1298 args = inspect.getargspec(CIMProvider.enum_instances)[0]
1299 args = ', '.join(args)
1300 code += '''
1301 return model
1302
1303 def enum_instances(%s):
1304 """%s"""
1305
1306 logger = env.get_logger()
1307 logger.log_debug('Entering %%s.enum_instances()' \\
1308 %% self.__class__.__name__)
1309
1310 while False: # TODO more instances?
1311 # TODO fetch system resource
1312 # Key properties''' % (args, CIMProvider.enum_instances.__doc__)
1313 for kp in keyProps:
1314 if kp.name == 'CreationClassName':
1315 line = "model['%s'] = '%s'" % (kp.name, cc.classname)
1316 else:
1317 line = "#model['%s'] = # TODO (type = %s)" % \
1318 (kp.name, type_str(kp))
1319 code += '''
1320 %s''' % line
1321 code += '''
1322 if keys_only:
1323 yield model
1324 else:
1325 try:
1326 yield self.get_instance(env, model, cim_class)
1327 except pywbem.CIMError, (num, msg):
1328 if num not in (pywbem.CIM_ERR_NOT_FOUND,
1329 pywbem.CIM_ERR_ACCESS_DENIED):
1330 raise\n'''
1331
1332 args = inspect.getargspec(CIMProvider.set_instance)[0]
1333 args = ', '.join(args)
1334 code += '''
1335 def set_instance(%s):
1336 """%s"""
1337
1338 logger = env.get_logger()
1339 logger.log_debug('Entering %%s.set_instance()' \\
1340 %% self.__class__.__name__)
1341 # TODO create or modify the instance
1342 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED) # Remove to implement
1343 return instance''' % (args, CIMProvider.set_instance.__doc__)
1344
1345 args = inspect.getargspec(CIMProvider.delete_instance)[0]
1346 args = ', '.join(args)
1347 code += '''
1348
1349 def delete_instance(%s):
1350 """%s"""
1351
1352 logger = env.get_logger()
1353 logger.log_debug('Entering %%s.delete_instance()' \\
1354 %% self.__class__.__name__)
1355
1356 # TODO delete the resource
1357 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED) # Remove to implement
1358 ''' % (args, CIMProvider.delete_instance.__doc__)
1359
1360 for method in cc.methods.values():
1361 inParms = [p for p in method.parameters.values() if \
1362 'in' in p.qualifiers and p.qualifiers['in'].value]
1363 outParms = [p for p in method.parameters.values() if \
1364 'out' in p.qualifiers and p.qualifiers['out'].value]
1365 code += '''
1366 def cim_method_%s(self, env, object_name, method''' % method.name.lower()
1367 for p in inParms:
1368 code += ''',\n%sparam_%s''' % (''.rjust(len(method.name)+20),
1369 p.name.lower())
1370 code += '''):
1371 """Implements %s.%s()\n''' % (cc.classname, method.name)
1372 code += format_desc(method, 8)
1373
1374 code += '''
1375 Keyword arguments:
1376 env -- Provider Environment (pycimmb.ProviderEnvironment)
1377 object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName
1378 specifying the object on which the method %s()
1379 should be invoked.
1380 method -- A pywbem.CIMMethod representing the method meta-data''' \
1381 % method.name
1382
1383 for p in inParms:
1384 code += '''
1385 param_%s -- The input parameter %s (type %s) %s''' \
1386 % (p.name.lower(), p.name, type_str(p, method.name),
1387 is_required(p))
1388 code += format_desc(p, 12)
1389
1390 code += '''
1391
1392 Returns a two-tuple containing the return value (type %s)
1393 and a dictionary with the out-parameters
1394
1395 Output parameters:''' % type_str(method)
1396
1397 if not outParms:
1398 code += ' none'
1399 else:
1400 for p in outParms:
1401 code += '''
1402 %s -- (type %s) %s''' % (p.name, type_str(p, method.name),
1403 is_required(p))
1404 code += format_desc(p, 12)
1405
1406 code += '''
1407
1408 Possible Errors:
1409 CIM_ERR_ACCESS_DENIED
1410 CIM_ERR_INVALID_PARAMETER (including missing, duplicate,
1411 unrecognized or otherwise incorrect parameters)
1412 CIM_ERR_NOT_FOUND (the target CIM Class or instance does not
1413 exist in the specified namespace)
1414 CIM_ERR_METHOD_NOT_AVAILABLE (the CIM Server is unable to honor
1415 the invocation request)
1416 CIM_ERR_FAILED (some other unspecified error occurred)
1417
1418 """
1419
1420 logger = env.get_logger()
1421 logger.log_debug('Entering %%s.cim_method_%s()' \\
1422 %% self.__class__.__name__)
1423
1424 # TODO do something
1425 raise pywbem.CIMError(pywbem.CIM_ERR_METHOD_NOT_AVAILABLE) # Remove to implemented
1426 out_params = {}''' % method.name.lower()
1427
1428 for p in outParms:
1429 code += '''
1430 #out_params['%s'] = %s # TODO''' % \
1431 (p.name.lower(), type_hint(p, method.name))
1432
1433 code += '''
1434 rval = None # TODO (type %s)
1435 return (rval, out_params)
1436 ''' % type_str(method)
1437
1438 if isAssoc:
1439 args = inspect.getargspec(CIMProvider.references)[0]
1440 args = format_desc(', '.join(args), 19).strip()
1441 code += '''
1442 def references(%s):
1443 """%s"""
1444
1445 logger = env.get_logger()
1446 logger.log_debug('Entering %%s.references()' \\
1447 %% self.__class__.__name__)
1448 ch = env.get_cimom_handle()
1449 # This is a common pattern. YMMV''' % \
1450 (args, CIMProvider.references.__doc__)
1451 refprops = []
1452 for prop in cc.properties.values():
1453 if prop.reference_class is not None:
1454 refprops.append((prop.name, prop.reference_class))
1455 for refprop in refprops:
1456 code += '''
1457 if (not role or role.lower() == '%(refpropnamel)s') and \\
1458 pywbem.is_subclass(ch, object_name.namespace,
1459 sub=object_name.classname,
1460 super='%(rolecname)s'):
1461 model['%(refpropname)s'] = object_name
1462 yield model # TODO: Add other REF properties.
1463 # Yield association instances where
1464 # object_name is %(refpropnamel)s.
1465 # Only appropriate if object_name.classname
1466 # is '%(rolecname)s' or a subclass.\n''' \
1467 % {'refpropname':refprop[0],
1468 'refpropnamel':refprop[0].lower(),
1469 'rolecname':refprop[1]}
1470
1471 if valuemaps:
1472 code += '''
1473 class Values(object):'''
1474 for group, maps in valuemaps.items():
1475 code += '''
1476 class %s(object):''' % group
1477 if '<vms>' in maps:
1478 for value, vm in maps['<vms>']:
1479 if value in maps:
1480 value = value+'_'
1481 code += '''
1482 %s = %s''' % (value, vm)
1483 for pname, vms in maps.items():
1484 if pname == '<vms>':
1485 continue
1486 code += '''
1487 class %s(object):''' % pname
1488 for value, vm in vms:
1489 code += '''
1490 %s = %s''' % (value, vm)
1491 code += '\n'
1492
1493 code += '''
1494 ## end of class %(classname)sProvider
1495
1496 def get_providers(env):
1497 %(classname_l)s_prov = %(classname)sProvider(env)
1498 return {'%(classname)s': %(classname_l)s_prov}
1499 ''' % mappings
1500
1501 owtypes = ['1', 'Instance']
1502 pegtypes = ['2', 'Instance']
1503 if isAssoc:
1504 owtypes[0] += ',3'
1505 owtypes[1] += ', Associator'
1506 pegtypes[0] += ',3'
1507 pegtypes[1] += ', Associator'
1508 if cc.methods:
1509 owtypes[0] += ',6'
1510 owtypes[1] += ', Method'
1511 pegtypes[0] += ',5'
1512 pegtypes[1] += ', Method'
1513 mof = '''
1514 // OpenWBEM Provider registration for %(classname)s
1515 instance of OpenWBEM_PyProviderRegistration
1516 {
1517 InstanceID = "<org:product:%(classname)s:unique_id>"; // TODO
1518 NamespaceNames = {"root/cimv2"}; // TODO
1519 ClassName = "%(classname)s";
1520 ProviderTypes = {%(owtypeNums)s}; // %(owtypeStrs)s
1521 ModulePath = "/usr/lib/pycim/%(classname)sProvider.py"; // TODO
1522 };
1523
1524 // Pegasus Provider registration for %(classname)s
1525 instance of PG_ProviderModule
1526 {
1527 Name = "/usr/lib/pycim/%(classname)sProvider.py";
1528 InterfaceType = "Python";
1529 InterfaceVersion = "1.0.0";
1530 Location = "/usr/lib/pycim/%(classname)sProvider.py";
1531 UserContext = 2; // Requestor
1532 Vendor = "TODO"; // TODO
1533 Version = "1.0";
1534 };
1535 instance of PG_Provider
1536 {
1537 Name = "%(classname)s";
1538 ProviderModuleName = "/usr/lib/pycim/%(classname)sProvider.py";
1539 };
1540 instance of PG_ProviderCapabilities
1541 {
1542 CapabilityID = "%(classname)s";
1543 ProviderModuleName = "/usr/lib/pycim/%(classname)sProvider.py";
1544 ProviderName = "%(classname)s";
1545 ClassName = "%(classname)s";
1546 Namespaces = {"root/cimv2"}; // TODO
1547 ProviderType = {%(pegtypeNum)s}; // %(pegtypeStr)s
1548 };\n''' % {'classname': cc.classname,
1549 'owtypeNums': owtypes[0],
1550 'owtypeStrs': owtypes[1],
1551 'pegtypeNum': pegtypes[0],
1552 'pegtypeStr': pegtypes[1]}
1553
1554
1555 return code, mof
1556
1558 """Wraps a provider module, and routes requests into the module """
1559
1561 if isinstance(provid, ModuleType):
1562 self.provmod = provid
1563 self.provid = provid.__name__
1564 self.filename = provid.__file__
1565 else:
1566 self.provid = provid
1567
1568 provider_name = 'pyprovider_'
1569 for ch in provid:
1570 provider_name += ch.isalnum() and ch or '_'
1571
1572 provdir = dirname(provid)
1573 if provdir not in sys.path:
1574 sys.path.append(provdir)
1575
1576 try:
1577 self.provmod = load_source(provider_name, provid)
1578 except IOError, arg:
1579 raise pywbem.CIMError(
1580 pywbem.CIM_ERR_FAILED,
1581 "Error loading provider %s: %s" % (provid, arg))
1582 self.filename = self.provmod.__file__
1583 self.provregs = {}
1584 if hasattr(self.provmod, 'init'):
1585 self.provmod.init(env)
1586 if hasattr(self.provmod, 'get_providers'):
1587 self.provregs = pywbem.NocaseDict(self.provmod.get_providers(env))
1588
1590 """Return a function or method object appropriate to fulfill a request
1591
1592 classname -- The CIM class name associated with the request.
1593 cname -- The function or method name to look for.
1594
1595 """
1596
1597 callable = None
1598 if classname in self.provregs:
1599 provClass = self.provregs[classname]
1600 if hasattr(provClass, cname):
1601 callable = getattr(provClass, cname)
1602 elif hasattr(self.provmod, cname):
1603 callable = getattr(self.provmod, cname)
1604 if callable is None:
1605 raise pywbem.CIMError(
1606 pywbem.CIM_ERR_FAILED,
1607 "No callable for %s:%s on provider %s" % \
1608 (classname, cname, self.provid))
1609 return callable
1610
1611
1612
1613
1618
1619 logger = env.get_logger()
1620 logger.log_debug('ProviderProxy MI_enumInstanceNames called...')
1621 for i in self._get_callable(cimClass.classname,
1622 'MI_enumInstanceNames') \
1623 (env, ns, cimClass):
1624 yield i
1625 logger.log_debug('CIMProvider MI_enumInstanceNames returning')
1626
1627
1628
1629
1630 - def MI_enumInstances(self,
1631 env,
1632 ns,
1633 propertyList,
1634 requestedCimClass,
1635 cimClass):
1636
1637 logger = env.get_logger()
1638 logger.log_debug('CIMProvider MI_enumInstances called...')
1639 for i in self._get_callable(cimClass.classname, 'MI_enumInstances') \
1640 (env,
1641 ns,
1642 propertyList,
1643 requestedCimClass,
1644 cimClass):
1645 yield i
1646 logger.log_debug('CIMProvider MI_enumInstances returning')
1647
1648
1649
1650
1651 - def MI_getInstance(self,
1652 env,
1653 instanceName,
1654 propertyList,
1655 cimClass):
1656
1657 logger = env.get_logger()
1658 logger.log_debug('CIMProvider MI_getInstance called...')
1659 rval = self._get_callable(cimClass.classname, 'MI_getInstance') \
1660 (env,
1661 instanceName,
1662 propertyList,
1663 cimClass)
1664 logger.log_debug('CIMProvider MI_getInstance returning')
1665 return rval
1666
1667
1668
1669
1673
1674 logger = env.get_logger()
1675 logger.log_debug('CIMProvider MI_createInstance called...')
1676 rval = self._get_callable(instance.classname, 'MI_createInstance') \
1677 (env, instance)
1678 logger.log_debug('CIMProvider MI_createInstance returning')
1679 return rval
1680
1681
1682
1683
1684 - def MI_modifyInstance(self,
1685 env,
1686 modifiedInstance,
1687 previousInstance,
1688 propertyList,
1689 cimClass):
1690
1691 logger = env.get_logger()
1692 logger.log_debug('CIMProvider MI_modifyInstance called...')
1693 self._get_callable(cimClass.classname, 'MI_modifyInstance') \
1694 (env, modifiedInstance, previousInstance,
1695 propertyList, cimClass)
1696 logger.log_debug('CIMProvider MI_modifyInstance returning')
1697
1698
1699
1700
1704
1705 logger = env.get_logger()
1706 logger.log_debug('CIMProvider MI_deleteInstance called...')
1707 self._get_callable(instanceName.classname, 'MI_deleteInstance') \
1708 (env, instanceName)
1709 logger.log_debug('CIMProvider MI_deleteInstance returning')
1710
1711
1712
1713
1714
1715 - def MI_associators(self,
1716 env,
1717 objectName,
1718 assocClassName,
1719 resultClassName,
1720 role,
1721 resultRole,
1722 propertyList):
1723
1724
1725
1726 logger = env.get_logger()
1727 logger.log_debug('CIMProvider MI_associators called. assocClass: %s' % \
1728 (assocClassName))
1729 cname = assocClassName
1730 for i in self._get_callable(cname, 'MI_associators') \
1731 (env, objectName, assocClassName, resultClassName,
1732 role, resultRole, propertyList):
1733 yield i
1734 logger.log_debug('CIMProvider MI_associators returning')
1735
1736
1737
1738
1739 - def MI_associatorNames(self,
1740 env,
1741 objectName,
1742 assocClassName,
1743 resultClassName,
1744 role,
1745 resultRole):
1746
1747 logger = env.get_logger()
1748 logger.log_debug('CIMProvider MI_associatorNames called. ' \
1749 'assocClass: %s' % (assocClassName))
1750 cname = assocClassName
1751 for i in self._get_callable(cname, 'MI_associatorNames') \
1752 (env, objectName, assocClassName, resultClassName,
1753 role, resultRole):
1754 yield i
1755 logger.log_debug('CIMProvider MI_associatorNames returning')
1756
1757
1758
1759
1760 - def MI_references(self,
1761 env,
1762 objectName,
1763 resultClassName,
1764 role,
1765 propertyList):
1766
1767 logger = env.get_logger()
1768 logger.log_debug('CIMProvider MI_references called. resultClass: %s' % \
1769 (resultClassName))
1770 cname = resultClassName
1771 if not cname:
1772 return
1773 for i in self._get_callable(cname, 'MI_references') \
1774 (env,
1775 objectName,
1776 resultClassName,
1777 role,
1778 propertyList):
1779 yield i
1780 logger.log_debug('CIMProvider MI_references returning')
1781
1782
1783
1784
1785 - def MI_referenceNames(self,
1786 env,
1787 objectName,
1788 resultClassName,
1789 role):
1790
1791 logger = env.get_logger()
1792 logger.log_debug('CIMProvider MI_referenceNames <1> called. ' \
1793 'resultClass: %s' % (resultClassName))
1794 cname = resultClassName
1795 if not cname:
1796 return
1797 for i in self._get_callable(cname, 'MI_referenceNames') \
1798 (env,
1799 objectName,
1800 resultClassName,
1801 role):
1802 yield i
1803 logger.log_debug('CIMProvider MI_referenceNames returning')
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1818
1819 logger = env.get_logger()
1820 logger.log_debug('CIMProvider MI_invokeMethod called. method: %s:%s' \
1821 % (objectName.classname, metaMethod.name))
1822 rval = self._get_callable(objectName.classname, 'MI_invokeMethod') \
1823 (env, objectName, metaMethod, inputParams)
1824 logger.log_debug('CIMProvider MI_invokeMethod returning')
1825 return rval
1826
1827
1829
1830 logger = env.get_logger()
1831 logger.log_debug('CIMProvider MI_poll called')
1832 if hasattr(self.provmod, 'poll'):
1833 rval = self.provmod.poll(env)
1834 elif hasattr(self.provmod, 'MI_poll'):
1835 rval = self.provmod.MI_poll(env)
1836 else:
1837 raise pywbem.CIMError(
1838 pywbem.CIM_ERR_FAILED,
1839 "Provider %s has no support for polling" % self.provid)
1840 logger.log_debug('CIMProvider MI_poll returning %s' % str(rval))
1841 return rval
1842
1843
1845
1846 logger = env.get_logger()
1847 logger.log_debug('CIMProvider MI_poll called')
1848 if hasattr(self.provmod, 'get_initial_polling_interval'):
1849 rval = self.provmod.get_initial_polling_interval(env)
1850 elif hasattr(self.provmod, 'MI_getInitialPollingInterval'):
1851 rval = self.provmod.MI_getInitialPollingInterval(env)
1852 else:
1853 raise pywbem.CIMError(
1854 pywbem.CIM_ERR_FAILED,
1855 "Provider %s has no support for polling" % self.provid)
1856 logger.log_debug('CIMProvider MI_poll returning %s' % str(rval))
1857 return rval
1858
1859
1860 - def MI_activateFilter(self,
1861 env,
1862 filter,
1863 namespace,
1864 classes,
1865 firstActivation):
1866
1867 logger = env.get_logger()
1868 logger.log_debug('CIMProvider MI_activateFilter called')
1869 if hasattr(self.provmod, 'activate_filter'):
1870 self.provmod.activate_filter(env, filter, namespace,
1871 classes, firstActivation)
1872 elif hasattr(self.provmod, 'MI_activateFilter'):
1873 self.provmod.MI_activateFilter(env, filter, namespace,
1874 classes, firstActivation)
1875 else:
1876 raise pywbem.CIMError(
1877 pywbem.CIM_ERR_FAILED,
1878 "Provider %s has no support for activate filter" % \
1879 self.provid)
1880 logger.log_debug('CIMProvider MI_activateFilter returning')
1881
1882
1883
1884 - def MI_deActivateFilter(self,
1885 env,
1886 filter,
1887 namespace,
1888 classes,
1889 lastActivation):
1890
1891 logger = env.get_logger()
1892 logger.log_debug('CIMProvider MI_deActivateFilter called')
1893 if hasattr(self.provmod, 'deactivate_filter'):
1894 self.provmod.deactivate_filter(env, filter, namespace, classes,
1895 lastActivation)
1896 elif hasattr(self.provmod, 'MI_deActivateFilter'):
1897 self.provmod.MI_deActivateFilter(env, filter, namespace, classes,
1898 lastActivation)
1899 else:
1900 raise pywbem.CIMError(
1901 pywbem.CIM_ERR_FAILED,
1902 "Provider %s has no support for deactivate filter" % \
1903 self.provid)
1904 logger.log_debug('CIMProvider MI_deActivateFilter returning')
1905
1906
1907
1909
1910 modname = self.provmod.__name__
1911 if hasattr(self.provmod, "shutdown"):
1912 self.provmod.shutdown(env)
1913 self.provmod = None
1914 del sys.modules[modname]
1915
1916
1917
1918
1920
1921 if hasattr(self.provmod, "canunload"):
1922 return self.provmod.canunload
1923 else:
1924 return True
1925
1926
1928
1929
1930 logger = env.get_logger()
1931 logger.log_debug('ProviderProxy MI_consumeIndication called')
1932 if hasattr(self.provmod, 'consume_indication'):
1933 self.provmod.consume_indication(env, destinationPath,
1934 indicationInstance)
1935 elif hasattr(self.provmod, 'MI_consumeIndication'):
1936 self.provmod.MI_consumeIndication(env, destinationPath,
1937 indicationInstance)
1938 else:
1939 raise pywbem.CIMError(
1940 pywbem.CIM_ERR_FAILED,
1941 "Provider %s has no support for consume indication" % \
1942 self.provid)
1943 logger.log_debug('ProviderProxy MI_consumeIndication returning')
1944
1945
1946
1947 - def MI_handleIndication(self,
1948 env,
1949 ns,
1950 handlerInstance,
1951 indicationInstance):
1952
1953
1954 logger = env.get_logger()
1955 logger.log_debug('ProviderProxy MI_handleIndication called')
1956 if hasattr(self.provmod, 'handle_indication'):
1957 self.provmod.handle_indication(env, ns, handlerInstance,
1958 indicationInstance)
1959 elif hasattr(self.provmod, 'MI_handleIndication'):
1960 self.provmod.MI_handleIndication(env, ns, handlerInstance,
1961 indicationInstance)
1962 else:
1963 raise pywbem.CIMError(
1964 pywbem.CIM_ERR_FAILED,
1965 "Provider %s has no support for handle indication" % \
1966 self.provid)
1967 logger.log_debug('ProviderProxy MI_handleIndication returning')
1968