Repository :
http://git.fedorahosted.org/cgit/cura-tools.git
On branch : master
---------------------------------------------------------------
commit ecefb9068acfc42cf65759505a3f1b3f234af5f8
Author: Peter Hatina <phatina(a)redhat.com>
Date: Mon Jul 21 14:48:09 2014 +0200
allow LMIInstanceNames to call CIMMethods
---------------------------------------------------------------
cli/lmi/shell/LMICompleter.py | 1 +
cli/lmi/shell/LMIDecorators.py | 29 ++++++++++++++++++++
cli/lmi/shell/LMIInstanceName.py | 27 +++++++++++++++++++
cli/lmi/shell/LMIMethod.py | 53 ++++++++++++++++++++++++++++++-------
4 files changed, 100 insertions(+), 10 deletions(-)
diff --git a/cli/lmi/shell/LMICompleter.py b/cli/lmi/shell/LMICompleter.py
index b5a117b..2cd8609 100644
--- a/cli/lmi/shell/LMICompleter.py
+++ b/cli/lmi/shell/LMICompleter.py
@@ -97,6 +97,7 @@ class LMICompleter(rlcompleter.Completer):
words.extend([m + "(" for m in obj.methods()])
words.extend(obj.properties())
elif isinstance(obj, LMIInstanceName):
+ words.extend([m + "(" for m in obj.methods()])
words.extend(obj.key_properties())
elif isinstance(obj, LMIMethod):
words.extend([p + "Values" for p in obj.valuemap_parameters()])
diff --git a/cli/lmi/shell/LMIDecorators.py b/cli/lmi/shell/LMIDecorators.py
index f35db2b..cc33605 100644
--- a/cli/lmi/shell/LMIDecorators.py
+++ b/cli/lmi/shell/LMIDecorators.py
@@ -18,6 +18,7 @@ from functools import wraps
from lmi.shell.compat import *
from lmi.shell.LMIReturnValue import LMIReturnValue
+from lmi.shell.LMIUtil import lmi_wrap_cim_class
from lmi.shell.LMIUtil import lmi_raise_or_dump_exception
from lmi.shell.LMIExceptions import CIMError
@@ -253,6 +254,34 @@ class lmi_class_fetch_lazy(object):
return fn(self_wr, *args, **kwargs)
return wrapped
+class lmi_instance_name_fetch_lazy(object):
+ """
+ Decorator for :py:class:`.LMIInstanceName`, which first fetches a wrapped
+ :py:class:`wbem.CIMInstance` object and then executes a wrapped method.
+
+ :param bool full_fetch: True, if :py:class:`wbem.CIMClass` should include
+ qualifiers and class origin. Default value is False.
+ """
+ def __init__(self, full_fetch=False):
+ self._full_fetch = full_fetch
+
+ def __call__(self, fn):
+ """
+ Fetches a :py:class:`.LMIClass`, if necessary, and exeutes a wrapped
+ method.
+
+ :param instancemethod fn: decorated method
+ """
+ @wraps(fn)
+ def wrapped(self_wr, *args, **kwargs):
+ if self_wr._lmi_class is None:
+ self_wr._lmi_class = lmi_wrap_cim_class(
+ self_wr._conn,
+ self_wr._cim_instance_name.classname,
+ self_wr._cim_instance_name.namespace)
+ self_wr._lmi_class.fetch(self._full_fetch)
+ return fn(self_wr, *args, **kwargs)
+ return wrapped
# Default lmi_process_cim_exceptions error handler
def return_lmi_rval(rval, exc):
diff --git a/cli/lmi/shell/LMIInstanceName.py b/cli/lmi/shell/LMIInstanceName.py
index db344dd..2e45a8b 100644
--- a/cli/lmi/shell/LMIInstanceName.py
+++ b/cli/lmi/shell/LMIInstanceName.py
@@ -19,7 +19,9 @@ from lmi.shell.compat import *
from lmi.shell.LMIObjectFactory import LMIObjectFactory
from lmi.shell.LMIBaseObject import LMIWrapperBaseObject
+from lmi.shell.LMIDecorators import lmi_instance_name_fetch_lazy
from lmi.shell.LMIUtil import lmi_transform_to_lmi
+from lmi.shell.LMIUtil import lmi_wrap_cim_method
class LMIInstanceName(LMIWrapperBaseObject):
@@ -35,6 +37,7 @@ class LMIInstanceName(LMIWrapperBaseObject):
# We use __dict__ to avoid recursion potentially caused by
# combo __setattr__ and __getattr__
self.__dict__["_cim_instance_name"] = cim_instance_name
+ self.__dict__["_lmi_class"] = None
super(LMIInstanceName, self).__init__(conn)
def __cmp__(self, other):
@@ -71,6 +74,10 @@ class LMIInstanceName(LMIWrapperBaseObject):
if isinstance(member, wbem.CIMInstanceName):
member = lmi_transform_to_lmi(self._conn, member)
return member
+ elif not self._conn.is_wsman() and name in self.methods():
+ return lmi_wrap_cim_method(self._conn, name, self)
+ elif self._conn.is_wsman() and not name.startswith("_"):
+ return lmi_wrap_cim_method(self._conn, name, self)
raise AttributeError(name)
def __setattr__(self, name, value):
@@ -434,6 +441,26 @@ class LMIInstanceName(LMIWrapperBaseObject):
return None
return lmi_transform_to_lmi(self._conn, instance)
+ @lmi_instance_name_fetch_lazy()
+ def methods(self):
+ """
+ Returns a list of :py:class:`wbem.CIMInstance` methods' names.
+
+ :returns: list of :py:class:`wbem.CIMInstance` methods' names
+
+ **Usage:** :ref:`instances_methods`.
+ """
+ return self._lmi_class.methods()
+
+ @lmi_instance_name_fetch_lazy()
+ def print_methods(self):
+ """
+ Prints out the list of :py:class:`wbem.CIMInstance` methods' names.
+
+ **Usage:** :ref:`instances_methods`.
+ """
+ self._lmi_class.print_methods()
+
def key_properties(self):
"""
:returns: list of strings of key properties
diff --git a/cli/lmi/shell/LMIMethod.py b/cli/lmi/shell/LMIMethod.py
index 3aea5d6..7b9a316 100644
--- a/cli/lmi/shell/LMIMethod.py
+++ b/cli/lmi/shell/LMIMethod.py
@@ -47,6 +47,7 @@ from lmi.shell.LMIUtil import lmi_get_use_exceptions
from lmi.shell.LMIUtil import lmi_raise_or_dump_exception
from lmi.shell.LMIUtil import lmi_transform_to_cim_param
from lmi.shell.LMIUtil import lmi_transform_to_lmi
+from lmi.shell.LMIUtil import lmi_wrap_cim_class
from lmi.shell.LMIExceptions import *
@@ -141,8 +142,9 @@ class LMIMethod(LMIWrapperBaseObject):
LMI wrapper class representing :py:class:`wbem.CIMMethod`.
:param LMIConnection conn: connection object
- :param LMIInstance lmi_instance: :py:class:`.LMIInstance` object, on which
- the method call will be issued
+ :param LMIInstance(Name) lmi_instance: :py:class:`.LMIInstance` or
+ :py:class:`.LMIInstanceName` object, on which the method call will be
+ issued
:param string method_name: method name
"""
# 15 seconds sleep timeout for main waiting thread
@@ -175,7 +177,11 @@ class LMIMethod(LMIWrapperBaseObject):
def __init__(self, conn, lmi_instance, method_name):
super(LMIMethod, self).__init__(conn)
- self._lmi_instance = lmi_instance.copy()
+ if not isinstance(lmi_instance, (
+ LMIObjectFactory().LMIInstance,
+ LMIObjectFactory().LMIInstanceName)):
+ raise TypeError("lmi_instance must be LMIInstance(Name) type")
+ self._lmi_instance = lmi_instance
self._sync_method = False
self._method = None
self._method_name = method_name
@@ -190,8 +196,17 @@ class LMIMethod(LMIWrapperBaseObject):
self._method_name = method_name[4:]
# We need to have CIMClass with qualifiers. Fetch full class.
- lmi_class = self._lmi_instance._lmi_class
+ if isinstance(self._lmi_instance, LMIObjectFactory().LMIInstance):
+ # LMIInstance
+ lmi_class = self._lmi_instance._lmi_class
+ else:
+ # LMIInstanceName
+ lmi_class = lmi_wrap_cim_class(
+ self._conn,
+ self._lmi_instance.classname,
+ self._lmi_instance.namespace)
lmi_class.fetch(True)
+
self._method = lmi_class._cim_class.methods[self._method_name]
# Store the constant values as a list. This can consume some time, if
@@ -664,12 +679,15 @@ class LMIMethod(LMIWrapperBaseObject):
return LMIReturnValue(rval=-1, errorstr=e.message)
call_rparams = lmi_transform_to_lmi(self._conn, call_rparams)
- # Refresh the instance, within which the method was called
- if refresh_requested and not self._lmi_instance.refresh():
- # NOTE: this is wrong! What should we do?
- errorstr = "Could not update an LMI object after a method call"
- lmi_raise_or_dump_exception(LMIMethodCallError(errorstr))
- return LMIReturnValue(rval=rval, errorstr=errorstr)
+ # Refresh is requested
+ if refresh_requested:
+ # Refresh the instance, within which the method was called
+ ref_rval, _, ref_errorstr = self.__refresh_instance()
+ if not ref_rval:
+ errorstr = "Could not update an LMI object after a method
call"
+ lmi_raise_or_dump_exception(LMIMethodCallError(ref_errorstr))
+ return LMIReturnValue(rval=ref_rval, errorstr=ref_errorstr)
+
return LMIReturnValue(
rval=rval, rparams=call_rparams, errorstr=call_errorstr)
@@ -699,6 +717,21 @@ class LMIMethod(LMIWrapperBaseObject):
cond.notify()
cond.release()
+ def __refresh_instance(self):
+ """
+ Refreshes nested :py:class:`.LMIInstance`.
+
+ **NOTE:** This method refreshes only nested :py:class:`.LMIInstance`.
+ Objects of this class may also contain :py:class:`.LMIInstanceName`; in
+ this case, no refreshing is performed.
+
+ :rtype: :py:class:`.LMIReturnValue`
+ """
+ if not isinstance(self._lmi_instance, LMIObjectFactory().LMIInstance):
+ # There is nothing to refresh here.
+ return LMIReturnValue(rval=True)
+ return self._lmi_instance.refresh()
+
def doc(self):
"""
Prints out pretty verbose message with documentation for the class. If