1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """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_module()
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 CIMProvider2 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 CIMProvider2 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 CIMProvider2 subclasses. Note that multiple classes can be
76 instrumented by the same instance of a CIMProvider2 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(CIMProvider2):
86 ...
87
88 def get_providers(env):
89 _fbp = Py_FooBarProvider()
90 return {'Py_Foo':_fbp, 'Py_Bar':_fbp}
91
92 can_unload(env):
93 Return True if the provider can be unloaded.
94
95 The CIMOM may try to unload a provider after a period of inactivity.
96 Before unloading a provider, the CIMOM asks the provider if it can
97 be unloaded.
98
99 Arguments:
100 env -- Provider Environment (pycimmb.ProviderEnvironment)
101
102 shutdown(env):
103 Perform any cleanup tasks prior to being unloaded.
104
105 The provider will shortly be unloaded, and is given an opportunity
106 to perform any needed cleanup. The provider may be unloaded after
107 a period of inactivity (see the documentation for can_unload), or
108 because the CIMOM is shutting down.
109
110 Arguments:
111 env -- Provider Environment (pycimmb.ProviderEnvironment)
112
113 handle_indication(env, ns, handler_instance, indication_instance):
114 Process an indication.
115
116 Arguments:
117 env -- Provider Environment (pycimmb.ProviderEnvironment)
118 ns -- The namespace where the event occurred
119 handler_instance --
120 indication_instance -- The indication
121
122 authorize_filter (env, filter, ns, classes,
123 owner):
124 Allow or disallow an indication subscription request.
125
126 Arguments:
127 env -- Provider Environment (pycimmb.ProviderEnvironment)
128 filter -- The WQL select statement
129 namespace -- The namepace where the indication is registered for
130 classes -- The classpath of the indication registered for
131 owner -- The name of the principal (cimom user)
132
133 activate_filter (env, filter, ns, classes,
134 first_activation):
135 Activate an indication subscription.
136
137 Arguments:
138 env -- Provider Environment (pycimmb.ProviderEnvironment)
139 filter -- The WQL select statement
140 namespace -- The namepace where the indication is registered for
141 classes -- The classpath of the indication registered for
142 first_activation -- boolean - whether first activation
143
144 deactivate_filter(env, filter, ns, classes,
145 last_activation):
146 Deactivate an indication subscription.
147
148 Arguments:
149 env -- Provider Environment (pycimmb.ProviderEnvironment)
150 filter -- The WQL select statement
151 ns -- The namepace where the indication is registered for
152 classes -- The classpath of the indication registered for
153 last_activation -- boolean - whether last activation
154
155 enable_indications(env):
156 Enable indications.
157
158 Arguments:
159 env -- Provider Environment (pycimmb.ProviderEnvironment)
160
161 disable_indications(env):
162 Disable indications.
163
164 Arguments:
165 env -- Provider Environment (pycimmb.ProviderEnvironment)
166
167 Provider Environment
168
169 A pycimmb.ProviderEnvironment is passed to many functions. This is
170 a handle back into the CIMOM. You can use it for logging and for
171 making "up-calls" to the CIMOM. For example:
172
173 logger = env.get_logger()
174 logger.log_debug('Debug Info')
175
176 ch = env.get_cimom_handle()
177 other_inst = ch.GetInstance(inst_path, LocalOnly=False,
178 IncludeQualifiers=False,
179 IncludeClassOrigin=False)
180
181 The API of the pycimmb.CIMOMHandle resembles that of
182 pywbem.WBEMConnection.
183
184 For more information on the ProviderEnvironments, and other features
185 provided by pycimmb, refer to the pycimmb documentation.
186
187 CodeGen
188
189 The codegen function can be used to generate provider stub code for a
190 given CIM class. This is a quick way to get started writing a provider.
191
192 """
193
194 from os.path import dirname
195 from types import ModuleType
196 import os
197 import imp
198 import threading
199
200 import pywbem
201
202 g_mod_lock = threading.RLock()
203
204
205
206 __all__ = ['CIMProvider2', 'codegen']
207
208
210 """If one object path doesn't inlcude a host, don't include the hosts
211 in the comparison
212
213 """
214
215 if lhs is rhs:
216 return True
217 if lhs.host is not None and rhs.host is not None and lhs.host != rhs.host:
218 return False
219
220 return not (pywbem.cmpname(rhs.classname, lhs.classname) or
221 cmp(rhs.keybindings, lhs.keybindings) or
222 pywbem.cmpname(rhs.namespace, lhs.namespace))
223
224
226 """Base class for CIM Providers.
227
228 A derived class might normally override the following:
229 - enum_instances
230 - get_instance
231 - set_instance
232 - delete_instance
233 - references
234
235 If the provider is a "read-only" instance provider, set_instance and
236 delete_instance need not be overridden.
237
238 Only association providers need to override references.
239
240 A method provider should implement a method of the form:
241 def cim_method_<method_name>(self, env, object_name, method,
242 param_<input_param_1>,
243 param_<input_param_2>,
244 ...):
245 Where <method_name> is the name of the method from the CIM schema.
246 <method_name> needs to be all lowercase, regardless of the case of
247 the method name in the CIM schema (CIM method names are case
248 insensitive).
249
250 Keyword arguments:
251 env -- Provider Environment (pycimmb.ProviderEnvironment)
252 object_name -- A pywbem.CIMInstanceName or pywbem.CIMClassname
253 specifying the object on which the method is to be invoked.
254 method -- A pywbem.CIMMethod, representing the method to execute.
255 param_<param_name> -- Corresponds to the input parameter <param_name>
256 from the CIM schema. <param_name> needs to be all lowercase,
257 regardless of the case of the parameter name in the CIM schema
258 (CIM parameter names are case insensitive).
259
260 The method returns a two-tuple containing the return value of the
261 method, and a dictionary containing the output parameters.
262
263 Example:
264 def cim_method_requeststatechange(self, env, object_name, method,
265 param_requestedstate,
266 param_timeoutperiod):
267 # do stuff.
268 out_params = {'job': pywbem.CIMInstanceName(...)}
269 rval = pywbem.Uint32(0)
270 return (rval, out_params)
271
272 The methods prefixed with "MI_" correspond to the WBEM operations
273 from http://www.dmtf.org/standards/published_documents/DSP200.html
274 The default implementations of these methods call the methods
275 described above. These will not normally be overridden or extended
276 by a subclass.
277
278 """
279
281 """Return an instance.
282
283 Keyword arguments:
284 env -- Provider Environment (pycimmb.ProviderEnvironment)
285 model -- A template of the pywbem.CIMInstance to be returned. The
286 key properties are set on this instance to correspond to the
287 instanceName that was requested. The properties of the model
288 are already filtered according to the PropertyList from the
289 request. Only properties present in the model need to be
290 given values. If you prefer, you can set all of the
291 values, and the instance will be filtered for you.
292
293 Possible Errors:
294 CIM_ERR_ACCESS_DENIED
295 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
296 or otherwise incorrect parameters)
297 CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
298 Instance does not exist in the specified namespace)
299 CIM_ERR_FAILED (some other unspecified error occurred)
300
301 """
302 return None
303
305 """Enumerate instances.
306
307 The WBEM operations EnumerateInstances and EnumerateInstanceNames
308 are both mapped to this method.
309 This method is a python generator
310
311 Keyword arguments:
312 env -- Provider Environment (pycimmb.ProviderEnvironment)
313 model -- A template of the pywbem.CIMInstances to be generated.
314 The properties of the model are already filtered according to
315 the PropertyList from the request. Only properties present in
316 the model need to be given values. If you prefer, you can
317 always set all of the values, and the instance will be filtered
318 for you.
319 keys_only -- A boolean. True if only the key properties should be
320 set on the generated instances.
321
322 Possible Errors:
323 CIM_ERR_FAILED (some other unspecified error occurred)
324
325 """
326 pass
327
329 """Return a newly created or modified instance.
330
331 Keyword arguments:
332 env -- Provider Environment (pycimmb.ProviderEnvironment)
333 instance -- The new pywbem.CIMInstance. If modifying an existing
334 instance, the properties on this instance have been filtered by
335 the PropertyList from the request.
336 modify_existing -- True if ModifyInstance, False if CreateInstance
337
338 Return the new instance. The keys must be set on the new instance.
339
340 Possible Errors:
341 CIM_ERR_ACCESS_DENIED
342 CIM_ERR_NOT_SUPPORTED
343 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
344 or otherwise incorrect parameters)
345 CIM_ERR_ALREADY_EXISTS (the CIM Instance already exists -- only
346 valid if modify_existing is False, indicating that the operation
347 was CreateInstance)
348 CIM_ERR_NOT_FOUND (the CIM Instance does not exist -- only valid
349 if modify_existing is True, indicating that the operation
350 was ModifyInstance)
351 CIM_ERR_FAILED (some other unspecified error occurred)
352
353 """
354 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED, "")
355
357 """Delete an instance.
358
359 Keyword arguments:
360 env -- Provider Environment (pycimmb.ProviderEnvironment)
361 instance_name -- A pywbem.CIMInstanceName specifying the instance
362 to delete.
363
364 Possible Errors:
365 CIM_ERR_ACCESS_DENIED
366 CIM_ERR_NOT_SUPPORTED
367 CIM_ERR_INVALID_NAMESPACE
368 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
369 or otherwise incorrect parameters)
370 CIM_ERR_INVALID_CLASS (the CIM Class does not exist in the specified
371 namespace)
372 CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
373 Instance does not exist in the specified namespace)
374 CIM_ERR_FAILED (some other unspecified error occurred)
375
376 """
377 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED, "")
378
379 - def references(self, env, object_name, model,
380 result_class_name, role, result_role, keys_only):
381 """Instrument Associations.
382
383 All four association-related operations (Associators, AssociatorNames,
384 References, ReferenceNames) are mapped to this method.
385 This method is a python generator
386
387 Keyword arguments:
388 env -- Provider Environment (pycimmb.ProviderEnvironment)
389 object_name -- A pywbem.CIMInstanceName that defines the source
390 CIM Object whose associated Objects are to be returned.
391 model -- A template pywbem.CIMInstance to serve as a model
392 of the objects to be returned. Only properties present on this
393 model need to be set.
394 result_class_name -- If not empty, this string acts as a filter on
395 the returned set of Instances by mandating that each returned
396 Instances MUST represent an association between object_name
397 and an Instance of a Class whose name matches this parameter
398 or a subclass.
399 role -- If not empty, MUST be a valid Property name. It acts as a
400 filter on the returned set of Instances by mandating that each
401 returned Instance MUST refer to object_name via a Property
402 whose name matches the value of this parameter.
403 result_role -- If not empty, MUST be a valid Property name. It acts
404 as a filter on the returned set of Instances by mandating that
405 each returned Instance MUST represent associations of
406 object_name to other Instances, where the other Instances play
407 the specified result_role in the association (i.e. the
408 name of the Property in the Association Class that refers to
409 the Object related to object_name MUST match the value of this
410 parameter).
411 keys_only -- A boolean. True if only the key properties should be
412 set on the generated instances.
413
414 The following diagram may be helpful in understanding the role,
415 result_role, and result_class_name parameters.
416 +------------------------+ +-------------------+
417 | object_name.classname | | result_class_name |
418 | ~~~~~~~~~~~~~~~~~~~~~ | | ~~~~~~~~~~~~~~~~~ |
419 +------------------------+ +-------------------+
420 | +-----------------------------------+ |
421 | | [Association] model.classname | |
422 | object_name | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
423 +--------------+ object_name.classname REF role | |
424 (CIMInstanceName) | result_class_name REF result_role +------+
425 | |(CIMInstanceName)
426 +-----------------------------------+
427
428 Possible Errors:
429 CIM_ERR_ACCESS_DENIED
430 CIM_ERR_NOT_SUPPORTED
431 CIM_ERR_INVALID_NAMESPACE
432 CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
433 or otherwise incorrect parameters)
434 CIM_ERR_FAILED (some other unspecified error occurred)
435
436 """
437
438
439 return None
440
441 - def simple_refs(self, env, object_name, model,
442 result_class_name, role, result_role, keys_only):
443
444 gen = self.enum_instances(env, model, keys_only)
445 if role:
446 role = role.lower()
447 for inst in gen:
448 for prop in inst.properties.values():
449 if prop.type != 'reference':
450 continue
451 if role and prop.name.lower() != role:
452 continue
453 if self.paths_equal(object_name, prop.value):
454 yield inst
455
456
458 """If one object path doesn't inlcude a host, don't include the hosts
459 in the comparison
460
461 """
462
463 if lhs is rhs:
464 return True
465 if lhs.host is not None and rhs.host is not None and\
466 lhs.host != rhs.host:
467 return False
468
469 return not (pywbem.cmpname(rhs.classname, lhs.classname) or
470 cmp(rhs.keybindings, lhs.keybindings) or
471 pywbem.cmpname(rhs.namespace, lhs.namespace))
472
473
477
478 """Return instance names of a given CIM class
479
480 Implements the WBEM operation EnumerateInstanceNames in terms
481 of the enum_instances method. A derived class will not normally
482 override this method.
483
484 """
485
486 logger = env.get_logger()
487 logger.log_debug('CIMProvider2 MI_enumInstanceNames called...')
488 model = pywbem.CIMInstance(classname=objPath.classname,
489 path=objPath)
490 gen = self.enum_instances(env=env,
491 model=model,
492 keys_only=True)
493 try:
494 iter(gen)
495 except TypeError:
496 logger.log_debug('CIMProvider2 MI_enumInstanceNames returning')
497 return
498
499 for inst in gen:
500 yield inst.path
501 logger.log_debug('CIMProvider2 MI_enumInstanceNames returning')
502
507
508 """Return instances of a given CIM class
509
510 Implements the WBEM operation EnumerateInstances in terms
511 of the enum_instances method. A derived class will not normally
512 override this method.
513
514 """
515 logger = env.get_logger()
516 logger.log_debug('CIMProvider2 MI_enumInstances called...')
517
518 model = pywbem.CIMInstance(classname=objPath.classname,
519 path=objPath)
520 gen = self.enum_instances(env=env,
521 model=model,
522 keys_only=False)
523 try:
524 iter(gen)
525 except TypeError:
526 logger.log_debug('CIMProvider2 MI_enumInstances returning')
527 return
528 return gen
529
530 - def MI_getInstance(self,
531 env,
532 instanceName,
533 propertyList):
534
535 """Return a specific CIM instance
536
537 Implements the WBEM operation GetInstance in terms
538 of the get_instance method. A derived class will not normally
539 override this method.
540
541 """
542
543 logger = env.get_logger()
544 logger.log_debug('CIMProvider2 MI_getInstance called...')
545 plist = None
546 if propertyList is not None:
547 plist = [s.lower() for s in propertyList]
548 plist += [s.lower() for s in instanceName.keybindings.keys()]
549 model = pywbem.CIMInstance(classname=instanceName.classname,
550 path=instanceName, property_list=plist)
551 model.update(model.path.keybindings)
552
553 rval = self.get_instance(env=env, model=model)
554 logger.log_debug('CIMProvider2 MI_getInstance returning')
555 if rval is None:
556 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "")
557 return rval
558
562
563 """Create a CIM instance, and return its instance name
564
565 Implements the WBEM operation CreateInstance in terms
566 of the set_instance method. A derived class will not normally
567 override this method.
568
569 """
570
571 logger = env.get_logger()
572 logger.log_debug('CIMProvider2 MI_createInstance called...')
573 rval = None
574 '''
575 ch = env.get_cimom_handle()
576 cimClass = ch.GetClass(instance.classname,
577 instance.path.namespace,
578 LocalOnly=False,
579 IncludeQualifiers=True)
580 '''
581
582
583 rval = self.set_instance(env=env,
584 instance=instance,
585 modify_existing=False)
586 logger.log_debug('CIMProvider2 MI_createInstance returning')
587 return rval.path
588
593
594 """Modify a CIM instance
595
596 Implements the WBEM operation ModifyInstance in terms
597 of the set_instance method. A derived class will not normally
598 override this method.
599
600 """
601
602 logger = env.get_logger()
603 logger.log_debug('CIMProvider2 MI_modifyInstance called...')
604 plist = None
605 if propertyList is not None:
606 plist = [s.lower() for s in propertyList]
607 plist += [s.lower()
608 for s in modifiedInstance.path.keybindings.keys()]
609 self.filter_instance(modifiedInstance, plist)
610 modifiedInstance.property_list = plist
611 modifiedInstance.update(modifiedInstance.path)
612 self.set_instance(env=env,
613 instance=modifiedInstance,
614 modify_existing=True)
615 logger.log_debug('CIMProvider2 MI_modifyInstance returning')
616
620
621 """Delete a CIM instance
622
623 Implements the WBEM operation DeleteInstance in terms
624 of the delete_instance method. A derived class will not normally
625 override this method.
626
627 """
628
629 logger = env.get_logger()
630 logger.log_debug('CIMProvider2 MI_deleteInstance called...')
631 self.delete_instance(env=env, instance_name=instanceName)
632 logger.log_debug('CIMProvider2 MI_deleteInstance returning')
633
634
635 - def MI_associators(self,
636 env,
637 objectName,
638 assocClassName,
639 resultClassName,
640 role,
641 resultRole,
642 propertyList):
643
644 """Return instances associated to a given object.
645
646 Implements the WBEM operation Associators in terms
647 of the references method. A derived class will not normally
648 override this method.
649
650 """
651
652
653
654 logger = env.get_logger()
655 logger.log_debug('CIMProvider2 MI_associators called. ' \
656 'assocClass: %s' % (assocClassName))
657 if not assocClassName:
658 raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
659 "Empty assocClassName passed to Associators")
660 ch = env.get_cimom_handle()
661 model = pywbem.CIMInstance(classname=assocClassName)
662 model.path = pywbem.CIMInstanceName(classname=assocClassName,
663 namespace=objectName.namespace)
664 gen = self.references(env=env,
665 object_name=objectName,
666 model=model,
667 result_class_name=resultClassName,
668 role=role,
669 result_role=None,
670 keys_only=False)
671 if gen is None:
672 logger.log_debug('references() returned None instead of ' \
673 'generator object')
674 return
675 for inst in gen:
676 for prop in inst.properties.values():
677 lpname = prop.name.lower()
678 if prop.type != 'reference':
679 continue
680 if role and role.lower() == lpname:
681 continue
682 if resultRole and resultRole.lower() != lpname:
683 continue
684 if self.paths_equal(prop.value, objectName):
685 continue
686 if resultClassName and \
687 resultClassName.lower() != prop.value.classname.lower():
688 continue
689 try:
690 if prop.value.namespace is None:
691 prop.value.namespace = objectName.namespace
692 inst = ch.GetInstance(prop.value, propertyList)
693 except pywbem.CIMError, (num, msg):
694 if num == pywbem.CIM_ERR_NOT_FOUND:
695 continue
696 else:
697 raise
698 if inst.path is None:
699 inst.path = prop.value
700 yield inst
701 logger.log_debug('CIMProvider2 MI_associators returning')
702
703 - def MI_associatorNames(self,
704 env,
705 objectName,
706 assocClassName,
707 resultClassName,
708 role,
709 resultRole):
710
711 """Return instances names associated to a given object.
712
713 Implements the WBEM operation AssociatorNames in terms
714 of the references method. A derived class will not normally
715 override this method.
716
717 """
718
719 logger = env.get_logger()
720 logger.log_debug('CIMProvider2 MI_associatorNames called. ' \
721 'assocClass: %s' % (assocClassName))
722 if not assocClassName:
723 raise pywbem.CIMError(
724 pywbem.CIM_ERR_FAILED,
725 "Empty assocClassName passed to AssociatorNames")
726 model = pywbem.CIMInstance(classname=assocClassName)
727 model.path = pywbem.CIMInstanceName(classname=assocClassName,
728 namespace=objectName.namespace)
729 gen = self.references(env=env,
730 object_name=objectName,
731 model=model,
732 result_class_name=resultClassName,
733 role=role,
734 result_role=None,
735 keys_only=False)
736 if gen is None:
737 logger.log_debug('references() returned None instead of ' \
738 'generator object')
739 return
740 for inst in gen:
741 for prop in inst.properties.values():
742 lpname = prop.name.lower()
743 if prop.type != 'reference':
744 continue
745 if role and role.lower() == lpname:
746 continue
747 if resultRole and resultRole.lower() != lpname:
748 continue
749 if self.paths_equal(prop.value, objectName):
750 continue
751 if resultClassName and \
752 resultClassName.lower() != prop.value.classname.lower():
753 continue
754 if prop.value.namespace is None:
755 prop.value.namespace = objectName.namespace
756 yield prop.value
757 logger.log_debug('CIMProvider2 MI_associatorNames returning')
758
759 - def MI_references(self,
760 env,
761 objectName,
762 resultClassName,
763 role,
764 propertyList):
765
766 """Return instances of an association class.
767
768 Implements the WBEM operation References in terms
769 of the references method. A derived class will not normally
770 override this method.
771
772 """
773
774 logger = env.get_logger()
775 logger.log_debug('CIMProvider2 MI_references called. ' \
776 'resultClass: %s' % (resultClassName))
777 if not resultClassName:
778 raise pywbem.CIMError(
779 pywbem.CIM_ERR_FAILED,
780 "Empty resultClassName passed to References")
781 plist = None
782 if propertyList is not None:
783 plist = [s.lower() for s in propertyList]
784 model = pywbem.CIMInstance(classname=resultClassName,
785 property_list=plist)
786 model.path = pywbem.CIMInstanceName(classname=resultClassName,
787 namespace=objectName.namespace)
788 if role:
789 if role in model.properties:
790 model[role] = objectName
791
792 gen = self.references(env=env,
793 object_name=objectName,
794 model=model,
795 result_class_name='',
796 role=role,
797 result_role=None,
798 keys_only=False)
799 if gen is None:
800 logger.log_debug('references() returned None instead of ' \
801 'generator object')
802 return
803 for inst in gen:
804 for prop in inst.properties.values():
805 if hasattr(prop.value, 'namespace') and \
806 prop.value.namespace is None:
807 prop.value.namespace = objectName.namespace
808 yield inst
809 logger.log_debug('CIMProvider2 MI_references returning')
810
811 - def MI_referenceNames(self,
812 env,
813 objectName,
814 resultClassName,
815 role):
816
817 """Return instance names of an association class.
818
819 Implements the WBEM operation ReferenceNames in terms
820 of the references method. A derived class will not normally
821 override this method.
822
823 """
824
825 logger = env.get_logger()
826 logger.log_debug('CIMProvider2 MI_referenceNames <2> called. ' \
827 'resultClass: %s' % (resultClassName))
828 if not resultClassName:
829 raise pywbem.CIMError(
830 pywbem.CIM_ERR_FAILED,
831 "Empty resultClassName passed to ReferenceNames")
832
833 model = pywbem.CIMInstance(classname=resultClassName)
834 model.path = pywbem.CIMInstanceName(classname=resultClassName,
835 namespace=objectName.namespace)
836 if role:
837 if role in model.properties:
838 model[role] = objectName
839 gen = self.references(env=env,
840 object_name=objectName,
841 model=model,
842 result_class_name='',
843 role=role,
844 result_role=None,
845 keys_only=True)
846 if gen is None:
847 logger.log_debug('references() returned None instead of ' \
848 'generator object')
849 return
850 for inst in gen:
851 for prop in inst.properties.values():
852 if hasattr(prop.value, 'namespace') and \
853 prop.value.namespace is None:
854 prop.value.namespace = objectName.namespace
855 yield inst.path
856 logger.log_debug('CIMProvider2 MI_referenceNames returning')
857
859
860 """Invoke an extrinsic method.
861
862 Implements the InvokeMethod WBEM operation by calling the
863 method on a derived class called cim_method_<method_name>,
864 where <method_name> is the name of the CIM method, in all
865 lower case.
866
867 Arguments:
868 env -- Provider Environment (pycimmb.ProviderEnvironment)
869 objectName -- The InstanceName or ClassName of the object on
870 which the method is invoked.
871 methodName -- The name of the method to be invoked.
872 inputParams -- A Dictionary where the key is the parameter name
873 and the value is the parameter value.
874
875 The return value for invokeMethod must be a tuple of size 2
876 where:
877 element 0 is a tuple of size 2 where element 0 is the return
878 data type name and element 1 is the actual data value.
879 element 1 is a dictionary where the key is the output
880 parameter name and the value is a tuple of size 2 where
881 element 0 is the data type name for the output parameter
882 and element 1 is the actual value of the output parameter.
883
884 A derived class will not normally override this method.
885
886 """
887
888 logger = env.get_logger()
889 logger.log_debug('CIMProvider2 MI_invokeMethod called. ' \
890 'method: %s:%s' % (objectName.classname, methodName))
891 lmethName = "cim_method_%s" % methodName.lower()
892 if hasattr(self, lmethName):
893 method = getattr(self, lmethName)
894 new_inputs = dict([('param_%s' % k.lower(), v) \
895 for k, v in inputParams.items()])
896 try:
897 (rval, outs) = method(env=env, object_name=objectName,
898 **new_inputs)
899 except TypeError, e:
900 raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, str(e))
901
902 def add_type(v):
903 if isinstance(v, pywbem.CIMParameter):
904 return (v.type, v.value)
905 lv = v
906 if type(v) == list and len(v) > 0:
907 lv = v[0]
908 if isinstance(lv, pywbem.CIMClass):
909 tp = 'class'
910 elif isinstance(lv, pywbem.CIMInstance):
911 tp = 'instance'
912 elif isinstance(lv, pywbem.CIMInstanceName):
913 tp = 'reference'
914 elif v is None or (type(v) == list and len(v) == 0):
915 assert(None == 'This should not happen')
916 else:
917 tp = pywbem.cimtype(v)
918 return (tp, v)
919
920 louts = {}
921 for op in outs:
922 louts[op.name] = (op.type, op.value)
923 rval = add_type(rval)
924 rval = (rval, louts)
925 else:
926 raise pywbem.CIMError(
927 pywbem.CIM_ERR_METHOD_NOT_FOUND,
928 "%s:%s"%(objectName.classname, methodName))
929 logger.log_debug('CIMProvider2 MI_invokeMethod returning')
930 return rval
931
933 """Remove properties from an instance that aren't in the PropertyList
934
935 inst -- The CIMInstance
936 plist -- The property List, or None. The list items must be all
937 lowercase.
938
939 """
940
941 if plist is not None:
942 for pname in inst.properties.keys():
943 if pname.lower() not in plist and pname:
944 if inst.path is not None and pname in inst.path.keybindings:
945 continue
946 del inst.properties[pname]
947
949 """Allow or disallow an indication subscription request.
950
951 Arguments:
952 env -- Provider Environment (pycimmb.ProviderEnvironment)
953 filter -- The WQL select statement
954 namespace -- The namepace where the indication is registered for
955 classes -- The classpath of the indication registered for
956 owner -- The name of the principal (cimom user)
957 """
958 pass
959
961 """Activate an indication subscription.
962
963 Arguments:
964 env -- Provider Environment (pycimmb.ProviderEnvironment)
965 filter -- The WQL select statement
966 namespace -- The namepace where the indication is registered for
967 classes -- The classpath of the indication registered for
968 first_activation -- boolean - whether first activation
969 """
970 pass
971
973 """Deactivate an indication subscription.
974
975 Arguments:
976 env -- Provider Environment (pycimmb.ProviderEnvironment)
977 filter -- The WQL select statement
978 ns -- The namepace where the indication is registered for
979 classes -- The classpath of the indication registered for
980 last_activation -- boolean - whether last activation
981 """
982 pass
983
985 """Enable indications.
986
987 Arguments:
988 env -- Provider Environment (pycimmb.ProviderEnvironment)
989 """
990 pass
991
993 """Disable indications.
994
995 Arguments:
996 env -- Provider Environment (pycimmb.ProviderEnvironment)
997 """
998 pass
999
1000
1002 """Generate a Python Provider template.
1003
1004 Parameters:
1005 cc - A CIMClass to generate code for.
1006
1007 Returns a two-tuple containing the Python provider code stubs, and
1008 the provider registration MOF.
1009
1010 """
1011
1012 import inspect
1013
1014 def format_desc(obj, indent):
1015 linelen = 75 - indent
1016 if isinstance(obj, basestring):
1017 raw = obj
1018 else:
1019 try:
1020 raw = obj.qualifiers['description'].value
1021 except KeyError:
1022 return ''
1023 txt = ''
1024 beg = 0
1025 end = 0
1026 while beg < len(raw):
1027 beg = end
1028 end += linelen
1029 while beg < len(raw) and raw[beg].isspace():
1030 beg = beg+1
1031 while end < len(raw) and end > beg and not raw[end].isspace():
1032 end = end-1
1033 if beg == end:
1034 while end < len(raw) and not raw[end].isspace():
1035 end += 1
1036 line = raw[beg:end]
1037 line = line.replace('\n', ' ')
1038 line = line.replace('\r', '')
1039 txt += '\n%s%s'% (''.ljust(indent), line)
1040 return txt
1041
1042
1043 def map_value(obj, val):
1044 rv = str(val)
1045 if 'ValueMap' not in obj.qualifiers:
1046 return rv
1047 if 'Values' not in obj.qualifiers:
1048 return rv
1049 vals = [str(x) for x in obj.qualifiers['Values'].value]
1050 maps = [str(x) for x in obj.qualifiers['ValueMap'].value]
1051 d = dict(zip(maps, vals))
1052 try:
1053 tmp = d[str(val)]
1054 rv = ''
1055 for ch in tmp:
1056 rv += ch.isalnum() and ch or '_'
1057 except KeyError:
1058 pass
1059 return rv
1060
1061
1062 def type_hint(obj, method_name=None):
1063 if hasattr(obj, 'type'):
1064 tx = obj.type
1065 if 'embeddedinstance' in obj.qualifiers:
1066 tx = "pywbem.CIMInstance(classname='%s', ...)" % \
1067 obj.qualifiers['embeddedinstance'].value
1068 elif tx == 'reference':
1069 tx = "pywbem.CIMInstanceName(classname='%s', ...)" % \
1070 obj.reference_class
1071 else:
1072 tx = obj.return_type
1073 if hasattr(obj, 'value') and obj.value is not None:
1074 defval = str(obj.value)
1075 else:
1076 defval = ''
1077 if not tx.startswith('pywbem.'):
1078 if tx == 'boolean':
1079 tx = 'bool(%s)' % defval
1080 elif tx == 'datetime':
1081 tx = 'pywbem.CIMDateTime()'
1082 elif tx == 'string':
1083 tx = "''"
1084 else:
1085 tx = 'pywbem.%s(%s)' % (tx.capitalize(), defval)
1086 if 'valuemap' in obj.qualifiers:
1087 if defval:
1088 defval = map_value(obj, defval)
1089 else:
1090 defval = '<VAL>'
1091 tx = 'self.Values.%s%s.%s' % \
1092 (method_name and '%s.'%method_name or '',
1093 obj.name, defval)
1094 if hasattr(obj, 'is_array') and obj.is_array:
1095 tx = '[%s,]' % tx
1096 return tx
1097
1098 def type_str(obj, method_name=None):
1099 if hasattr(obj, 'type'):
1100 tx = obj.type
1101 if 'embeddedinstance' in obj.qualifiers:
1102 return "pywbem.CIMInstance(classname='%s', ...)" % \
1103 obj.qualifiers['embeddedinstance'].value
1104 elif tx == 'reference':
1105 return "REF (pywbem.CIMInstanceName(classname='%s', ...)" % \
1106 obj.reference_class
1107 else:
1108 tx = obj.return_type
1109 if tx == 'boolean':
1110 tx = 'bool'
1111 elif tx == 'datetime':
1112 tx = 'pywbem.CIMDateTime'
1113 elif tx == 'string':
1114 tx = 'unicode'
1115 else:
1116 tx = 'pywbem.%s' % tx.capitalize()
1117 if hasattr(obj, 'is_array') and obj.is_array:
1118 tx = '[%s,]' % tx
1119 if 'valuemap' in obj.qualifiers:
1120 tx += ' self.Values.%s%s' % \
1121 (method_name and '%s.'%method_name or '', obj.name)
1122 return tx
1123
1124 def is_required(obj):
1125 if 'required' in obj.qualifiers and obj.qualifiers['required'].value:
1126 return '(Required)'
1127 return ''
1128
1129 def build_reverse_val_map(obj):
1130 vm = obj.qualifiers['valuemap'].value
1131 if 'values' in obj.qualifiers:
1132 vals = obj.qualifiers['values'].value
1133 else:
1134 vals = vm
1135 tmap = zip(vals, vm)
1136 rv = {}
1137 for val, vm in tmap:
1138 try:
1139 vmi = int(vm)
1140 except ValueError:
1141 continue
1142 rv[vmi] = str(val)
1143 return rv
1144
1145 def build_val_map(obj):
1146 vm = obj.qualifiers['valuemap'].value
1147 if 'values' in obj.qualifiers:
1148 vals = obj.qualifiers['values'].value
1149 else:
1150 vals = vm
1151 tmap = zip(vals, vm)
1152 map = []
1153 for t in tmap:
1154 nname = ''
1155 for ch in t[0]:
1156 if ch.isalnum():
1157 nname += ch
1158 else:
1159 nname += '_'
1160 if hasattr(obj, 'return_type'):
1161 tp = obj.return_type
1162 else:
1163 tp = obj.type
1164 if tp == 'string':
1165 val = "'%s'" % t[1]
1166 else:
1167 try:
1168 int(t[1])
1169 val = 'pywbem.%s(%s)' % (tp.capitalize(), t[1])
1170 except ValueError:
1171 val = t[1]
1172 nname = "# "+nname
1173 map.append((nname, val))
1174 return map
1175
1176 valuemaps = {}
1177 rvaluemaps = pywbem.NocaseDict()
1178
1179 for prop in cc.properties.values():
1180 if 'valuemap' in prop.qualifiers and 'values' in prop.qualifiers:
1181 rvaluemaps[prop.name] = build_reverse_val_map(prop)
1182
1183 for obj in cc.properties.values() + cc.methods.values():
1184 if 'valuemap' in obj.qualifiers:
1185 valuemaps[obj.name] = {'<vms>':build_val_map(obj)}
1186
1187 for meth in cc.methods.values():
1188 for parm in meth.parameters.values():
1189 if 'valuemap' in parm.qualifiers:
1190 if meth.name not in valuemaps:
1191 valuemaps[meth.name] = {}
1192 valuemaps[meth.name][parm.name] = build_val_map(parm)
1193
1194 mappings = {'classname':cc.classname,
1195 'classname_l':cc.classname.lower()}
1196 isAssoc = 'association' in cc.qualifiers
1197 isIndication = 'indication' in cc.qualifiers
1198
1199 code = '''"""Python Provider for %(classname)s
1200
1201 Instruments the CIM class %(classname)s
1202
1203 """
1204
1205 import pywbem
1206 from pywbem.cim_provider2 import CIMProvider2
1207
1208 class %(classname)s(CIMProvider2):
1209 """Instrument the CIM class %(classname)s \n''' % mappings
1210 code += format_desc(cc, 4)
1211 code += '''
1212 """'''
1213
1214
1215 args = inspect.getargspec(CIMProvider2.get_instance)[0]
1216 args = ', '.join(args)
1217 code += '''
1218
1219 def __init__ (self, env):
1220 logger = env.get_logger()
1221 logger.log_debug('Initializing provider %%s from %%s' \\
1222 %% (self.__class__.__name__, __file__))
1223
1224 def get_instance(%s):
1225 """%s"""
1226
1227 logger = env.get_logger()
1228 logger.log_debug('Entering %%s.get_instance()' \\
1229 %% self.__class__.__name__)
1230 ''' % (args, CIMProvider2.get_instance.__doc__)
1231 keyProps = [p for p in cc.properties.values() \
1232 if 'key' in p.qualifiers]
1233 if not keyProps and 'association' in cc.qualifiers:
1234
1235
1236 keyProps = [p for p in cc.properties.values() \
1237 if p.type == 'reference']
1238 for prop in keyProps:
1239 prop.qualifiers['KEY'] = True
1240 code += '''
1241
1242 # TODO fetch system resource matching the following keys:'''
1243 for kp in keyProps:
1244 code += '''
1245 # model['%s']''' % kp.name
1246 code += '\n'
1247 props = cc.properties.values()
1248 props.sort()
1249 for prop in props:
1250 if 'key' in prop.qualifiers:
1251 continue
1252 line = "#model['%s'] = %s # TODO %s" % \
1253 (prop.name, type_hint(prop), is_required(prop))
1254 code += '''
1255 %s''' % line
1256
1257 args = inspect.getargspec(CIMProvider2.enum_instances)[0]
1258 args = ', '.join(args)
1259 code += '''
1260 return model
1261
1262 def enum_instances(%s):
1263 """%s"""
1264
1265 logger = env.get_logger()
1266 logger.log_debug('Entering %%s.enum_instances()' \\
1267 %% self.__class__.__name__)
1268 ''' % (args, CIMProvider2.enum_instances.__doc__)
1269 keydict = dict([(str(kp.name), None) for kp in keyProps])
1270 code += '''
1271 # Prime model.path with knowledge of the keys, so key values on
1272 # the CIMInstanceName (model.path) will automatically be set when
1273 # we set property values on the model.
1274 model.pa%s
1275 ''' % format_desc('th.update('+str(keydict)+')', 12).strip()
1276
1277 code += '''
1278 while False: # TODO more instances?
1279 # TODO fetch system resource
1280 # Key properties'''
1281 for kp in keyProps:
1282 if kp.name == 'CreationClassName':
1283 line = "model['%s'] = '%s'" % (kp.name, cc.classname)
1284 else:
1285 line = "#model['%s'] = %s # TODO (type = %s)" % \
1286 (kp.name, type_hint(kp), type_str(kp))
1287 code += '''
1288 %s''' % line
1289 code += '''
1290 if keys_only:
1291 yield model
1292 else:
1293 try:
1294 yield self.get_instance(env, model)
1295 except pywbem.CIMError, (num, msg):
1296 if num not in (pywbem.CIM_ERR_NOT_FOUND,
1297 pywbem.CIM_ERR_ACCESS_DENIED):
1298 raise\n'''
1299
1300 args = inspect.getargspec(CIMProvider2.set_instance)[0]
1301 args = ', '.join(args)
1302 code += '''
1303 def set_instance(%s):
1304 """%s"""
1305
1306 logger = env.get_logger()
1307 logger.log_debug('Entering %%s.set_instance()' \\
1308 %% self.__class__.__name__)
1309 # TODO create or modify the instance
1310 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED) # Remove to implement
1311 return instance''' % (args, CIMProvider2.set_instance.__doc__)
1312
1313 args = inspect.getargspec(CIMProvider2.delete_instance)[0]
1314 args = ', '.join(args)
1315 code += '''
1316
1317 def delete_instance(%s):
1318 """%s"""
1319
1320 logger = env.get_logger()
1321 logger.log_debug('Entering %%s.delete_instance()' \\
1322 %% self.__class__.__name__)
1323
1324 # TODO delete the resource
1325 raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED) # Remove to implement
1326 ''' % (args, CIMProvider2.delete_instance.__doc__)
1327
1328 for method in cc.methods.values():
1329 inParms = [p for p in method.parameters.values() if \
1330 'in' in p.qualifiers and p.qualifiers['in'].value]
1331 outParms = [p for p in method.parameters.values() if \
1332 'out' in p.qualifiers and p.qualifiers['out'].value]
1333 code += '''
1334 def cim_method_%s(self, env, object_name''' % method.name.lower()
1335 for p in inParms:
1336 if 'required' in p.qualifiers and p.qualifiers['required']:
1337 code += ''',\n%sparam_%s''' % (''.rjust(len(method.name)+20),
1338 p.name.lower())
1339 for p in inParms:
1340 if 'required' not in p.qualifiers or not p.qualifiers['required']:
1341 code += ''',\n%sparam_%s=None''' % \
1342 (''.rjust(len(method.name)+20),
1343 p.name.lower())
1344 code += '''):
1345 """Implements %s.%s()\n''' % (cc.classname, method.name)
1346 code += format_desc(method, 8)
1347
1348 code += '''
1349 Keyword arguments:
1350 env -- Provider Environment (pycimmb.ProviderEnvironment)
1351 object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName
1352 specifying the object on which the method %s()
1353 should be invoked.'''\
1354 % method.name
1355
1356 for p in inParms:
1357 code += '''
1358 param_%s -- The input parameter %s (type %s) %s''' \
1359 % (p.name.lower(), p.name, type_str(p, method.name),
1360 is_required(p))
1361 code += format_desc(p, 12)
1362
1363 code += '''
1364
1365 Returns a two-tuple containing the return value (type %s)
1366 and a list of CIMParameter objects representing the output parameters
1367
1368 Output parameters:''' % type_str(method)
1369
1370 if not outParms:
1371 code += ' none'
1372 else:
1373 for p in outParms:
1374 code += '''
1375 %s -- (type %s) %s''' % (p.name, type_str(p, method.name),
1376 is_required(p))
1377 code += format_desc(p, 12)
1378
1379 code += '''
1380
1381 Possible Errors:
1382 CIM_ERR_ACCESS_DENIED
1383 CIM_ERR_INVALID_PARAMETER (including missing, duplicate,
1384 unrecognized or otherwise incorrect parameters)
1385 CIM_ERR_NOT_FOUND (the target CIM Class or instance does not
1386 exist in the specified namespace)
1387 CIM_ERR_METHOD_NOT_AVAILABLE (the CIM Server is unable to honor
1388 the invocation request)
1389 CIM_ERR_FAILED (some other unspecified error occurred)
1390
1391 """
1392
1393 logger = env.get_logger()
1394 logger.log_debug('Entering %%s.cim_method_%s()' \\
1395 %% self.__class__.__name__)
1396
1397 # TODO do something
1398 raise pywbem.CIMError(pywbem.CIM_ERR_METHOD_NOT_AVAILABLE) # Remove to implemented
1399 out_params = []''' % method.name.lower()
1400
1401 for p in outParms:
1402 code += '''
1403 #out_params+= [pywbem.CIMParameter('%s', type='%s',
1404 # value=%s)] # TODO''' % \
1405 (p.name.lower(), p.type, type_hint(p, method.name))
1406
1407 code += '''
1408 #rval = # TODO (type %s)
1409 return (rval, out_params)
1410 ''' % type_str(method)
1411
1412 if isAssoc:
1413 args = inspect.getargspec(CIMProvider2.references)[0]
1414 args = format_desc(', '.join(args), 19).strip()
1415 code += '''
1416 def references(%s):
1417 """%s"""
1418
1419 logger = env.get_logger()
1420 logger.log_debug('Entering %%s.references()' \\
1421 %% self.__class__.__name__)
1422 ch = env.get_cimom_handle()''' % \
1423 (args, CIMProvider2.references.__doc__)
1424
1425 refprops = []
1426 for prop in cc.properties.values():
1427 if prop.reference_class is not None:
1428 refprops.append((prop.name, prop.reference_class))
1429
1430 code += '''\n
1431 # If you want to get references for free, implemented in terms
1432 # of enum_instances, just leave the code below unaltered.'''
1433
1434 for i, refprop in enumerate(refprops):
1435 if i == 0:
1436 code += '''
1437 if ch.is_subclass(object_name.namespace,
1438 sub=object_name.classname,
1439 super='%s')''' % refprop[1]
1440
1441 else:
1442 code += ''' or \\
1443 ch.is_subclass(object_name.namespace,
1444 sub=object_name.classname,
1445 super='%s')''' % refprop[1]
1446 code += ''':
1447 return self.simple_refs(env, object_name, model,
1448 result_class_name, role, result_role, keys_only)
1449 '''
1450
1451
1452 code += '''
1453 # If you are doing simple refs with the code above, remove the
1454 # remainder of this method. Or, remove the stuff above and
1455 # implement references below. You need to pick either the
1456 # above approach or the below, and delete the other. Otherwise
1457 # you'll get a SyntaxError on the first yield below.
1458
1459 # Prime model.path with knowledge of the keys, so key values on
1460 # the CIMInstanceName (model.path) will automatically be set when
1461 # we set property values on the model.
1462 model.pa%s
1463
1464 # This is a common pattern. YMMV''' % \
1465 format_desc('th.update('+str(keydict)+')', 12).strip()
1466
1467 for refprop in refprops:
1468 code += '''
1469 if (not role or role.lower() == '%(refpropnamel)s') and \\
1470 ch.is_subclass(object_name.namespace,
1471 sub=object_name.classname,
1472 super='%(rolecname)s'):
1473 model['%(refpropname)s'] = object_name
1474 yield model # TODO: Add other REF properties.
1475 # Yield association instances where
1476 # object_name is %(refpropnamel)s.
1477 # Only appropriate if object_name.classname
1478 # is '%(rolecname)s' or a subclass.\n''' \
1479 % {'refpropname':refprop[0],
1480 'refpropnamel':refprop[0].lower(),
1481 'rolecname':refprop[1]}
1482
1483 if valuemaps:
1484 code += '''
1485 class Values(object):'''
1486 for group, maps in valuemaps.items():
1487 code += '''
1488 class %s(object):''' % group
1489 if '<vms>' in maps:
1490 for value, vm in maps['<vms>']:
1491 if value in maps:
1492 value = value+'_'
1493 code += '''
1494 %s = %s''' % (value, vm)
1495 if group in rvaluemaps:
1496 code += '''
1497 _reverse_map = %s''' % repr(rvaluemaps[group])
1498 for pname, vms in maps.items():
1499 if pname == '<vms>':
1500 continue
1501 code += '''
1502 class %s(object):''' % pname
1503 for value, vm in vms:
1504 code += '''
1505 %s = %s''' % (value, vm)
1506 code += '\n'
1507
1508 code += '''
1509 ## end of class %(classname)sProvider
1510
1511 ## get_providers() for associating CIM Class Name to python provider class name
1512
1513 def get_providers(env):
1514 %(classname_l)s_prov = %(classname)s(env)
1515 return {'%(classname)s': %(classname_l)s_prov}
1516 ''' % mappings
1517
1518 if isIndication:
1519 code += '''
1520
1521 ## Indication support methods...
1522 ## Use these methods if this class will deliver indications.
1523 ## Remove these methods if this class will not deliver indications.'''
1524 args = inspect.getargspec(CIMProvider2.authorize_filter)[0]
1525 args = format_desc(', '.join(args), 19).strip()
1526 code += '''
1527
1528
1529 def authorize_filter(%s):
1530 """%s"""
1531
1532 logger = env.get_logger()
1533 logger.log_debug('Entering %%s.authorize_filter()' \\
1534 %% self.__class__.__name__)
1535 ch = env.get_cimom_handle()
1536 #raise pywbem.CIMError(pywbem.CIM_ERR_***) to indicate failure
1537 #otherwise just fall through for success''' % \
1538 (args, CIMProvider2.authorize_filter.__doc__ or "Doc Goes Here")
1539
1540 args = inspect.getargspec(CIMProvider2.enable_indications)[0]
1541 args = format_desc(', '.join(args), 19).strip()
1542 code += '''
1543
1544
1545 def enable_indications(%s):
1546 """%s"""
1547
1548 logger = env.get_logger()
1549 logger.log_debug('Entering %%s.enable_indications()' \\
1550 %% self.__class__.__name__)
1551 ch = env.get_cimom_handle()
1552 #raise pywbem.CIMError(pywbem.CIM_ERR_***) to indicate failure
1553 #otherwise just fall through for success''' % \
1554 (args, CIMProvider2.enable_indications.__doc__ or "Doc Goes Here")
1555
1556 args = inspect.getargspec(CIMProvider2.disable_indications)[0]
1557 args = format_desc(', '.join(args), 19).strip()
1558 code += '''
1559
1560
1561 def disable_indications(%s):
1562 """%s"""
1563
1564 logger = env.get_logger()
1565 logger.log_debug('Entering %%s.disable_indications()' \\
1566 %% self.__class__.__name__)
1567 ch = env.get_cimom_handle()
1568 #raise pywbem.CIMError(pywbem.CIM_ERR_***) to indicate failure
1569 #otherwise just fall through for success''' % \
1570 (args, CIMProvider2.disable_indications.__doc__ or "Doc Goes Here")
1571
1572 args = inspect.getargspec(CIMProvider2.activate_filter)[0]
1573 args = format_desc(', '.join(args), 19).strip()
1574 code += '''
1575
1576
1577 def activate_filter(%s):
1578 """%s"""
1579
1580 logger = env.get_logger()
1581 logger.log_debug('Entering %%s.activate_filter()' \\
1582 %% self.__class__.__name__)
1583 ch = env.get_cimom_handle()
1584 #raise pywbem.CIMError(pywbem.CIM_ERR_***) to indicate failure
1585 #otherwise just fall through for success''' % \
1586 (args, CIMProvider2.activate_filter.__doc__ or "Doc Goes Here")
1587
1588
1589 args = inspect.getargspec(CIMProvider2.deactivate_filter)[0]
1590 args = format_desc(', '.join(args), 19).strip()
1591 code += '''
1592
1593
1594 def deactivate_filter(%s):
1595 """%s"""
1596
1597 logger = env.get_logger()
1598 logger.log_debug('Entering %%s.deactivate_filter()' \\
1599 %% self.__class__.__name__)
1600 ch = env.get_cimom_handle()
1601 #raise pywbem.CIMError(pywbem.CIM_ERR_***) to indicate failure
1602 #otherwise just fall through for success''' % \
1603 (args, CIMProvider2.deactivate_filter.__doc__ or "Doc Goes Here")
1604
1605 code += '''
1606
1607 ## End of Indication Support Methods'''
1608
1609 owtypes = ['1', 'Instance']
1610 pegtypes = ['2', 'Instance']
1611 sfcbtypes = 'instance'
1612 if isAssoc:
1613 owtypes[0] += ',3'
1614 owtypes[1] += ', Associator'
1615 pegtypes[0] += ',3'
1616 pegtypes[1] += ', Associator'
1617 sfcbtypes += ' association'
1618 if cc.methods:
1619 owtypes[0] += ',6'
1620 owtypes[1] += ', Method'
1621 pegtypes[0] += ',5'
1622 pegtypes[1] += ', Method'
1623 sfcbtypes += ' method'
1624 omitted = '''
1625 // OpenWBEM Provider registration for %(classname)s
1626 instance of OpenWBEM_PyProviderRegistration
1627 {
1628 InstanceID = "<org:product:%(classname)s:unique_id>"; // TODO
1629 NamespaceNames = {"root/cimv2"}; // TODO
1630 ClassName = "%(classname)s";
1631 ProviderTypes = {%(owtypeNums)s}; // %(owtypeStrs)s
1632 ModulePath = "/usr/lib/pycim/%(classname)sProvider.py"; // TODO
1633 };
1634 '''
1635
1636 mof = '''
1637 // SFCB Provider registration for %(classname)s
1638 [%(classname)s]
1639 provider: %(classname)s
1640 location: pyCmpiProvider
1641 type: %(sfcbtypes)s
1642 namespace: root/cimv2 // TODO
1643
1644 // Pegasus Provider registration for %(classname)s
1645 instance of PG_ProviderModule
1646 {
1647 Name = "pyCmpiProvider_%(classname)s";
1648 InterfaceType = "CMPI";
1649 InterfaceVersion = "2.0.0";
1650 Location = "pyCmpiProvider";
1651 UserContext = 2; // Requestor
1652 Vendor = "TODO"; // TODO
1653 Version = "1.0";
1654 };
1655 instance of PG_Provider
1656 {
1657 Name = "%(classname)s";
1658 ProviderModuleName = "pyCmpiProvider_%(classname)s";
1659 };
1660 instance of PG_ProviderCapabilities
1661 {
1662 CapabilityID = "%(classname)s";
1663 ProviderModuleName = "pyCmpiProvider_%(classname)s";
1664 ProviderName = "%(classname)s";
1665 ClassName = "%(classname)s";
1666 Namespaces = {"root/cimv2"}; // TODO
1667 ProviderType = {%(pegtypeNum)s}; // %(pegtypeStr)s
1668 };\n''' % {'classname': cc.classname,
1669 'owtypeNums': owtypes[0],
1670 'owtypeStrs': owtypes[1],
1671 'pegtypeNum': pegtypes[0],
1672 'pegtypeStr': pegtypes[1],
1673 'sfcbtypes' : sfcbtypes}
1674
1675
1676 return code, mof
1677
1679 """Wraps a provider module, and routes requests into the module """
1680
1682 self.env = env
1683 if isinstance(provid, ModuleType):
1684 self.provmod = provid
1685 self.provid = provid.__name__
1686 self.filename = provid.__file__
1687 else:
1688 logger = env.get_logger()
1689 logger.log_debug('Loading python provider at %s' %provid)
1690 self.provid = provid
1691 self._load_provider_source(logger)
1692 self._init_provider(env)
1693
1695 self.provregs = {}
1696 if hasattr(self.provmod, 'init'):
1697 self.provmod.init(env)
1698 if hasattr(self.provmod, 'get_providers'):
1699 self.provregs = pywbem.NocaseDict(self.provmod.get_providers(env))
1700
1702 self.provider_module_name = os.path.basename(self.provid)[:-3]
1703
1704 provdir = dirname(self.provid)
1705 if provdir not in sys.path:
1706 sys.path.append(provdir)
1707 try:
1708 self.provmod = sys.modules[self.provider_module_name]
1709 logger.log_debug('Provider %s already loaded, found in ' \
1710 'sys.modules' % self.provmod)
1711 except KeyError:
1712 try:
1713
1714 logger.log_debug('Loading provider %s from source' % \
1715 self.provid)
1716 fn = imp.find_module(self.provider_module_name, [provdir])
1717 try:
1718 g_mod_lock.acquire()
1719 imp.acquire_lock()
1720 self.provmod = imp.load_module(
1721 self.provider_module_name, *fn)
1722 self.provmod.provmod_timestamp = \
1723 os.path.getmtime(self.provid)
1724 finally:
1725 imp.release_lock()
1726 g_mod_lock.release()
1727 fn[0].close()
1728 except IOError, arg:
1729 raise pywbem.CIMError(
1730 pywbem.CIM_ERR_FAILED,
1731 "Error loading provider %s: %s" % (self.provid, arg))
1732 self.filename = self.provmod.__file__
1733
1735 """Return a function or method object appropriate to fulfill a request
1736
1737 classname -- The CIM class name associated with the request.
1738 cname -- The function or method name to look for.
1739
1740 """
1741
1742 callable = None
1743 if classname in self.provregs:
1744 provClass = self.provregs[classname]
1745 if hasattr(provClass, cname):
1746 callable = getattr(provClass, cname)
1747 elif hasattr(self.provmod, cname):
1748 callable = getattr(self.provmod, cname)
1749 if callable is None:
1750 raise pywbem.CIMError(
1751 pywbem.CIM_ERR_FAILED,
1752 "No provider registered for %s or no callable for %s:%s on " \
1753 "provider %s" % (classname, classname, cname, self.provid))
1754 return callable
1755
1757 """Check timestamp of loaded python provider module, and if it has
1758 changed since load, then reload the provider module.
1759 """
1760 try:
1761 mod = sys.modules[self.provider_module_name]
1762 except KeyError:
1763 mod = None
1764 if (mod is None or \
1765 mod.provmod_timestamp != os.path.getmtime(self.provid)):
1766 logger = env.get_logger()
1767 logger.log_debug("Need to reload provider at %s" % self.provid)
1768
1769
1770 if self.provmod and hasattr(self.provmod, "shutdown"):
1771 self.provmod.shutdown(env)
1772
1773 try:
1774 del sys.modules[self.provider_module_name]
1775 except KeyError:
1776 pass
1777 try:
1778 self._load_provider_source(logger)
1779 self._init_provider(env)
1780 except IOError, arg:
1781 raise pywbem.CIMError(
1782 pywbem.CIM_ERR_FAILED,
1783 "Error loading provider %s: %s" % (provid, arg))
1784
1785
1786
1787
1788
1792
1793 logger = env.get_logger()
1794 logger.log_debug('ProviderProxy MI_enumInstanceNames called...')
1795 self._reload_if_necessary(env)
1796 return self._get_callable(objPath.classname,
1797 'MI_enumInstanceNames')(env, objPath)
1798
1799
1800
1801
1806
1807 logger = env.get_logger()
1808 logger.log_debug('CIMProvider2 MI_enumInstances called...')
1809 self._reload_if_necessary(env)
1810 return self._get_callable(objPath.classname, 'MI_enumInstances') \
1811 (env,
1812 objPath,
1813 propertyList)
1814
1815
1816
1817
1818 - def MI_getInstance(self,
1819 env,
1820 instanceName,
1821 propertyList):
1822
1823 logger = env.get_logger()
1824 logger.log_debug('CIMProvider2 MI_getInstance called...')
1825 self._reload_if_necessary(env)
1826 rval = self._get_callable(instanceName.classname, 'MI_getInstance') \
1827 (env,
1828 instanceName,
1829 propertyList)
1830 logger.log_debug('CIMProvider2 MI_getInstance returning')
1831 return rval
1832
1833
1834
1835
1839
1840 logger = env.get_logger()
1841 logger.log_debug('CIMProvider2 MI_createInstance called...')
1842 self._reload_if_necessary(env)
1843 rval = self._get_callable(instance.classname, 'MI_createInstance') \
1844 (env, instance)
1845 logger.log_debug('CIMProvider2 MI_createInstance returning')
1846 return rval
1847
1848
1849
1850
1855
1856 logger = env.get_logger()
1857 logger.log_debug('CIMProvider2 MI_modifyInstance called...')
1858 self._reload_if_necessary(env)
1859 self._get_callable(modifiedInstance.classname, 'MI_modifyInstance') \
1860 (env, modifiedInstance, propertyList)
1861 logger.log_debug('CIMProvider2 MI_modifyInstance returning')
1862
1863
1864
1865
1869
1870 logger = env.get_logger()
1871 logger.log_debug('CIMProvider2 MI_deleteInstance called...')
1872 self._reload_if_necessary(env)
1873 self._get_callable(instanceName.classname, 'MI_deleteInstance') \
1874 (env, instanceName)
1875 logger.log_debug('CIMProvider2 MI_deleteInstance returning')
1876
1877
1878
1879
1880
1881 - def MI_associators(self,
1882 env,
1883 objectName,
1884 assocClassName,
1885 resultClassName,
1886 role,
1887 resultRole,
1888 propertyList):
1889
1890
1891
1892 logger = env.get_logger()
1893 logger.log_debug('CIMProvider2 MI_associators called. ' \
1894 'assocClass: %s' % (assocClassName))
1895 self._reload_if_necessary(env)
1896
1897 cname = assocClassName
1898 if not cname and hasattr(self.provmod, 'MI_associators'):
1899 for i in self.provmod.MI_associators(env,
1900 objectName,
1901 assocClassName,
1902 resultClassName,
1903 role,
1904 resultRole,
1905 propertyList):
1906 yield i
1907 return
1908
1909 lcnames = []
1910 if cname:
1911 lcnames = [cname]
1912 else:
1913 lcnames = self.provregs.keys()
1914
1915 for lcname in lcnames:
1916 fn = self._get_callable(lcname, 'MI_associators')
1917 for i in fn(env,
1918 objectName,
1919 lcname,
1920 resultClassName,
1921 role,
1922 resultRole,
1923 propertyList):
1924 yield i
1925 logger.log_debug('CIMProvider2 MI_associators returning')
1926
1927
1928
1929
1930 - def MI_associatorNames(self,
1931 env,
1932 objectName,
1933 assocClassName,
1934 resultClassName,
1935 role,
1936 resultRole):
1937
1938 logger = env.get_logger()
1939 logger.log_debug('CIMProvider2 MI_associatorNames called. ' \
1940 'assocClass: %s' % (assocClassName))
1941 self._reload_if_necessary(env)
1942 cname = assocClassName
1943 if not cname and hasattr(self.provmod, 'MI_associatorNames'):
1944 for i in self.provmod.MI_associatorNames(env,
1945 objectName,
1946 assocClassName,
1947 resultClassName,
1948 role,
1949 resultRole):
1950 yield i
1951 return
1952
1953 lcnames = []
1954 if cname:
1955 lcnames = [cname]
1956 else:
1957 lcnames = self.provregs.keys()
1958
1959 for lcname in lcnames:
1960 fn = self._get_callable(lcname, 'MI_associatorNames')
1961 for i in fn(env,
1962 objectName,
1963 lcname,
1964 resultClassName,
1965 role,
1966 resultRole):
1967 yield i
1968
1969 logger.log_debug('CIMProvider2 MI_associatorNames returning')
1970
1971
1972
1973
1974 - def MI_references(self,
1975 env,
1976 objectName,
1977 resultClassName,
1978 role,
1979 propertyList):
1980
1981 logger = env.get_logger()
1982 logger.log_debug('CIMProvider2 MI_references called. ' \
1983 'resultClass: %s' % (resultClassName))
1984 self._reload_if_necessary(env)
1985 cname = resultClassName
1986 if not cname and hasattr(self.provmod, 'MI_references'):
1987 for i in self.provmod.MI_references(env, objectName,
1988 resultClassName, role,
1989 propertyList):
1990 yield i
1991 return
1992
1993 lcnames = []
1994 if cname:
1995 lcnames = [cname]
1996 else:
1997 lcnames = self.provregs.keys()
1998
1999 for lcname in lcnames:
2000 fn = self._get_callable(lcname, 'MI_references')
2001 for i in fn(env,
2002 objectName,
2003 lcname,
2004 role,
2005 propertyList):
2006 yield i
2007
2008 logger.log_debug('CIMProvider2 MI_references returning')
2009
2010
2011
2012
2013 - def MI_referenceNames(self,
2014 env,
2015 objectName,
2016 resultClassName,
2017 role):
2018
2019 logger = env.get_logger()
2020 logger.log_debug('CIMProvider2 MI_referenceNames <1> called. ' \
2021 'resultClass: %s' % (resultClassName))
2022 self._reload_if_necessary(env)
2023
2024 cname = resultClassName
2025 if not cname and hasattr(self.provmod, 'MI_referenceNames'):
2026 for i in self.provmod.MI_referenceNames(env, objectName,
2027 resultClassName, role):
2028 yield i
2029 return
2030
2031 lcnames = []
2032 if cname:
2033 lcnames = [cname]
2034 else:
2035 lcnames = self.provregs.keys()
2036
2037 for lcname in lcnames:
2038 fn = self._get_callable(lcname, 'MI_referenceNames')
2039 for i in fn(env,
2040 objectName,
2041 lcname,
2042 role):
2043 yield i
2044
2045 logger.log_debug('CIMProvider2 MI_referenceNames returning')
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2060
2061 logger = env.get_logger()
2062 logger.log_debug('CIMProvider2 MI_invokeMethod called. ' \
2063 'method: %s:%s' % (objectName.classname, methodName))
2064 self._reload_if_necessary(env)
2065 rval = self._get_callable(objectName.classname, 'MI_invokeMethod') \
2066 (env, objectName, methodName, inputParams)
2067 logger.log_debug('CIMProvider2 MI_invokeMethod returning')
2068 return rval
2069
2070
2071 - def MI_authorizeFilter(self,
2072 env,
2073 filter,
2074 classname,
2075 classPath,
2076 owner):
2077
2078 logger = env.get_logger()
2079 logger.log_debug('CIMProvider2 MI_authorizeFilter called')
2080 self._reload_if_necessary(env)
2081 if hasattr(self.provmod, 'authorize_filter'):
2082 self.provmod.authorize_filter(env, filter, classname,
2083 classPath, owner)
2084 elif hasattr(self.provmod, 'MI_authorizeFilter'):
2085 self.provmod.MI_authorizeFilter(env, filter, classname,
2086 classPath, owner)
2087 else:
2088
2089 logger.log_debug("Provider %s has no support for authorize " \
2090 "filter" % self.provid)
2091 logger.log_debug('CIMProvider2 MI_authorizeFilter returning')
2092 return
2093
2094
2095
2096 - def MI_activateFilter(self,
2097 env,
2098 filter,
2099 namespace,
2100 classes,
2101 firstActivation):
2102
2103 logger = env.get_logger()
2104 logger.log_debug('CIMProvider2 MI_activateFilter called')
2105 self._reload_if_necessary(env)
2106 if hasattr(self.provmod, 'activate_filter'):
2107 self.provmod.activate_filter(env, filter, namespace,
2108 classes, firstActivation)
2109 elif hasattr(self.provmod, 'MI_activateFilter'):
2110 self.provmod.MI_activateFilter(env, filter, namespace,
2111 classes, firstActivation)
2112 else:
2113
2114 logger.log_debug("Provider %s has no support for activate " \
2115 "filter" % self.provid)
2116 logger.log_debug('CIMProvider2 MI_activateFilter returning')
2117 return
2118
2119
2120
2121 - def MI_deActivateFilter(self,
2122 env,
2123 filter,
2124 namespace,
2125 classes,
2126 lastActivation):
2127
2128 logger = env.get_logger()
2129 logger.log_debug('CIMProvider2 MI_deActivateFilter called')
2130 self._reload_if_necessary(env)
2131 if hasattr(self.provmod, 'deactivate_filter'):
2132 self.provmod.deactivate_filter(env, filter, namespace, classes,
2133 lastActivation)
2134 elif hasattr(self.provmod, 'MI_deActivateFilter'):
2135 self.provmod.MI_deActivateFilter(env, filter, namespace, classes,
2136 lastActivation)
2137 else:
2138
2139 logger.log_debug("Provider %s has no support for deactivate " \
2140 "filter" % self.provid)
2141 logger.log_debug('CIMProvider2 MI_deActivateFilter returning')
2142 return
2143
2144
2145
2147
2148 logger = env.get_logger()
2149 logger.log_debug('CIMProvider2 MI_enableIndications called')
2150 self._reload_if_necessary(env)
2151 if hasattr(self.provmod, 'enable_indications'):
2152 self.provmod.enable_indications(env)
2153 elif hasattr(self.provmod, 'MI_enableIndications'):
2154 self.provmod.MI_enableIndications(env)
2155 else:
2156
2157 logger.log_debug("Provider %s has no support for enable " \
2158 "indications" % self.provid)
2159 logger.log_debug('CIMProvider2 MI_enableIndications returning')
2160 return
2161
2162
2163
2166
2167 logger = env.get_logger()
2168 logger.log_debug('CIMProvider2 MI_disableIndications called')
2169 self._reload_if_necessary(env)
2170 if hasattr(self.provmod, 'disable_indications'):
2171 self.provmod.disable_indications(env)
2172 elif hasattr(self.provmod, 'MI_disableIndications'):
2173 self.provmod.MI_disableIndications(env)
2174 else:
2175
2176 logger.log_debug("Provider %s has no support for disable " \
2177 "indications" % self.provid)
2178 logger.log_debug('CIMProvider2 MI_disableIndications returning')
2179 return
2180
2181
2182
2184
2185
2186
2187
2188 if self.provmod is None:
2189 return
2190 modname = self.provmod.__name__
2191 if hasattr(self.provmod, "shutdown"):
2192 self.provmod.shutdown(env)
2193 self.provmod = None
2194 del sys.modules[modname]
2195
2196
2197
2198
2200
2201 if hasattr(self.provmod, "can_unload"):
2202 return self.provmod.can_unload(env)
2203 else:
2204 return True
2205
2206
2208
2209
2210 logger = env.get_logger()
2211 logger.log_debug('ProviderProxy MI_consumeIndication called')
2212 self._reload_if_necessary(env)
2213 if hasattr(self.provmod, 'consume_indication'):
2214 self.provmod.consume_indication(env, destinationPath,
2215 indicationInstance)
2216 elif hasattr(self.provmod, 'MI_consumeIndication'):
2217 self.provmod.MI_consumeIndication(env, destinationPath,
2218 indicationInstance)
2219 else:
2220 raise pywbem.CIMError(
2221 pywbem.CIM_ERR_FAILED,
2222 "Provider %s has no support for consume indication" % \
2223 self.provid)
2224 logger.log_debug('ProviderProxy MI_consumeIndication returning')
2225
2226
2227
2228 - def MI_handleIndication(self,
2229 env,
2230 ns,
2231 handlerInstance,
2232 indicationInstance):
2233
2234
2235 logger = env.get_logger()
2236 logger.log_debug('ProviderProxy MI_handleIndication called')
2237 self._reload_if_necessary(env)
2238 if hasattr(self.provmod, 'handle_indication'):
2239 self.provmod.handle_indication(env, ns, handlerInstance,
2240 indicationInstance)
2241 elif hasattr(self.provmod, 'MI_handleIndication'):
2242 self.provmod.MI_handleIndication(env, ns, handlerInstance,
2243 indicationInstance)
2244 else:
2245 raise pywbem.CIMError(
2246 pywbem.CIM_ERR_FAILED,
2247 "Provider %s has no support for handle indication" % \
2248 self.provid)
2249 logger.log_debug('ProviderProxy MI_handleIndication returning')
2250