diff options
author | Michal Minar <miminar@redhat.com> | 2013-08-22 09:37:03 +0200 |
---|---|---|
committer | Michal Minar <miminar@redhat.com> | 2013-08-23 06:47:40 +0200 |
commit | 00d048f15816a319044f192d8a12e09b96f8bf72 (patch) | |
tree | 3273f7cd1a19dcbb21ea8f2b63e55ebb808d15ff /src | |
parent | 1ad3a75d07f2b8d1d0518d76c83c3fb26540bdbe (diff) | |
download | openlmi-providers-00d048f15816a319044f192d8a12e09b96f8bf72.tar.gz openlmi-providers-00d048f15816a319044f192d8a12e09b96f8bf72.tar.xz openlmi-providers-00d048f15816a319044f192d8a12e09b96f8bf72.zip |
software: added FindIdentity() function
Since disablement of SoftwareIdentity enumeration, there has been no way
to search for particular package (using [WC]QL query for example). This
serious limitation is now treated by this addition to
LMI_SoftwareInstallationService.
Diffstat (limited to 'src')
-rw-r--r-- | src/software/lmi/software/LMI_SoftwareInstallationService.py | 93 | ||||
-rw-r--r-- | src/software/lmi/software/core/InstallationService.py | 4 | ||||
-rw-r--r-- | src/software/lmi/software/yumdb/__init__.py | 5 | ||||
-rw-r--r-- | src/software/lmi/software/yumdb/jobs.py | 11 | ||||
-rw-r--r-- | src/software/lmi/software/yumdb/process.py | 33 |
5 files changed, 133 insertions, 13 deletions
diff --git a/src/software/lmi/software/LMI_SoftwareInstallationService.py b/src/software/lmi/software/LMI_SoftwareInstallationService.py index f4cb326..fa31df6 100644 --- a/src/software/lmi/software/LMI_SoftwareInstallationService.py +++ b/src/software/lmi/software/LMI_SoftwareInstallationService.py @@ -25,9 +25,12 @@ Instruments the CIM class LMI_SoftwareInstallationService import pywbem from pywbem.cim_provider2 import CIMProvider2 +from lmi.software.core import Identity +from lmi.software.core import IdentityResource from lmi.software.core import InstallationService from lmi.software.core import Job from lmi.software.util import cmpi_logging +from lmi.software.yumdb import YumDB LOG = cmpi_logging.get_logger(__name__) @@ -859,3 +862,93 @@ class LMI_SoftwareInstallationService(CIMProvider2): rval = exc.return_code return (rval, out_params) + @cmpi_logging.trace_method + def cim_method_findidentity(self, env, object_name, + param_name=None, + param_epoch=None, + param_version=None, + param_release=None, + param_architecture=None, + param_allowduplicates=None, + param_exactmatch=None, + param_repository=None): + """Implements LMI_SoftwareInstallationService.FindIdentity() + + Search for installed or available software identity matching + specified properties. In case "Repository" is given, only + available packages of this repository will be browsed. + "AllowDuplicates" causes, that packages of the name <name>.<arch> + will be listed multiple times if more versions are available. + Other input parameters with non-NULL values are compared to + corresponding properties of LMI_SoftwareIdentity instances. 0 is + returned if any matching package is found, 1 otherwise. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName + specifying the object on which the method FindIdentity() + should be invoked. + param_name -- The input parameter Name (type unicode) + param_repository -- The input parameter Repository ( + type REF (pywbem.CIMInstanceName( + classname='LMI_SoftwareIdentityResource', ...)) + Allows to specify particular software repository, where the + search shall take place. If given, only available packages + will be browsed. + + param_epoch -- The input parameter Epoch (type pywbem.Uint32) + param_version -- The input parameter Version (type unicode) + param_architecture -- The input parameter Architecture (type unicode) + param_allowduplicates -- The input parameter AllowDuplicates ( + type bool) + Whether the different versions of the same package shall be + included in result. This defaults to "False". + param_exactmatch -- The input parameter ExactMatch (type bool) + Whether to compare "Name" for exact match. If "False", package name + and its summary string ("Caption") will be searched for occurences + of "Name" parameter's value. Defaults to "True". + param_release -- The input parameter Release (type unicode) + + Returns a two-tuple containing the return value (type pywbem.Uint32) + and a list of CIMParameter objects representing the output parameters + + Output parameters: + Matches -- (type REF (pywbem.CIMInstanceName( + classname='LMI_SoftwareIdentity', ...)) + All matching packages found shall be available in this + parameter. + + Possible Errors: + CIM_ERR_ACCESS_DENIED + CIM_ERR_INVALID_PARAMETER (including missing, duplicate, + unrecognized or otherwise incorrect parameters) + CIM_ERR_NOT_FOUND (the target CIM Class or instance does not + exist in the specified namespace) + CIM_ERR_METHOD_NOT_AVAILABLE (the CIM Server is unable to honor + the invocation request) + CIM_ERR_FAILED (some other unspecified error occurred) + """ + InstallationService.check_path(env, object_name, "object_name") + out_params = [pywbem.CIMParameter( + 'Matches', type='reference', value=None, is_array=True)] + kwargs = { + 'name' : param_name, + 'epoch' : param_epoch, + 'version' : param_version, + 'release' : param_release, + 'arch' : param_architecture, + 'allow_duplicates' : param_allowduplicates, + 'exact_match' : param_exactmatch, + 'sort' : True, + } + if param_repository is not None: + repo = IdentityResource.object_path2repo(env, param_repository) + kwargs['repoid'] = repo.repoid + pkgs = YumDB.get_instance().filter_packages('all', **kwargs) + out_params[0].value = [Identity.pkg2model(p) for p in pkgs] + if len(pkgs) > 0: + rval = self.values.FindIdentity.Found + else: + rval = self.values.FindIdentity.NoMatch + return (rval, out_params) + diff --git a/src/software/lmi/software/core/InstallationService.py b/src/software/lmi/software/core/InstallationService.py index 1df368f..70df285 100644 --- a/src/software/lmi/software/core/InstallationService.py +++ b/src/software/lmi/software/core/InstallationService.py @@ -560,6 +560,10 @@ class Values(object): 3: 'Error' } + class FindIdentity(object): + Found = pywbem.Uint32(0) + NoMatch = pywbem.Uint32(1) + def get_path(): """@return instance name with prefilled properties""" systemop = ComputerSystem.get_path() diff --git a/src/software/lmi/software/yumdb/__init__.py b/src/software/lmi/software/yumdb/__init__.py index d9cd3bc..5ccdc1b 100644 --- a/src/software/lmi/software/yumdb/__init__.py +++ b/src/software/lmi/software/yumdb/__init__.py @@ -413,6 +413,7 @@ class YumDB(singletonmixin.Singleton): @job_request() def filter_packages(self, kind, allow_duplicates=False, + exact_match=True, sort=False, include_repos=None, exclude_repos=None, @@ -422,8 +423,8 @@ class YumDB(singletonmixin.Singleton): @see yumdb.jobs.YumFilterPackages job for supported filter keys """ return self._do_job(jobs.YumFilterPackages( - kind, allow_duplicates=allow_duplicates, sort=sort, - include_repos=include_repos, exclude_repos=exclude_repos, + kind, allow_duplicates=allow_duplicates, exact_match=exact_match, + sort=sort, include_repos=include_repos, exclude_repos=exclude_repos, **filters)) @job_request() diff --git a/src/software/lmi/software/yumdb/jobs.py b/src/software/lmi/software/yumdb/jobs.py index dbd9d5e..7987382 100644 --- a/src/software/lmi/software/yumdb/jobs.py +++ b/src/software/lmi/software/yumdb/jobs.py @@ -412,7 +412,12 @@ class YumFilterPackages(YumGetPackageList): #pylint: disable=R0903 Job similar to YumGetPackageList, but allowing to specify filter on packages. Arguments (plus those in YumGetPackageList): - name, epoch, version, release, arch, nevra, envra, evra + name, epoch, version, release, arch, nevra, envra, evra, + repoid, exact_match + + Argument ``exact_match`` makes the name property being compared byte + by byte. If ``False``, all packages containing ``name``'s value either + in name of summary will match. Some of those are redundant, but filtering is optimized for speed, so supplying all of them won't affect performance. @@ -421,9 +426,10 @@ class YumFilterPackages(YumGetPackageList): #pylint: disable=R0903 """ __slots__ = ( 'name', 'epoch', 'version', 'release', 'arch', - 'nevra', 'envra', 'evra', 'repoid') + 'nevra', 'envra', 'evra', 'repoid', 'exact_match') def __init__(self, kind, allow_duplicates, + exact_match=True, sort=False, include_repos=None, exclude_repos=None, name=None, epoch=None, version=None, release=None, arch=None, @@ -447,6 +453,7 @@ class YumFilterPackages(YumGetPackageList): #pylint: disable=R0903 self.evra = evra self.envra = envra self.repoid = repoid + self.exact_match = bool(exact_match) class YumSpecificPackageJob(YumAsyncJob): #pylint: disable=R0903 """ diff --git a/src/software/lmi/software/yumdb/process.py b/src/software/lmi/software/yumdb/process.py index 07bca8f..1745e49 100644 --- a/src/software/lmi/software/yumdb/process.py +++ b/src/software/lmi/software/yumdb/process.py @@ -29,6 +29,7 @@ import logging from multiprocessing import Process import os import Queue as TQueue # T as threaded +import re import sys import time import traceback @@ -52,11 +53,14 @@ LOG = None # ***************************************************************************** # Utilities # **************************************************************************** -def _get_package_filter_function(filters): +def _get_package_filter_function(filters, exact_match=True): """ - @param filters is a dictionary, where keys are package property - names and values are their desired values. - @return a function used to filter list of packages + :param filters: (``dict``) Dictionary with keys of package property + names and values of their desired values. + :param exact_match: (``bool``) Whether the ``name`` should be checked + for exact match or for presence in package's name or summary + strings. + :rtype: (``function``) A function used to filter list of packages. """ if not isinstance(filters, dict): raise TypeError("filters must be a dictionary") @@ -78,6 +82,7 @@ def _get_package_filter_function(filters): elif "evra" in filters: for prop_name in ("epoch", "version", "release", "epoch"): filters.pop(prop_name, None) + filter_list = [] # properties are sorted by their filtering ability # (the most unprobable property, that can match, comes first) @@ -85,10 +90,20 @@ def _get_package_filter_function(filters): "release", "repoid", "arch"): if not prop_name in filters: continue + if not exact_match and 'name' in filters: + continue filter_list.append((prop_name, filters.pop(prop_name))) - def _cmp_props(pkg): - """@return True if pkg matches properies filter""" - return all(getattr(pkg, p) == v for p, v in filter_list) + if not exact_match and 'name' in filters: + re_name = re.compile(re.escape(filters['name'])) + def _cmp_props(pkg): + """ :rtype: (``bool``) Does pkg matche properies filter? """ + if re_name.search(pkg.name) or re_name.search(pkg.summary): + return all(getattr(pkg, p) == v for p, v in filter_list) + return False + else: + def _cmp_props(pkg): + """ :rtype: (``bool``) Does pkg matche properies filter? """ + return all(getattr(pkg, p) == v for p, v in filter_list) return _cmp_props class RepoFilterSetter(object): @@ -570,7 +585,7 @@ class YumWorker(Process): @_needs_database def _handle_filter_packages(self, kind, allow_duplicates, sort, - include_repos=None, exclude_repos=None, + exact_match=True, include_repos=None, exclude_repos=None, transform=True, **filters): """ Handler for filtering packages job. @@ -588,7 +603,7 @@ class YumWorker(Process): pkglist = self._handle_get_package_list(kind, allow_duplicates, False, include_repos=include_repos, exclude_repos=exclude_repos, transform=False) - matches = _get_package_filter_function(filters) + matches = _get_package_filter_function(filters, exact_match) result = [p for p in pkglist if matches(p)] if sort is True: result.sort() |