Package pywbem :: Module cim_operations

[frames] | no frames]

# Source Code for Module pywbem.cim_operations

       1  #
       2  # (C) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
       3  # (C) Copyright 2006-2007 Novell, Inc.
       4  #
       5  # This library is free software; you can redistribute it and/or
       6  # modify it under the terms of the GNU Lesser General Public
       7  # License as published by the Free Software Foundation; either
       8  # version 2.1 of the License, or (at your option) any later version.
       9  #
      10  # This program is distributed in the hope that it will be useful, but
      11  # WITHOUT ANY WARRANTY; without even the implied warranty of
      12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13  # Lesser General Public License for more details.
      14  #
      15  # You should have received a copy of the GNU Lesser General Public
      16  # License along with this program; if not, write to the Free Software
      17  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
      18  #
      19  # Author: Tim Potter <tpot@hp.com>
      20  # Author: Martin Pool <mbp@hp.com>
      21  # Author: Bart Whiteley <bwhiteley@suse.de>
      22  #
      23
      24  """CIM operations over HTTP.
      25
      26  The `WBEMConnection` class in this module opens a connection to a remote
      27  WBEM server. Across this connection you can run various CIM operations.
      28  Each method of this class corresponds fairly directly to a single CIM
      29  operation.
      30  """
      31
      32  # This module is meant to be safe for 'import *'.
      33
      34  import string
      35  import re
      36  from types import StringTypes
      37  from xml.dom import minidom
      38  from datetime import datetime, timedelta
      39  from xml.parsers.expat import ExpatError
      40
      41  from pywbem import cim_obj, cim_xml, cim_http, cim_types, tupletree, tupleparse
      42  from pywbem.cim_obj import CIMInstance, CIMInstanceName, CIMClass, \
      43                             CIMClassName, NocaseDict
      44  from pywbem.tupleparse import ParseError
      45
      46  __all__ = ['DEFAULT_NAMESPACE', 'check_utf8_xml_chars',
      47             'CIMError', 'WBEMConnection', 'is_subclass',
      48             'PegasusUDSConnection', 'SFCBUDSConnection',
      49             'OpenWBEMUDSConnection']
      50
      51  DEFAULT_NAMESPACE = 'root/cimv2'
      52
      53  if len(u'\U00010122') == 2:
      54      # This is a "narrow" Unicode build of Python (the normal case).
      55      _ILLEGAL_XML_CHARS_RE = re.compile(
      56          u'([\u0000-\u0008\u000B-\u000C\u000E-\u001F\uFFFE\uFFFF])')
      57  else:
      58      # This is a "wide" Unicode build of Python.
      59      _ILLEGAL_XML_CHARS_RE = re.compile(
      60          u'([\u0000-\u0008\u000B-\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE\uFFFF])')
      61
      62  _ILL_FORMED_UTF8_RE = re.compile(
      63      '(\xED[\xA0-\xBF][\x80-\xBF])')    # U+D800...U+DFFF
      64
      65
      66 -def _check_classname(val):
      67      """
      68      Validate a classname.
      69
      70      At this point, only the type is validated to be a string.
      71      """
      72      if not isinstance(val, StringTypes):
      73          raise ValueError("string expected for classname, not %s" % `val`)
      74
      75 -def check_utf8_xml_chars(utf8_xml, meaning):
      76      """
      77      Examine a UTF-8 encoded XML string and raise a `pywbem.ParseError`
      78      exception if the response contains Bytes that are invalid UTF-8
      79      sequences (incorrectly encoded or ill-formed) or that are invalid XML
      80      characters.
      81
      82      This function works in both "wide" and "narrow" Unicode builds of Python
      83      and supports the full range of Unicode characters from U+0000 to U+10FFFF.
      84
      85      This function is just a workaround for the bad error handling of Python's
      86      `xml.dom.minidom` package. It replaces the not very informative
      87      `ExpatError` "not well-formed (invalid token): line: x, column: y" with a
      88      `pywbem.ParseError` providing more useful information.
      89
      90      :Parameters:
      91
      92        utf8_xml : string
      93          The UTF-8 encoded XML string to be examined.
      94
      95        meaning : string
      96          Short text with meaning of the XML string, for messages in exceptions.
      97
      98      :Exceptions:
      99
     100        `TypeError`, if invoked with incorrect Python object type for `utf8_xml`.
     101
     102        `pywbem.ParseError`, if `utf8_xml` contains Bytes that are invalid UTF-8
     103        sequences (incorrectly encoded or ill-formed) or invalid XML characters.
     104
     105      Notes on Unicode support in Python:
     106
     107      (1) For internally representing Unicode characters in the unicode type, a
     108          "wide" Unicode build of Python uses UTF-32, while a "narrow" Unicode
     109          build uses UTF-16. The difference is visible to Python programs for
     110          Unicode characters assigned to code points above U+FFFF: The "narrow"
     111          build uses 2 characters (a surrogate pair) for them, while the "wide"
     112          build uses just 1 character. This affects all position- and
     113          length-oriented functions, such as `len()` or string slicing.
     114
     115      (2) In a "wide" Unicode build of Python, the Unicode characters assigned to
     116          code points U+10000 to U+10FFFF are represented directly (using code
     117          points U+10000 to U+10FFFF) and the surrogate code points
     118          U+D800...U+DFFF are never used; in a "narrow" Unicode build of Python,
     119          the Unicode characters assigned to code points U+10000 to U+10FFFF are
     120          represented using pairs of the surrogate code points U+D800...U+DFFF.
     121
     122      Notes on the Unicode code points U+D800...U+DFFF ("surrogate code points"):
     123
     124      (1) These code points have no corresponding Unicode characters assigned,
     125          because they are reserved for surrogates in the UTF-16 encoding.
     126
     127      (2) The UTF-8 encoding can technically represent the surrogate code points.
     128          ISO/IEC 10646 defines that a UTF-8 sequence containing the surrogate
     129          code points is ill-formed, but it is technically possible that such a
     130          sequence is in a UTF-8 encoded XML string.
     131
     132      (3) The Python escapes ``\\u`` and ``\\U`` used in literal strings can
     133          represent the surrogate code points (as well as all other code points,
     134          regardless of whether they are assigned to Unicode characters).
     135
     136      (4) The Python `str.encode()` and `str.decode()` functions successfully
     137          translate the surrogate code points back and forth for encoding UTF-8.
     138
     139          For example, ``'\\xed\\xb0\\x80'.decode("utf-8") = u'\\udc00'``.
     140
     141      (5) Because Python supports the encoding and decoding of UTF-8 sequences
     142          also for the surrogate code points, the "narrow" Unicode build of
     143          Python can be (mis-)used to transport each surrogate unit separately
     144          encoded in (ill-formed) UTF-8.
     145
     146          For example, code point U+10122 can be (illegally) created from a
     147          sequence of code points U+D800,U+DD22 represented in UTF-8:
     148
     149            ``'\\xED\\xA0\\x80\\xED\\xB4\\xA2'.decode("utf-8") = u'\\U00010122'``
     150
     151          while the correct UTF-8 sequence for this code point is:
     152
     153            ``u'\\U00010122'.encode("utf-8") = '\\xf0\\x90\\x84\\xa2'``
     154
     155      Notes on XML characters:
     156
     157      (1) The legal XML characters are defined in W3C XML 1.0 (Fith Edition):
     158
     159          ::
     160
     161            Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
     162                     [#x10000-#x10FFFF]
     163
     164          These are the code points of Unicode characters using a non-surrogate
     165          representation.
     166      """
     167
     168      context_before = 16    # number of chars to print before any bad chars
     169      context_after  = 16    # number of chars to print after any bad chars
     170
     171      if not isinstance(utf8_xml, str):
     172          raise TypeError("utf8_xml argument does not have str type, but %s" % \
     173                          type(utf8_xml))
     174
     175      # Check for ill-formed UTF-8 sequences. This needs to be done
     176      # before the str type gets decoded to unicode, because afterwards
     177      # surrogates produced from ill-formed UTF-8 cannot be distinguished from
     178      # legally produced surrogates (for code points above U+FFFF).
     179      ic_list = list()
     180      for m in _ILL_FORMED_UTF8_RE.finditer(utf8_xml):
     181          ic_pos = m.start(1)
     182          ic_seq = m.group(1)
     183          ic_list.append((ic_pos,ic_seq))
     184      if len(ic_list) > 0:
     185          exc_txt = "Ill-formed (surrogate) UTF-8 Byte sequences found in %s:" %\
     186                    meaning
     187          for (ic_pos,ic_seq) in ic_list:
     188              exc_txt += "\n  At offset %d:" % ic_pos
     189              for c in ic_seq:
     190                  exc_txt += " 0x%02X" % ord(c)
     191              cpos1 = max(ic_pos-context_before,0)
     192              cpos2 = min(ic_pos+context_after,len(utf8_xml))
     193              exc_txt += ", CIM-XML snippet: %r" % utf8_xml[cpos1:cpos2]
     194          raise ParseError(exc_txt)
     195
     196      # Check for incorrectly encoded UTF-8 sequences.
     197      # @ibm.13@ Simplified logic (removed loop).
     198      try:
     199          utf8_xml_u = utf8_xml.decode("utf-8")
     200      except UnicodeDecodeError as exc:
     201          # Only raised for incorrectly encoded UTF-8 sequences; technically
     202          # correct sequences that are ill-formed (e.g. representing surrogates)
     203          # do not cause this exception to be raised.
     204          # If more than one incorrectly encoded sequence is present, only
     205          # information about the first one is returned in the exception object.
     206          # Also, the stated reason (in _msg) is not always correct.
     207          _codec, _str, _p1, _p2, _msg = exc.args
     208          exc_txt = "Incorrectly encoded UTF-8 Byte sequences found in %s" %\
     209                    meaning
     210          exc_txt += "\n  At offset %d:" % _p1
     211          for c in utf8_xml[_p1:_p2+1]:
     212              exc_txt += " 0x%02X" % ord(c)
     213          cpos1 = max(_p1-context_before,0)
     214          cpos2 = min(_p2+context_after,len(utf8_xml))
     215          exc_txt += ", CIM-XML snippet: %r" % utf8_xml[cpos1:cpos2]
     216          raise ParseError(exc_txt)
     217
     218      # Now we know the Unicode characters are valid.
     219      # Check for Unicode characters that cannot legally be represented as XML
     220      # characters.
     221      ic_list = list()
     222      last_ic_pos = -2
     223      for m in _ILLEGAL_XML_CHARS_RE.finditer(utf8_xml_u):
     224          ic_pos = m.start(1)
     225          ic_char = m.group(1)
     226          if ic_pos > last_ic_pos + 1:
     227              ic_list.append((ic_pos,ic_char))
     228          last_ic_pos = ic_pos
     229      if len(ic_list) > 0:
     230          exc_txt = "Invalid XML characters found in %s:" % meaning
     231          for (ic_pos,ic_char) in ic_list:
     232              cpos1 = max(ic_pos-context_before,0)
     233              cpos2 = min(ic_pos+context_after,len(utf8_xml_u))
     234              exc_txt += "\n  At offset %d: U+%04X, CIM-XML snippet: %r" % \
     235                  (ic_pos, ord(ic_char), utf8_xml_u[cpos1:cpos2])
     236          raise ParseError(exc_txt)
     237
     238      return utf8_xml
     239
     240
     241 -class CIMError(cim_http.Error):
     242      """
     243      Exception indicating that the WBEM server has returned an error response
     244      with a CIM status code.
     245
     246      The exception value is a tuple of
     247      ``(error_code, description, exception_obj)``, where:
     248
     249        * ``error_code``: the numeric CIM status code. See `cim_constants` for
     250          constants defining CIM status code values.
     251
     252        * ``description``: a string (`unicode` or UTF-8 encoded `str`)
     253          that is the CIM status description text returned by the server,
     254          representing a human readable message describing the error.
     255
     256        * ``exception_obj``: the underlying exception object that caused this
     257          exception to be raised, or ``None``. Will always be ``None``.
     258      """
     259      pass
     260
     261 -class WBEMConnection(object):
     262      """
     263      A client's connection to a WBEM server. This is the main class of the
     264      PyWBEM client.
     265
     266      The connection object knows a default CIM namespace, which is used when no
     267      namespace is specified on subsequent CIM operations (that support
     268      specifying namespaces). Thus, the connection object can be used as a
     269      connection to multiple CIM namespaces on a WBEM server (when the namespace
     270      is specified on subsequent operations), or as a connection to only the
     271      default namespace (this allows omitting the namespace on subsequent
     272      operations).
     273
     274      As usual in HTTP, there is no persistent TCP connection; the connectedness
     275      provided by this class is  only conceptual. That is, the creation of the
     276      connection object does not cause any interaction with the WBEM server, and
     277      each subsequent CIM operation performs an independent, state-less
     278      HTTP/HTTPS request.
     279
     280      After creating a `WBEMConnection` object, various methods may be called on
     281      the object, which cause CIM operations to be invoked on the WBEM server.
     282      All these methods take regular Python objects or objects defined in
     283      `cim_types` as arguments, and return the same.
     284      The caller does not need to know about the CIM-XML encoding that is used
     285      underneath (It should be possible to use a different transport below this
     286      layer without disturbing any callers).
     287
     288      The connection remembers the XML of the last request and last reply if
     289      debugging is turned on via the `debug` instance variable of the connection
     290      object.
     291      This may be useful in debugging: If a problem occurs, you can examine the
     292      `last_request` and `last_reply` instance variables of the connection
     293      object. These are the prettified XML of request and response, respectively.
     294      The real request and response that are sent and received are available in
     295      the `last_raw_request` and `last_raw_reply` instance variables of the
     296      connection object.
     297
     298      The methods of this class may raise the following exceptions:
     299
     300      * Exceptions indicating processing errors:
     301
     302        - `pywbem.ConnectionError` - A connection with the WBEM server could not
     303          be established or broke down.
     304
     305        - `pywbem.AuthError` - Authentication failed with the WBEM server.
     306
     307        - `pywbem.ParseError` - The response from the WBEM server cannot be
     308          parsed (for example, invalid characters or UTF-8 sequences, ill-formed
     309          XML, or invalid CIM-XML).
     310
     311        - `pywbem.CIMError` - The WBEM server returned an error response with a
     312          CIM status code.
     313
     314        - `pywbem.TimeoutError` - The WBEM server did not respond in time and the
     315          client timed out.
     316
     317      * Exceptions indicating programming errors:
     318
     319        - `TypeError`
     320        - `KeyError`
     321        - `ValueError`
     322        - ... possibly others ...
     323
     324        Exceptions indicating programming errors should not happen and should be
     325        reported as bugs, unless caused by the code using this class.
     326
     327      :Ivariables:
     328
     329        ...
     330          All parameters of `__init__` are set as instance variables.
     331
     332        debug : `bool`
     333          A boolean indicating whether logging of the last request and last reply
     334          is enabled.
     335
     336          The initial value of this instance variable is `False`.
     337          Debug logging can be enabled for future operations by setting this
     338          instance variable to `True`.
     339
     340        last_request : `unicode`
     341          CIM-XML data of the last request sent to the WBEM server
     342          on this connection, formatted as prettified XML. Prior to sending the
     343          very first request on this connection object, it is `None`.
     344
     345        last_raw_request : `unicode`
     346          CIM-XML data of the last request sent to the WBEM server
     347          on this connection, formatted as it was sent. Prior to sending the
     348          very first request on this connection object, it is `None`.
     349
     350        last_reply : `unicode`
     351          CIM-XML data of the last response received from the WBEM server
     352          on this connection, formatted as prettified XML. Prior to sending the
     353          very first request on this connection object, while waiting for any
     354          response, it is `None`.
     355
     356        last_raw_reply : `unicode`
     357          CIM-XML data of the last response received from the WBEM server
     358          on this connection, formatted as it was received. Prior to sending the
     359          very first request on this connection object, while waiting for any
     360          response, it is `None`.
     361      """
     362
     363 -    def __init__(self, url, creds=None, default_namespace=DEFAULT_NAMESPACE,
     364                   x509=None, verify_callback=None, ca_certs=None,
     365                   no_verification=False, timeout=None):
     366          """
     367          Initialize the `WBEMConnection` object.
     368
     369          :Parameters:
     370
     371            url : string
     372              URL of the WBEM server (e.g. ``"https://10.11.12.13:6988"``).
     373
     374              TODO: Describe supported formats.
     375
     376            creds
     377              Credentials for authenticating with the WBEM server. Currently,
     378              that is always a tuple of ``(userid, password)``, where:
     379
     380              * ``userid`` is a string that is the userid to be used for
     381                authenticating with the WBEM server.
     382
     383              * ``password`` is a string that is the password for that userid.
     384
     385            default_namespace : string
     386              Optional: Name of the CIM namespace to be used by default (if no
     387              namespace is specified for an operation).
     388
     389              Default: See method definition.
     390
     391            x509 : dictionary
     392              Optional: X.509 certificates for HTTPS to be used instead of the
     393              credentials provided in the `creds` parameter. This parameter is
     394              used only when the `url` parameter specifies a scheme of ``https``.
     395
     396              If `None`, certificates are not used (and credentials are used
     397              instead).
     398
     399              Otherwise, certificates are used instead of the credentials, and
     400              this parameter must be a dictionary containing the following
     401              key/value pairs:
     402
     403              * ``'cert_file'`` : The file path of a file containing an X.509
     404                certificate.
     405
     406              * ``'key_file'`` : The file path of a file containing the private
     407                key belonging to the public key that is part of the X.509
     408                certificate file.
     409
     410              Default: `None`.
     411
     412            verify_callback : function
     413              Optional: Registers a callback function that will be called to
     414              verify the certificate returned by the WBEM server during the SSL
     415              handshake, in addition to the verification alreay performed by
     416              `M2Crypto`.
     417
     418              If `None`, no such callback function will be registered.
     419
     420              The specified function will be called for the returned certificate,
     421              and for each of the certificates in its chain of trust.
     422
     423              See `M2Crypto.SSL.Context.set_verify` for details, as well as
     424              http://blog.san-ss.com.ar/2012/05/validating-ssl-certificate-in-python.html):
     425
     426              The callback function must take five parameters:
     427
     428              * the `M2Crypto.SSL.Connection` object that triggered the
     429                verification.
     430
     431              * an `OpenSSL.crypto.X509` object representing the certificate
     432                to be validated (the returned certificate or one of the
     433                certificates in its chain of trust).
     434
     435              * an integer containing the error number (0 in case no error) of
     436                any validation error detected by `M2Crypto`.
     437                You can find their meaning in the OpenSSL documentation.
     438
     439              * an integer indicating the depth (=position) of the certificate to
     440                be validated (the one in the second parameter) in the chain of
     441                trust of the returned certificate. A value of 0 indicates
     442                that the returned is currently validated; any other value
     443                indicates the distance of the currently validated certificate to
     444                the returned certificate in its chain of trust.
     445
     446              * an integer that indicates whether the validation of the
     447                certificate specified in the second argument passed or did not
     448                pass the validation by `M2Crypto`. A value of 1 indicates a
     449                successful validation and 0 an unsuccessful one.
     450
     451              The callback function must return `True` if the verification
     452              passes and `False` otherwise.
     453
     454              Default: `None`.
     455
     456            ca_certs : string
     457              Optional: Location of CA certificates (trusted certificates) for
     458              verification purposes.
     459
     460              The parameter value is either the directory path of a directory
     461              prepared using the ``c_rehash`` tool included with OpenSSL, or the
     462              file path of a file in PEM format.
     463
     464              If `None`, the default system path will be used.
     465
     466              Default: `None`.
     467
     468            no_verification : `bool`
     469              Optional: Indicates that verification of the certificate returned
     470              by the WBEM server is disabled (both by `M2Crypto` and by the
     471              callback function specified in `verify_callback`).
     472
     473              Disabling the verification is insecure and should be avoided.
     474
     475              If `True`, verification is disabled; otherwise, it is enabled.
     476
     477              Default: `False`.
     478
     479            timeout : number
     480              Timeout in seconds, for requests sent to the server. If the server
     481              did not respond within the timeout duration, the socket for the
     482              connection will be closed, causing a `TimeoutError` to be raised.
     483
     484              A value of ``None`` means there is no timeout.
     485
     486              A value of ``0`` means the timeout is very short, and does not
     487              really make any sense.
     488
     489              Note that not all situations can be handled within this timeout, so
     490              for some issues, operations may take longer before raising an
     491              exception.
     492
     493          :Exceptions:
     494
     495              See the list of exceptions described in `WBEMConnection`.
     496          """
     497
     498          self.url = url
     499          self.creds = creds
     500          self.x509 = x509
     501          self.verify_callback = verify_callback
     502          self.ca_certs = ca_certs
     503          self.no_verification = no_verification
     504          self.default_namespace = default_namespace
     505          self.timeout = timeout
     506
     507          self.debug = False
     508          self.last_raw_request = None
     509          self.last_raw_reply = None
     510          self.last_request = None
     511          self.last_reply = None
     512
     513 -    def __repr__(self):
     514          """
     515          Return a representation of the connection object with the major
     516          instance variables, except for the password in the credentials.
     517
     518          TODO: Change to show all instance variables.
     519          """
     520          if self.creds is None:
     521              user = 'anonymous'
     522          else:
     523              user = 'user=%s' % `self.creds[0]`
     524          return "%s(%s, %s, namespace=%s)" % \
     525              (self.__class__.__name__, `self.url`, user,
     526               `self.default_namespace`)
     527
     528 -    def imethodcall(self, methodname, namespace, **params):
     529          """
     530          Perform an intrinsic method call (= CIM operation).
     531
     532          This is a low-level function that is used by the operation-specific
     533          methods of this class (e.g. `EnumerateInstanceNames`). In general,
     534          clients should call these operation-specific methods instead of this
     535          function.
     536
     537          The parameters are automatically converted to the right CIM-XML
     538          elements.
     539
     540          :Returns:
     541
     542              A tupletree (see `tupletree` module) with an ``IRETURNVALUE``
     543              element at the root.
     544
     545          :Exceptions:
     546
     547              See the list of exceptions described in `WBEMConnection`.
     548          """
     549
     550          # Create HTTP headers
     551
     552          headers = ['CIMOperation: MethodCall',
     553                     'CIMMethod: %s' % methodname,
     554                     cim_http.get_object_header(namespace)]
     555
     556          # Create parameter list
     557
     558          plist = map(lambda x:
     559                      cim_xml.IPARAMVALUE(x[0], cim_obj.tocimxml(x[1])),
     560                      params.items())
     561
     562          # Build XML request
     563
     564          req_xml = cim_xml.CIM(
     565              cim_xml.MESSAGE(
     566                  cim_xml.SIMPLEREQ(
     567                      cim_xml.IMETHODCALL(
     568                          methodname,
     569                          cim_xml.LOCALNAMESPACEPATH(
     570                              [cim_xml.NAMESPACE(ns)
     571                               for ns in string.split(namespace, '/')]),
     572                          plist)),
     573                  '1001', '1.0'),
     574              '2.0', '2.0')
     575
     576          if self.debug:
     577              self.last_raw_request = req_xml.toxml()
     578              self.last_request = req_xml.toprettyxml(indent='  ')
     579              # Reset replies in case we fail before they are set
     580              self.last_raw_reply = None
     581              self.last_reply = None
     582
     583          # Send request and receive response
     584
     585          try:
     586              reply_xml = cim_http.wbem_request(
     587                  self.url, req_xml.toxml(), self.creds, headers,
     588                  x509=self.x509,
     589                  verify_callback=self.verify_callback,
     590                  ca_certs=self.ca_certs,
     591                  no_verification=self.no_verification,
     592                  timeout=self.timeout)
     593          except (cim_http.AuthError, cim_http.ConnectionError,
     594                  cim_http.TimeoutError, cim_http.Error):
     595              raise
     596
     597          # Set the raw response before parsing (which can fail)
     598          if self.debug:
     599              self.last_raw_reply = reply_xml
     600
     601          try:
     602              reply_dom = minidom.parseString(reply_xml)
     603          except ParseError as exc:
     604              msg = str(exc)
     605              parsing_error = True
     606          except ExpatError as exc:
     607              # This is raised e.g. when XML numeric entity references of invalid
     608              # XML characters are used (e.g. '&#0;').
     609              # str(exc) is: "{message}, line {X}, offset {Y}"
     610              parsed_line = str(reply_xml).splitlines()[exc.lineno-1]
     611              msg = "ExpatError %s: %s: %r" % (str(exc.code), str(exc),
     612                                               parsed_line)
     613              parsing_error = True
     614          else:
     615              parsing_error = False
     616
     617          if parsing_error or self.debug:
     618              # Here we just improve the quality of the exception information,
     619              # so we do this only if it already has failed. Because the check
     620              # function we invoke catches more errors than minidom.parseString,
     621              # we call it also when debug is turned on.
     622              try:
     623                  check_utf8_xml_chars(reply_xml, "CIM-XML response")
     624              except ParseError:
     625                  raise
     626              else:
     627                  if parsing_error:
     628                      # We did not catch it in the check function, but
     629                      # minidom.parseString() failed.
     630                      raise ParseError(msg) # data from previous exception
     631
     632          if self.debug:
     633              pretty_reply = reply_dom.toprettyxml(indent='  ')
     634              self.last_reply = re.sub(r'>( *[\r\n]+)+( *)<', r'>\n\2<',
     635                                       pretty_reply) # remove extra empty lines
     636
     637          # Parse response
     638
     639          tt = tupleparse.parse_cim(tupletree.dom_to_tupletree(reply_dom))
     640
     641          if tt[0] != 'CIM':
     642              raise ParseError('Expecting CIM element, got %s' % tt[0])
     643          tt = tt[2]
     644
     645          if tt[0] != 'MESSAGE':
     646              raise ParseError('Expecting MESSAGE element, got %s' % tt[0])
     647          tt = tt[2]
     648
     649          if len(tt) != 1 or tt[0][0] != 'SIMPLERSP':
     650              raise ParseError('Expecting one SIMPLERSP element')
     651          tt = tt[0][2]
     652
     653          if tt[0] != 'IMETHODRESPONSE':
     654              raise ParseError('Expecting IMETHODRESPONSE element, got %s' %\
     655                               tt[0])
     656
     657          if tt[1]['NAME'] != methodname:
     658              raise ParseError('Expecting attribute NAME=%s, got %s' %\
     659                               (methodname, tt[1]['NAME']))
     660          tt = tt[2]
     661
     662          # At this point we either have a IRETURNVALUE, ERROR element
     663          # or None if there was no child nodes of the IMETHODRESPONSE
     664          # element.
     665
     666          if tt is None:
     667              return None
     668
     669          if tt[0] == 'ERROR':
     670              code = int(tt[1]['CODE'])
     671              if tt[1].has_key('DESCRIPTION'):
     672                  raise CIMError(code, tt[1]['DESCRIPTION'])
     673              raise CIMError(code, 'Error code %s' % tt[1]['CODE'])
     674
     675          if tt[0] != 'IRETURNVALUE':
     676              raise ParseError('Expecting IRETURNVALUE element, got %s' % tt[0])
     677
     678          return tt
     679
     680 -    def methodcall(self, methodname, localobject, Params=None, **params):
     681          """
     682          Perform an extrinsic method call (= CIM method invocation).
     683
     684          This is a low-level function that is used by the 'InvokeMethod'
     685          method of this class. In general, clients should use 'InvokeMethod'
     686          instead of this function.
     687
     688          The Python method parameters are automatically converted to the right
     689          CIM-XML elements. See `InvokeMethod` for details.
     690
     691          :Returns:
     692
     693              A tupletree (see `tupletree` module) with a ``RETURNVALUE``
     694              element at the root.
     695
     696          :Exceptions:
     697
     698              See the list of exceptions described in `WBEMConnection`.
     699          """
     700
     701          # METHODCALL only takes a LOCALCLASSPATH or LOCALINSTANCEPATH
     702          if hasattr(localobject, 'host') and localobject.host is not None:
     703              localobject = localobject.copy()
     704              localobject.host = None
     705
     706          # Create HTTP headers
     707
     708          headers = ['CIMOperation: MethodCall',
     709                     'CIMMethod: %s' % methodname,
     710                     cim_http.get_object_header(localobject)]
     711
     712          # Create parameter list
     713
     714          def paramtype(obj):
     715              """Return a string to be used as the CIMTYPE for a parameter."""
     716              if isinstance(obj, cim_types.CIMType):
     717                  return obj.cimtype
     718              elif type(obj) == bool:
     719                  return 'boolean'
     720              elif isinstance(obj, StringTypes):
     721                  return 'string'
     722              elif isinstance(obj, (datetime, timedelta)):
     723                  return 'datetime'
     724              elif isinstance(obj, (CIMClassName, CIMInstanceName)):
     725                  return 'reference'
     726              elif isinstance(obj, (CIMClass, CIMInstance)):
     727                  return 'string'
     728              elif isinstance(obj, list):
     729                  if obj:
     730                      return paramtype(obj[0])
     731                  else:
     732                      return None
     733              raise TypeError('Unsupported parameter type "%s"' % type(obj))
     734
     735          def paramvalue(obj):
     736              """Return a cim_xml node to be used as the value for a
     737              parameter."""
     738              if isinstance(obj, (datetime, timedelta)):
     739                  obj = cim_types.CIMDateTime(obj)
     740              if isinstance(obj, (cim_types.CIMType, bool, StringTypes)):
     741                  return cim_xml.VALUE(cim_types.atomic_to_cim_xml(obj))
     742              if isinstance(obj, (CIMClassName, CIMInstanceName)):
     743                  return cim_xml.VALUE_REFERENCE(obj.tocimxml())
     744              if isinstance(obj, (CIMClass, CIMInstance)):
     745                  return cim_xml.VALUE(obj.tocimxml().toxml())
     746              if isinstance(obj, list):
     747                  if obj and isinstance(obj[0], (CIMClassName, CIMInstanceName)):
     748                      return cim_xml.VALUE_REFARRAY([paramvalue(x) for x in obj])
     749                  return cim_xml.VALUE_ARRAY([paramvalue(x) for x in obj])
     750              raise TypeError('Unsupported parameter type "%s"' % type(obj))
     751
     752          def is_embedded(obj):
     753              """Determine if an object requires an EmbeddedObject attribute"""
     754              if isinstance(obj, list) and obj:
     755                  return is_embedded(obj[0])
     756              elif isinstance(obj, CIMClass):
     757                  return 'object'
     758              elif isinstance(obj, CIMInstance):
     759                  return 'instance'
     760              return None
     761
     762          if Params is None:
     763              Params = []
     764          plist = [cim_xml.PARAMVALUE(x[0],
     765                                      paramvalue(x[1]),
     766                                      paramtype(x[1]),
     767                                      embedded_object=is_embedded(x[1]))
     768                   for x in Params]
     769          plist += [cim_xml.PARAMVALUE(x[0],
     770                                      paramvalue(x[1]),
     771                                      paramtype(x[1]),
     772                                      embedded_object=is_embedded(x[1]))
     773                   for x in params.items()]
     774
     775          # Build XML request
     776
     777          req_xml = cim_xml.CIM(
     778              cim_xml.MESSAGE(
     779                  cim_xml.SIMPLEREQ(
     780                      cim_xml.METHODCALL(
     781                          methodname,
     782                          localobject.tocimxml(),
     783                          plist)),
     784                  '1001', '1.0'),
     785              '2.0', '2.0')
     786
     787          if self.debug:
     788              self.last_raw_request = req_xml.toxml()
     789              self.last_request = req_xml.toprettyxml(indent='  ')
     790              # Reset replies in case we fail before they are set
     791              self.last_raw_reply = None
     792              self.last_reply = None
     793
     794          # Send request and receive response
     795
     796          try:
     797              reply_xml = cim_http.wbem_request(
     798                  self.url, req_xml.toxml(), self.creds, headers,
     799                  x509=self.x509,
     800                  verify_callback=self.verify_callback,
     801                  ca_certs=self.ca_certs,
     802                  no_verification=self.no_verification,
     803                  timeout=self.timeout)
     804          except (cim_http.AuthError, cim_http.ConnectionError,
     805                  cim_http.TimeoutError, cim_http.Error):
     806              raise
     807
     808          # Set the raw response before parsing and checking (which can fail)
     809          if self.debug:
     810              self.last_raw_reply = reply_xml
     811
     812          try:
     813              reply_dom = minidom.parseString(reply_xml)
     814          except ParseError as exc:
     815              msg = str(exc)
     816              parsing_error = True
     817          except ExpatError as exc:
     818              # This is raised e.g. when XML numeric entity references of invalid
     819              # XML characters are used (e.g. '&#0;').
     820              # str(exc) is: "{message}, line {X}, offset {Y}"
     821              parsed_line = str(reply_xml).splitlines()[exc.lineno-1]
     822              msg = "ExpatError %s: %s: %r" % (str(exc.code), str(exc),
     823                                               parsed_line)
     824              parsing_error = True
     825          else:
     826              parsing_error = False
     827
     828          if parsing_error or self.debug:
     829              # Here we just improve the quality of the exception information,
     830              # so we do this only if it already has failed. Because the check
     831              # function we invoke catches more errors than minidom.parseString,
     832              # we call it also when debug is turned on.
     833              try:
     834                  check_utf8_xml_chars(reply_xml, "CIM-XML response")
     835              except ParseError:
     836                  raise
     837              else:
     838                  if parsing_error:
     839                      # We did not catch it in the check function, but
     840                      # minidom.parseString() failed.
     841                      raise ParseError(msg) # data from previous exception
     842
     843          if self.debug:
     844              pretty_reply = reply_dom.toprettyxml(indent='  ')
     845              self.last_reply = re.sub(r'>( *[\r\n]+)+( *)<', r'>\n\2<',
     846                                       pretty_reply) # remove extra empty lines
     847
     848          # Parse response
     849
     850          tt = tupleparse.parse_cim(tupletree.dom_to_tupletree(reply_dom))
     851
     852          if tt[0] != 'CIM':
     853              raise ParseError('Expecting CIM element, got %s' % tt[0])
     854          tt = tt[2]
     855
     856          if tt[0] != 'MESSAGE':
     857              raise ParseError('Expecting MESSAGE element, got %s' % tt[0])
     858          tt = tt[2]
     859
     860          if len(tt) != 1 or tt[0][0] != 'SIMPLERSP':
     861              raise ParseError('Expecting one SIMPLERSP element')
     862          tt = tt[0][2]
     863
     864          if tt[0] != 'METHODRESPONSE':
     865              raise ParseError('Expecting METHODRESPONSE element, got %s' %\
     866                               tt[0])
     867
     868          if tt[1]['NAME'] != methodname:
     869              raise ParseError('Expecting attribute NAME=%s, got %s' %\
     870                               (methodname, tt[1]['NAME']))
     871          tt = tt[2]
     872
     873          # At this point we have an optional RETURNVALUE and zero or
     874          # more PARAMVALUE elements representing output parameters.
     875
     876          if len(tt) > 0 and tt[0][0] == 'ERROR':
     877              code = int(tt[0][1]['CODE'])
     878              if tt[0][1].has_key('DESCRIPTION'):
     879                  raise CIMError(code, tt[0][1]['DESCRIPTION'])
     880              raise CIMError(code, 'Error code %s' % tt[0][1]['CODE'])
     881
     882          return tt
     883
     884      #
     885      # Instance provider API
     886      #
     887
     888 -    def EnumerateInstanceNames(self, ClassName, namespace=None, **params):
     889          # pylint: disable=invalid-name
     890          """
     891          Enumerate the instance paths of instances of a class (including
     892          instances of its subclasses).
     893
     894          This method performs the EnumerateInstanceNames CIM-XML operation.
     895          If the operation succeeds, this method returns.
     896          Otherwise, this method raises an exception.
     897
     898          :Parameters:
     899
     900            ClassName : string
     901              Name of the class to be enumerated.
     902
     903            namespace : string
     904              Optional: Name of the CIM namespace to be used. The value `None`
     905              causes the default namespace of the connection object to be used.
     906
     907              Default: `None`.
     908
     909          :Returns:
     910
     911              A list of `CIMInstanceName` objects that are the enumerated
     912              instance paths.
     913
     914          :Exceptions:
     915
     916              See the list of exceptions described in `WBEMConnection`.
     917          """
     918
     919          if namespace is None:
     920              namespace = self.default_namespace
     921
     922          result = self.imethodcall(
     923              'EnumerateInstanceNames',
     924              namespace,
     925              ClassName=CIMClassName(ClassName),
     926              **params)
     927
     928          names = []
     929
     930          if result is not None:
     931              names = result[2]
     932
     933          [setattr(n, 'namespace', namespace) for n in names]
     934
     935          return names
     936
     937 -    def EnumerateInstances(self, ClassName, namespace=None, **params):
     938          # pylint: disable=invalid-name
     939          """
     940          Enumerate the instances of a class (including instances of its
     941          subclasses).
     942
     943          This method performs the EnumerateInstances CIM-XML operation.
     944          If the operation succeeds, this method returns.
     945          Otherwise, this method raises an exception.
     946
     947          :Parameters:
     948
     949            ClassName : string
     950              Name of the class to be enumerated.
     951
     952            namespace : string
     953              Optional: Name of the CIM namespace to be used. The value `None`
     954              causes the default namespace of the connection object to be used.
     955
     956              Default: `None`.
     957
     958            LocalOnly : `bool`
     959              Optional: Controls the exclusion of inherited properties from the
     960              returned instances, as follows:
     961
     962              * If `False`, inherited properties are not excluded.
     963              * If `True`, the behavior is WBEM server specific.
     964
     965              Default: `True`.
     966
     967              This parameter has been deprecated in CIM-XML and should be set to
     968              `False` by the caller.
     969
     970            DeepInheritance : `bool`
     971              Optional: Indicates that properties added by subclasses of the
     972              specified class are to be included in the returned instances.
     973              Note, the semantics of this parameter differs between instance and
     974              class level operations.
     975
     976              Default: `True`.
     977
     978            IncludeQualifiers : `bool`
     979              Optional: Indicates that qualifiers are to be included in the
     980              returned instance.
     981
     982              Default: `False`.
     983
     984              This parameter has been deprecated in CIM-XML. Clients cannot rely
     985              on it being implemented by WBEM servers.
     986
     987            IncludeClassOrigin : `bool`
     988              Optional: Indicates that class origin information is to be included
     989              on each property in the returned instances.
     990
     991              Default: `False`.
     992
     993            PropertyList : iterable of string
     994              Optional: An iterable specifying the names of the properties to be
     995              included in the returned instances. An empty iterable indicates to
     996              include no properties. A value of `None` for this parameter
     997              indicates to include all properties.
     998
     999              Default: `None`.
    1000
    1001          :Returns:
    1002
    1003              A list of `CIMInstance` objects that are representations of
    1004              the enumerated instances.
    1005
    1006          :Exceptions:
    1007
    1008              See the list of exceptions described in `WBEMConnection`.
    1009          """
    1010
    1011          if namespace is None:
    1012              namespace = self.default_namespace
    1013
    1014          result = self.imethodcall(
    1015              'EnumerateInstances',
    1016              namespace,
    1017              ClassName=CIMClassName(ClassName),
    1018              **params)
    1019
    1020          instances = []
    1021
    1022          if result is not None:
    1023              instances = result[2]
    1024
    1025          [setattr(i.path, 'namespace', namespace) for i in instances]
    1026
    1027          return instances
    1028
    1029 -    def GetInstance(self, InstanceName, **params):
    1030          # pylint: disable=invalid-name
    1031          """
    1032          Retrieve an instance.
    1033
    1034          This method performs the GetInstance CIM-XML operation.
    1035          If the operation succeeds, this method returns.
    1036          Otherwise, this method raises an exception.
    1037
    1038          :Parameters:
    1039
    1040            InstanceName : `CIMInstanceName`
    1041              Instance path of the instance to be retrieved.
    1042
    1043            LocalOnly : `bool`
    1044              Optional: Controls the exclusion of inherited properties from the
    1045              returned instance, as follows:
    1046
    1047              * If `False`, inherited properties are not excluded.
    1048              * If `True`, the behavior is WBEM server specific.
    1049
    1050              Default: `True`.
    1051
    1052              This parameter has been deprecated in CIM-XML and should be set to
    1053              `False` by the caller.
    1054
    1055            IncludeQualifiers : `bool`
    1056              Optional: Indicates that qualifiers are to be included in the
    1057              returned instance.
    1058
    1059              Default: `False`.
    1060
    1061              This parameter has been deprecated in CIM-XML. Clients cannot rely
    1062              on it being implemented by WBEM servers.
    1063
    1064            IncludeClassOrigin : `bool`
    1065              Optional: Indicates that class origin information is to be included
    1066              on each property in the returned instance.
    1067
    1068              Default: `False`.
    1069
    1070            PropertyList : iterable of string
    1071              Optional: An iterable specifying the names of the properties to be
    1072              included in the returned instances. An empty iterable indicates to
    1073              include no properties. A value of `None` for this parameter
    1074              indicates to include all properties.
    1075
    1076              Default: `None`.
    1077
    1078          :Returns:
    1079
    1080              A `CIMInstance` object that is a representation of the
    1081              retrieved instance.
    1082
    1083          :Exceptions:
    1084
    1085              See the list of exceptions described in `WBEMConnection`.
    1086          """
    1087
    1088          # Strip off host and namespace to make this a "local" object
    1089
    1090          iname = InstanceName.copy()
    1091          iname.host = None
    1092          iname.namespace = None
    1093
    1094          if InstanceName.namespace is None:
    1095              namespace = self.default_namespace
    1096          else:
    1097              namespace = InstanceName.namespace
    1098
    1099          result = self.imethodcall(
    1100              'GetInstance',
    1101              namespace,
    1102              InstanceName=iname,
    1103              **params)
    1104
    1105          instance = result[2][0]
    1106          instance.path = InstanceName
    1107          instance.path.namespace = namespace
    1108
    1109          return instance
    1110
    1111 -    def DeleteInstance(self, InstanceName, **params):
    1112          # pylint: disable=invalid-name
    1113          """
    1114          Delete an instance.
    1115
    1116          This method performs the DeleteInstance CIM-XML operation.
    1117          If the operation succeeds, this method returns.
    1118          Otherwise, this method raises an exception.
    1119
    1120          :Parameters:
    1121
    1122            InstanceName : `CIMInstanceName`
    1123              Instance path of the instance to be deleted.
    1124
    1125          :Exceptions:
    1126
    1127              See the list of exceptions described in `WBEMConnection`.
    1128          """
    1129
    1130          # Strip off host and namespace to make this a "local" object
    1131
    1132          iname = InstanceName.copy()
    1133          iname.host = None
    1134          iname.namespace = None
    1135
    1136          if InstanceName.namespace is None:
    1137              namespace = self.default_namespace
    1138          else:
    1139              namespace = InstanceName.namespace
    1140
    1141          self.imethodcall(
    1142              'DeleteInstance',
    1143              namespace,
    1144              InstanceName=iname,
    1145              **params)
    1146
    1147 -    def CreateInstance(self, NewInstance, **params):
    1148          # pylint: disable=invalid-name
    1149          """
    1150          Create an instance.
    1151
    1152          This method performs the CreateInstance CIM-XML operation.
    1153          If the operation succeeds, this method returns.
    1154          Otherwise, this method raises an exception.
    1155
    1156          :Parameters:
    1157
    1158            NewInstance : `CIMInstance`
    1159              A representation of the instance to be created.
    1160
    1161              The `namespace` and `classname` instance variables of this object
    1162              specify CIM namespace and creation class for the new instance,
    1163              respectively.
    1164              An instance path specified using the `path` instance variable of
    1165              this object will be ignored.
    1166
    1167              The `properties` instance variable of this object specifies initial
    1168              property values for the new instance.
    1169
    1170              Instance-level qualifiers have been deprecated in CIM, so any
    1171              qualifier values specified using the `qualifiers` instance variable
    1172              of this object will be ignored.
    1173
    1174          :Returns:
    1175
    1176              `CIMInstanceName` object that is the instance path of the new
    1177              instance.
    1178
    1179          :Exceptions:
    1180
    1181              See the list of exceptions described in `WBEMConnection`.
    1182          """
    1183
    1184          # Take namespace path from object parameter
    1185
    1186          if NewInstance.path is not None and \
    1187             NewInstance.path.namespace is not None:
    1188              namespace = NewInstance.path.namespace
    1189          else:
    1190              namespace = self.default_namespace
    1191
    1192          # Strip off path to avoid producing a VALUE.NAMEDINSTANCE
    1193          # element instead of an INSTANCE element.
    1194
    1195          instance = NewInstance.copy()
    1196          instance.path = None
    1197
    1198          result = self.imethodcall(
    1199              'CreateInstance',
    1200              namespace,
    1201              NewInstance=instance,
    1202              **params)
    1203
    1204          name = result[2][0]
    1205          name.namespace = namespace
    1206
    1207          return name
    1208
    1209 -    def ModifyInstance(self, ModifiedInstance, **params):
    1210          # pylint: disable=invalid-name
    1211          """
    1212          Modify the property values of an instance.
    1213
    1214          This method performs the ModifyInstance CIM-XML operation.
    1215          If the operation succeeds, this method returns.
    1216          Otherwise, this method raises an exception.
    1217
    1218          :Parameters:
    1219
    1220            ModifiedInstance : `CIMInstance`
    1221              A representation of the modified instance. This object needs to
    1222              contain any new property values and the instance path of the
    1223              instance to be modified. Missing properties (relative to the class
    1224              declaration) and properties provided with a value of `None` will be
    1225              set to NULL. Typically, this object has been retrieved by other
    1226              operations, such as GetInstance.
    1227
    1228            IncludeQualifiers : `bool`
    1229              Optional: Indicates that qualifiers are to be modified as specified
    1230              in the `ModifiedInstance` parameter.
    1231
    1232              Default: `True`.
    1233
    1234              This parameter has been deprecated in CIM-XML. Clients cannot rely
    1235              on it being implemented by WBEM servers.
    1236
    1237            PropertyList : iterable of string
    1238              Optional: An iterable specifying the names of the properties to be
    1239              modified. An empty iterable indicates to modify no properties. A
    1240              value of `None` for this parameter indicates to modify all
    1241              properties.
    1242
    1243              Default: `None`.
    1244
    1245          :Exceptions:
    1246
    1247              See the list of exceptions described in `WBEMConnection`.
    1248          """
    1249
    1250          # Must pass a named CIMInstance here (i.e path attribute set)
    1251
    1252          if ModifiedInstance.path is None:
    1253              raise ValueError(
    1254                  'ModifiedInstance parameter must have path attribute set')
    1255
    1256          # Take namespace path from object parameter
    1257
    1258          if ModifiedInstance.path.namespace is None:
    1259              namespace = self.default_namespace
    1260          else:
    1261              namespace = ModifiedInstance.path.namespace
    1262
    1263          instance = ModifiedInstance.copy()
    1264          instance.path.namespace = None
    1265
    1266          self.imethodcall(
    1267              'ModifyInstance',
    1268              namespace,
    1269              ModifiedInstance=instance,
    1270              **params)
    1271
    1272 -    def ExecQuery(self, QueryLanguage, Query, namespace=None):
    1273          # pylint: disable=invalid-name
    1274          """
    1275          Execute a query in a namespace.
    1276
    1277          This method performs the ExecQuery CIM-XML operation.
    1278          If the operation succeeds, this method returns.
    1279          Otherwise, this method raises an exception.
    1280
    1281          :Parameters:
    1282
    1283            QueryLanguage : string
    1284              Name of the query language used in the `Query` parameter.
    1285
    1286            Query : string
    1287              Query string in the query language specified in the `QueryLanguage`
    1288              parameter.
    1289
    1290            namespace : string
    1291              Optional: Name of the CIM namespace to be used. The value `None`
    1292              causes the default namespace of the connection object to be used.
    1293
    1294              Default: `None`.
    1295
    1296          :Returns:
    1297
    1298              A list of `CIMInstance` objects that represents the query
    1299              result.
    1300              These instances have their `path` instance variable set to identify
    1301              their creation class and the target namespace of the query, but
    1302              they are not addressable instances.
    1303
    1304          :Exceptions:
    1305
    1306              See the list of exceptions described in `WBEMConnection`.
    1307          """
    1308
    1309          if namespace is None:
    1310              namespace = self.default_namespace
    1311
    1312          result = self.imethodcall(
    1313              'ExecQuery',
    1314              namespace,
    1315              QueryLanguage=QueryLanguage,
    1316              Query=Query)
    1317
    1318          instances = []
    1319
    1320          if result is not None:
    1321              instances = [tt[2] for tt in result[2]]
    1322
    1323          [setattr(i.path, 'namespace', namespace) for i in instances]
    1324
    1325          return instances
    1326
    1327      #
    1328      # Schema management API
    1329      #
    1330
    1331 -    def _map_classname_param(self, params):
    1332          """Convert string ClassName parameter to a CIMClassName."""
    1333
    1334          if params.has_key('ClassName') and \
    1335             isinstance(params['ClassName'], StringTypes):
    1336              params['ClassName'] = CIMClassName(params['ClassName'])
    1337
    1338          return params
    1339
    1340 -    def EnumerateClassNames(self, namespace=None, **params):
    1341          # pylint: disable=invalid-name
    1342          """
    1343          Enumerate the names of subclasses of a class, or of the top-level
    1344          classes in a namespace.
    1345
    1346          This method performs the EnumerateClassNames CIM-XML operation.
    1347          If the operation succeeds, this method returns.
    1348          Otherwise, this method raises an exception.
    1349
    1350          :Parameters:
    1351
    1352            namespace : string
    1353              Optional: Name of the namespace of the class, as a string.
    1354              The value `None` causes the default namespace of the connection to
    1355              be used.
    1356
    1357              Default: `None`
    1358
    1359            ClassName : string
    1360              Optional: Name of the class whose subclasses are to be retrieved.
    1361              The value `None` causes the top-level classes in the namespace to
    1362              be retrieved.
    1363
    1364              Default: `None`
    1365
    1366            DeepInheritance : `bool`
    1367              Optional: Indicates that all (direct and indirect) subclasses of
    1368              the specified class or of the top-level classes are to be included
    1369              in the result.
    1370              `False` indicates that only direct subclasses of the specified
    1371              class or ony top-level classes are to be included in the result.
    1372
    1373              Note, the semantics of this parameter differs between instance and
    1374              class level operations.
    1375
    1376              Default: `False`.
    1377
    1378          :Returns:
    1379
    1380              A list of strings that are the class names of the enumerated
    1381              classes.
    1382
    1383          :Exceptions:
    1384
    1385              See the list of exceptions described in `WBEMConnection`.
    1386          """
    1387
    1388          params = self._map_classname_param(params)
    1389
    1390          if namespace is None:
    1391              namespace = self.default_namespace
    1392
    1393          result = self.imethodcall(
    1394              'EnumerateClassNames',
    1395              namespace,
    1396              **params)
    1397
    1398          if result is None:
    1399              return []
    1400          else:
    1401              return map(lambda x: x.classname, result[2])
    1402
    1403 -    def EnumerateClasses(self, namespace=None, **params):
    1404          # pylint: disable=invalid-name
    1405          """
    1406          Enumerate the subclasses of a class, or the top-level classes in a
    1407          namespace.
    1408
    1409          This method performs the EnumerateClasses CIM-XML operation.
    1410          If the operation succeeds, this method returns.
    1411          Otherwise, this method raises an exception.
    1412
    1413          :Parameters:
    1414
    1415            namespace : string
    1416              Optional: Name of the namespace of the class, as a string.
    1417              The value `None` causes the default namespace of the connection to
    1418              be used.
    1419
    1420              Default: `None`
    1421
    1422            ClassName : string
    1423              Optional: Name of the class whose subclasses are to be retrieved.
    1424              The value `None` causes the top-level classes in the namespace to
    1425              be retrieved.
    1426
    1427              Default: `None`
    1428
    1429            DeepInheritance : `bool`
    1430              Optional: Indicates that all (direct and indirect) subclasses of
    1431              the specified class or of the top-level classes are to be included
    1432              in the result.
    1433              `False` indicates that only direct subclasses of the specified
    1434              class or ony top-level classes are to be included in the result.
    1435
    1436              Note, the semantics of this parameter differs between instance and
    1437              class level operations.
    1438
    1439              Default: `False`.
    1440
    1441            LocalOnly : `bool`
    1442              Optional: Indicates that inherited properties, methods, and
    1443              qualifiers are to be excluded from the returned classes.
    1444
    1445              Default: `True`.
    1446
    1447            IncludeQualifiers : `bool`
    1448              Optional: Indicates that qualifiers are to be included in the
    1449              returned classes.
    1450
    1451              Default: `False`.
    1452
    1453            IncludeClassOrigin : `bool`
    1454              Optional: Indicates that class origin information is to be included
    1455              on each property and method in the returned classes.
    1456
    1457              Default: `False`.
    1458
    1459          :Returns:
    1460
    1461              A list of `CIMClass` objects that are representations of the
    1462              enumerated classes.
    1463
    1464          :Exceptions:
    1465
    1466              See the list of exceptions described in `WBEMConnection`.
    1467          """
    1468
    1469          params = self._map_classname_param(params)
    1470
    1471          if namespace is None:
    1472              namespace = self.default_namespace
    1473
    1474          result = self.imethodcall(
    1475              'EnumerateClasses',
    1476              namespace,
    1477              **params)
    1478
    1479          if result is None:
    1480              return []
    1481
    1482          return result[2]
    1483
    1484 -    def GetClass(self, ClassName, namespace=None, **params):
    1485          # pylint: disable=invalid-name
    1486          """
    1487          Retrieve a class.
    1488
    1489          This method performs the GetClass CIM-XML operation.
    1490          If the operation succeeds, this method returns.
    1491          Otherwise, this method raises an exception.
    1492
    1493          :Parameters:
    1494
    1495            ClassName : string
    1496              Name of the class to be retrieved.
    1497
    1498            namespace : string
    1499              Optional: Name of the namespace of the class, as a string.
    1500              The value `None` causes the default namespace of the connection to
    1501              be used.
    1502
    1503              Default: `None`
    1504
    1505            LocalOnly : `bool`
    1506              Optional: Indicates that inherited properties, methods, and
    1507              qualifiers are to be excluded from the returned class.
    1508
    1509              Default: `True`.
    1510
    1511            IncludeQualifiers : `bool`
    1512              Optional: Indicates that qualifiers are to be included in the
    1513              returned class.
    1514
    1515              Default: `False`.
    1516
    1517            IncludeClassOrigin : `bool`
    1518              Optional: Indicates that class origin information is to be included
    1519              on each property and method in the returned class.
    1520
    1521              Default: `False`.
    1522
    1523            PropertyList : iterable of string
    1524              Optional: An iterable specifying the names of the properties to be
    1525              included in the returned class. An empty iterable indicates to
    1526              include no properties. A value of `None` for this parameter
    1527              indicates to include all properties.
    1528
    1529              Default: `None`.
    1530
    1531          :Returns:
    1532
    1533              A `CIMClass` object that is a representation of the
    1534              retrieved class.
    1535
    1536          :Exceptions:
    1537
    1538              See the list of exceptions described in `WBEMConnection`.
    1539          """
    1540
    1541          params = self._map_classname_param(params)
    1542
    1543          if namespace is None:
    1544              namespace = self.default_namespace
    1545
    1546          result = self.imethodcall(
    1547              'GetClass',
    1548              namespace,
    1549              ClassName=CIMClassName(ClassName),
    1550              **params)
    1551
    1552          return result[2][0]
    1553
    1554 -    def DeleteClass(self, ClassName, namespace=None, **params):
    1555          # pylint: disable=invalid-name
    1556          """
    1557          Delete a class.
    1558
    1559          This method performs the DeleteClass CIM-XML operation.
    1560          If the operation succeeds, this method returns.
    1561          Otherwise, this method raises an exception.
    1562
    1563          TODO This method is UNSUPPORTED right now. Test and verify description.
    1564
    1565          :Parameters:
    1566
    1567            ClassName : string
    1568              Name of the class to be deleted.
    1569
    1570            namespace : string
    1571              Optional: Name of the namespace of the class, as a string.
    1572              The value `None` causes the default namespace of the connection to
    1573              be used.
    1574
    1575              Default: `None`
    1576
    1577          :Exceptions:
    1578
    1579              See the list of exceptions described in `WBEMConnection`.
    1580          """
    1581
    1582          params = self._map_classname_param(params)
    1583
    1584          if namespace is None:
    1585              namespace = self.default_namespace
    1586
    1587          self.imethodcall(
    1588              'DeleteClass',
    1589              namespace,
    1590              ClassName=CIMClassName(ClassName),
    1591              **params)
    1592
    1593 -    def ModifyClass(self, ModifiedClass, namespace=None, **params):
    1594          # pylint: disable=invalid-name
    1595          """
    1596          Modify a class.
    1597
    1598          This method performs the ModifyClass CIM-XML operation.
    1599          If the operation succeeds, this method returns.
    1600          Otherwise, this method raises an exception.
    1601
    1602          TODO This method is UNSUPPORTED right now. Test and verify description.
    1603
    1604          :Parameters:
    1605
    1606            ModifiedClass : `CIMClass`
    1607              A representation of the modified class. This object needs to
    1608              contain any modified properties, methods and qualifiers and the
    1609              class path of the class to be modified.
    1610              Typically, this object has been retrieved by other operations, such
    1611              as GetClass.
    1612
    1613          :Exceptions:
    1614
    1615              See the list of exceptions described in `WBEMConnection`.
    1616          """
    1617
    1618          if namespace is None:
    1619              namespace = self.default_namespace
    1620
    1621          self.imethodcall(
    1622              'ModifyClass',
    1623              namespace,
    1624              ModifiedClass=ModifiedClass,
    1625              **params)
    1626
    1627 -    def CreateClass(self, NewClass, namespace=None, **params):
    1628          # pylint: disable=invalid-name
    1629          """
    1630          Create a class.
    1631
    1632          This method performs the ModifyClass CIM-XML operation.
    1633          If the operation succeeds, this method returns.
    1634          Otherwise, this method raises an exception.
    1635
    1636          TODO This method is UNSUPPORTED right now. Test and verify description.
    1637
    1638          :Parameters:
    1639
    1640            NewClass : `CIMClass`
    1641              A representation of the class to be created. This object needs to
    1642              contain any properties, methods, qualifiers, superclass name, and
    1643              the class name of the class to be created.
    1644              The class path in this object (`path` instance variable) will be
    1645              ignored.
    1646
    1647            namespace : string
    1648              Optional: Name of the namespace in which the class is to be
    1649              created. The value `None` causes the default namespace of the
    1650              connection to be used.
    1651
    1652              Default: `None`
    1653
    1654          :Exceptions:
    1655
    1656              See the list of exceptions described in `WBEMConnection`.
    1657          """
    1658
    1659          if namespace is None:
    1660              namespace = self.default_namespace
    1661
    1662          self.imethodcall(
    1663              'CreateClass',
    1664              namespace,
    1665              NewClass=NewClass,
    1666              **params)
    1667
    1668      #
    1669      # Association provider API
    1670      #
    1671
    1672 -    def _add_objectname_param(self, params, object):
    1673          """Add an object name (either a class name or an instance
    1674          name) to a dictionary of parameter names."""
    1675
    1676          if isinstance(object, (CIMClassName, CIMInstanceName)):
    1677              params['ObjectName'] = object.copy()
    1678              params['ObjectName'].namespace = None
    1679          elif isinstance(object, StringTypes):
    1680              params['ObjectName'] = CIMClassName(object)
    1681          else:
    1682              raise ValueError('Expecting a classname, CIMClassName or '
    1683                               'CIMInstanceName object')
    1684
    1685          return params
    1686
    1687 -    def _map_association_params(self, params):
    1688          """Convert various convenience parameters and types into their
    1689          correct form for passing to the imethodcall() function."""
    1690
    1691          # ResultClass and Role parameters that are strings should be
    1692          # mapped to CIMClassName objects.
    1693
    1694          if params.has_key('ResultClass') and \
    1695             isinstance(params['ResultClass'], StringTypes):
    1696              params['ResultClass'] = CIMClassName(params['ResultClass'])
    1697
    1698          if params.has_key('AssocClass') and \
    1699             isinstance(params['AssocClass'], StringTypes):
    1700              params['AssocClass'] = CIMClassName(params['AssocClass'])
    1701
    1702          return params
    1703
    1704 -    def Associators(self, ObjectName, **params):
    1705          # pylint: disable=invalid-name
    1706          """
    1707          Retrieve the instances (or classes) associated to a source instance
    1708          (or source class).
    1709
    1710          This method performs the Associators CIM-XML operation.
    1711          If the operation succeeds, this method returns.
    1712          Otherwise, this method raises an exception.
    1713
    1714          :Parameters:
    1715
    1716            ObjectName
    1717              For instance level usage: The instance path of the source instance,
    1718              as a `CIMInstanceName` object. If that object does not
    1719              specify a namespace, the default namespace of the connection is
    1720              used.
    1721
    1722              For class level usage: The class path of the source class, as a
    1723              string or as a `CIMClassName` object.
    1724              If specified as a string, the string is interpreted as a class name
    1725              in the default namespace of the connection.
    1726              If specified as a `CIMClassName` object that does not
    1727              specify a namespace, the default namespace of the connection is
    1728              used.
    1729
    1730            AssocClass : string or `CIMClassName`
    1731              Optional: Class name of an association class, to filter the result
    1732              to include only traversals of that association class (or
    1733              subclasses).
    1734
    1735              Default: `None` (no filtering).
    1736
    1737            ResultClass : string or `CIMClassName`
    1738              Optional: Class name of an associated class, to filter the result
    1739              to include only traversals to that associated class (or
    1740              subclasses).
    1741
    1742              Default: `None` (no filtering).
    1743
    1744            Role : string
    1745              Optional: Role name (= property name) of the source end, to filter
    1746              the result to include only traversals from that source role.
    1747
    1748              Default: `None` (no filtering).
    1749
    1750            ResultRole
    1751              Optional: Role name (= property name) of the far end, to filter
    1752              the result to include only traversals to that far role.
    1753
    1754              Default: `None` (no filtering).
    1755
    1756            IncludeQualifiers : `bool`
    1757              Optional: Indicates that qualifiers are to be included in the
    1758              returned instances (or classes).
    1759
    1760              Default: `False`.
    1761
    1762              This parameter has been deprecated in CIM-XML. Clients cannot rely
    1763              on it being implemented by WBEM servers.
    1764
    1765            IncludeClassOrigin : `bool`
    1766              Optional: Indicates that class origin information is to be included
    1767              on each property or method in the returned instances (or classes).
    1768
    1769              Default: `False`.
    1770
    1771            PropertyList : iterable of string
    1772              Optional: An iterable specifying the names of the properties to be
    1773              included in the returned instances (or classes). An empty iterable
    1774              indicates to include no properties. A value of `None` for this
    1775              parameter indicates to include all properties.
    1776
    1777              Default: `None`.
    1778
    1779          :Returns:
    1780
    1781              For instance level usage, a list of `CIMInstance` objects
    1782              that are representations of the associated instances.
    1783
    1784              For class level usage, a list of `CIMClass` objects
    1785              that are representations the associated classes.
    1786
    1787          :Exceptions:
    1788
    1789              See the list of exceptions described in `WBEMConnection`.
    1790          """
    1791
    1792          params = self._map_association_params(params)
    1793          params = self._add_objectname_param(params, ObjectName)
    1794
    1795          namespace = self.default_namespace
    1796
    1797          if isinstance(ObjectName, CIMInstanceName) and \
    1798             ObjectName.namespace is not None:
    1799              namespace = ObjectName.namespace
    1800
    1801          result = self.imethodcall(
    1802              'Associators',
    1803              namespace,
    1804              **params)
    1805
    1806          if result is None:
    1807              return []
    1808
    1809          return map(lambda x: x[2], result[2])
    1810
    1811 -    def AssociatorNames(self, ObjectName, **params):
    1812          # pylint: disable=invalid-name
    1813          """
    1814          Retrieve the instance paths of the instances (or class paths of the
    1815          classes) associated to a source instance (or source class).
    1816
    1817          This method performs the AssociatorNames CIM-XML operation.
    1818          If the operation succeeds, this method returns.
    1819          Otherwise, this method raises an exception.
    1820
    1821          :Parameters:
    1822
    1823            ObjectName
    1824              For instance level usage: The instance path of the source instance,
    1825              as a `CIMInstanceName` object. If that object does not
    1826              specify a namespace, the default namespace of the connection is
    1827              used.
    1828
    1829              For class level usage: The class path of the source class, as a
    1830              string or as a `CIMClassName` object.
    1831              If specified as a string, the string is interpreted as a class name
    1832              in the default namespace of the connection.
    1833              If specified as a `CIMClassName` object that does not
    1834              specify a namespace, the default namespace of the connection is
    1835              used.
    1836
    1837            AssocClass : string or `CIMClassName`
    1838              Optional: Class name of an association class, to filter the result
    1839              to include only traversals of that association class (or
    1840              subclasses).
    1841
    1842              Default: `None` (no filtering).
    1843
    1844            ResultClass : string or `CIMClassName`
    1845              Optional: Class name of an associated class, to filter the result
    1846              to include only traversals to that associated class (or
    1847              subclasses).
    1848
    1849              Default: `None` (no filtering).
    1850
    1851            Role : string
    1852              Optional: Role name (= property name) of the source end, to filter
    1853              the result to include only traversals from that source role.
    1854
    1855              Default: `None` (no filtering).
    1856
    1857            ResultRole
    1858              Optional: Role name (= property name) of the far end, to filter
    1859              the result to include only traversals to that far role.
    1860
    1861              Default: `None` (no filtering).
    1862
    1863          :Returns:
    1864
    1865              For instance level usage, a list of `CIMInstanceName`
    1866              objects that are the instance paths of the associated instances.
    1867
    1868              For class level usage, a list of `CIMClassName` objects
    1869              that are the class paths of the associated classes.
    1870
    1871          :Exceptions:
    1872
    1873              See the list of exceptions described in `WBEMConnection`.
    1874          """
    1875
    1876          params = self._map_association_params(params)
    1877          params = self._add_objectname_param(params, ObjectName)
    1878
    1879          namespace = self.default_namespace
    1880
    1881          if isinstance(ObjectName, CIMInstanceName) and \
    1882             ObjectName.namespace is not None:
    1883              namespace = ObjectName.namespace
    1884
    1885          result = self.imethodcall(
    1886              'AssociatorNames',
    1887              namespace,
    1888              **params)
    1889
    1890          if result is None:
    1891              return []
    1892
    1893          return map(lambda x: x[2], result[2])
    1894
    1895 -    def References(self, ObjectName, **params):
    1896          # pylint: disable=invalid-name
    1897          """
    1898          Retrieve the association instances (or association classes) that
    1899          reference a source instance (or source class).
    1900
    1901          This method performs the References CIM-XML operation.
    1902          If the operation succeeds, this method returns.
    1903          Otherwise, this method raises an exception.
    1904
    1905          :Parameters:
    1906
    1907            ObjectName
    1908              For instance level usage: The instance path of the source instance,
    1909              as a `CIMInstanceName` object. If that object does not
    1910              specify a namespace, the default namespace of the connection is
    1911              used.
    1912
    1913              For class level usage: The class path of the source class, as a
    1914              string or as a `CIMClassName` object.
    1915              If specified as a string, the string is interpreted as a class name
    1916              in the default namespace of the connection.
    1917              If specified as a `CIMClassName` object that does not
    1918              specify a namespace, the default namespace of the connection is
    1919              used.
    1920
    1921            ResultClass : string or `CIMClassName`
    1922              Optional: Class name of an association class, to filter the result
    1923              to include only traversals of that association class (or
    1924              subclasses).
    1925
    1926              Default: `None` (no filtering).
    1927
    1928            Role : string
    1929              Optional: Role name (= property name) of the source end, to filter
    1930              the result to include only traversals from that source role.
    1931
    1932              Default: `None` (no filtering).
    1933
    1934            IncludeQualifiers : `bool`
    1935              Optional: Indicates that qualifiers are to be included in the
    1936              returned instances (or classes).
    1937
    1938              Default: `False`.
    1939
    1940              This parameter has been deprecated in CIM-XML. Clients cannot rely
    1941              on it being implemented by WBEM servers.
    1942
    1943            IncludeClassOrigin : `bool`
    1944              Optional: Indicates that class origin information is to be included
    1945              on each property or method in the returned instances (or classes).
    1946
    1947              Default: `False`.
    1948
    1949            PropertyList : iterable of string
    1950              Optional: An iterable specifying the names of the properties to be
    1951              included in the returned instances (or classes). An empty iterable
    1952              indicates to include no properties. A value of `None` for this
    1953              parameter indicates to include all properties.
    1954
    1955              Default: `None`.
    1956
    1957          :Returns:
    1958
    1959              For instance level usage, a list of `CIMInstance` objects
    1960              that are representations of the referencing association instances.
    1961
    1962              For class level usage, a list of `CIMClass` objects
    1963              that are representations the referencing association classes.
    1964
    1965          :Exceptions:
    1966
    1967              See the list of exceptions described in `WBEMConnection`.
    1968          """
    1969
    1970          params = self._map_association_params(params)
    1971          params = self._add_objectname_param(params, ObjectName)
    1972
    1973          namespace = self.default_namespace
    1974
    1975          if isinstance(ObjectName, CIMInstanceName) and \
    1976             ObjectName.namespace is not None:
    1977              namespace = ObjectName.namespace
    1978
    1979          result = self.imethodcall(
    1980              'References',
    1981              namespace,
    1982              **params)
    1983
    1984          if result is None:
    1985              return []
    1986
    1987          return map(lambda x: x[2], result[2])
    1988
    1989 -    def ReferenceNames(self, ObjectName, **params):
    1990          # pylint: disable=invalid-name
    1991          """
    1992          Retrieve the instance paths of the association instances (or class
    1993          paths of the association classes) that reference a source instance
    1994          (or source class).
    1995
    1996          This method performs the ReferenceNames CIM-XML operation.
    1997          If the operation succeeds, this method returns.
    1998          Otherwise, this method raises an exception.
    1999
    2000          :Parameters:
    2001
    2002            ObjectName
    2003              For instance level usage: The instance path of the source instance,
    2004              as a `CIMInstanceName` object. If that object does not
    2005              specify a namespace, the default namespace of the connection is
    2006              used.
    2007
    2008              For class level usage: The class path of the source class, as a
    2009              string or as a `CIMClassName` object.
    2010              If specified as a string, the string is interpreted as a class name
    2011              in the default namespace of the connection.
    2012              If specified as a `CIMClassName` object that does not
    2013              specify a namespace, the default namespace of the connection is
    2014              used.
    2015
    2016            ResultClass : string or `CIMClassName`
    2017              Optional: Class name of an association class, to filter the result
    2018              to include only traversals of that association class (or
    2019              subclasses).
    2020
    2021              Default: `None` (no filtering).
    2022
    2023            Role : string
    2024              Optional: Role name (= property name) of the source end, to filter
    2025              the result to include only traversals from that source role.
    2026
    2027              Default: `None` (no filtering).
    2028
    2029          :Returns:
    2030
    2031              For instance level usage, a list of `CIMInstanceName`
    2032              objects that are the instance paths of the referencing association
    2033              instances.
    2034
    2035              For class level usage, a list of `CIMClassName` objects
    2036              that are the class paths of the referencing association classes.
    2037
    2038          :Exceptions:
    2039
    2040              See the list of exceptions described in `WBEMConnection`.
    2041          """
    2042
    2043          params = self._map_association_params(params)
    2044          params = self._add_objectname_param(params, ObjectName)
    2045
    2046          namespace = self.default_namespace
    2047
    2048          if isinstance(ObjectName, CIMInstanceName) and \
    2049             ObjectName.namespace is not None:
    2050              namespace = ObjectName.namespace
    2051
    2052          result = self.imethodcall(
    2053              'ReferenceNames',
    2054              namespace,
    2055              **params)
    2056
    2057          if result is None:
    2058              return []
    2059
    2060          return map(lambda x: x[2], result[2])
    2061
    2062      #
    2063      # Method provider API
    2064      #
    2065
    2066 -    def InvokeMethod(self, MethodName, ObjectName, Params=None, **params):
    2067          # pylint: disable=invalid-name
    2068          """
    2069          Invoke a method on a target instance or on a target class.
    2070
    2071          The methods that can be invoked are static and non-static methods
    2072          defined in a class (also known as *extrinsic* methods).
    2073          Static methods can be invoked on instances and on classes.
    2074          Non-static methods can be invoked only on instances.
    2075
    2076          This method performs the InvokeMethod CIM-XML operation.
    2077          If the operation succeeds, this method returns.
    2078          Otherwise, this method raises an exception.
    2079
    2080          Input parameters for the CIM method can be specified in a
    2081          order-preserving way using the ``Params`` parameter, and in a
    2082          order-agnostic way using the ``**params`` keyword parameters.
    2083
    2084          :Parameters:
    2085
    2086            MethodName : string
    2087              Name of the method to be invoked (without parenthesis or any
    2088              parameter signature).
    2089
    2090            ObjectName
    2091              For instance level usage: The instance path of the target instance,
    2092              as a `CIMInstanceName` object. If that object does not
    2093              specify a namespace, the default namespace of the connection is
    2094              used.
    2095
    2096              For class level usage: The class path of the target class, as a
    2097              string or as a `CIMClassName` object.
    2098              If specified as a string, the string is interpreted as a class name
    2099              in the default namespace of the connection.
    2100              If specified as a `CIMClassName` object that does not
    2101              specify a namespace, the default namespace of the connection is
    2102              used.
    2103
    2104            Params
    2105              A list of input parameters for the CIM method.
    2106
    2107              Each list item represents a single input parameter for the CIM
    2108              method and must be a ``tuple(name,value)``, where ``name`` is the
    2109              parameter name in any lexical case, and ``value`` is the parameter
    2110              value as a CIM typed value as described in `cim_types`.
    2111
    2112            **params
    2113              Keyword parameters for the input parameters for the CIM method.
    2114
    2115              Each keyword parameter represents a single input parameter for the
    2116              CIM method, where the key is the parameter name in any lexical
    2117              case, and the value is the parameter value as a CIM typed value as
    2118              described in `cim_types`.
    2119
    2120              The overall list of input parameters represented in the CIM-XML
    2121              request message that is sent to the WBEM server is formed from
    2122              the list of parameters specified in ``Params`` preserving its
    2123              order, followed by the set of parameters specified in ``**params``
    2124              in any order. There is no checking for duplicate parameter names
    2125              in the PyWBEM client.
    2126
    2127
    2128          :Returns:
    2129
    2130            A tuple of ``(returnvalue, outparams)``, where:
    2131
    2132              - ``returnvalue`` : Return value of the CIM method, as a CIM typed
    2133                value as described in `cim_types`.
    2134              - ``outparams`` : Output parameters of the CIM method, as a
    2135                `NocaseDict` dictionary containing all CIM method output
    2136                parameters, where the dictionary items have:
    2137
    2138                * a key that is the CIM parameter name, as a string.
    2139                * a value that is the CIM parameter value, as a CIM typed value
    2140                  as described in `cim_types`.
    2141
    2142          :Exceptions:
    2143
    2144              See the list of exceptions described in `WBEMConnection`.
    2145          """
    2146
    2147          # Convert string to CIMClassName
    2148
    2149          obj = ObjectName
    2150
    2151          if isinstance(obj, StringTypes):
    2152              obj = CIMClassName(obj, namespace=self.default_namespace)
    2153
    2154          if isinstance(obj, CIMInstanceName) and obj.namespace is None:
    2155              obj = ObjectName.copy()
    2156              obj.namespace = self.default_namespace
    2157
    2158          # Make the method call
    2159
    2160          result = self.methodcall(MethodName, obj, Params, **params)
    2161
    2162          # Convert optional RETURNVALUE into a Python object
    2163
    2164          returnvalue = None
    2165
    2166          if len(result) > 0 and result[0][0] == 'RETURNVALUE':
    2167
    2168              returnvalue = cim_obj.tocimobj(result[0][1]['PARAMTYPE'],
    2169                                             result[0][2])
    2170              result = result[1:]
    2171
    2172          # Convert zero or more PARAMVALUE elements into dictionary
    2173
    2174          output_params = NocaseDict()
    2175
    2176          for p in result:
    2177              if p[1] == 'reference':
    2178                  output_params[p[0]] = p[2]
    2179              else:
    2180                  output_params[p[0]] = cim_obj.tocimobj(p[1], p[2])
    2181
    2182          return returnvalue, output_params
    2183
    2184      #
    2185      # Qualifiers API
    2186      #
    2187
    2188 -    def EnumerateQualifiers(self, namespace=None, **params):
    2189          # pylint: disable=invalid-name
    2190          """
    2191          Enumerate qualifier types.
    2192
    2193          Returns a list of `CIMQualifier` objects.
    2194
    2195          TODO Complete this description.
    2196          """
    2197
    2198          if namespace is None:
    2199              namespace = self.default_namespace
    2200
    2201          result = self.imethodcall(
    2202              'EnumerateQualifiers',
    2203              namespace,
    2204              **params)
    2205
    2206          qualifiers = []
    2207
    2208          if result is not None:
    2209              names = result[2]
    2210          else:
    2211              names = []
    2212
    2213          return names
    2214
    2215 -    def GetQualifier(self, QualifierName, namespace=None, **params):
    2216          # pylint: disable=invalid-name
    2217          """
    2218          Retrieve a qualifier type.
    2219
    2220          Returns a `CIMQualifier` object.
    2221
    2222          TODO Complete this description.
    2223          """
    2224
    2225          if namespace is None:
    2226              namespace = self.default_namespace
    2227
    2228          result = self.imethodcall(
    2229              'GetQualifier',
    2230              namespace,
    2231              QualifierName=QualifierName,
    2232              **params)
    2233
    2234          if result is not None:
    2235              names = result[2][0]
    2236
    2237          return names
    2238
    2239 -    def SetQualifier(self, QualifierDeclaration, namespace=None, **params):
    2240          # pylint: disable=invalid-name
    2241          """
    2242          Create or modify a qualifier type.
    2243
    2244          TODO Complete this description.
    2245          """
    2246
    2247          if namespace is None:
    2248              namespace = self.default_namespace
    2249
    2250          result = self.imethodcall(
    2251              'SetQualifier',
    2252              namespace,
    2253              QualifierDeclaration=QualifierDeclaration,
    2254              **params)
    2255
    2256 -    def DeleteQualifier(self, QualifierName, namespace=None, **params):
    2257          # pylint: disable=invalid-name
    2258          """
    2259          Delete a qualifier type.
    2260
    2261          TODO Complete this description.
    2262          """
    2263
    2264          if namespace is None:
    2265              namespace = self.default_namespace
    2266
    2267          result = self.imethodcall(
    2268              'DeleteQualifier',
    2269              namespace,
    2270              QualifierName=QualifierName,
    2271              **params)
    2272
    2273 -def is_subclass(ch, ns, super, sub):
    2274      """Determine if one class is a subclass of another
    2275
    2276      Keyword Arguments:
    2277      ch -- A CIMOMHandle.  Either a pycimmb.CIMOMHandle or a
    2278          pywbem.WBEMConnection.
    2279      ns -- Namespace.
    2280      super -- A string containing the super class name.
    2281      sub -- The subclass.  This can either be a string or a pywbem.CIMClass.
    2282
    2283      """
    2284
    2285      lsuper = super.lower()
    2286      if isinstance(sub, CIMClass):
    2287          subname = sub.classname
    2288          subclass = sub
    2289      else:
    2290          subname = sub
    2291          subclass = None
    2292      if subname.lower() == lsuper:
    2293          return True
    2294      if subclass is None:
    2295          subclass = ch.GetClass(subname,
    2296                                 ns,
    2297                                 LocalOnly=True,
    2298                                 IncludeQualifiers=False,
    2299                                 PropertyList=[],
    2300                                 IncludeClassOrigin=False)
    2301      while subclass.superclass is not None:
    2302          if subclass.superclass.lower() == lsuper:
    2303              return True
    2304          subclass = ch.GetClass(subclass.superclass,
    2305                                 ns,
    2306                                 LocalOnly=True,
    2307                                 IncludeQualifiers=False,
    2308                                 PropertyList=[],
    2309                                 IncludeClassOrigin=False)
    2310      return False
    2311
    2312 -def PegasusUDSConnection(creds=None, **kwargs):
    2313      # pylint: disable=invalid-name
    2314      return WBEMConnection('/var/run/tog-pegasus/cimxml.socket', creds, **kwargs)
    2315
    2316 -def SFCBUDSConnection(creds=None, **kwargs):
    2317      # pylint: disable=invalid-name
    2318      return WBEMConnection('/tmp/sfcbHttpSocket', creds, **kwargs)
    2319
    2320 -def OpenWBEMUDSConnection(creds=None, **kwargs):
    2321      # pylint: disable=invalid-name
    2322      return WBEMConnection('/tmp/OW@LCL@APIIPC_72859_Xq47Bf_P9r761-5_J-7_Q',
    2323                            creds, **kwargs)
    2324