Package pywbem :: Module cim_provider

[frames] | no frames]

# Source Code for Module pywbem.cim_provider

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