From 19ab3372fe708be3e937df5d1ed6945ac813b51c Mon Sep 17 00:00:00 2001 From: Michal Minar Date: Mon, 4 Mar 2013 15:15:36 +0100 Subject: added association providers for SoftwareIdentityResource simplified writing references() method of any association provider --- .../software/LMI_HostedSoftwareIdentityResource.py | 281 +++++++++++++++++++++ .../software/LMI_InstalledSoftwareIdentity.py | 75 +++--- .../software/LMI_MemberOfSoftwareCollection.py | 97 +++---- src/software/openlmi/software/cimom_entry.py | 19 +- src/software/openlmi/software/core/__init__.py | 58 +++++ .../test/test_hosted_software_identity_resource.py | 165 ++++++++++++ .../test/test_resource_for_software_identity.py | 176 +++++++++++++ 7 files changed, 781 insertions(+), 90 deletions(-) create mode 100644 src/software/openlmi/software/LMI_HostedSoftwareIdentityResource.py create mode 100755 src/software/test/test_hosted_software_identity_resource.py create mode 100755 src/software/test/test_resource_for_software_identity.py (limited to 'src') diff --git a/src/software/openlmi/software/LMI_HostedSoftwareIdentityResource.py b/src/software/openlmi/software/LMI_HostedSoftwareIdentityResource.py new file mode 100644 index 0000000..09ab5d3 --- /dev/null +++ b/src/software/openlmi/software/LMI_HostedSoftwareIdentityResource.py @@ -0,0 +1,281 @@ +# Software Management Providers +# +# Copyright (C) 2012 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 +# +# Authors: Michal Minar +# + +"""Python Provider for LMI_HostedSoftwareIdentityResource + +Instruments the CIM class LMI_HostedSoftwareIdentityResource + +""" + +import pywbem +from pywbem.cim_provider2 import CIMProvider2 + +from openlmi.common import cmpi_logging +from openlmi.software.core import generate_references +from openlmi.software.core import ComputerSystem +from openlmi.software.core import SoftwareIdentityResource +from openlmi.software.yumdb import YumDB + +@cmpi_logging.trace_function +def generate_system_referents(env, object_name, model, _keys_only): + """ + Handler for referents enumeration request. + """ + ComputerSystem.check_path(env, object_name, "Antecedent") + repomodel = pywbem.CIMInstanceName( + classname='LMI_SoftwareIdentityResource', + namespace='root/cimv2', + host=model.path.host) + model["Antecedent"] = ComputerSystem.get_path() + for repo in YumDB.get_instance().get_repository_list('all'): + model["Dependent"] = SoftwareIdentityResource.repo2model( + repo, model=repomodel) + yield model + +@cmpi_logging.trace_function +def generate_repository_referents(env, object_name, model, _keys_only): + """ + Handler for referents enumeration request. + """ + repo = SoftwareIdentityResource.object_path2repo( + env, object_name, kind='all') + model["Antecedent"] = ComputerSystem.get_path() + model["Dependent"] = SoftwareIdentityResource.repo2model(repo) + yield model + +class LMI_HostedSoftwareIdentityResource(CIMProvider2): + """Instrument the CIM class LMI_HostedSoftwareIdentityResource + + CIM_HostedAccessPoint is an association between a Service AccessPoint + and the System on which it is provided. The cardinality of this + association is one-to-many and is weak with respect to the System. + Each System can host many ServiceAccessPoints. Heuristic: If the + implementation of the ServiceAccessPoint is modeled, it must be + implemented by a Device or SoftwareFeature that is part of the System + that is hosting the ServiceAccessPoint. + + """ + + def __init__ (self, _env): + cmpi_logging.logger.debug('Initializing provider %s from %s' \ + % (self.__class__.__name__, __file__)) + + @cmpi_logging.trace_method + def get_instance(self, env, model): + """Return an instance. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + model -- A template of the pywbem.CIMInstance to be returned. The + key properties are set on this instance to correspond to the + instanceName that was requested. The properties of the model + are already filtered according to the PropertyList from the + request. Only properties present in the model need to be + given values. If you prefer, you can set all of the + values, and the instance will be filtered for you. + + Possible Errors: + CIM_ERR_ACCESS_DENIED + CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized + or otherwise incorrect parameters) + CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM + Instance does not exist in the specified namespace) + CIM_ERR_FAILED (some other unspecified error occurred) + + """ + ComputerSystem.check_path_property(env, model, "Antecedent") + if not "Name" in model['Dependent']: + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + 'Missing key property "Name" in Dependent!') + + with YumDB.get_instance() as ydb: + repoid = model["Dependent"]["Name"] + repos = ydb.filter_repositories('all', repoid=repoid) + if len(repos) < 1: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + 'Unknown repository "%s".' % repoid) + model["Antecedent"] = ComputerSystem.get_path() + model["Dependent"] = SoftwareIdentityResource.repo2model(repos[0]) + + return model + + @cmpi_logging.trace_method + def enum_instances(self, env, model, keys_only): + """Enumerate instances. + + The WBEM operations EnumerateInstances and EnumerateInstanceNames + are both mapped to this method. + This method is a python generator + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + model -- A template of the pywbem.CIMInstances to be generated. + The properties of the model are already filtered according to + the PropertyList from the request. Only properties present in + the model need to be given values. If you prefer, you can + always set all of the values, and the instance will be filtered + for you. + keys_only -- A boolean. True if only the key properties should be + set on the generated instances. + + Possible Errors: + CIM_ERR_FAILED (some other unspecified error occurred) + + """ + + # Prime model.path with knowledge of the keys, so key values on + # the CIMInstanceName (model.path) will automatically be set when + # we set property values on the model. + model.path.update({'Dependent': None, 'Antecedent': None}) + + repolist = YumDB.get_instance().get_repository_list('all') + model["Antecedent"] = ComputerSystem.get_path() + repomodel = pywbem.CIMInstanceName( + classname='LMI_SoftwareIdentityResource', + namespace='root/cimv2') + for repo in repolist: + model["Dependent"] = SoftwareIdentityResource.repo2model( + repo, model=repomodel) + yield model + + @cmpi_logging.trace_method + def set_instance(self, env, instance, modify_existing): + """Return a newly created or modified instance. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + instance -- The new pywbem.CIMInstance. If modifying an existing + instance, the properties on this instance have been filtered by + the PropertyList from the request. + modify_existing -- True if ModifyInstance, False if CreateInstance + + Return the new instance. The keys must be set on the new instance. + + Possible Errors: + CIM_ERR_ACCESS_DENIED + CIM_ERR_NOT_SUPPORTED + CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized + or otherwise incorrect parameters) + CIM_ERR_ALREADY_EXISTS (the CIM Instance already exists -- only + valid if modify_existing is False, indicating that the operation + was CreateInstance) + CIM_ERR_NOT_FOUND (the CIM Instance does not exist -- only valid + if modify_existing is True, indicating that the operation + was ModifyInstance) + CIM_ERR_FAILED (some other unspecified error occurred) + + """ + + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED) + + @cmpi_logging.trace_method + def delete_instance(self, env, instance_name): + """Delete an instance. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + instance_name -- A pywbem.CIMInstanceName specifying the instance + to delete. + + Possible Errors: + CIM_ERR_ACCESS_DENIED + CIM_ERR_NOT_SUPPORTED + CIM_ERR_INVALID_NAMESPACE + CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized + or otherwise incorrect parameters) + CIM_ERR_INVALID_CLASS (the CIM Class does not exist in the specified + namespace) + CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM + Instance does not exist in the specified namespace) + CIM_ERR_FAILED (some other unspecified error occurred) + + """ + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED) + + @cmpi_logging.trace_method + def references(self, env, object_name, model, result_class_name, role, + result_role, keys_only): + """Instrument Associations. + + All four association-related operations (Associators, AssociatorNames, + References, ReferenceNames) are mapped to this method. + This method is a python generator + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + object_name -- A pywbem.CIMInstanceName that defines the source + CIM Object whose associated Objects are to be returned. + model -- A template pywbem.CIMInstance to serve as a model + of the objects to be returned. Only properties present on this + model need to be set. + result_class_name -- If not empty, this string acts as a filter on + the returned set of Instances by mandating that each returned + Instances MUST represent an association between object_name + and an Instance of a Class whose name matches this parameter + or a subclass. + role -- If not empty, MUST be a valid Property name. It acts as a + filter on the returned set of Instances by mandating that each + returned Instance MUST refer to object_name via a Property + whose name matches the value of this parameter. + result_role -- If not empty, MUST be a valid Property name. It acts + as a filter on the returned set of Instances by mandating that + each returned Instance MUST represent associations of + object_name to other Instances, where the other Instances play + the specified result_role in the association (i.e. the + name of the Property in the Association Class that refers to + the Object related to object_name MUST match the value of this + parameter). + keys_only -- A boolean. True if only the key properties should be + set on the generated instances. + + The following diagram may be helpful in understanding the role, + result_role, and result_class_name parameters. + +------------------------+ +-------------------+ + | object_name.classname | | result_class_name | + | ~~~~~~~~~~~~~~~~~~~~~ | | ~~~~~~~~~~~~~~~~~ | + +------------------------+ +-------------------+ + | +-----------------------------------+ | + | | [Association] model.classname | | + | object_name | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | + +--------------+ object_name.classname REF role | | + (CIMInstanceName) | result_class_name REF result_role +------+ + | |(CIMInstanceName) + +-----------------------------------+ + + Possible Errors: + CIM_ERR_ACCESS_DENIED + CIM_ERR_NOT_SUPPORTED + CIM_ERR_INVALID_NAMESPACE + CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized + or otherwise incorrect parameters) + CIM_ERR_FAILED (some other unspecified error occurred) + + """ + + handlers = [ + ("Antecedent", "CIM_ComputerSystem" , generate_system_referents), + ("Dependent", "LMI_SoftwareIdentityResource", + generate_repository_referents) + ] + for ref in generate_references(env, object_name, model, + result_class_name, role, result_role, keys_only, handlers): + yield ref + diff --git a/src/software/openlmi/software/LMI_InstalledSoftwareIdentity.py b/src/software/openlmi/software/LMI_InstalledSoftwareIdentity.py index 08dc674..b4c1b6f 100644 --- a/src/software/openlmi/software/LMI_InstalledSoftwareIdentity.py +++ b/src/software/openlmi/software/LMI_InstalledSoftwareIdentity.py @@ -29,10 +29,39 @@ import pywbem from pywbem.cim_provider2 import CIMProvider2 from openlmi.common import cmpi_logging +from openlmi.software.core import generate_references from openlmi.software.core import ComputerSystem from openlmi.software.core import SoftwareIdentity from openlmi.software.yumdb import YumDB +@cmpi_logging.trace_function +def generate_system_referents(env, object_name, model, _keys_only): + """ + Handler for referents enumeration request. + """ + ComputerSystem.check_path(env, object_name, "object_name") + + pkg_model = pywbem.CIMInstanceName( + classname='LMI_SoftwareIdentity', + namespace="root/cimv2", + host=model.path.host) + model["System"] = ComputerSystem.get_path() + with YumDB.get_instance() as ydb: + for pkg_info in ydb.get_package_list('installed', sort=True): + model["InstalledSoftware"] = SoftwareIdentity.pkg2model( + pkg_info, model=pkg_model) + yield model + +@cmpi_logging.trace_function +def generate_package_referents(_env, object_name, model, _keys_only): + """ + Handler for referents enumeration request. + """ + pkg_info = SoftwareIdentity.object_path2pkg(object_name, kind="installed") + model['InstalledSoftware'] = SoftwareIdentity.pkg2model(pkg_info) + model["System"] = ComputerSystem.get_path() + yield model + class LMI_InstalledSoftwareIdentity(CIMProvider2): """Instrument the CIM class LMI_InstalledSoftwareIdentity @@ -268,41 +297,13 @@ class LMI_InstalledSoftwareIdentity(CIMProvider2): CIM_ERR_FAILED (some other unspecified error occurred) """ - cimhandle = env.get_cimom_handle() - - model.path.update({'InstalledSoftware': None, 'System': None}) - - with YumDB.get_instance() as ydb: - try: - if ( (not role or role.lower() == 'system') - and cimhandle.is_subclass(object_name.namespace, - sub=object_name.classname, - super='CIM_ComputerSystem')): - ComputerSystem.check_path(env, object_name, "object_name") - - pkg_model = pywbem.CIMInstanceName( - classname='LMI_SoftwareIdentity', - namespace="root/cimv2", - host=model.path.host) - model["System"] = ComputerSystem.get_path() - for pkg_info in ydb.get_package_list('installed', - sort=True): - model["InstalledSoftware"] = SoftwareIdentity.pkg2model( - pkg_info, model=pkg_model) - yield model - - if ( (not role or role.lower() == 'installedsoftware') - and cimhandle.is_subclass(object_name.namespace, - sub=object_name.classname, - super='LMI_SoftwareIdentity')): - pkg_info = SoftwareIdentity.object_path2pkg( - object_name, kind="installed") - model['InstalledSoftware'] = SoftwareIdentity.pkg2model( - pkg_info) - model["System"] = ComputerSystem.get_path() - yield model - - except pywbem.CIMError as exc: - if exc.args[0] != pywbem.CIM_ERR_NOT_FOUND: - raise + handlers = [ + ("System", "CIM_ComputerSystem", generate_system_referents), + ("InstalledSoftware", "LMI_SoftwareIdentity", + generate_package_referents) + ] + + for ref in generate_references(env, object_name, model, + result_class_name, role, result_role, keys_only, handlers): + yield ref diff --git a/src/software/openlmi/software/LMI_MemberOfSoftwareCollection.py b/src/software/openlmi/software/LMI_MemberOfSoftwareCollection.py index 6fa6ea4..e9f73b5 100644 --- a/src/software/openlmi/software/LMI_MemberOfSoftwareCollection.py +++ b/src/software/openlmi/software/LMI_MemberOfSoftwareCollection.py @@ -25,10 +25,51 @@ import pywbem from pywbem.cim_provider2 import CIMProvider2 from openlmi.common import cmpi_logging +from openlmi.software.core import generate_references from openlmi.software.core import SystemSoftwareCollection from openlmi.software.core import SoftwareIdentity from openlmi.software.yumdb import YumDB +@cmpi_logging.trace_function +def generate_collection_referents(env, object_name, model, _keys_only): + """ + Handler for referents enumeration request. + """ + SystemSoftwareCollection.check_path(env, object_name, "collection") + pkg_model = pywbem.CIMInstanceName( + classname='LMI_SoftwareIdentity', + namespace="root/cimv2", + host=model.path.host) + model["Collection"] = SystemSoftwareCollection.get_path() + with YumDB.get_instance() as ydb: + for pkg_info in ydb.get_package_list('available', + allow_duplicates=True, sort=True): + model["Member"] = SoftwareIdentity.pkg2model( + pkg_info, model=pkg_model) + yield model + +@cmpi_logging.trace_function +def generate_member_referents(_env, object_name, model, _keys_only): + """ + Handler for referents enumeration request. + """ + try: + pkg_info = SoftwareIdentity.object_path2pkg( + object_name, kind="available") + model['Member'] = SoftwareIdentity.pkg2model(pkg_info) + model["Collection"] = SystemSoftwareCollection.get_path() + except pywbem.CIMError as exc: + if exc.args[0] == pywbem.CIM_ERR_NOT_FOUND: + msg = "Could not find requested package%s." + if "InstanceID" in object_name: + msg = msg % (' with InstanceID="%s"' %object_name["InstanceID"]) + else: + msg = msg % "" + raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, msg) + else: + raise + yield model + class LMI_MemberOfSoftwareCollection(CIMProvider2): """Instrument the CIM class LMI_MemberOfSoftwareCollection @@ -232,51 +273,13 @@ class LMI_MemberOfSoftwareCollection(CIMProvider2): CIM_ERR_FAILED (some other unspecified error occurred) """ - cimhandle = env.get_cimom_handle() - - model.path.update({'Collection': None, 'Member': None}) - - with YumDB.get_instance() as ydb: - if ( (not role or role.lower() == 'collection') - and cimhandle.is_subclass(object_name.namespace, - sub=object_name.classname, - super='LMI_SystemSoftwareCollection')): - try: - SystemSoftwareCollection.check_path(env, object_name, - "collection") - pkg_model = pywbem.CIMInstanceName( - classname='LMI_SoftwareIdentity', - namespace="root/cimv2", - host=model.path.host) - model["Collection"] = SystemSoftwareCollection.get_path() - for pkg_info in ydb.get_package_list('available', - allow_duplicates=True, sort=True): - model["Member"] = SoftwareIdentity.pkg2model( - pkg_info, model=pkg_model) - yield model - except pywbem.CIMError as exc: - if exc.args[0] != pywbem.CIM_ERR_NOT_FOUND: - raise - - if ( (not role or role.lower() == 'member') - and cimhandle.is_subclass(object_name.namespace, - sub=object_name.classname, - super='LMI_SoftwareIdentity')): - try: - pkg_info = SoftwareIdentity.object_path2pkg( - object_name, kind="available") - model['Member'] = SoftwareIdentity.pkg2model(pkg_info) - model["Collection"] = SystemSoftwareCollection.get_path() - except pywbem.CIMError as exc: - if exc.args[0] == pywbem.CIM_ERR_NOT_FOUND: - msg = "Could not find requested package%s." - if "InstanceID" in object_name: - msg = msg % (' with InstanceID="%s"' % \ - object_name["InstanceID"]) - else: - msg = msg % "" - raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, msg) - else: - raise - yield model + handlers = [ + ("Collection", "LMI_SystemSoftwareCollection", + generate_collection_referents), + ("Member", "LMI_SoftwareIdentity", generate_member_referents) + ] + + for ref in generate_references(env, object_name, model, + result_class_name, role, result_role, keys_only, handlers): + yield ref diff --git a/src/software/openlmi/software/cimom_entry.py b/src/software/openlmi/software/cimom_entry.py index a259ff0..a598fb1 100644 --- a/src/software/openlmi/software/cimom_entry.py +++ b/src/software/openlmi/software/cimom_entry.py @@ -36,6 +36,10 @@ from openlmi.software.LMI_InstalledSoftwareIdentity import \ LMI_InstalledSoftwareIdentity from openlmi.software.LMI_SoftwareIdentityResource import \ LMI_SoftwareIdentityResource +from openlmi.software.LMI_ResourceForSoftwareIdentity import \ + LMI_ResourceForSoftwareIdentity +from openlmi.software.LMI_HostedSoftwareIdentityResource import \ + LMI_HostedSoftwareIdentityResource from openlmi.software.yumdb import YumDB def get_providers(env): @@ -45,12 +49,15 @@ def get_providers(env): cmpi_logging.LogManager(env) providers = { - "LMI_SoftwareIdentity" : LMI_SoftwareIdentity(env), - "LMI_SystemSoftwareCollection" : LMI_SystemSoftwareCollection(env), - "LMI_HostedSoftwareCollection" : LMI_HostedSoftwareCollection(env), - "LMI_MemberOfSoftwareCollection" : LMI_MemberOfSoftwareCollection(env), - "LMI_InstalledSoftwareIdentity" : LMI_InstalledSoftwareIdentity(env), - "LMI_SoftwareIdentityResource" : LMI_SoftwareIdentityResource(env) + "LMI_SoftwareIdentity" : LMI_SoftwareIdentity(env), + "LMI_SystemSoftwareCollection" : LMI_SystemSoftwareCollection(env), + "LMI_HostedSoftwareCollection" : LMI_HostedSoftwareCollection(env), + "LMI_MemberOfSoftwareCollection" : LMI_MemberOfSoftwareCollection(env), + "LMI_InstalledSoftwareIdentity" : LMI_InstalledSoftwareIdentity(env), + "LMI_SoftwareIdentityResource" : LMI_SoftwareIdentityResource(env), + "LMI_ResourceForSoftwareIdentity" : LMI_ResourceForSoftwareIdentity(env), + "LMI_HostedSoftwareIdentityResource" : + LMI_HostedSoftwareIdentityResource(env) } return providers diff --git a/src/software/openlmi/software/core/__init__.py b/src/software/openlmi/software/core/__init__.py index 61158e1..a684897 100644 --- a/src/software/openlmi/software/core/__init__.py +++ b/src/software/openlmi/software/core/__init__.py @@ -24,3 +24,61 @@ Core functionality of particular providers. Each provider having functionality useful to others has a submodule in this subpackage with the same name except for LMI_ prefix. """ + +import pywbem +from openlmi.common import cmpi_logging + +@cmpi_logging.trace_function +def generate_references( + env, + object_name, + model, + filter_result_class_name, + filter_role, + filter_result_role, + keys_only, + handlers): + """ + Function for generating references to object_name. It's supposed + to be used directly from references method of provider classes. + @param handlers is a list of tuples: + [ (role, class_name, handler), ... ] + where handler is a function, that will be called for matching + parameters, yielding instance(s/names). It accepts arguments: + env, object_name, model, keys_only. + """ + if not isinstance(object_name, pywbem.CIMInstanceName): + raise TypeError("object_name must be a CIMInstanceName") + if not isinstance(model, pywbem.CIMInstance): + raise TypeError("model must be a CIMInstance") + + ch = env.get_cimom_handle() + model.path.update(dict((t[0], None) for t in handlers)) + + try: + for i, (role, clsname, handler) in enumerate(handlers): + if ( ( filter_role + and filter_role.lower() != role.lower()) + or not ch.is_subclass(object_name.namespace, + sub=object_name.classname, + super=clsname)): + continue + other_results = list((htuple[0], htuple[1]) for htuple in ( + handlers[:i] + handlers[i+1:])) + for res_role, res_clsname in other_results: + if ( ( not filter_result_role + or filter_result_role.lower() == res_role.lower()) + and (not filter_result_class_name or ch.is_subclass( + object_name.namespace, + sub=filter_result_class_name, + super=res_clsname))): + break + else: + continue + # matches filters + for obj in handler(env, object_name, model, keys_only): + yield obj + except pywbem.CIMError as exc: + if exc.args[0] != pywbem.CIM_ERR_NOT_FOUND: + raise + diff --git a/src/software/test/test_hosted_software_identity_resource.py b/src/software/test/test_hosted_software_identity_resource.py new file mode 100755 index 0000000..af7b491 --- /dev/null +++ b/src/software/test/test_hosted_software_identity_resource.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +# +# Copyright (C) 2012 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 +# +# Authors: Michal Minar +# +""" +Unit tests for LMI_HostedSoftwareIdentityResource provider. +""" + +import pywbem +import socket +import unittest + +import base + +class TestHostedSoftwareIdentityResource(base.SoftwareBaseTestCase): + """ + Basic cim operations test. + """ + + CLASS_NAME = "LMI_HostedSoftwareIdentityResource" + KEYS = ("Antecedent", "Dependent") + + @classmethod + def needs_pkgdb(cls): + return False + + @classmethod + def needs_repodb(cls): + return True + + def make_op(self, repo): + """ + @return object path of HostedSoftwareIdentityResource association + """ + objpath = self.objpath.copy() + objpath["Antecedent"] = pywbem.CIMInstanceName( + classname="Linux_ComputerSystem", + namespace="root/cimv2", + keybindings=pywbem.NocaseDict({ + "CreationClassName" : "Linux_ComputerSystem", + "Name" : socket.gethostname() + })) + objpath["Dependent"] = pywbem.CIMInstanceName( + classname="LMI_SoftwareIdentityResource", + namespace="root/cimv2", + keybindings=pywbem.NocaseDict({ + "CreationClassName" : "LMI_SoftwareIdentityResource", + "SystemCreationClassName" : "Linux_ComputerSystem", + "SystemName" : socket.gethostname(), + "Name" : repo.repoid + })) + return objpath + + def test_get_instance(self): + """ + Tests GetInstance call on repositories from our rpm cache. + """ + for repo in self.repodb: + objpath = self.make_op(repo) + inst = self.conn.GetInstance(InstanceName=objpath) + self.assertEqual(objpath, inst.path, + "Object paths should match for repo %s" % repo.repoid) + for key in self.KEYS: + self.assertTrue(inst.properties.has_key(key), + 'OP is missing \"%s\" key for repo "%s".' % (key, repo.repoid)) + self.assertEqual(inst[key], inst.path[key], + 'Key property "%s" does not match for repo "%s"!' % + (key, repo.repoid)) + + def test_enum_instance_names(self): + """ + Tests EnumInstanceNames call on repositories from our cache. + """ + inames = self.conn.EnumerateInstanceNames(ClassName=self.CLASS_NAME) + repos = { r.repoid: r for r in self.repodb } + self.assertEqual(len(repos), len(inames)) + for iname in inames: + self.assertIn('Dependent', iname) + self.assertIn('Name', iname['Dependent']) + self.assertIn(iname['Dependent']['Name'], repos) + objpath = self.make_op(repos[iname['Dependent']['Name']]) + self.assertEqual(objpath, iname) + + def test_enum_instances(self): + """ + Tests EnumInstanceNames call on repositories from our cache. + """ + inames = self.conn.EnumerateInstances(ClassName=self.CLASS_NAME) + repos = { r.repoid: r for r in self.repodb } + self.assertEqual(len(repos), len(inames)) + for inst in inames: + self.assertIn('Dependent', inst) + self.assertIn('Name', inst['Dependent']) + repoid = inst['Dependent']['Name'] + self.assertIn(repoid, repos) + objpath = self.make_op(repos[repoid]) + self.assertEqual(objpath, inst.path) + for key in self.KEYS: + self.assertTrue(inst.properties.has_key(key), + 'OP is missing \"%s\" key for repo "%s".' % (key, repoid)) + self.assertEqual(inst[key], inst.path[key], + 'Key property "%s" does not match for repo "%s"!' % + (key, repoid)) + + def test_get_antecedent_referents(self): + """ + Test ReferenceNames for ComputerSystem. + """ + if not self.repodb: + return + repo = self.repodb[0] + objpath = self.make_op(repo) + refs = self.conn.AssociatorNames( + Role="Antecedent", + ObjectName=objpath["Antecedent"], + ResultRole="Dependent", + ResultClass="LMI_SoftwareIdentityResource") + repos = {r.repoid: r for r in self.repodb} + for ref in refs: + self.assertIsInstance(ref, pywbem.CIMInstanceName) + self.assertEqual(ref.namespace, 'root/cimv2') + self.assertEqual(ref.classname, "LMI_SoftwareIdentityResource") + self.assertIn("Name", ref.keys()) + objpath = self.make_op(repos[ref["Name"]]) + self.assertEqual(objpath["Dependent"], ref) + del repos[ref["Name"]] + self.assertEqual(0, len(repos)) + + def test_get_dependent_referents(self): + """ + Test ReferenceNames for repository. + """ + for repo in self.repodb: + objpath = self.make_op(repo=repo) + refs = self.conn.AssociatorNames( + Role="Dependent", + ObjectName=objpath["Dependent"], + ResultRole="Antecedent", + ResultClass="Linux_ComputerSystem") + self.assertEqual(len(refs), 1) + self.assertEqual(objpath["Antecedent"], refs[0]) + +def suite(): + """For unittest loaders.""" + return unittest.TestLoader().loadTestsFromTestCase( + TestHostedSoftwareIdentityResource) + +if __name__ == '__main__': + unittest.main() diff --git a/src/software/test/test_resource_for_software_identity.py b/src/software/test/test_resource_for_software_identity.py new file mode 100755 index 0000000..15fc047 --- /dev/null +++ b/src/software/test/test_resource_for_software_identity.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# +# Copyright (C) 2012 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 +# +# Authors: Michal Minar +# +""" +Unit tests for LMI_ResourceForSoftwareIdentity provider. +""" + +import pywbem +import socket +import unittest + +import base + +class TestResourceForSoftwareIdentity(base.SoftwareBaseTestCase): + """ + Basic cim operations test. + """ + + CLASS_NAME = "LMI_ResourceForSoftwareIdentity" + KEYS = ("ManagedElement", "AvailableSAP") + + @classmethod + def needs_repodb(cls): + return True + + def make_op(self, pkg=None, newer=True, repo=None): + """ + @return object path of ResourceForSoftwareIdentity association + """ + objpath = self.objpath.copy() + objpath["AvailableSAP"] = pywbem.CIMInstanceName( + classname="LMI_SoftwareIdentityResource", + namespace="root/cimv2", + keybindings=pywbem.NocaseDict({ + "CreationClassName" : "LMI_SoftwareIdentityResource", + "SystemCreationClassName" : "Linux_ComputerSystem", + "SystemName" : socket.gethostname() + })) + if repo is not None: + objpath["AvailableSAP"]["Name"] = repo.repoid + elif pkg is not None: + objpath["AvailableSAP"]["Name"] = getattr(pkg, + 'up_repo' if newer else 'repo') + objpath["ManagedElement"] = pywbem.CIMInstanceName( + classname="LMI_SoftwareIdentity", + namespace="root/cimv2") + if pkg is not None: + objpath["ManagedElement"]["InstanceID"] = \ + 'LMI:PKG:' + pkg.get_nevra(newer=newer, with_epoch="ALWAYS") + return objpath + + def test_get_instance(self): + """ + Tests GetInstance call on packages from our rpm cache. + """ + for pkg in self.dangerous_pkgs: + objpath = self.make_op(pkg) + inst = self.conn.GetInstance(InstanceName=objpath) + self.assertEqual(objpath, inst.path, + "Object paths should match for package %s"%pkg) + for key in self.KEYS: + self.assertTrue(inst.properties.has_key(key), + 'OP is missing \"%s\" key for package "%s".' % (key, pkg)) + self.assertEqual(inst[key], inst.path[key], + 'Key property "%s" does not match for package "%s"!' % + (key, pkg)) + + @base.mark_tedious + def test_get_resource_referents(self): + """ + Test ReferenceNames for AvailableSAP. + """ + for repo in self.repodb: + objpath = self.make_op(repo=repo) + if not repo.pkg_count or repo.pkg_count > 10000: + # do not test too big repositories + continue + refs = self.conn.AssociatorNames( + Role="AvailableSAP", + ObjectName=objpath["AvailableSAP"], + ResultRole="ManagedElement", + ResultClass="LMI_SoftwareIdentity") + # there may be empty repositories + #self.assertGreater(len(refs), 0) + for ref in refs: + self.assertIsInstance(ref, pywbem.CIMInstanceName) + self.assertEqual(ref.namespace, 'root/cimv2') + self.assertEqual(ref.classname, "LMI_SoftwareIdentity") + self.assertEqual(sorted(ref.keys()), ["InstanceID"]) + self.assertTrue(ref["InstanceID"].startswith("LMI:PKG:")) + + nevra_set = set(i["InstanceID"] for i in refs) + # NOTE: installed packages might not be available + for pkg, up in ((pkg, up) for pkg in self.dangerous_pkgs + for up in (True, False)): + nevra = 'LMI:PKG:'+pkg.get_nevra( + newer=up, with_epoch="ALWAYS") + reponame = getattr(pkg, 'up_repo' if up else 'repo') + if reponame == repo.repoid: + self.assertTrue(nevra in nevra_set, + 'Missing nevra "%s" for repo "%s".' % (nevra, + reponame)) + + @base.mark_tedious + def test_get_resource_referents_for_disabled_repo(self): + """ + Test ReferenceNames for AvailableSAP, which is disabled. + """ + for repo in self.repodb: + if repo.status: + continue # test only disabled repositories + objpath = self.make_op(repo=repo) + refs = self.conn.AssociatorNames( + Role="AvailableSAP", + ObjectName=objpath["AvailableSAP"], + ResultRole="ManagedElement", + ResultClass="LMI_SoftwareIdentity") + self.assertGreater(len(refs), 0) + for ref in refs: + self.assertIsInstance(ref, pywbem.CIMInstanceName) + self.assertEqual(ref.namespace, 'root/cimv2') + self.assertEqual(ref.classname, "LMI_SoftwareIdentity") + self.assertEqual(sorted(ref.keys()), ["InstanceID"]) + self.assertTrue(ref["InstanceID"].startswith("LMI:PKG:")) + + def test_get_managed_element_referents(self): + """ + Test ReferenceNames for SoftwareIdentity. + """ + for pkg, up in ((pkg, up) for pkg in self.dangerous_pkgs + for up in (True, False)): + objpath = self.make_op(pkg, newer=up) + refs = self.conn.AssociatorNames( + ObjectName=objpath["ManagedElement"], + Role="ManagedElement", + ResultRole="AvailableSAP", + ResultClass="LMI_SoftwareIdentityResource") + self.assertEqual(1, len(refs), + 'No repo found for pkg "%s".' % pkg.get_nevra(newer=up, + with_epoch="ALWAYS")) + ref = refs[0] + self.assertIsInstance(ref, pywbem.CIMInstanceName) + self.assertEqual(ref.namespace, 'root/cimv2') + self.assertEqual(ref.classname, "LMI_SoftwareIdentityResource") + self.assertEqual(sorted(ref.keys()), + sorted(["SystemCreationClassName", "SystemName", + "Name", "CreationClassName"])) + self.assertEqual( + getattr(pkg, 'up_repo' if up else 'repo'), + ref["Name"], 'Repository name does not match for pkg "%s"'% + pkg.get_nevra(newer=up, with_epoch="ALWAYS")) + +def suite(): + """For unittest loaders.""" + return unittest.TestLoader().loadTestsFromTestCase( + TestResourceForSoftwareIdentity) + +if __name__ == '__main__': + unittest.main() -- cgit