pywbem.twisted_client

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

# Source Code for Module pywbem.twisted_client

      1  #
      2  # (C) Copyright 2005,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: Tim Potter <tpot@hp.com>
     19  #
     20
     21  """pywbem.twisted - WBEM client bindings for Twisted Python.
     22
     23  This module contains factory classes that produce WBEMClient instances
     24  that perform WBEM requests over HTTP using the
     25  twisted.protocols.http.HTTPClient base class.
     26  """
     27
     28  import string
     29  import base64
     30  from types import StringTypes
     31  from datetime import datetime, timedelta
     32  import urllib
     33  try:
     34      from elementtree.ElementTree import fromstring, tostring
     35  except ImportError, arg:
     36      from xml.etree.ElementTree import fromstring, tostring
     37
     38  from twisted.internet import reactor, protocol, defer
     39  from twisted.web import http #, client, error
     40
     41  # TODO: Eww - we should get rid of the tupletree, tupleparse modules
     42  # and replace with elementtree based code.
     43  from pywbem import cim_types, cim_xml, cim_obj, tupleparse, tupletree
     44  from pywbem.cim_obj import CIMClass, CIMClassName, CIMInstance, CIMInstanceName
     45  from pywbem.cim_operations import CIMError
     46  from pywbem.cim_types import CIMDateTime
     47
     48  __all__ = ['WBEMClient', 'WBEMClientFactory', 'EnumerateInstances',
     49             'EnumerateInstanceNames', 'GetInstance', 'DeleteInstance',
     50             'CreateInstance', 'ModifyInstance', 'EnumerateClassNames',
     51             'EnumerateClasses', 'GetClass', 'Associators', 'AssociatorNames',
     52             'References', 'ReferenceNames', 'InvokeMethod', 'ExecQuery']
     53
     54 -class WBEMClient(http.HTTPClient):
     55      """A HTTPClient subclass that handles WBEM requests."""
     56
     57      status = None
     58
     59 -    def connectionMade(self):
     60          """Send a HTTP POST command with the appropriate CIM over HTTP
     61          headers and payload."""
     62
     63          self.factory.request_xml = str(self.factory.payload)
     64
     65          self.sendCommand('POST', '/cimom')
     66
     67          self.sendHeader('Host', '%s:%d' %
     68                          (self.transport.addr[0], self.transport.addr[1]))
     69          self.sendHeader('User-Agent', 'pywbem/twisted')
     70          self.sendHeader('Content-length', len(self.factory.payload))
     71          self.sendHeader('Content-type', 'application/xml')
     72
     73          if self.factory.creds:
     74              auth = base64.b64encode('%s:%s' % (self.factory.creds[0],
     75                                                 self.factory.creds[1]))
     76
     77              self.sendHeader('Authorization', 'Basic %s' % auth)
     78
     79          self.sendHeader('CIMOperation', str(self.factory.operation))
     80          self.sendHeader('CIMMethod', str(self.factory.method))
     81          self.sendHeader('CIMObject', str(self.factory.object))
     82
     83          self.endHeaders()
     84
     85          # TODO: Figure out why twisted doesn't support unicode.  An
     86          # exception should be thrown by the str() call if the payload
     87          # can't be converted to the current codepage.
     88
     89          self.transport.write(str(self.factory.payload))
     90
     91 -    def handleResponse(self, data):
     92          """Called when all response data has been received."""
     93
     94          self.factory.response_xml = data
     95
     96          if self.status == '200':
     97              self.factory.parseErrorAndResponse(data)
     98
     99          self.factory.deferred = None
    100          self.transport.loseConnection()
    101
    102 -    def handleStatus(self, version, status, message):
    103          """Save the status code for processing when we get to the end
    104          of the headers."""
    105
    106          self.status = status
    107          self.message = message
    108
    109 -    def handleHeader(self, key, value):
    110          """Handle header values."""
    111
    112          if key == 'CIMError':
    113              self.CIMError = urllib.unquote(value)
    114          if key == 'PGErrorDetail':
    115              self.PGErrorDetail = urllib.unquote(value)
    116
    117 -    def handleEndHeaders(self):
    118          """Check whether the status was OK and raise an error if not
    119          using previously saved header information."""
    120
    121          if self.status != '200':
    122
    123              if not hasattr(self, 'cimerror') or \
    124                 not hasattr(self, 'errordetail'):
    125
    126                  self.factory.deferred.errback(
    127                      CIMError(0, 'HTTP error %s: %s' %
    128                               (self.status, self.message)))
    129
    130              else:
    131
    132                  self.factory.deferred.errback(
    133                      CIMError(0, '%s: %s' % (cimerror, errordetail)))
    134
    135 -class WBEMClientFactory(protocol.ClientFactory):
    136      """Create instances of the WBEMClient class."""
    137
    138      request_xml = None
    139      response_xml = None
    140      xml_header = '<?xml version="1.0" encoding="utf-8" ?>'
    141
    142 -    def __init__(self, creds, operation, method, object, payload):
    143          self.creds = creds
    144          self.operation = operation
    145          self.method = method
    146          self.object = object
    147          self.payload = payload
    148          self.protocol = lambda: WBEMClient()
    149          self.deferred = defer.Deferred()
    150
    151 -    def clientConnectionFailed(self, connector, reason):
    152          if self.deferred is not None:
    153              reactor.callLater(0, self.deferred.errback, reason)
    154
    155 -    def clientConnectionLost(self, connector, reason):
    156          if self.deferred is not None:
    157              reactor.callLater(0, self.deferred.errback, reason)
    158
    159 -    def imethodcallPayload(self, methodname, localnsp, **kwargs):
    160          """Generate the XML payload for an intrinsic methodcall."""
    161
    162          param_list = [pywbem.IPARAMVALUE(x[0], pywbem.tocimxml(x[1]))
    163                        for x in kwargs.items()]
    164
    165          payload = cim_xml.CIM(
    166              cim_xml.MESSAGE(
    167                  cim_xml.SIMPLEREQ(
    168                      cim_xml.IMETHODCALL(
    169                          methodname,
    170                          cim_xml.LOCALNAMESPACEPATH(
    171                              [cim_xml.NAMESPACE(ns)
    172                               for ns in string.split(localnsp, '/')]),
    173                          param_list)),
    174                  '1001', '1.0'),
    175              '2.0', '2.0')
    176
    177          return self.xml_header + payload.toxml()
    178
    179 -    def methodcallPayload(self, methodname, obj, namespace, **kwargs):
    180          """Generate the XML payload for an extrinsic methodcall."""
    181
    182          if isinstance(obj, CIMInstanceName):
    183
    184              path = obj.copy()
    185
    186              path.host = None
    187              path.namespace = None
    188
    189              localpath = cim_xml.LOCALINSTANCEPATH(
    190                  cim_xml.LOCALNAMESPACEPATH(
    191                      [cim_xml.NAMESPACE(ns)
    192                       for ns in string.split(namespace, '/')]),
    193                  path.tocimxml())
    194          else:
    195              localpath = cim_xml.LOCALCLASSPATH(
    196                  cim_xml.LOCALNAMESPACEPATH(
    197                      [cim_xml.NAMESPACE(ns)
    198                       for ns in string.split(namespace, '/')]),
    199                  obj)
    200
    201          def paramtype(obj):
    202              """Return a string to be used as the CIMTYPE for a parameter."""
    203              if isinstance(obj, cim_types.CIMType):
    204                  return obj.cimtype
    205              elif type(obj) == bool:
    206                  return 'boolean'
    207              elif isinstance(obj, StringTypes):
    208                  return 'string'
    209              elif isinstance(obj, (datetime, timedelta)):
    210                  return 'datetime'
    211              elif isinstance(obj, (CIMClassName, CIMInstanceName)):
    212                  return 'reference'
    213              elif isinstance(obj, (CIMClass, CIMInstance)):
    214                  return 'string'
    215              elif isinstance(obj, list):
    216                  return paramtype(obj[0])
    217              raise TypeError('Unsupported parameter type "%s"' % type(obj))
    218
    219          def paramvalue(obj):
    220              """Return a cim_xml node to be used as the value for a
    221              parameter."""
    222              if isinstance(obj, (datetime, timedelta)):
    223                  obj = CIMDateTime(obj)
    224              if isinstance(obj, (cim_types.CIMType, bool, StringTypes)):
    225                  return cim_xml.VALUE(cim_types.atomic_to_cim_xml(obj))
    226              if isinstance(obj, (CIMClassName, CIMInstanceName)):
    227                  return cim_xml.VALUE_REFERENCE(obj.tocimxml())
    228              if isinstance(obj, (CIMClass, CIMInstance)):
    229                  return cim_xml.VALUE(obj.tocimxml().toxml())
    230              if isinstance(obj, list):
    231                  if isinstance(obj[0], (CIMClassName, CIMInstanceName)):
    232                      return cim_xml.VALUE_REFARRAY([paramvalue(x) for x in obj])
    233                  return cim_xml.VALUE_ARRAY([paramvalue(x) for x in obj])
    234              raise TypeError('Unsupported parameter type "%s"' % type(obj))
    235
    236          param_list = [cim_xml.PARAMVALUE(x[0],
    237                                          paramvalue(x[1]),
    238                                          paramtype(x[1]))
    239                        for x in kwargs.items()]
    240
    241          payload = cim_xml.CIM(
    242              cim_xml.MESSAGE(
    243                  cim_xml.SIMPLEREQ(
    244                      cim_xml.METHODCALL(methodname,
    245                                        localpath,
    246                                        param_list)),
    247                  '1001', '1.0'),
    248              '2.0', '2.0')
    249
    250          return self.xml_header + payload.toxml()
    251
    252 -    def parseErrorAndResponse(self, data):
    253          """Parse returned XML for errors, then convert into
    254          appropriate Python objects."""
    255
    256          xml = fromstring(data)
    257          error = xml.find('.//ERROR')
    258
    259          if error is None:
    260              self.deferred.callback(self.parseResponse(xml))
    261              return
    262
    263          try:
    264              code = int(error.attrib['CODE'])
    265          except ValueError:
    266              code = 0
    267
    268          self.deferred.errback(CIMError(code, error.attrib['DESCRIPTION']))
    269
    270 -    def parseResponse(self, xml):
    271          """Parse returned XML and convert into appropriate Python
    272          objects.  Override in subclass"""
    273
    274          pass
    275
    276 -class EnumerateInstances(WBEMClientFactory):
    277      """Factory to produce EnumerateInstances WBEM clients."""
    278
    279 -    def __init__(self, creds, classname, namespace='root/cimv2', **kwargs):
    280
    281          self.classname = classname
    282          self.namespace = namespace
    283
    284          payload = self.imethodcallPayload(
    285              'EnumerateInstances',
    286              namespace,
    287              ClassName=CIMClassName(classname),
    288              **kwargs)
    289
    290          WBEMClientFactory.__init__(
    291              self,
    292              creds,
    293              operation='MethodCall',
    294              method='EnumerateInstances',
    295              object=namespace,
    296              payload=payload)
    297
    298 -    def __repr__(self):
    299          return '<%s(/%s:%s) at 0x%x>' % \
    300                 (self.__class__, self.namespace, self.classname, id(self))
    301
    302 -    def parseResponse(self, xml):
    303
    304          tt = [tupletree.xml_to_tupletree(tostring(x))
    305                for x in xml.findall('.//VALUE.NAMEDINSTANCE')]
    306
    307          return [tupleparse.parse_value_namedinstance(x) for x in tt]
    308
    309 -class EnumerateInstanceNames(WBEMClientFactory):
    310      """Factory to produce EnumerateInstanceNames WBEM clients."""
    311
    312 -    def __init__(self, creds, classname, namespace='root/cimv2', **kwargs):
    313
    314          self.classname = classname
    315          self.namespace = namespace
    316
    317          payload = self.imethodcallPayload(
    318              'EnumerateInstanceNames',
    319              namespace,
    320              ClassName=CIMClassName(classname),
    321              **kwargs)
    322
    323          WBEMClientFactory.__init__(
    324              self,
    325              creds,
    326              operation='MethodCall',
    327              method='EnumerateInstanceNames',
    328              object=namespace,
    329              payload=payload)
    330
    331 -    def __repr__(self):
    332          return '<%s(/%s:%s) at 0x%x>' % \
    333                 (self.__class__, self.namespace, self.classname, id(self))
    334
    335 -    def parseResponse(self, xml):
    336
    337          tt = [tupletree.xml_to_tupletree(tostring(x))
    338                for x in xml.findall('.//INSTANCENAME')]
    339
    340          names = [tupleparse.parse_instancename(x) for x in tt]
    341
    342          [setattr(n, 'namespace', self.namespace) for n in names]
    343
    344          return names
    345
    346 -class GetInstance(WBEMClientFactory):
    347      """Factory to produce GetInstance WBEM clients."""
    348
    349 -    def __init__(self, creds, instancename, namespace='root/cimv2', **kwargs):
    350
    351          self.instancename = instancename
    352          self.namespace = namespace
    353
    354          payload = self.imethodcallPayload(
    355              'GetInstance',
    356              namespace,
    357              InstanceName=instancename,
    358              **kwargs)
    359
    360          WBEMClientFactory.__init__(
    361              self,
    362              creds,
    363              operation='MethodCall',
    364              method='GetInstance',
    365              object=namespace,
    366              payload=payload)
    367
    368 -    def __repr__(self):
    369          return '<%s(/%s:%s) at 0x%x>' % \
    370                 (self.__class__, self.namespace, self.instancename, id(self))
    371
    372 -    def parseResponse(self, xml):
    373
    374          tt = tupletree.xml_to_tupletree(
    375              tostring(xml.find('.//INSTANCE')))
    376
    377          return tupleparse.parse_instance(tt)
    378
    379 -class DeleteInstance(WBEMClientFactory):
    380      """Factory to produce DeleteInstance WBEM clients."""
    381
    382 -    def __init__(self, creds, instancename, namespace='root/cimv2', **kwargs):
    383
    384          self.instancename = instancename
    385          self.namespace = namespace
    386
    387          payload = self.imethodcallPayload(
    388              'DeleteInstance',
    389              namespace,
    390              InstanceName=instancename,
    391              **kwargs)
    392
    393          WBEMClientFactory.__init__(
    394              self,
    395              creds,
    396              operation='MethodCall',
    397              method='DeleteInstance',
    398              object=namespace,
    399              payload=payload)
    400
    401 -    def __repr__(self):
    402          return '<%s(/%s:%s) at 0x%x>' % \
    403                 (self.__class__, self.namespace, self.instancename, id(self))
    404
    405 -class CreateInstance(WBEMClientFactory):
    406      """Factory to produce CreateInstance WBEM clients."""
    407
    408      # TODO: Implement __repr__ method
    409
    410 -    def __init__(self, creds, instance, namespace='root/cimv2', **kwargs):
    411
    412          payload = self.imethodcallPayload(
    413              'CreateInstance',
    414              namespace,
    415              NewInstance=instance,
    416              **kwargs)
    417
    418          WBEMClientFactory.__init__(
    419              self,
    420              creds,
    421              operation='MethodCall',
    422              method='CreateInstance',
    423              object=namespace,
    424              payload=payload)
    425
    426 -    def parseResponse(self, xml):
    427
    428          tt = tupletree.xml_to_tupletree(
    429              tostring(xml.find('.//INSTANCENAME')))
    430
    431          return tupleparse.parse_instancename(tt)
    432
    433 -class ModifyInstance(WBEMClientFactory):
    434      """Factory to produce ModifyInstance WBEM clients."""
    435
    436      # TODO: Implement __repr__ method
    437
    438 -    def __init__(self, creds, instancename, instance, namespace='root/cimv2',
    439                   **kwargs):
    440
    441          wrapped_instance = CIMNamedInstance(instancename, instance)
    442
    443          payload = self.imethodcallPayload(
    444              'ModifyInstance',
    445              namespace,
    446              ModifiedInstance=wrapped_instance,
    447              **kwargs)
    448
    449          WBEMClientFactory.__init__(
    450              self,
    451              creds,
    452              operation='MethodCall',
    453              method='ModifyInstance',
    454              object=namespace,
    455              payload=payload)
    456
    457 -class EnumerateClassNames(WBEMClientFactory):
    458      """Factory to produce EnumerateClassNames WBEM clients."""
    459
    460 -    def __init__(self, creds, namespace='root/cimv2', **kwargs):
    461
    462          self.localnsp = namespace
    463
    464          payload = self.imethodcallPayload(
    465              'EnumerateClassNames',
    466              namespace,
    467              **kwargs)
    468
    469          WBEMClientFactory.__init__(
    470              self,
    471              creds,
    472              operation='MethodCall',
    473              method='EnumerateClassNames',
    474              object=namespace,
    475              payload=payload)
    476
    477 -    def __repr__(self):
    478          return '<%s(/%s) at 0x%x>' % \
    479                 (self.__class__, self.namespace, id(self))
    480
    481 -    def parseResponse(self, xml):
    482
    483          tt = [tupletree.xml_to_tupletree(tostring(x))
    484                for x in xml.findall('.//CLASSNAME')]
    485
    486          return [tupleparse.parse_classname(x) for x in tt]
    487
    488 -class EnumerateClasses(WBEMClientFactory):
    489      """Factory to produce EnumerateClasses WBEM clients."""
    490
    491 -    def __init__(self, creds, namespace='root/cimv2', **kwargs):
    492
    493          self.localnsp = namespace
    494          self.namespace = namespace
    495
    496          payload = self.imethodcallPayload(
    497              'EnumerateClasses',
    498              namespace,
    499              **kwargs)
    500
    501          WBEMClientFactory.__init__(
    502              self,
    503              creds,
    504              operation='MethodCall',
    505              method='EnumerateClasses',
    506              object=namespace,
    507              payload=payload)
    508
    509 -    def __repr__(self):
    510          return '<%s(/%s) at 0x%x>' % \
    511                 (self.__class__, self.namespace, id(self))
    512
    513 -    def parseResponse(self, xml):
    514
    515          tt = [tupletree.xml_to_tupletree(tostring(x))
    516                for x in xml.findall('.//CLASS')]
    517
    518          return [tupleparse.parse_class(x) for x in tt]
    519
    520 -class GetClass(WBEMClientFactory):
    521      """Factory to produce GetClass WBEM clients."""
    522
    523 -    def __init__(self, creds, classname, namespace='root/cimv2', **kwargs):
    524
    525          self.classname = classname
    526          self.namespace = namespace
    527
    528          payload = self.imethodcallPayload(
    529              'GetClass',
    530              namespace,
    531              ClassName=CIMClassName(classname),
    532              **kwargs)
    533
    534          WBEMClientFactory.__init__(
    535              self,
    536              creds,
    537              operation='MethodCall',
    538              method='GetClass',
    539              object=namespace,
    540              payload=payload)
    541
    542 -    def __repr__(self):
    543          return '<%s(/%s:%s) at 0x%x>' % \
    544                 (self.__class__, self.namespace, self.classname, id(self))
    545
    546 -    def parseResponse(self, xml):
    547
    548          tt = tupletree.xml_to_tupletree(
    549              tostring(xml.find('.//CLASS')))
    550
    551          return tupleparse.parse_class(tt)
    552
    553 -class Associators(WBEMClientFactory):
    554      """Factory to produce Associators WBEM clients."""
    555
    556      # TODO: Implement __repr__ method
    557
    558 -    def __init__(self, creds, obj, namespace='root/cimv2', **kwargs):
    559
    560          if isinstance(obj, CIMInstanceName):
    561              kwargs['ObjectName'] = obj
    562          else:
    563              kwargs['ObjectName'] = CIMClassName(obj)
    564
    565          payload = self.imethodcallPayload(
    566              'Associators',
    567              namespace,
    568              **kwargs)
    569
    570          WBEMClientFactory.__init__(
    571              self,
    572              creds,
    573              operation='MethodCall',
    574              method='Associators',
    575              object=namespace,
    576              payload=payload)
    577
    578 -class AssociatorNames(WBEMClientFactory):
    579      """Factory to produce AssociatorNames WBEM clients."""
    580
    581      # TODO: Implement __repr__ method
    582
    583 -    def __init__(self, creds, obj, namespace='root/cimv2', **kwargs):
    584
    585          if isinstance(obj, CIMInstanceName):
    586              kwargs['ObjectName'] = obj
    587          else:
    588              kwargs['ObjectName'] = CIMClassName(obj)
    589
    590          payload = self.imethodcallPayload(
    591              'AssociatorNames',
    592              namespace,
    593              **kwargs)
    594
    595          WBEMClientFactory.__init__(
    596              self,
    597              creds,
    598              operation='MethodCall',
    599              method='AssociatorNames',
    600              object=namespace,
    601              payload=payload)
    602
    603 -    def parseResponse(self, xml):
    604
    605          if len(xml.findall('.//INSTANCENAME')) > 0:
    606
    607              tt = [tupletree.xml_to_tupletree(tostring(x))
    608                    for x in xml.findall('.//INSTANCENAME')]
    609
    610              return [tupleparse.parse_instancename(x) for x in tt]
    611
    612          else:
    613
    614              tt = [tupletree.xml_to_tupletree(tostring(x))
    615                    for x in xml.findall('.//OBJECTPATH')]
    616
    617              return [tupleparse.parse_objectpath(x)[2] for x in tt]
    618
    619 -class References(WBEMClientFactory):
    620      """Factory to produce References WBEM clients."""
    621
    622 -    def __init__(self, creds, obj, namespace='root/cimv2', **kwargs):
    623
    624          if isinstance(obj, CIMInstanceName):
    625              kwargs['ObjectName'] = obj
    626          else:
    627              kwargs['ObjectName'] = CIMClassName(obj)
    628
    629          payload = self.imethodcallPayload(
    630              'References',
    631              namespace,
    632              **kwargs)
    633
    634          WBEMClientFactory.__init__(
    635              self,
    636              creds,
    637              operation='MethodCall',
    638              method='References',
    639              object=namespace,
    640              payload=payload)
    641
    642 -class ReferenceNames(WBEMClientFactory):
    643      """Factory to produce ReferenceNames WBEM clients."""
    644
    645      # TODO: Implement __repr__ method
    646
    647 -    def __init__(self, creds, obj, namespace='root/cimv2', **kwargs):
    648
    649          if isinstance(obj, CIMInstanceName):
    650              kwargs['ObjectName'] = obj
    651          else:
    652              kwargs['ObjectName'] = CIMClassName(obj)
    653
    654          payload = self.imethodcallPayload(
    655              'ReferenceNames',
    656              namespace,
    657              **kwargs)
    658
    659          WBEMClientFactory.__init__(
    660              self,
    661              creds,
    662              operation='MethodCall',
    663              method='ReferenceNames',
    664              object=namespace,
    665              payload=payload)
    666
    667 -    def parseResponse(self, xml):
    668
    669          if len(xml.findall('.//INSTANCENAME')) > 0:
    670
    671              tt = [tupletree.xml_to_tupletree(tostring(x))
    672                    for x in xml.findall('.//INSTANCENAME')]
    673
    674              return [tupleparse.parse_instancename(x) for x in tt]
    675
    676          else:
    677
    678              tt = [tupletree.xml_to_tupletree(tostring(x))
    679                    for x in xml.findall('.//OBJECTPATH')]
    680
    681              return [tupleparse.parse_objectpath(x)[2] for x in tt]
    682
    683 -class InvokeMethod(WBEMClientFactory):
    684      """Factory to produce InvokeMethod WBEM clients."""
    685
    686 -    def __init__(self, creds, MethodName, ObjectName, namespace='root/cimv2',
    687                   **kwargs):
    688
    689          # Convert string to CIMClassName
    690
    691          obj = ObjectName
    692
    693          if isinstance(obj, StringTypes):
    694              obj = CIMClassName(obj, namespace=namespace)
    695
    696          if isinstance(obj, CIMInstanceName) and obj.namespace is None:
    697              obj = ObjectName.copy()
    698              obj.namespace = namespace
    699
    700          # Make the method call
    701
    702          payload = self.methodcallPayload(
    703              MethodName,
    704              obj,
    705              namespace,
    706              **kwargs)
    707
    708          WBEMClientFactory.__init__(
    709              self,
    710              creds,
    711              operation='MethodCall',
    712              method=MethodName,
    713              object=obj,
    714              payload=payload)
    715
    716 -    def parseResponse(self, xml):
    717
    718          # Return value of method
    719
    720          result_xml = tupletree.xml_to_tupletree(
    721              tostring(xml.find('.//RETURNVALUE')))
    722
    723          result_tt = tupleparse.parse_any(result_xml)
    724
    725          result = cim_obj.tocimobj(result_tt[1]['PARAMTYPE'],
    726                                    result_tt[2])
    727
    728          # Output parameters
    729
    730          params_xml = [tupletree.xml_to_tupletree(tostring(x))
    731                        for x in xml.findall('.//PARAMVALUE')]
    732
    733          params_tt = [tupleparse.parse_any(x) for x in params_xml]
    734
    735          params = {}
    736
    737          for p in params_tt:
    738              if p[1] == 'reference':
    739                  params[p[0]] = p[2]
    740              else:
    741                  params[p[0]] = cim_obj.tocimobj(p[1], p[2])
    742
    743          return (result, params)
    744
    745 -class ExecQuery(WBEMClientFactory):
    746
    747 -    def __init__(self, creds, QueryLanguage, Query, namespace='root/cimv2'):
    748
    749          self.QueryLanguage = QueryLanguage
    750          self.Query = Query
    751          self.namespace = namespace
    752
    753          payload = self.imethodcallPayload(
    754              'ExecQuery',
    755              namespace,
    756              QueryLanguage = QueryLanguage,
    757              Query = Query)
    758
    759          WBEMClientFactory.__init__(
    760              self,
    761              creds,
    762              operation='MethodCall',
    763              method='ExecQuery',
    764              object=namespace,
    765              payload=payload)
    766
    767 -    def __repr__(self):
    768          return '<%s(/%s:%s) at 0x%x>' % \
    769                 (self.__class__, self.namespace, self.Query, id(self))
    770
    771 -    def parseResponse(self, xml):
    772          tt = [pywbem.tupletree.xml_to_tupletree(tostring(x))
    773                for x in xml.findall('.//INSTANCE')]
    774          return [pywbem.tupleparse.parse_instance(x) for x in tt]
    775