Package pywbem :: Module cim_provider2

[frames] | no frames]

# Source Code for Module pywbem.cim_provider2

       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  """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
     209 -def _paths_equal(lhs, rhs):
     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      # need to make sure this stays in sync with CIMInstanceName.__cmp__()
     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
     225 -class CIMProvider2(object):
     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
     280 -    def get_instance(self, env, model):
     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
     304 -    def enum_instances(self, env, model, keys_only):
     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
     328 -    def set_instance(self, env, instance, modify_existing):
     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
     356 -    def delete_instance(self, env, instance_name):
     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          # Don't change this return value.  If affects the behavior
     438          # of the MI_* methods.
     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
     457 -    def paths_equal(self, lhs, rhs):
     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          # need to make sure this stays in sync with CIMInstanceName.__cmp__()
     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
     474 -    def MI_enumInstanceNames(self,
     475                               env,
     476                               objPath):
     477          # pylint: disable=invalid-name
     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
     503 -    def MI_enumInstances(self,
     504                           env,
     505                           objPath,
     506                           propertyList):
     507          # pylint: disable=invalid-name
     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          # pylint: disable=invalid-name
     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
     559 -    def MI_createInstance(self,
     560                            env,
     561                            instance):
     562          # pylint: disable=invalid-name
     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          # CIMOM has already filled in default property values for
     582          # props with default values, if values not supplied by client.
     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
     589 -    def MI_modifyInstance(self,
     590                            env,
     591                            modifiedInstance,
     592                            propertyList):
     593          # pylint: disable=invalid-name
     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
     617 -    def MI_deleteInstance(self,
     618                            env,
     619                            instanceName):
     620          # pylint: disable=invalid-name
     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          # pylint: disable=invalid-name
     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          # NOTE: This should honor the parameters resultClassName, role,
     653          #       resultRole, and propertyList
     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          # pylint: disable=invalid-name
     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          # pylint: disable=invalid-name
     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          # pylint: disable=invalid-name
     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
     858 -    def MI_invokeMethod(self, env, objectName, methodName, inputParams):
     859          # pylint: disable=invalid-name
     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
     932 -    def filter_instance(self, inst, plist):
     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
     948 -    def authorize_filter(env, filter, ns, classes, owner):
     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
     960 -    def activate_filter(env, filter, ns, classes, first_activation):
     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
     972 -    def deactivate_filter(env, filter, ns, classes, last_activation):
     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
     984 -    def enable_indications(env):
     985          """Enable indications.
     986
     987          Arguments:
     988          env -- Provider Environment (pycimmb.ProviderEnvironment)
     989          """
     990          pass
     991
     992 -    def disable_indications(env):
     993          """Disable indications.
     994
     995          Arguments:
     996          env -- Provider Environment (pycimmb.ProviderEnvironment)
     997          """
     998          pass
     999
    1000
    1001 -def codegen(cc):
    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: # a long URL
    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) # we want normal strings, not unicode
    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          # SFCB has problems with qualifiers on REF properties.
    1235          # http://sourceforge.net/tracker/index.php?func=detail&aid=2104565&group_id=128809&atid=712784
    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
    1678 -class ProviderProxy(object):
    1679      """Wraps a provider module, and routes requests into the module """
    1680
    1681 -    def __init__(self, env, provid):
    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
    1694 -    def _init_provider(self, env):
    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
    1701 -    def _load_provider_source(self, logger):
    1702          self.provider_module_name = os.path.basename(self.provid)[:-3]
    1703          # let providers import other providers in the same directory
    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                  # use full path in module name for uniqueness.
    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
    1734 -    def _get_callable(self, classname, cname):
    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
    1756 -    def _reload_if_necessary(self, env):
    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              #first unload the module
    1770              if self.provmod and hasattr(self.provmod, "shutdown"):
    1771                  self.provmod.shutdown(env)
    1772              #now reload and reinit module
    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  # enumInstanceNames
    1788  ##############################################################################
    1789 -    def MI_enumInstanceNames(self,
    1790                               env,
    1791                               objPath):
    1792          # pylint: disable=invalid-name
    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  # enumInstances
    1801  ##############################################################################
    1802 -    def MI_enumInstances(self,
    1803                           env,
    1804                           objPath,
    1805                           propertyList):
    1806          # pylint: disable=invalid-name
    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  # getInstance
    1817  ##############################################################################
    1818 -    def MI_getInstance(self,
    1819                         env,
    1820                         instanceName,
    1821                         propertyList):
    1822          # pylint: disable=invalid-name
    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  # createInstance
    1835  ##############################################################################
    1836 -    def MI_createInstance(self,
    1837                            env,
    1838                            instance):
    1839          # pylint: disable=invalid-name
    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  # modifyInstance
    1850  ##############################################################################
    1851 -    def MI_modifyInstance(self,
    1852                            env,
    1853                            modifiedInstance,
    1854                            propertyList):
    1855          # pylint: disable=invalid-name
    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  # deleteInstance
    1865  ##############################################################################
    1866 -    def MI_deleteInstance(self,
    1867                            env,
    1868                            instanceName):
    1869          # pylint: disable=invalid-name
    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  # associators
    1880  ##############################################################################
    1881 -    def MI_associators(self,
    1882                         env,
    1883                         objectName,
    1884                         assocClassName,
    1885                         resultClassName,
    1886                         role,
    1887                         resultRole,
    1888                         propertyList):
    1889          # pylint: disable=invalid-name
    1890          # NOTE: This should honor the parameters resultClassName, role,
    1891          #       resultRole, and propertyList
    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  # associatorNames
    1929  ##############################################################################
    1930 -    def MI_associatorNames(self,
    1931                             env,
    1932                             objectName,
    1933                             assocClassName,
    1934                             resultClassName,
    1935                             role,
    1936                             resultRole):
    1937          # pylint: disable=invalid-name
    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  # references
    1973  ##############################################################################
    1974 -    def MI_references(self,
    1975                        env,
    1976                        objectName,
    1977                        resultClassName,
    1978                        role,
    1979                        propertyList):
    1980          # pylint: disable=invalid-name
    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  # referenceNames
    2012  ##############################################################################
    2013 -    def MI_referenceNames(self,
    2014                            env,
    2015                            objectName,
    2016                            resultClassName,
    2017                            role):
    2018          # pylint: disable=invalid-name
    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  # invokeMethod
    2049  #       inputParam is a Dictionary where the key is the parameter name
    2050  #       and the value is the parameter value
    2051  # The return value for invokeMethod must be a tuple of size 2 where
    2052  # element 0 is a tuple of size 2 where element 0 is the return data type name
    2053  #       and element 1 is the actual data value
    2054  # element 1 is a dictionary where the key is the output parameter name
    2055  #       and the value is a tuple of size 2 where element 0 is the data type name
    2056  #       for the output parameter and element 1 is the actual value of the
    2057  #       output parameter.
    2058  ##############################################################################
    2059 -    def MI_invokeMethod(self, env, objectName, methodName, inputParams):
    2060          # pylint: disable=invalid-name
    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          # pylint: disable=invalid-name
    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              # if not instrumented in provider, assume success
    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          # pylint: disable=invalid-name
    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              # if not instrumented in provider, assume success
    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          # pylint: disable=invalid-name
    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              # if not instrumented in provider, assume success
    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  ##############################################################################
    2146 -    def MI_enableIndications(self, env):
    2147          # pylint: disable=invalid-name
    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              # if not instrumented in provider, assume success
    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  ##############################################################################
    2164 -    def MI_disableIndications(self,
    2165                                env):
    2166          # pylint: disable=invalid-name
    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              # if not instrumented in provider, assume success
    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  ##############################################################################
    2183 -    def MI_shutdown(self, env):
    2184          # pylint: disable=invalid-name
    2185          # shutdown may be called multiple times -- once per MI type
    2186          # (instance/method/association/...)  We'll only do stuff on
    2187          # the first time.
    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          #TODO concurrency problems here??
    2196
    2197
    2198  ##############################################################################
    2199 -    def MI_canunload(self, env):
    2200          # pylint: disable=invalid-name
    2201          if hasattr(self.provmod, "can_unload"):
    2202              return self.provmod.can_unload(env)
    2203          else:
    2204              return True
    2205
    2206  ##############################################################################
    2207 -    def MI_consumeIndication(self, env, destinationPath, indicationInstance):
    2208          # pylint: disable=invalid-name
    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          # pylint: disable=invalid-name
    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