Package pywbem :: Module cim_provider
[frames] | no frames]

Source Code for Module pywbem.cim_provider

   1  # 
   2  # (C) Copyright 2003-2007 Hewlett-Packard Development Company, L.P. 
   3  # 
   4  # This library is free software; you can redistribute it and/or 
   5  # modify it under the terms of the GNU Lesser General Public 
   6  # License as published by the Free Software Foundation; either 
   7  # version 2.1 of the License, or (at your option) any later version. 
   8  # 
   9  # This program is distributed in the hope that it will be useful, but 
  10  # WITHOUT ANY WARRANTY; without even the implied warranty of 
  11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  12  # Lesser General Public License for more details. 
  13  # 
  14  # You should have received a copy of the GNU Lesser General Public 
  15  # License along with this program; if not, write to the Free Software 
  16  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  17  # 
  18  # Author: Bart Whiteley 
  19  # Author: Jon Carey 
  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   
200 -def _path_equals_ignore_host(lhs, rhs):
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 # need to make sure this stays in sync with CIMInstanceName.__cmp__() 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
216 -class CIMProvider(object):
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
271 - def get_instance(self, env, model, cim_class):
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
296 - def enum_instances(self, env, model, cim_class, keys_only):
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
351 - def delete_instance(self, env, instance_name):
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
435 - def _set_filter_results(self, value):
436 self._filter_results = value
437 - def _get_filter_results(self):
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
458 - def MI_enumInstanceNames(self, 459 env, 460 ns, 461 cimClass):
462 # pylint: disable=invalid-name 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 # pylint: disable=invalid-name 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 # pylint: disable=invalid-name 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
597 - def MI_createInstance(self, 598 env, 599 instance):
600 # pylint: disable=invalid-name 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 # CIMOM has already filled in default property values for 618 # props with default values, if values not supplied by client. 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 # pylint: disable=invalid-name 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
654 - def MI_deleteInstance(self, 655 env, 656 instanceName):
657 # pylint: disable=invalid-name 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 # pylint: disable=invalid-name 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 # NOTE: This should honor the parameters resultClassName, role, 690 # resultRole, and propertyList 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 # pylint: disable=invalid-name 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 # pylint: disable=invalid-name 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 #if role is None: 857 # raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, 858 # "** this shouldn't happen") 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 # pylint: disable=invalid-name 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 #if role is None: 922 # raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, 923 # "** this shouldn't happen") 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
944 - def MI_invokeMethod(self, env, objectName, metaMethod, inputParams):
945 # pylint: disable=invalid-name 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
1015 -def filter_instance(inst, plist):
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
1029 -def get_keys_from_class(cc):
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
1034 -def build_instance_name(inst, obj=None):
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
1056 -def _strip_quals(props):
1057 for prop in props.values(): # remove all but key quals 1058 try: 1059 prop.qualifiers = pywbem.NocaseDict({'KEY': 1060 prop.qualifiers['KEY']}) 1061 except KeyError: 1062 prop.qualifiers = pywbem.NocaseDict()
1063 1064
1065 -def codegen(cc):
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: # a long URL 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 #line = "#ux(%s=%s) # TODO (type = %s) %s" % \ 1292 # (prop.name, type_hint(prop), type_str(prop), is_required(prop)) 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
1557 -class ProviderProxy(object):
1558 """Wraps a provider module, and routes requests into the module """ 1559
1560 - def __init__(self, env, provid):
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 # odd chars in a module name tend to break things 1568 provider_name = 'pyprovider_' 1569 for ch in provid: 1570 provider_name += ch.isalnum() and ch or '_' 1571 # let providers import other providers in the same directory 1572 provdir = dirname(provid) 1573 if provdir not in sys.path: 1574 sys.path.append(provdir) 1575 # use full path in module name for uniqueness. 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
1589 - def _get_callable(self, classname, cname):
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 # enumInstanceNames 1613 ##############################################################################
1614 - def MI_enumInstanceNames(self, 1615 env, 1616 ns, 1617 cimClass):
1618 # pylint: disable=invalid-name 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 # enumInstances 1629 ##############################################################################
1630 - def MI_enumInstances(self, 1631 env, 1632 ns, 1633 propertyList, 1634 requestedCimClass, 1635 cimClass):
1636 # pylint: disable=invalid-name 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 # getInstance 1650 ##############################################################################
1651 - def MI_getInstance(self, 1652 env, 1653 instanceName, 1654 propertyList, 1655 cimClass):
1656 # pylint: disable=invalid-name 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 # createInstance 1669 ##############################################################################
1670 - def MI_createInstance(self, 1671 env, 1672 instance):
1673 # pylint: disable=invalid-name 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 # modifyInstance 1683 ##############################################################################
1684 - def MI_modifyInstance(self, 1685 env, 1686 modifiedInstance, 1687 previousInstance, 1688 propertyList, 1689 cimClass):
1690 # pylint: disable=invalid-name 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 # deleteInstance 1700 ##############################################################################
1701 - def MI_deleteInstance(self, 1702 env, 1703 instanceName):
1704 # pylint: disable=invalid-name 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 # associators 1714 ##############################################################################
1715 - def MI_associators(self, 1716 env, 1717 objectName, 1718 assocClassName, 1719 resultClassName, 1720 role, 1721 resultRole, 1722 propertyList):
1723 # pylint: disable=invalid-name 1724 # NOTE: This should honor the parameters resultClassName, role, 1725 # resultRole, and propertyList 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 # associatorNames 1738 ##############################################################################
1739 - def MI_associatorNames(self, 1740 env, 1741 objectName, 1742 assocClassName, 1743 resultClassName, 1744 role, 1745 resultRole):
1746 # pylint: disable=invalid-name 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 # references 1759 ##############################################################################
1760 - def MI_references(self, 1761 env, 1762 objectName, 1763 resultClassName, 1764 role, 1765 propertyList):
1766 # pylint: disable=invalid-name 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 # referenceNames 1784 ##############################################################################
1785 - def MI_referenceNames(self, 1786 env, 1787 objectName, 1788 resultClassName, 1789 role):
1790 # pylint: disable=invalid-name 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 # invokeMethod 1807 # inputParam is a Dictionary where the key is the parameter name 1808 # and the value is the parameter value 1809 # The return value for invokeMethod must be a tuple of size 2 where 1810 # element 0 is a tuple of size 2 where element 0 is the return data type name 1811 # and element 1 is the actual data value 1812 # element 1 is a dictionary where the key is the output parameter name 1813 # and the value is a tuple of size 2 where element 0 is the data type name 1814 # for the output parameter and element 1 is the actual value of the 1815 # output parameter. 1816 ##############################################################################
1817 - def MI_invokeMethod(self, env, objectName, metaMethod, inputParams):
1818 # pylint: disable=invalid-name 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 ##############################################################################
1828 - def MI_poll(self, env):
1829 # pylint: disable=invalid-name 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 ##############################################################################
1844 - def MI_getInitialPollingInterval(self, env):
1845 # pylint: disable=invalid-name 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 # pylint: disable=invalid-name 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 # pylint: disable=invalid-name 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 ##############################################################################
1908 - def MI_shutdown(self, env):
1909 # pylint: disable=invalid-name 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 #TODO concurrency problems here?? 1916 1917 1918 ##############################################################################
1919 - def MI_canunload(self, env):
1920 # pylint: disable=invalid-name 1921 if hasattr(self.provmod, "canunload"): 1922 return self.provmod.canunload 1923 else: 1924 return True
1925 1926 ##############################################################################
1927 - def MI_consumeIndication(self, env, destinationPath, indicationInstance):
1928 # pylint: disable=invalid-name 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 # pylint: disable=invalid-name 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