summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichal Minar <miminar@redhat.com>2013-05-10 16:16:46 +0200
committerMichal Minar <miminar@redhat.com>2013-07-03 12:40:22 +0200
commita380de9372056e2530dd7a5a67c54f08ae150a34 (patch)
treef02829f5002bc3b594197c883a4a93981b8f7e86 /src
parentd07c839858c04d528b12bb2d8bf94528f29959f1 (diff)
downloadopenlmi-providers-a380de9372056e2530dd7a5a67c54f08ae150a34.tar.gz
openlmi-providers-a380de9372056e2530dd7a5a67c54f08ae150a34.tar.xz
openlmi-providers-a380de9372056e2530dd7a5a67c54f08ae150a34.zip
added implementation for verification classes
implemented: LMI_SoftwareIdentityFileCheck LMI_SoftwareIdentityChecks
Diffstat (limited to 'src')
-rw-r--r--src/software/openlmi/software/LMI_SoftwareIdentityChecks.py256
-rw-r--r--src/software/openlmi/software/LMI_SoftwareIdentityFileCheck.py244
-rw-r--r--src/software/openlmi/software/cimom_entry.py8
-rw-r--r--src/software/openlmi/software/core/IdentityFileCheck.py965
-rw-r--r--src/software/openlmi/software/yumdb/__init__.py14
-rw-r--r--src/software/openlmi/software/yumdb/errors.py6
-rw-r--r--src/software/openlmi/software/yumdb/jobs.py30
-rw-r--r--src/software/openlmi/software/yumdb/packagecheck.py61
-rw-r--r--src/software/openlmi/software/yumdb/process.py47
9 files changed, 1603 insertions, 28 deletions
diff --git a/src/software/openlmi/software/LMI_SoftwareIdentityChecks.py b/src/software/openlmi/software/LMI_SoftwareIdentityChecks.py
new file mode 100644
index 0000000..f90f6c2
--- /dev/null
+++ b/src/software/openlmi/software/LMI_SoftwareIdentityChecks.py
@@ -0,0 +1,256 @@
+# 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
+#
+# Authors: Michal Minar <miminar@redhat.com>
+#
+
+"""Python Provider for LMI_SoftwareIdentityChecks
+
+Instruments the CIM class LMI_SoftwareIdentityChecks
+
+"""
+
+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 Identity, IdentityFileCheck
+from openlmi.software.yumdb import YumDB
+
+def generate_identity_referents(_env, object_name, model, _keys_only):
+ """
+ Handler for referents enumeration request enumerating file checks
+ associated to software identity.
+ """
+ filecheck_model = pywbem.CIMInstanceName(
+ classname='LMI_SoftwareIdentityFileCheck',
+ namespace="root/cimv2",
+ host=model.path.host)
+ pkg_info = Identity.object_path2pkg(
+ object_name, kind="installed")
+ model['Element'] = Identity.pkg2model(pkg_info)
+ pkg_info, pkg_check = YumDB.get_instance().check_package(pkg_info)
+ for file_name in pkg_check:
+ model['Check'] = IdentityFileCheck.file_check2model(
+ IdentityFileCheck.FileCheck(pkg_info, pkg_check[file_name],
+ pkg_check.file_checksum_type),
+ model=filecheck_model)
+ yield model
+
+def generate_check_referents(_env, object_name, model, _keys_only):
+ """
+ Handler for referents enumeration request enumerating software
+ identities associated to file check.
+ """
+ file_check = IdentityFileCheck.object_path2file_check(object_name)
+ model['Check'] = IdentityFileCheck.file_check2model(file_check)
+ model['Element'] = Identity.pkg2model(file_check.pkg_info)
+ yield model
+
+class LMI_SoftwareIdentityChecks(CIMProvider2):
+ """Instrument the CIM class LMI_SoftwareIdentityChecks
+
+ This association ties a SoftwareElement to a specific Check to validate
+ its state or its movement to the next state. Note that
+ SoftwareElements in a running state cannot transition to another
+ state. Therefore, the value of the Phase property is restricted to 0
+ ("In-State") for SoftwareElements in the running state.
+
+ """
+
+ 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)
+
+ """
+ file_check = IdentityFileCheck.object_path2file_check(model['Check'])
+ model['Check'] = IdentityFileCheck.file_check2model(file_check)
+ model['Element'] = Identity.pkg2model(file_check.pkg_info)
+ 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)
+
+ """
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED,
+ "Enumeration of instances is not supported.")
+
+ @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 = [
+ ("Element", "LMI_SoftwareIdentity", generate_identity_referents),
+ ("Check", "LMI_SoftwareIdentityFileCheck",
+ generate_check_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_SoftwareIdentityFileCheck.py b/src/software/openlmi/software/LMI_SoftwareIdentityFileCheck.py
new file mode 100644
index 0000000..2a79302
--- /dev/null
+++ b/src/software/openlmi/software/LMI_SoftwareIdentityFileCheck.py
@@ -0,0 +1,244 @@
+# 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
+#
+# Authors: Michal Minar <miminar@redhat.com>
+#
+
+"""Python Provider for LMI_SoftwareIdentityFileCheck
+
+Instruments the CIM class LMI_SoftwareIdentityFileCheck
+
+"""
+
+import pywbem
+from pywbem.cim_provider2 import CIMProvider2
+
+from openlmi.common import cmpi_logging
+from openlmi.software.core import IdentityFileCheck
+from openlmi.software.core import ComputerSystem
+
+class LMI_SoftwareIdentityFileCheck(CIMProvider2):
+ """Instrument the CIM class LMI_SoftwareIdentityFileCheck
+
+ Identifies a file contained by RPM package. It's located in directory
+ identified in FileName. The Invoke methods check for file existence
+ and whether its attributes match those given by RPM package.
+
+ """
+
+ def __init__(self, _env):
+ cmpi_logging.logger.debug('Initializing provider %s from %s' \
+ % (self.__class__.__name__, __file__))
+ self.values = IdentityFileCheck.Values
+
+ @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)
+
+ """
+ file_check = IdentityFileCheck.object_path2file_check(model.path)
+ return IdentityFileCheck.file_check2model(file_check, keys_only=False,
+ model=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)
+
+ """
+ # this won't be supported because of enormous amount of data
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED)
+
+ @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 cim_method_invoke(self, env, object_name):
+ """Implements LMI_SoftwareIdentityFileCheck.Invoke()
+
+ The Invoke method evaluates this Check. The details of the
+ evaluation are described by the specific subclasses of CIM_Check.
+ When the SoftwareElement being checked is already installed, the
+ CIM_InstalledSoftwareElement association identifies the
+ CIM_ComputerSystem in whose context the Invoke is executed. If
+ this association is not in place, then the InvokeOnSystem method
+ should be used - since it identifies the TargetSystem as an input
+ parameter of the method. \nThe results of the Invoke method are
+ based on the return value. A zero is returned if the condition is
+ satisfied. A one is returned if the method is not supported. Any
+ other value indicates the condition is not satisfied.
+
+ Keyword arguments:
+ env -- Provider Environment (pycimmb.ProviderEnvironment)
+ object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName
+ specifying the object on which the method Invoke()
+ should be invoked.
+
+ Returns a two-tuple containing the return value (type pywbem.Uint32)
+ and a list of CIMParameter objects representing the output parameters
+
+ Output parameters: none
+
+ 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)
+
+ """
+ file_check = IdentityFileCheck.object_path2file_check(object_name)
+ out_params = []
+ return ( self.values.Invoke.Satisfied
+ if IdentityFileCheck.file_check_passed(file_check)
+ else self.values.Invoke.Not_Satisfied,
+ out_params)
+
+ @cmpi_logging.trace_method
+ def cim_method_invokeonsystem(self, env, object_name,
+ param_targetsystem=None):
+ """Implements LMI_SoftwareIdentityFileCheck.InvokeOnSystem()
+
+ The InvokeOnSystem method evaluates this Check. The details of the
+ evaluation are described by the specific subclasses of CIM_Check.
+ The method\'s TargetSystem input parameter specifies the
+ ComputerSystem in whose context the method is invoked. \nThe
+ results of the InvokeOnSystem method are based on the return
+ value. A zero is returned if the condition is satisfied. A one is
+ returned if the method is not supported. Any other value indicates
+ the condition is not satisfied.
+
+ Keyword arguments:
+ env -- Provider Environment (pycimmb.ProviderEnvironment)
+ object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName
+ specifying the object on which the method InvokeOnSystem()
+ should be invoked.
+ param_targetsystem -- The input parameter TargetSystem (
+ type REF (pywbem.CIMInstanceName(
+ classname='CIM_ComputerSystem', ...))
+ Reference to ComputerSystem in whose context the method is to
+ be invoked.
+
+
+ Returns a two-tuple containing the return value (type pywbem.Uint32)
+ and a list of CIMParameter objects representing the output parameters
+
+ Output parameters: none
+
+ 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)
+ """
+ if param_targetsystem is not None:
+ ComputerSystem.check_path(env, param_targetsystem, "TargetSystem")
+ return self.cim_method_invoke(env, object_name)
+
diff --git a/src/software/openlmi/software/cimom_entry.py b/src/software/openlmi/software/cimom_entry.py
index 70df071..f34188c 100644
--- a/src/software/openlmi/software/cimom_entry.py
+++ b/src/software/openlmi/software/cimom_entry.py
@@ -65,6 +65,10 @@ from openlmi.software.LMI_AssociatedSoftwareJobMethodResult import \
LMI_AssociatedSoftwareJobMethodResult
from openlmi.software.LMI_OwningSoftwareJobElement import \
LMI_OwningSoftwareJobElement
+from openlmi.software.LMI_SoftwareIdentityFileCheck import \
+ LMI_SoftwareIdentityFileCheck
+from openlmi.software.LMI_SoftwareIdentityChecks import \
+ LMI_SoftwareIdentityChecks
from openlmi.software.yumdb import jobmanager, YumDB
def get_providers(env):
@@ -107,7 +111,9 @@ def get_providers(env):
"LMI_AffectedSoftwareJobElement" : LMI_AffectedSoftwareJobElement(env),
"LMI_AssociatedSoftwareJobMethodResult" : \
LMI_AssociatedSoftwareJobMethodResult(env),
- "LMI_OwningSoftwareJobElement" : LMI_OwningSoftwareJobElement(env)
+ "LMI_OwningSoftwareJobElement" : LMI_OwningSoftwareJobElement(env),
+ "LMI_SoftwareIdentityFileCheck" : LMI_SoftwareIdentityFileCheck(env),
+ "LMI_SoftwareIdentityChecks" : LMI_SoftwareIdentityChecks(env)
}
# Initialization of indication manager -- running in separate thread as
diff --git a/src/software/openlmi/software/core/IdentityFileCheck.py b/src/software/openlmi/software/core/IdentityFileCheck.py
new file mode 100644
index 0000000..30112e8
--- /dev/null
+++ b/src/software/openlmi/software/core/IdentityFileCheck.py
@@ -0,0 +1,965 @@
+# -*- 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
+#
+# Authors: Michal Minar <miminar@redhat.com>
+#
+
+"""
+Just a common functionality related to SoftwareIdentityFileCheck provider.
+"""
+
+import hashlib
+import os
+import pywbem
+import stat
+import yum
+
+from openlmi.common import cmpi_logging
+from openlmi.software import util
+from openlmi.software.yumdb import errors
+from openlmi.software.yumdb import jobs
+from openlmi.software.yumdb import packageinfo
+from openlmi.software.yumdb import packagecheck
+from openlmi.software.yumdb import YumDB
+
+class Values(object):
+ class TargetOperatingSystem(object):
+ Unknown = pywbem.Uint16(0)
+ Other = pywbem.Uint16(1)
+ MACOS = pywbem.Uint16(2)
+ ATTUNIX = pywbem.Uint16(3)
+ DGUX = pywbem.Uint16(4)
+ DECNT = pywbem.Uint16(5)
+ Tru64_UNIX = pywbem.Uint16(6)
+ OpenVMS = pywbem.Uint16(7)
+ HPUX = pywbem.Uint16(8)
+ AIX = pywbem.Uint16(9)
+ MVS = pywbem.Uint16(10)
+ OS400 = pywbem.Uint16(11)
+ OS_2 = pywbem.Uint16(12)
+ JavaVM = pywbem.Uint16(13)
+ MSDOS = pywbem.Uint16(14)
+ WIN3x = pywbem.Uint16(15)
+ WIN95 = pywbem.Uint16(16)
+ WIN98 = pywbem.Uint16(17)
+ WINNT = pywbem.Uint16(18)
+ WINCE = pywbem.Uint16(19)
+ NCR3000 = pywbem.Uint16(20)
+ NetWare = pywbem.Uint16(21)
+ OSF = pywbem.Uint16(22)
+ DC_OS = pywbem.Uint16(23)
+ Reliant_UNIX = pywbem.Uint16(24)
+ SCO_UnixWare = pywbem.Uint16(25)
+ SCO_OpenServer = pywbem.Uint16(26)
+ Sequent = pywbem.Uint16(27)
+ IRIX = pywbem.Uint16(28)
+ Solaris = pywbem.Uint16(29)
+ SunOS = pywbem.Uint16(30)
+ U6000 = pywbem.Uint16(31)
+ ASERIES = pywbem.Uint16(32)
+ HP_NonStop_OS = pywbem.Uint16(33)
+ HP_NonStop_OSS = pywbem.Uint16(34)
+ BS2000 = pywbem.Uint16(35)
+ LINUX = pywbem.Uint16(36)
+ Lynx = pywbem.Uint16(37)
+ XENIX = pywbem.Uint16(38)
+ VM = pywbem.Uint16(39)
+ Interactive_UNIX = pywbem.Uint16(40)
+ BSDUNIX = pywbem.Uint16(41)
+ FreeBSD = pywbem.Uint16(42)
+ NetBSD = pywbem.Uint16(43)
+ GNU_Hurd = pywbem.Uint16(44)
+ OS9 = pywbem.Uint16(45)
+ MACH_Kernel = pywbem.Uint16(46)
+ Inferno = pywbem.Uint16(47)
+ QNX = pywbem.Uint16(48)
+ EPOC = pywbem.Uint16(49)
+ IxWorks = pywbem.Uint16(50)
+ VxWorks = pywbem.Uint16(51)
+ MiNT = pywbem.Uint16(52)
+ BeOS = pywbem.Uint16(53)
+ HP_MPE = pywbem.Uint16(54)
+ NextStep = pywbem.Uint16(55)
+ PalmPilot = pywbem.Uint16(56)
+ Rhapsody = pywbem.Uint16(57)
+ Windows_2000 = pywbem.Uint16(58)
+ Dedicated = pywbem.Uint16(59)
+ OS_390 = pywbem.Uint16(60)
+ VSE = pywbem.Uint16(61)
+ TPF = pywbem.Uint16(62)
+ Windows__R__Me = pywbem.Uint16(63)
+ Caldera_Open_UNIX = pywbem.Uint16(64)
+ OpenBSD = pywbem.Uint16(65)
+ Not_Applicable = pywbem.Uint16(66)
+ Windows_XP = pywbem.Uint16(67)
+ z_OS = pywbem.Uint16(68)
+ Microsoft_Windows_Server_2003 = pywbem.Uint16(69)
+ Microsoft_Windows_Server_2003_64_Bit = pywbem.Uint16(70)
+ Windows_XP_64_Bit = pywbem.Uint16(71)
+ Windows_XP_Embedded = pywbem.Uint16(72)
+ Windows_Vista = pywbem.Uint16(73)
+ Windows_Vista_64_Bit = pywbem.Uint16(74)
+ Windows_Embedded_for_Point_of_Service = pywbem.Uint16(75)
+ Microsoft_Windows_Server_2008 = pywbem.Uint16(76)
+ Microsoft_Windows_Server_2008_64_Bit = pywbem.Uint16(77)
+ FreeBSD_64_Bit = pywbem.Uint16(78)
+ RedHat_Enterprise_Linux = pywbem.Uint16(79)
+ RedHat_Enterprise_Linux_64_Bit = pywbem.Uint16(80)
+ Solaris_64_Bit = pywbem.Uint16(81)
+ SUSE = pywbem.Uint16(82)
+ SUSE_64_Bit = pywbem.Uint16(83)
+ SLES = pywbem.Uint16(84)
+ SLES_64_Bit = pywbem.Uint16(85)
+ Novell_OES = pywbem.Uint16(86)
+ Novell_Linux_Desktop = pywbem.Uint16(87)
+ Sun_Java_Desktop_System = pywbem.Uint16(88)
+ Mandriva = pywbem.Uint16(89)
+ Mandriva_64_Bit = pywbem.Uint16(90)
+ TurboLinux = pywbem.Uint16(91)
+ TurboLinux_64_Bit = pywbem.Uint16(92)
+ Ubuntu = pywbem.Uint16(93)
+ Ubuntu_64_Bit = pywbem.Uint16(94)
+ Debian = pywbem.Uint16(95)
+ Debian_64_Bit = pywbem.Uint16(96)
+ Linux_2_4_x = pywbem.Uint16(97)
+ Linux_2_4_x_64_Bit = pywbem.Uint16(98)
+ Linux_2_6_x = pywbem.Uint16(99)
+ Linux_2_6_x_64_Bit = pywbem.Uint16(100)
+ Linux_64_Bit = pywbem.Uint16(101)
+ Other_64_Bit = pywbem.Uint16(102)
+ Microsoft_Windows_Server_2008_R2 = pywbem.Uint16(103)
+ VMware_ESXi = pywbem.Uint16(104)
+ Microsoft_Windows_7 = pywbem.Uint16(105)
+ CentOS_32_bit = pywbem.Uint16(106)
+ CentOS_64_bit = pywbem.Uint16(107)
+ Oracle_Enterprise_Linux_32_bit = pywbem.Uint16(108)
+ Oracle_Enterprise_Linux_64_bit = pywbem.Uint16(109)
+ eComStation_32_bitx = pywbem.Uint16(110)
+ Microsoft_Windows_Server_2011 = pywbem.Uint16(111)
+ Microsoft_Windows_Server_2012 = pywbem.Uint16(113)
+ Microsoft_Windows_8 = pywbem.Uint16(114)
+ Microsoft_Windows_8_64_bit = pywbem.Uint16(115)
+ _reverse_map = {
+ 0 : 'Unknown',
+ 1 : 'Other',
+ 2 : 'MACOS',
+ 3 : 'ATTUNIX',
+ 4 : 'DGUX',
+ 5 : 'DECNT',
+ 6 : 'Tru64 UNIX',
+ 7 : 'OpenVMS',
+ 8 : 'HPUX',
+ 9 : 'AIX',
+ 10 : 'MVS',
+ 11 : 'OS400',
+ 12 : 'OS/2',
+ 13 : 'JavaVM',
+ 14 : 'MSDOS',
+ 15 : 'WIN3x',
+ 16 : 'WIN95',
+ 17 : 'WIN98',
+ 18 : 'WINNT',
+ 19 : 'WINCE',
+ 20 : 'NCR3000',
+ 21 : 'NetWare',
+ 22 : 'OSF',
+ 23 : 'DC/OS',
+ 24 : 'Reliant UNIX',
+ 25 : 'SCO UnixWare',
+ 26 : 'SCO OpenServer',
+ 27 : 'Sequent',
+ 28 : 'IRIX',
+ 29 : 'Solaris',
+ 30 : 'SunOS',
+ 31 : 'U6000',
+ 32 : 'ASERIES',
+ 33 : 'HP NonStop OS',
+ 34 : 'HP NonStop OSS',
+ 35 : 'BS2000',
+ 36 : 'LINUX',
+ 37 : 'Lynx',
+ 38 : 'XENIX',
+ 39 : 'VM',
+ 40 : 'Interactive UNIX',
+ 41 : 'BSDUNIX',
+ 42 : 'FreeBSD',
+ 43 : 'NetBSD',
+ 44 : 'GNU Hurd',
+ 45 : 'OS9',
+ 46 : 'MACH Kernel',
+ 47 : 'Inferno',
+ 48 : 'QNX',
+ 49 : 'EPOC',
+ 50 : 'IxWorks',
+ 51 : 'VxWorks',
+ 52 : 'MiNT',
+ 53 : 'BeOS',
+ 54 : 'HP MPE',
+ 55 : 'NextStep',
+ 56 : 'PalmPilot',
+ 57 : 'Rhapsody',
+ 58 : 'Windows 2000',
+ 59 : 'Dedicated',
+ 60 : 'OS/390',
+ 61 : 'VSE',
+ 62 : 'TPF',
+ 63 : 'Windows (R) Me',
+ 64 : 'Caldera Open UNIX',
+ 65 : 'OpenBSD',
+ 66 : 'Not Applicable',
+ 67 : 'Windows XP',
+ 68 : 'z/OS',
+ 69 : 'Microsoft Windows Server 2003',
+ 70 : 'Microsoft Windows Server 2003 64-Bit',
+ 71 : 'Windows XP 64-Bit',
+ 72 : 'Windows XP Embedded',
+ 73 : 'Windows Vista',
+ 74 : 'Windows Vista 64-Bit',
+ 75 : 'Windows Embedded for Point of Service',
+ 76 : 'Microsoft Windows Server 2008',
+ 77 : 'Microsoft Windows Server 2008 64-Bit',
+ 78 : 'FreeBSD 64-Bit',
+ 79 : 'RedHat Enterprise Linux',
+ 80 : 'RedHat Enterprise Linux 64-Bit',
+ 81 : 'Solaris 64-Bit',
+ 82 : 'SUSE',
+ 83 : 'SUSE 64-Bit',
+ 84 : 'SLES',
+ 85 : 'SLES 64-Bit',
+ 86 : 'Novell OES',
+ 87 : 'Novell Linux Desktop',
+ 88 : 'Sun Java Desktop System',
+ 89 : 'Mandriva',
+ 90 : 'Mandriva 64-Bit',
+ 91 : 'TurboLinux',
+ 92 : 'TurboLinux 64-Bit',
+ 93 : 'Ubuntu',
+ 94 : 'Ubuntu 64-Bit',
+ 95 : 'Debian',
+ 96 : 'Debian 64-Bit',
+ 97 : 'Linux 2.4.x',
+ 98 : 'Linux 2.4.x 64-Bit',
+ 99 : 'Linux 2.6.x',
+ 100 : 'Linux 2.6.x 64-Bit',
+ 101 : 'Linux 64-Bit',
+ 102 : 'Other 64-Bit',
+ 103 : 'Microsoft Windows Server 2008 R2',
+ 104 : 'VMware ESXi',
+ 105 : 'Microsoft Windows 7',
+ 106 : 'CentOS 32-bit',
+ 107 : 'CentOS 64-bit',
+ 108 : 'Oracle Enterprise Linux 32-bit',
+ 109 : 'Oracle Enterprise Linux 64-bit',
+ 110 : 'eComStation 32-bitx',
+ 111 : 'Microsoft Windows Server 2011',
+ 113 : 'Microsoft Windows Server 2012',
+ 114 : 'Microsoft Windows 8',
+ 115 : 'Microsoft Windows 8 64-bit'
+ }
+
+ class ChecksumType(object):
+ UNKNOWN = pywbem.Uint16(0)
+ MD5 = pywbem.Uint16(1)
+ SHA_1 = pywbem.Uint16(2)
+ RIPE_MD_160 = pywbem.Uint16(3)
+ SHA256 = pywbem.Uint16(8)
+ SHA384 = pywbem.Uint16(9)
+ SHA512 = pywbem.Uint16(10)
+ SHA224 = pywbem.Uint16(11)
+ _reverse_map = {
+ 0 : 'UNKNOWN',
+ 1 : 'MD5',
+ 2 : 'SHA-1',
+ 3 : 'RIPE-MD/160',
+ 8 : 'SHA256',
+ 9 : 'SHA384',
+ 10 : 'SHA512',
+ 11 : 'SHA224'
+ }
+
+ class FileType(object):
+ Unknown = pywbem.Uint16(0)
+ File = pywbem.Uint16(1)
+ Directory = pywbem.Uint16(2)
+ Symlink = pywbem.Uint16(3)
+ FIFO = pywbem.Uint16(4)
+ Character_Device = pywbem.Uint16(5)
+ Block_Device = pywbem.Uint16(6)
+ _reverse_map = {
+ 0 : 'Unknown',
+ 1 : 'File',
+ 2 : 'Directory',
+ 3 : 'Symlink',
+ 4 : 'FIFO',
+ 5 : 'Character Device',
+ 6 : 'Block Device'
+ }
+
+ class FileModeFlags(object):
+ Execute_Other = pywbem.Uint8(0)
+ Write_Other = pywbem.Uint8(1)
+ Read_Other = pywbem.Uint8(2)
+ Execute_Group = pywbem.Uint8(3)
+ Write_Group = pywbem.Uint8(4)
+ Read_Group = pywbem.Uint8(5)
+ Execute_User = pywbem.Uint8(6)
+ Write_User = pywbem.Uint8(7)
+ Read_User = pywbem.Uint8(8)
+ Sticky = pywbem.Uint8(9)
+ SGID = pywbem.Uint8(10)
+ SUID = pywbem.Uint8(11)
+ _reverse_map = {
+ 0 : 'Execute Other',
+ 1 : 'Write Other',
+ 2 : 'Read Other',
+ 3 : 'Execute Group',
+ 4 : 'Write Group',
+ 5 : 'Read Group',
+ 6 : 'Execute User',
+ 7 : 'Write User',
+ 8 : 'Read User',
+ 9 : 'Sticky',
+ 10 : 'SGID',
+ 11 : 'SUID'
+ }
+
+ class FileModeFlagsOriginal(object):
+ Execute_Other = pywbem.Uint8(0)
+ Write_Other = pywbem.Uint8(1)
+ Read_Other = pywbem.Uint8(2)
+ Execute_Group = pywbem.Uint8(3)
+ Write_Group = pywbem.Uint8(4)
+ Read_Group = pywbem.Uint8(5)
+ Execute_User = pywbem.Uint8(6)
+ Write_User = pywbem.Uint8(7)
+ Read_User = pywbem.Uint8(8)
+ Sticky = pywbem.Uint8(9)
+ SGID = pywbem.Uint8(10)
+ SUID = pywbem.Uint8(11)
+ _reverse_map = {
+ 0 : 'Execute Other',
+ 1 : 'Write Other',
+ 2 : 'Read Other',
+ 3 : 'Execute Group',
+ 4 : 'Write Group',
+ 5 : 'Read Group',
+ 6 : 'Execute User',
+ 7 : 'Write User',
+ 8 : 'Read User',
+ 9 : 'Sticky',
+ 10 : 'SGID',
+ 11 : 'SUID'
+ }
+
+ class FailedFlags(object):
+ Existence = pywbem.Uint16(0)
+ FileSize = pywbem.Uint16(1)
+ FileMode = pywbem.Uint16(2)
+ Checksum = pywbem.Uint16(3)
+ Device_Number = pywbem.Uint16(4)
+ LinkTarget = pywbem.Uint16(5)
+ UserID = pywbem.Uint16(6)
+ GroupID = pywbem.Uint16(7)
+ Last_Modification_Time = pywbem.Uint16(8)
+ _reverse_map = {
+ 0 : 'Existence',
+ 1 : 'FileSize',
+ 2 : 'FileMode',
+ 3 : 'Checksum',
+ 4 : 'Device Number',
+ 5 : 'LinkTarget',
+ 6 : 'UserID',
+ 7 : 'GroupID',
+ 8 : 'Last Modification Time'
+ }
+
+ class SoftwareElementState(object):
+ Deployable = pywbem.Uint16(0)
+ Installable = pywbem.Uint16(1)
+ Executable = pywbem.Uint16(2)
+ Running = pywbem.Uint16(3)
+ _reverse_map = {
+ 0 : 'Deployable',
+ 1 : 'Installable',
+ 2 : 'Executable',
+ 3 : 'Running'
+ }
+
+ class FileTypeOriginal(object):
+ Unknown = pywbem.Uint16(0)
+ File = pywbem.Uint16(1)
+ Directory = pywbem.Uint16(2)
+ Symlink = pywbem.Uint16(3)
+ FIFO = pywbem.Uint16(4)
+ Character_Device = pywbem.Uint16(5)
+ Block_Device = pywbem.Uint16(6)
+ _reverse_map = {
+ 0 : 'Unknown',
+ 1 : 'File',
+ 2 : 'Directory',
+ 3 : 'Symlink',
+ 4 : 'FIFO',
+ 5 : 'Character Device',
+ 6 : 'Block Device'
+ }
+
+ class Invoke(object):
+ """
+ This is not an enumeration from mof file, it just gives human
+ names to numeric values.
+ """
+ Satisfied = pywbem.Uint32(0)
+ Not_Supported = pywbem.Uint32(1)
+ Not_Satisfied = pywbem.Uint32(2)
+
+class FileCheck(object):
+ """
+ File attribute storage keeping both RPM database metadata and info
+ from local filesystem for single file. Most attributes are loaded at the
+ time of first request and cached for later use.
+
+ Most of properties return tuple:
+ ``(installed, original)``
+ where
+ ``installed`` is a state of property of installed file, while
+ ``original`` is the value stored in RPM database.
+
+ If any of those values are None, it means that property could not be
+ retrieved or it's not applicable to file's type.
+ """
+
+ def __init__(self, pkg_info, pkg_file, checksum_type):
+ """
+ :param pkg_file: (``yumdb.packagecheck.PackageFile``) Metadata for
+ file loaded from rpm database.
+ :param checksum_type: (``int``) Indentificator of checksum algorithm
+ corresponding to values in yum.constants.RPM_CHECKSUM_TYPES.
+ """
+ if not isinstance(pkg_info, packageinfo.PackageInfo):
+ raise TypeError("pkg_info must be an instance of PackageInfo")
+ if not isinstance(pkg_file, packagecheck.PackageFile):
+ raise TypeError("pkg_file must be an instance of PackageFile")
+ self._pkg_info = pkg_info
+ self._pkg_file = pkg_file
+ self._exists = None
+ # (md5 checksum, rpm-type checksum) - this is made on first request
+ self._checksums = None
+ self._checksum_type = checksum_type
+ self._link_target = None
+ # stores result of os.stat() call
+ self._stat = None
+
+ @property
+ def pkg_info(self):
+ """:rtype: (``PackageInfo``)"""
+ return self._pkg_info
+
+ @property
+ def pkg_file(self):
+ """:rtype: (``PackageFile``)"""
+ return self._pkg_file
+
+ @property
+ def path(self):
+ """Return absolute file path."""
+ return self._pkg_file.path
+
+ @property
+ def exists(self):
+ """Return true if file exists on local file system."""
+ if self._exists is None:
+ self._exists = os.path.lexists(self._pkg_file.path)
+ return self._exists
+
+ @property
+ def stat(self):
+ """
+ Return cached stat object - result of ``os.lstat()``.
+ None is returned if file does not exist.
+ """
+ if self._stat is None and self.exists:
+ self._stat = os.lstat(self.path)
+ return self._stat
+
+ @property
+ def file_type(self):
+ """
+ Return identifiers of file type for installed and rpm file.
+ If the installed file does not exist, None is returned on
+ its position.
+ :rtype: (``tuple``) Pair of (installed, original).
+ """
+ fm = self.file_mode[0]
+ if fm is None:
+ ft = None
+ elif stat.S_ISLNK(fm):
+ ft = packagecheck.FILE_TYPE_SYMLINK
+ elif stat.S_ISDIR(fm):
+ ft = packagecheck.FILE_TYPE_DIRECTORY
+ elif stat.S_ISFIFO(fm):
+ ft = packagecheck.FILE_TYPE_FIFO
+ elif stat.S_ISCHR(fm):
+ ft = packagecheck.FILE_TYPE_CHARACTER_DEVICE
+ elif stat.S_ISBLK(fm):
+ ft = packagecheck.FILE_TYPE_BLOCK_DEVICE
+ elif stat.S_ISREG(fm):
+ ft = packagecheck.FILE_TYPE_FILE
+ else:
+ ft = packagecheck.FILE_TYPE_UNKNOWN
+ return (ft, self._pkg_file.file_type)
+
+ @property
+ def md5_checksum(self):
+ """
+ Return md5 checksum string of installed file.
+ This is computed on first access either to this or ``file_checksum``
+ property and cached for later access.
+ :rtype: (``str``)
+ """
+ if self._checksums is None:
+ self.make_checksums()
+ return self._checksums[0] if self._checksums else None
+
+ @property
+ def file_checksum_type(self):
+ """
+ Return identifier of hash algorithm used in rpm package.
+ :rtype: (``int``)
+ """
+ return self._checksum_type
+
+ @property
+ def file_checksum(self):
+ """
+ Return checksum strings for installed and rpm file.
+ This is computed on first access either to this or ``md5_checksum``
+ property and cached for later access.
+ :rtype: (``tuple``) Pair of (installed, original).
+ """
+ if self._checksums is None:
+ self.make_checksums()
+ return ( self._checksums[1] if self._checksums else None
+ , self._pkg_file.checksum)
+
+ @property
+ def file_size(self):
+ """:rtype: (``tuple``) Pair of (installed, original)."""
+ return (self.getstat('size'), self._pkg_file.size)
+
+ @property
+ def file_mode(self):
+ """:rtype: (``tuple``) Pair of (installed, original)."""
+ return (self.getstat('mode'), self._pkg_file.mode)
+
+ @property
+ def device(self):
+ """:rtype: (``tuple``) Pair of (installed, original)."""
+ return (self.getstat('dev'), self._pkg_file.device)
+
+ @property
+ def link_target(self):
+ """:rtype: (``tuple``) Pair of (installed, original)."""
+ if ( self.file_type[0] == packagecheck.FILE_TYPE_SYMLINK
+ and self._link_target is None):
+ self._link_target = os.readlink(self.path)
+ return (self._link_target, self._pkg_file.link_target)
+
+ @property
+ def user_id(self):
+ """:rtype: (``tuple``) Pair of (installed, original)."""
+ return (self.getstat('uid'), self._pkg_file.uid)
+
+ @property
+ def group_id(self):
+ """:rtype: (``tuple``) Pair of (installed, original)."""
+ return (self.getstat('gid'), self._pkg_file.gid)
+
+ @property
+ def last_modification_time(self):
+ """:rtype: (``tuple``) Pair of (installed, original)."""
+ return (self.getstat('mtime'), self._pkg_file.mtime)
+
+ def getstat(self, attr):
+ """
+ Get attribute from stat object for given file.
+ :param attr: (``str``) Will be prefixed with "st_".
+ """
+ if self.stat is not None:
+ return getattr(self.stat, "st_"+attr)
+
+ def make_checksums(self):
+ """
+ Compute checksums for installed file and cache them.
+ :rtype: (``tuple``) MD5 and rpm-type checksums for given file
+ as a pair.
+ """
+ if self.file_type[0] == packagecheck.FILE_TYPE_FILE:
+ self._checksums = compute_checksums(
+ self._checksum_type, self.path)
+ else:
+ self._checksums = None
+ return self._checksums
+
+
+@cmpi_logging.trace_function
+def hashfile(afile, hashers, blocksize=65536):
+ """
+ Generic function computing multiple hashes from single file at once.
+
+ :param hashers: (``list``) A list of hash objects.
+ :rtype: (``list``) List of digest strings (in hex format) for each
+ given hash object in the same order.
+ """
+ if not isinstance(hashers, (tuple, list, set, frozenset)):
+ hashers = (hashers, )
+ buf = afile.read(blocksize)
+ while len(buf) > 0:
+ for hashfunc in hashers:
+ hashfunc.update(buf)
+ buf = afile.read(blocksize)
+ return [ hashfunc.hexdigest() for hashfunc in hashers ]
+
+@cmpi_logging.trace_function
+def compute_checksums(checksum_type, file_path):
+ """
+ Compute file checksums in one go.
+
+ :param checksum_type: (``int`) Selected hash algorithm to compute second
+ checksum (the one used for rpm package). Correct value can be
+ obtained from ``yum.constants.RPM_CHECKSUM_TYPES``.
+ :param file_path: (``str``) Absolute path of regular file to hash.
+ :rtype (md5sum, checksum) Tuple of strings containing hex represention
+ of computed checksums.
+
+ Both checksums are computed from file_path's content.
+ First one is always md5, the second one depends on checksum_type.
+ If file does not exists, (None, None) is returned.
+ """
+ cmpi_logging.logger.debug(
+ "checksuming file %s", file_path)
+ hashers = [hashlib.md5()] #pylint: disable=E1101
+ if checksum_type != packagecheck.CHECKSUMTYPE_STR2NUM["md5"]:
+ hashers.append(checksumtype_num2hash(checksum_type)())
+ try:
+ with open(file_path, 'rb') as fobj:
+ rslts = hashfile(fobj, hashers)
+ except (OSError, IOError) as exc:
+ cmpi_logging.logger.error("could not open file \"%s\""
+ " for reading: %s", file_path, exc)
+ return None, None
+ return (rslts[0], rslts[1] if len(rslts) > 1 else rslts[0]*2)
+
+@cmpi_logging.trace_function
+def checksumtype_num2hash(csumt):
+ """
+ Get checksum function for rpm hash identifier.
+
+ :param csumt: (``int``) Checksum type as a number obtained from package.
+ :rtype: (``function``) Hash function object corresponding to csumt.
+ """
+ return getattr(hashlib, yum.constants.RPM_CHECKSUM_TYPES[csumt])
+
+@cmpi_logging.trace_function
+def mode2pywbem_flags(mode):
+ """
+ Utility for creation of value of ``FileModeFlags`` property out of file's
+ raw mode.
+
+ :param mode: (``int``) File's mode. Retrieved from os.lstat().
+ If None, file does not exist.
+ :rtype: (``list``) Of integer flags describing file's access permissions.
+ """
+ if mode is None:
+ return None
+ flags = []
+ for i, flag in enumerate((
+ stat.S_IXOTH,
+ stat.S_IWOTH,
+ stat.S_IROTH,
+ stat.S_IXGRP,
+ stat.S_IWGRP,
+ stat.S_IRGRP,
+ stat.S_IXUSR,
+ stat.S_IWUSR,
+ stat.S_IRUSR,
+ stat.S_ISVTX,
+ stat.S_ISGID,
+ stat.S_ISUID)):
+ if flag & mode:
+ flags.append(pywbem.Uint8(i))
+ return flags
+
+def get_existing_check_from_job(check_id):
+ """
+ ``CheckID`` of ``LMI_SoftwareIdentityFileCheck`` refers to asynchronous job
+ that caused creation of this file check. Let's parse it, get the job out
+ of YumWorker and ask it for results so they don't have to be computed
+ again.
+
+ :param check_id: (``str``) Value of ``CheckID`` property.
+ :rtype: (``tuple``) Pair of (pkg_info, pkg_check).
+ ``None`` if job does not exists anymore.
+ """
+ try:
+ match = util.RE_INSTANCE_ID.match(check_id)
+ if not match:
+ raise ValueError(check_id)
+ if ( not match.group('clsname').lower()
+ == "LMI_SoftwareVerificationJob".lower()):
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ "CheckID does not contain supported job class name: "
+ " %s != %s" % (match.group('clsname'),
+ "LMI_SoftwareVerificationJob".lower()))
+ job_id = int(match.group('id'))
+ job = YumDB.get_instance().get_job(check_id)
+ if not isinstance(job,
+ (jobs.YumCheckPackage, jobs.YumCheckPackageFile)):
+ cmpi_logging.logger.error(
+ 'CheckID="%s" of LMI_SoftwareIdentityFileCheck refers'
+ ' to job %s.', check_id, job)
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ "CheckID refers to wrong job.")
+ return job.result_data
+
+ except errors.JobNotFound:
+ # allow this - job could already be deleted
+ cmpi_logging.logger.warn("could not find YumCheckPackage or"
+ " YumCheckPackageFile job with id \"%d\"" % job_id)
+ except ValueError:
+ raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER,
+ "Could not parse \"CheckID\" key property: \"%s\"." % check_id)
+
+@cmpi_logging.trace_function
+def object_path2file_check(objpath):
+ """
+ @return (package_info, package_check, file_name)
+ """
+ if not isinstance(objpath, pywbem.CIMInstanceName):
+ raise TypeError("objpath must be instance of CIMInstanceName, "
+ "not \"%s\"" % objpath.__class__.__name__)
+
+ for key in ('Name', 'SoftwareElementID', 'Version',
+ 'SoftwareElementState', 'TargetOperatingSystem'):
+ if not key in objpath or not objpath[key]:
+ raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER,
+ "Missing key property \"%s\"." % key)
+ version_match = util.RE_EVRA.match(objpath['Version'])
+ if not version_match:
+ raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER,
+ 'Failed to parse \"Version\" property for valid EVRA: "%s".' %
+ objpath['Version'])
+ pkg_fltr = util.nevra2filter(objpath["SoftwareElementID"])
+ if any( pkg_fltr[attr] != version_match.group(attr)
+ for attr in ('epoch', 'version', 'release', 'arch')):
+ raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER,
+ 'Inconsistent \"Version\" and \"SoftwareElementID\" key'
+ ' properties.')
+ if ( objpath['SoftwareElementState']
+ != Values.SoftwareElementState.Executable):
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ "Only \"Executable\" software element state supported")
+ if not util.check_target_operating_system(
+ objpath['TargetOperatingSystem']):
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ "Wrong target operating system.")
+
+ ydb = YumDB.get_instance()
+ pkg_check = None
+ if ( objpath["CheckID"].lower()
+ != "LMI:LMI_SoftwareIdentityFileCheck".lower()):
+ check = get_existing_check_from_job(objpath["CheckID"])
+ if check is not None:
+ pkg_info, pkg_check = check
+ # else - job does not exist (could be deleted)
+
+ if pkg_check is None:
+ # let the YumWorker check the rest
+ try:
+ pkg_info, pkg_check = ydb.check_package_file(
+ objpath["SoftwareElementID"], objpath["Name"])
+ except errors.PackageNotFound:
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ "Could not find package matching SoftwareElementID \"%s\"" %
+ objpath["SoftwareElementID"])
+ except errors.FileNotFound as exc:
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, exc.args[1])
+
+ # last check for file path
+ if objpath["Name"] not in pkg_check:
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ 'File \"%s\" not found in package \"%s\".' %
+ objpath["SoftwareElementID"])
+ return FileCheck(pkg_info, pkg_check[objpath["Name"]],
+ pkg_check.file_checksum_type)
+
+@cmpi_logging.trace_function
+def test_file(pkg_info, checksum_type, pkg_file):
+ """
+ :param checksum_type: (``int``) Identifier of checksum algorithm used
+ in rpm package. It's one of keys of
+ ``yum.constants.RPM_CHECKSUM_TYPES`` dictionary.
+ :rtype: (``FileCheck``)
+ """
+ for var, cls in (
+ ("pkg_info", packageinfo.PackageInfo),
+ ("pkg_file", packagecheck.PackageFile)):
+ if not isinstance(locals()[var], cls):
+ raise TypeError("%s must be an instance of %s, not %s" % (
+ var, cls.__name__, pkg_file.__class__.__name__))
+ return FileCheck(pkg_info, pkg_file, checksum_type)
+
+@cmpi_logging.trace_function
+def _file_check2failed_flags(file_check):
+ """
+ Makes value of ``FailedFlags`` property from ``FileCheck`` instance.
+
+ :param file_check: (``FileCheck``)
+ :rtype: (``pywbem.CIMProperty``) Property ``FailedFlags`` value.
+ """
+ if not isinstance(file_check, FileCheck):
+ raise TypeError("file_check must be an instance of FileCheck")
+
+ if not file_check.exists:
+ return [Values.FailedFlags.Existence]
+ flags = set()
+ fails_on = lambda attr: (
+ getattr(file_check, attr)[0] != getattr(file_check, attr)[1])
+ if fails_on('file_type'):
+ flags.add(Values.FailedFlags.FileMode)
+
+ # file type specific checks
+ if file_check.file_type[1] == packagecheck.FILE_TYPE_FILE:
+ if fails_on('file_size'):
+ flags.add(Values.FailedFlags.FileSize)
+ if fails_on('last_modification_time'):
+ flags.add(Values.FailedFlags.Last_Modification_Time)
+ if fails_on('file_checksum'):
+ flags.add(Values.FailedFlags.Checksum)
+ elif file_check.file_type[1] in (
+ packagecheck.FILE_TYPE_CHARACTER_DEVICE,
+ packagecheck.FILE_TYPE_BLOCK_DEVICE):
+ if fails_on('device'):
+ flags.add(Values.FailedFlags.Device_Number)
+ elif file_check.file_type[1] == packagecheck.FILE_TYPE_SYMLINK:
+ if fails_on('link_target'):
+ flags.add(Values.FailedFlags.LinkTarget)
+
+ # generic checks
+ if ( fails_on('file_mode')
+ # do not check permissions for symlinks
+ and file_check.file_type[1] != packagecheck.FILE_TYPE_SYMLINK):
+ flags.add(Values.FailedFlags.FileMode)
+ if fails_on('user_id'):
+ flags.add(Values.FailedFlags.UserID)
+ if fails_on('group_id'):
+ flags.add(Values.FailedFlags.GroupID)
+
+ return list(flags)
+
+@cmpi_logging.trace_function
+def file_check_passed(file_check):
+ """
+ Verify single file and return true if it passes.
+ """
+ return len(_file_check2failed_flags(file_check)) == 0
+
+@cmpi_logging.trace_function
+def _fill_non_key_values(model, file_check):
+ """
+ Fills a non key values into instance of SoftwareIdentityFileCheck.
+
+ :param model: (``CIMInstance``) Model, that will be filled with
+ all supported non-key properties.
+ """
+ set_prop = lambda name, kwargs: \
+ model.__setitem__(name, pywbem.CIMProperty(name, **kwargs))
+
+ set_prop("CheckMode", dict(type='boolean', value=True))
+ model["ChecksumType"] = pywbem.Uint16(file_check.file_checksum_type)
+
+ set_prop("FailedFlags", dict(type='uint16', is_array=True,
+ value=_file_check2failed_flags(file_check)))
+ for mattr, fattr, kwargs, convert in (
+ ('LastModificationTime', 'last_modification_time',
+ {'type':'uint64'}, pywbem.Uint64),
+ ('FileType' , 'file_type' ,{'type':'uint16'}, pywbem.Uint16),
+ ('UserID' , 'user_id' ,{'type':'uint32'}, pywbem.Uint32),
+ ('GroupID' , 'group_id' ,{'type':'uint32'}, pywbem.Uint32),
+ ('FileMode' , 'file_mode' ,{'type':'uint32'}, pywbem.Uint32),
+ ('FileSize' , 'file_size' ,{'type':'uint64'}, pywbem.Uint64),
+ ('LinkTarget' , 'link_target' ,{'type':'string'}, str),
+ ('FileChecksum', 'file_checksum',{'type':'string'}, str)):
+ installed, orig = getattr(file_check, fattr)
+ kwargs['value'] = None if orig is None else convert(orig)
+ set_prop(mattr+"Original", kwargs)
+ kwargs['value'] = None if installed is None else convert(installed)
+ set_prop(mattr, kwargs)
+ model['FileName'] = os.path.basename(file_check.path)
+ for suf in ('', 'Original'):
+ set_prop('FileModeFlags'+suf, dict(type='uint8', is_array=True,
+ value=mode2pywbem_flags(file_check.file_mode[1])))
+ set_prop("FileExists", dict(type='boolean', value=file_check.exists))
+ set_prop('MD5Checksum', dict(type='string',
+ value=file_check.md5_checksum))
+
+@cmpi_logging.trace_function
+def file_check2model(file_check, keys_only=True, model=None, job=None):
+ """
+ :param file_check: (``FileCheck``) File check information to transform
+ to cim instance.
+ :param keys_only: (``bool``) Whether to fill non-key properties.
+ :param model: (``CIMInstance`` | ``CIMInstanceName``) If given,
+ it will be used as a template. Only property values will be set.
+ This instance will be returned on completion.
+ :param job: (``YumAsyncJob``) If this is a consequence of asynchronous
+ job operation, the instance of job should be supplied so that
+ ``CheckID`` property can be filled.
+ :rtype: (``CIMInstance`` | ``CIMInstanceName``) Object of
+ LMI_SoftwareIdentityFileCheck with filled desired values.
+ """
+ if job is not None and not isinstance(job, jobs.YumCheckPackage):
+ raise TypeError("job must be instance of jobs.YumCheckPackage")
+ if not isinstance(file_check, FileCheck):
+ raise TypeError("file_check must be an instance of FileCheck")
+
+ if model is None:
+ model = pywbem.CIMInstanceName("LMI_SoftwareIdentityFileCheck",
+ namespace="root/cimv2")
+ if not keys_only:
+ model = pywbem.CIMInstance("LMI_SoftwareIdentityFileCheck",
+ path=model)
+
+ if not keys_only:
+ model.path.update( #pylint: disable=E1103
+ {k: None for k in ("Name", "SoftwareElementID",
+ "SoftwareElementState", "TargetOperatingSystem", "Version",
+ "CheckID")})
+
+ model['Name'] = file_check.path
+ model['SoftwareElementID'] = file_check.pkg_info.nevra
+ model['SoftwareElementState'] = Values.SoftwareElementState.Executable
+ model['TargetOperatingSystem'] = pywbem.Uint16(
+ util.get_target_operating_system()[0])
+ model['Version'] = file_check.pkg_info.evra
+ model['CheckID'] = ("LMI:LMI_SoftwareVerificationJob:%d" % job.jobid
+ if job is not None else "LMI:%s" % model.classname)
+ if not keys_only:
+ _fill_non_key_values(model, file_check)
+ return model
+
diff --git a/src/software/openlmi/software/yumdb/__init__.py b/src/software/openlmi/software/yumdb/__init__.py
index ccb4360..b913bfa 100644
--- a/src/software/openlmi/software/yumdb/__init__.py
+++ b/src/software/openlmi/software/yumdb/__init__.py
@@ -561,6 +561,20 @@ class YumDB(singletonmixin.Singleton):
pkg, async=async, metadata=metadata))
@job_request(async=True)
+ def check_package_file(self, pkg, file_name, async=False):
+ """
+ Return all necessary information from package database concerning
+ on particular file of package. If ``pkg`` does not contain
+ ``file_name``, ``FileNotFound`` error is raised.
+
+ :param pkg: (``PackageInfo``) An instance of PackageInfo
+ representing installed package or its nevra string.
+ :rtype: (``PackageFile``)
+ """
+ return self._do_job(_make_async_job(jobs.YumCheckPackageFile,
+ pkg, file_name, async=async))
+
+ @job_request(async=True)
def install_package_from_uri(self, uri,
async=False, update_only=False, force=False, **metadata):
"""
diff --git a/src/software/openlmi/software/yumdb/errors.py b/src/software/openlmi/software/yumdb/errors.py
index a6824b9..34230e5 100644
--- a/src/software/openlmi/software/yumdb/errors.py
+++ b/src/software/openlmi/software/yumdb/errors.py
@@ -59,6 +59,12 @@ class PackageNotInstalled(PackageError):
"""Raised, when requested package is not installed for desired action."""
def __init__(self, pkg):
PackageError.__init__(self, 'Package "%s" is not installed.' % pkg)
+class FileNotFound(PackageError):
+ """
+ Raised, when requesting check on file that does not belong to
+ particular package.
+ """
+ pass
class RepositoryError(YumDBError):
pass
diff --git a/src/software/openlmi/software/yumdb/jobs.py b/src/software/openlmi/software/yumdb/jobs.py
index 5195f50..966e625 100644
--- a/src/software/openlmi/software/yumdb/jobs.py
+++ b/src/software/openlmi/software/yumdb/jobs.py
@@ -534,14 +534,40 @@ class YumCheckPackage(YumSpecificPackageJob): #pylint: disable=R0903
"""
Request verification information for instaled package and its files.
- Worker replies with new instance of yumdb.PackageCheck.
+ Arguments:
+ pkg - either instance of PackageInfo or nevra string.
+ In latter case it will be replaced for YumWorker with instance
+ of PackageInfo.
+
+ Worker replies with ``(pkg_info, pkg_check)``.
+ where:
+ ``pkg_info`` - is instance of PackageInfo
+ ``pkg_check`` - new instance of yumdb.PackageCheck
"""
def __init__(self, pkg, async=False, metadata=None):
YumSpecificPackageJob.__init__(self, pkg, async=async,
metadata=metadata)
- if not pkg.installed:
+ if isinstance(pkg, PackageInfo) and not pkg.installed:
raise ValueError("package must be installed to check it")
+class YumCheckPackageFile(YumCheckPackage): #pylint: disable=R0903
+ """
+ Request verification information for particular file of installed
+ package.
+
+ Worker replies with ``(pkg_info, pkg_check)``.
+ where:
+ ``pkg_info`` - is instance of PackageInfo
+ ``pkg_check`` - new instance of yumdb.PackageCheck containing only
+ requested file.
+ """
+ __slots__ = ('file_name', )
+ def __init__(self, pkg, file_name, *args, **kwargs):
+ YumCheckPackage.__init__(self, pkg, *args, **kwargs)
+ if not isinstance(file_name, basestring):
+ raise TypeError("file_name must be string")
+ self.file_name = file_name
+
class YumInstallPackageFromURI(YumAsyncJob): #pylint: disable=R0903
"""
Job requesting installation of specific package from URI.
diff --git a/src/software/openlmi/software/yumdb/packagecheck.py b/src/software/openlmi/software/yumdb/packagecheck.py
index 4cdc5ee..89852b9 100644
--- a/src/software/openlmi/software/yumdb/packagecheck.py
+++ b/src/software/openlmi/software/yumdb/packagecheck.py
@@ -26,40 +26,76 @@ Module with definition of RPM package check class.
from collections import OrderedDict
from datetime import datetime
import grp
+import logging
import os
import pwd
import rpm
import yum
+from openlmi.software.yumdb import errors
+
CHECKSUMTYPE_STR2NUM = dict((val.lower(), k) for (k, val) in
yum.constants.RPM_CHECKSUM_TYPES.items())
+( FILE_TYPE_UNKNOWN
+, FILE_TYPE_FILE
+, FILE_TYPE_DIRECTORY
+, FILE_TYPE_SYMLINK
+, FILE_TYPE_FIFO
+, FILE_TYPE_CHARACTER_DEVICE
+, FILE_TYPE_BLOCK_DEVICE
+) = range(7)
+
+FILE_TYPE_NAMES = ( 'unknown', 'file', 'directory', 'symlink', 'fifo'
+ , 'character device', 'block device')
+
class PackageFile(object):
"""
Metadata related to particular file on filesystem belonging to RPM package.
Data contained here are from RPM database.
+
+ Attributes:
+ ``path`` - (``str``) Absolute path of file.
+ ``file_type`` - (``int``) One of ``FILE_TYPE_*`` identifiers above.
+ ``uid`` - (``int``) User ID.
+ ``gid`` - (``int``) Group ID.
+ ``mode`` - (``int``) Raw file mode.
+ ``device`` - (``int``) Device number.
+ ``mtime`` - (``int``) Last modification time in seconds.
+ ``size`` - (``long``) File size as a number of bytes.
+ ``link_target`` - (``str``) Link target of symlink. None if ``file_type``
+ is not symlink.
+ ``checksum`` - (``str``) Checksum as string in hexadecimal format.
+ None if file is not a regular file.
"""
__slots__ = ("path", "file_type", "uid", "gid", "mode", "device", "mtime",
"size", "link_target", "checksum")
def __init__(self, path, file_type, uid, gid, mode, device, mtime, size,
link_target, checksum):
+ if not isinstance(file_type, basestring):
+ raise TypeError("file_type must be a string")
for arg in ('uid', 'gid', 'mode', 'mtime', 'size'):
if not isinstance(locals()[arg], (int, long)):
raise TypeError("%s must be integer" % arg)
if not os.path.isabs(path):
raise ValueError("path must be an absolute path")
self.path = path
- self.file_type = file_type.lower()
+ try:
+ self.file_type = FILE_TYPE_NAMES.index(file_type.lower())
+ except ValueError:
+ logging.getLogger(__name__).error('unrecognized file type "%s" for'
+ ' file "%s"', file_type, path)
+ self.file_type = FILE_TYPE_NAMES[FILE_TYPE_UNKNOWN]
self.uid = uid
self.gid = gid
self.mode = mode
- self.device = device if file_type.endswith('device') else None
+ self.device = device
self.mtime = mtime
self.size = size
self.link_target = (link_target
- if file_type == "symlink" and link_target else None)
- self.checksum = checksum
+ if self.file_type == FILE_TYPE_SYMLINK else None)
+ self.checksum = checksum if self.file_type == FILE_TYPE_FILE else None
@property
def last_modification_datetime(self):
@@ -158,11 +194,15 @@ def pkg_checksum_type(pkg):
return pkg.hdr[rpm.RPMTAG_FILEDIGESTALGO]
return CHECKSUMTYPE_STR2NUM[pkg.yumdb_info.checksum_type.lower()]
-def make_package_check_from_db(vpkg):
+def make_package_check_from_db(vpkg, file_name=None):
"""
Create instance of PackageCheck from instance of
- yum.packages._RPMVerifyPackage
- @return instance of PackageCheck
+ yum.packages._RPMVerifyPackage.
+
+ :param file_name: (``str``) If not None, causes result to have just
+ one instance of ``PackageFile`` matching this file_name.
+ If it's not found in the package, ``FileNotFound`` will be raised.
+ :rtype (``PackageCheck``)
"""
if not isinstance(vpkg, yum.packages._RPMVerifyPackage):
raise TypeError("vpkg must be instance of"
@@ -172,6 +212,8 @@ def make_package_check_from_db(vpkg):
res = PackageCheck(id(pkg), pkg_checksum_type(pkg))
files = res.files
for vpf in vpkg:
+ if file_name is not None and file_name != vpf.filename:
+ continue
files[vpf.filename] = PackageFile(
vpf.filename,
vpf.ftype,
@@ -184,5 +226,10 @@ def make_package_check_from_db(vpkg):
vpf.readlink,
vpf.digest[1]
)
+ if file_name is not None:
+ break
+ if file_name is not None and len(files) < 1:
+ raise errors.FileNotFound('File "%s" not found in package "%s".' % (
+ file_name, pkg.nevra))
return res
diff --git a/src/software/openlmi/software/yumdb/process.py b/src/software/openlmi/software/yumdb/process.py
index 8ae6e46..2eb207f 100644
--- a/src/software/openlmi/software/yumdb/process.py
+++ b/src/software/openlmi/software/yumdb/process.py
@@ -442,15 +442,16 @@ class YumWorker(Process):
raise TypeError("job must be instance of YumJob")
try:
handler = {
- jobs.YumGetPackageList : self._handle_get_package_list,
- jobs.YumFilterPackages : self._handle_filter_packages,
- jobs.YumInstallPackage : self._handle_install_package,
- jobs.YumRemovePackage : self._handle_remove_package,
- jobs.YumUpdateToPackage: self._handle_update_to_package,
- jobs.YumUpdatePackage : self._handle_update_package,
- jobs.YumBeginSession : self._handle_begin_session,
- jobs.YumEndSession : self._handle_end_session,
- jobs.YumCheckPackage : self._handle_check_package,
+ jobs.YumGetPackageList : self._handle_get_package_list,
+ jobs.YumFilterPackages : self._handle_filter_packages,
+ jobs.YumInstallPackage : self._handle_install_package,
+ jobs.YumRemovePackage : self._handle_remove_package,
+ jobs.YumUpdateToPackage : self._handle_update_to_package,
+ jobs.YumUpdatePackage : self._handle_update_package,
+ jobs.YumBeginSession : self._handle_begin_session,
+ jobs.YumEndSession : self._handle_end_session,
+ jobs.YumCheckPackage : self._handle_check_package,
+ jobs.YumCheckPackageFile : self._handle_check_package_file,
jobs.YumInstallPackageFromURI : \
self._handle_install_package_from_uri,
jobs.YumGetRepositoryList : \
@@ -715,9 +716,9 @@ class YumWorker(Process):
return installed[0]
@_needs_database
- def _handle_check_package(self, pkg):
+ def _handle_check_package(self, pkg, file_name=None):
"""
- @return PackageFile instance for requested package
+ @return PackageCheck instance for requested package
"""
if isinstance(pkg, basestring):
pkgs = self._handle_filter_packages('installed',
@@ -726,14 +727,24 @@ class YumWorker(Process):
if len(pkgs) < 1:
raise errors.PackageNotFound('No available package matches'
' nevra "%s".' % pkg)
- pkg = pkgs[-1]
+ rpm = pkgs[-1]
+ pkg = self._transform_packages((rpm, ), cache_packages=False)[0]
else:
- pkg = self._lookup_package(pkg)
- if not isinstance(pkg, yum.rpmsack.RPMInstalledPackage):
- raise errors.PackageNotInstalled(pkg)
- vpkg = yum.packages._RPMVerifyPackage(pkg, pkg.hdr.fiFromHeader(),
- packagecheck.pkg_checksum_type(pkg), [], True)
- return packagecheck.make_package_check_from_db(vpkg)
+ rpm = self._lookup_package(pkg)
+ if not isinstance(rpm, yum.rpmsack.RPMInstalledPackage):
+ raise errors.PackageNotInstalled(rpm)
+ vpkg = yum.packages._RPMVerifyPackage(rpm, rpm.hdr.fiFromHeader(),
+ packagecheck.pkg_checksum_type(rpm), [], True)
+ return (pkg, packagecheck.make_package_check_from_db(vpkg,
+ file_name=file_name))
+
+ @_needs_database
+ def _handle_check_package_file(self, pkg, file_name):
+ """
+ @return PackageCheck instance for requested package containing
+ just one PackageFile instance for given ``file_name``.
+ """
+ return self._handle_check_package(pkg, file_name)
@_needs_database
def _handle_install_package_from_uri(self, uri,