diff options
author | Michal Minar <miminar@redhat.com> | 2013-10-31 12:36:15 +0100 |
---|---|---|
committer | Michal Minar <miminar@redhat.com> | 2013-10-31 13:24:02 +0100 |
commit | efd855b04e8c93d3ff14b4ea90e54fe21d7db2c4 (patch) | |
tree | b3243957f05b89c556f776719cb6f37d26a4d6fc /src/python | |
parent | e639b9b9129562fbe9568d07a2c63f8437dbf48b (diff) | |
download | openlmi-providers-efd855b04e8c93d3ff14b4ea90e54fe21d7db2c4.tar.gz openlmi-providers-efd855b04e8c93d3ff14b4ea90e54fe21d7db2c4.tar.xz openlmi-providers-efd855b04e8c93d3ff14b4ea90e54fe21d7db2c4.zip |
python: solve ComputerSystem issues
Added ComputerSystem module to lmi.providers with convenience functions
allowing to obtain instance from CIMOM and check for its correctness
when inspecting client's input.
Also removed obsoleted system_name property out of BaseConfiguration
class.
Diffstat (limited to 'src/python')
-rw-r--r-- | src/python/lmi/base/BaseConfiguration.py | 10 | ||||
-rw-r--r-- | src/python/lmi/providers/ComputerSystem.py | 154 | ||||
-rw-r--r-- | src/python/lmi/providers/__init__.py | 19 |
3 files changed, 177 insertions, 6 deletions
diff --git a/src/python/lmi/base/BaseConfiguration.py b/src/python/lmi/base/BaseConfiguration.py index 8333cca..baabcc6 100644 --- a/src/python/lmi/base/BaseConfiguration.py +++ b/src/python/lmi/base/BaseConfiguration.py @@ -72,6 +72,10 @@ class BaseConfiguration(Singleton): There should be only one instance of this class. """ + #: Allow to access global configuration object also from lmi.providers + #: subpackage where ``get_instance()`` can not be used. + #: This variable shall be set in ``__init__()`` method. + INSTANCE = None CONFIG_DIRECTORY_TEMPLATE_TOPLEVEL = '/etc/openlmi/' CONFIG_DIRECTORY_TEMPLATE_PROVIDER = '/etc/openlmi/%(provider_prefix)s/' CONFIG_FILE_PATH_TEMPLATE_TOPLEVEL = \ @@ -152,6 +156,7 @@ class BaseConfiguration(Singleton): self.config = ConfigParser.SafeConfigParser( defaults=self.default_options()) self.load() + BaseConfiguration.INSTANCE = self def add_listener(self, callback): """ @@ -199,11 +204,6 @@ class BaseConfiguration(Singleton): return self.config.get('CIM', 'SystemClassName') @property - def system_name(self): - """ Return SystemName of OpenLMI provider. """ - return socket.getfqdn() - - @property def logging_level(self): """ Return name of logging level in lower case. """ return self.config.get('Log', 'Level').lower() diff --git a/src/python/lmi/providers/ComputerSystem.py b/src/python/lmi/providers/ComputerSystem.py new file mode 100644 index 0000000..0b347f8 --- /dev/null +++ b/src/python/lmi/providers/ComputerSystem.py @@ -0,0 +1,154 @@ +# -*- encoding: utf-8 -*- +# Software Management Providers +# +# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +""" +Just a common functionality related to associated class ``CIM_ComputerSystem``. +""" + +import pywbem + +from lmi.base.BaseConfiguration import BaseConfiguration +from lmi.providers import cmpi_logging +from lmi.software import util + +class UninitializedError(Exception): + """ + Raised when the initialization parameter is not passed to function upon + its first invocation. + """ + pass + +class NotInstrumentedError(Exception): + """ + Raised when some CIM class is not instrumented in current *CIMOM*. + """ + pass + +@cmpi_logging.trace_function +def get_path(env=None): + """ + Get the instance name of preferred computer system. Instance is cached, + so the broker is accessed just upon the first invocation. Confiruation + instance must be instantiated before this function is called. + + :param ProviderEnvironment env: Provider environment, taken from CIMOM + callback (e.g. ``get_providers()``). It's needed just upon the first + invocation. + :returns: Instance of ``CIM_ComputerSystem``. Exact subclass is defined + in configuration file. + :rtype: :py:class:`pywbem.CIMInstanceName` + """ + if not hasattr(get_path, '_instance'): + if env is None: + raise UninitializedError("get_computer_system_path() needs to be" + " given environment object at first invocation") + inames = [ i for i in env.get_cimom_handle().EnumerateInstanceNames( + "root/cimv2", + BaseConfiguration.INSTANCE.system_class_name) ] + if len(inames) < 1: + raise NotInstrumentedError("CIM_ComputerSystem class is not" + " instrumented or EnumerateInstanceNames() operation" + " is not supported") + get_path._instance = inames[0] + return get_path._instance.copy() + +@cmpi_logging.trace_function +def get_system_name(env=None): + """ + Get the name of system contained in a ``Name`` property of instance of + ``CIM_ComputerSystem``. + + :param ProviderEnvironment env: Provider environment, taken from CIMOM + callback (e.g. ``get_providers()``). It's needed only upon a + first invocation of this function or + :py:func:`get_computer_system_path`. + :returns: Name of computer system. + :rtype: string + """ + return get_path(env)["Name"] + +@cmpi_logging.trace_function +def check_path(env, system, prop_name): + """ + Checks instance name of ``CIM_ComputerSystem``. If the object path matches + this computer system, ``True`` is returned. Exception is raised otherwise. + Especially useful when checking arguments of instance's method taking + reference to computer system an argument. + + :param system: Instance name of computer system to check. + :type system: :py:class:`pywbem.CIMInstanceName` + :param string prop_name: Name of argument or property referring to the object + path being checked. This is used in exception messages upon + unsuccessful checks. + :returns: ``True`` + :rtype: boolean + """ + if not isinstance(system, pywbem.CIMInstanceName): + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "\"%s\" must be a CIMInstanceName" % prop_name) + our_system = get_path(env) + ch = env.get_cimom_handle() + if system.namespace != our_system.namespace: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + 'Namespace of "%s" does not match "%s"' % ( + prop_name, our_system.namespace)) + if not ch.is_subclass(our_system.namespace, + sub=system.classname, + super="CIM_ComputerSystem"): + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "Class of \"%s\" must be a sublass of %s" % ( + prop_name, our_system.classname)) + if not 'CreationClassName' in system or not 'Name' in system: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "\"%s\" is missing one of keys", prop_name) + if not ch.is_subclass(our_system.namespace, + sub=system['CreationClassName'], + super="CIM_ComputerSystem"): + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "CreationClassName of \"%s\" must be a sublass of %s" % ( + prop_name, our_system.classname)) + if not util.is_this_system(system['Name']): + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "Name of \"%s\" does not match \"%s\"" % ( + prop_name, our_system['Name'])) + return True + +@cmpi_logging.trace_function +def check_path_property(env, op, prop_name): + """ + This checks, whether the object path contains correct instance name of + ``CIM_ComputerSystem`` corresponding to this system. If not, an exception + is raised. + + Example usage in ``get_instance()`` method of provider: :: + + # body of get_instance() method of some association class having + # *System* property referring to an instance of *CIM_ComputerSystem*. + ComputerSystem.check_path_property(env, model, "System") + + :param op: Object path to check. + :param string prop_name: Name of property referring to the object path being + checked. This is used in exception messages when check is unsuccessful. + :returns: ``True`` + :rtype: boolean + """ + if not prop_name in op: + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "Missing %s key property!" % prop_name) + return check_path(env, op[prop_name], prop_name) + diff --git a/src/python/lmi/providers/__init__.py b/src/python/lmi/providers/__init__.py index baebcdb..7aec342 100644 --- a/src/python/lmi/providers/__init__.py +++ b/src/python/lmi/providers/__init__.py @@ -18,10 +18,13 @@ # # Authors: Michal Minar <miminar@redhat.com> # - """ Common utilities for OpenLMI python providers. """ + +import socket +from lmi.base.BaseConfiguration import BaseConfiguration + def parse_instance_id(instance_id, classname=None): """ Parse InstanceID, check it has LMI:<classname>:<ID> format and return @@ -40,3 +43,17 @@ def parse_instance_id(instance_id, classname=None): if classname and real_classname.lower() != classname.lower(): return None return parts[2] + +def is_this_system(system_name): + """ + Return ``True`` if given *system_name* matches the hostname of currently + running system. + + Global configuration object must be initialized before calling this + function. + + :rtype: boolean + """ + return ( socket.gethostbyaddr(system_name)[0] + == socket.gethostbyaddr( + BaseConfiguration.INSTANCE.system_class_name)[0]) |