diff options
author | Michal Minar <miminar@redhat.com> | 2013-05-10 15:52:04 +0200 |
---|---|---|
committer | Michal Minar <miminar@redhat.com> | 2013-07-03 13:05:15 +0200 |
commit | 6e8736fd571767a74c334a6a112a337917519cb7 (patch) | |
tree | d83057df0d2b084313656b30118e0d7fad22fe9a | |
parent | d5ac71ea513deffe78fb48e4f29ef69102f74cdb (diff) | |
download | openlmi-providers-6e8736fd571767a74c334a6a112a337917519cb7.tar.gz openlmi-providers-6e8736fd571767a74c334a6a112a337917519cb7.tar.xz openlmi-providers-6e8736fd571767a74c334a6a112a337917519cb7.zip |
added another LMI_SoftwareVerificationJob
There are now two asynchronous jobs:
LMI_SoftwareInstallationJob
LMI_SoftwareVerificationJob
Previous LMI_SoftwareInstallationJob module made generic to handle both
jobs and possibly more.
Also added new static filters for LMI_SoftwareVerificationJob.
16 files changed, 346 insertions, 131 deletions
diff --git a/mof/60_LMI_Software.mof b/mof/60_LMI_Software.mof index 027bc75..4bd1c51 100644 --- a/mof/60_LMI_Software.mof +++ b/mof/60_LMI_Software.mof @@ -306,6 +306,40 @@ class LMI_HostedSoftwareIdentityResource : CIM_HostedAccessPoint { /****************************************************************************** * Software update profile classes */ +class LMI_SoftwareJob : LMI_ConcreteJob { + + [Implemented(true), Override("InstanceID")] + string InstanceID; + + [Implemented(true), Override("Caption")] + string Caption; + + [Implemented(true), Override("CommunicationStatus")] + uint16 CommunicationStatus; + + [Implemented(true), Override("Description")] + string Description; + + [Implemented(true), Override("ErrorCode")] + uint16 ErrorCode; + + [Implemented(true), Override("JobStatus")] + string JobStatus; + + [Implemented(true), Override("MethodName")] + string MethodName; + + [Implemented(true), Override("Priority")] + uint32 Priority; + + [Implemented(true), Override("RecoveryAction")] + uint16 RecoveryAction; + +}; + +class LMI_SoftwareInstallationJob : LMI_SoftwareJob { +}; + class LMI_SoftwareInstallationService : CIM_SoftwareInstallationService { [Implemented(true), Override("CreationClassName")] @@ -590,7 +624,7 @@ class LMI_SoftwareInstallationService : CIM_SoftwareInstallationService { CIM_ManagedElement REF Target, [IN ( false ), OUT, Description( "Reference to the job (may be null if job completed).")] - LMI_SoftwareInstallationJob REF Job, + LMI_SoftwareVerificationJob REF Job, [IN ( false ), OUT, Description( "Array of file checks that did not pass verification." " This is NULL in case that asynchronous job has been started.")] @@ -627,37 +661,6 @@ class LMI_SoftwareInstallationServiceCapabilities : }; -class LMI_SoftwareInstallationJob : LMI_ConcreteJob { - - [Implemented(true), Override("InstanceID")] - string InstanceID; - - [Implemented(true), Override("Caption")] - string Caption; - - [Implemented(true), Override("CommunicationStatus")] - uint16 CommunicationStatus; - - [Implemented(true), Override("Description")] - string Description; - - [Implemented(true), Override("ErrorCode")] - uint16 ErrorCode; - - [Implemented(true), Override("JobStatus")] - string JobStatus; - - [Implemented(true), Override("MethodName")] - string MethodName; - - [Implemented(true), Override("Priority")] - uint32 Priority; - - [Implemented(true), Override("RecoveryAction")] - uint16 RecoveryAction; - -}; - class LMI_SoftwareMethodResult : LMI_MethodResult { }; @@ -668,7 +671,7 @@ class LMI_SoftwareMethodResult : LMI_MethodResult { class LMI_AssociatedSoftwareJobMethodResult : LMI_AssociatedJobMethodResult { [Override("Job")] - LMI_SoftwareInstallationJob REF Job; + LMI_SoftwareJob REF Job; [Override("JobParameters")] LMI_SoftwareMethodResult REF JobParameters; @@ -682,7 +685,7 @@ class LMI_OwningSoftwareJobElement : LMI_OwningJobElement { LMI_SoftwareInstallationService REF OwningElement; [Override("OwnedElement")] - LMI_SoftwareInstallationJob REF OwnedElement; + LMI_SoftwareJob REF OwnedElement; }; @@ -690,7 +693,7 @@ class LMI_OwningSoftwareJobElement : LMI_OwningJobElement { class LMI_AffectedSoftwareJobElement : LMI_AffectedJobElement { [Override("AffectingElement")] - LMI_SoftwareInstallationJob REF AffectingElement; + LMI_SoftwareJob REF AffectingElement; }; @@ -749,6 +752,9 @@ class LMI_SoftwareInstModification : CIM_InstModification { /****************************************************************************** * OpenLMI additions *****************************************************************************/ +class LMI_SoftwareVerificationJob : LMI_SoftwareJob { +}; + [Description( "Identifies both a physical file installed from RPM package and its" " original source in package. It represents a set of checks made" diff --git a/mof/70_LMI_SoftwareIndicationFilters.mof b/mof/70_LMI_SoftwareIndicationFilters.mof index 6b36190..f1fae62 100644 --- a/mof/70_LMI_SoftwareIndicationFilters.mof +++ b/mof/70_LMI_SoftwareIndicationFilters.mof @@ -100,3 +100,81 @@ instance of CIM_IndicationFilter { SourceNamespace = "root/cimv2"; SourceNamespaces = {"root/cimv2"}; }; + +instance of CIM_IndicationFilter { + CreationClassName = "CIM_IndicationFilter"; + SystemCreationClassName = "CIM_ComputerSystem"; + SystemName = "HOSTNAME"; + Name = "LMI:LMI_SoftwareVerificationJob:PercentUpdated"; + Query = "SELECT * FROM LMI_SoftwareInstModification WHERE " + "SourceInstance ISA LMI_SoftwareVerificationJob AND " + "SourceInstance.CIM_ConcreteJob::PercentComplete <> " + "PreviousInstance.CIM_ConcreteJob::PercentComplete"; + /* CIM: prefix required for pegasus */ + QueryLanguage = "CIM:CQL"; + Description = "Modification of Percentage Complete for a " + "Concrete Job."; + /* required for sfcb - but deprecated */ + SourceNamespace = "root/cimv2"; + SourceNamespaces = {"root/cimv2"}; +}; + +instance of CIM_IndicationFilter { + CreationClassName = "CIM_IndicationFilter"; + SystemCreationClassName = "CIM_ComputerSystem"; + SystemName = "HOSTNAME"; + Name = "LMI:LMI_SoftwareVerificationJob:Succeeded"; + QueryLanguage = "CIM:CQL"; + Query = "SELECT * FROM LMI_SoftwareInstModification WHERE " + "SourceInstance ISA LMI_SoftwareVerificationJob AND " + "SourceInstance.CIM_ConcreteJob::JobState = 17"; + /* This is not supported by sfcb: + * " = CIM_ConcreteJob.JobState#'Completed'" */ + SourceNamespace = "root/cimv2"; + SourceNamespaces = {"root/cimv2"}; +}; + +instance of CIM_IndicationFilter { + CreationClassName = "CIM_IndicationFilter"; + SystemCreationClassName = "CIM_ComputerSystem"; + SystemName = "HOSTNAME"; + Name = "LMI:LMI_SoftwareVerificationJob:Failed"; + Query = "SELECT * FROM LMI_SoftwareInstModification WHERE " + "SourceInstance ISA LMI_SoftwareVerificationJob AND " + "SourceInstance.CIM_ConcreteJob::JobState = 10"; + /* This is not supported by sfcb: + * "CIM_ConcreteJob.JobState#'Exception'" */ + QueryLanguage = "CIM:CQL"; + Description = "Modification of Operational Status for a " + "Concrete Job to 'Complete' and 'OK'."; + SourceNamespace = "root/cimv2"; + SourceNamespaces = {"root/cimv2"}; +}; + +instance of CIM_IndicationFilter { + CreationClassName = "CIM_IndicationFilter"; + SystemCreationClassName = "CIM_ComputerSystem"; + SystemName = "HOSTNAME"; + Name = "LMI:LMI_SoftwareVerificationJob:Changed"; + Query = "SELECT * FROM LMI_SoftwareInstModification WHERE " + "SourceInstance ISA LMI_SoftwareVerificationJob AND " + "SourceInstance.CIM_ConcreteJob::JobState <> " + "PreviousInstance.CIM_ConcreteJob::JobState"; + QueryLanguage = "CIM:CQL"; + Description = "Modification of Job State for a ConcreteJob."; + SourceNamespace = "root/cimv2"; + SourceNamespaces = {"root/cimv2"}; +}; + +instance of CIM_IndicationFilter { + CreationClassName = "CIM_IndicationFilter"; + SystemCreationClassName = "CIM_ComputerSystem"; + SystemName = "HOSTNAME"; + Name = "LMI:LMI_SoftwareVerificationJob:Created"; + Query = "SELECT * FROM LMI_SoftwareInstCreation WHERE" + " SourceInstance ISA LMI_SoftwareVerificationJob"; + QueryLanguage = "CIM:CQL"; + Description = "Creation of a ConcreteJob."; + SourceNamespace = "root/cimv2"; + SourceNamespaces = {"root/cimv2"}; +}; diff --git a/mof/LMI_Software.reg b/mof/LMI_Software.reg index 23aca47..a629f0b 100644 --- a/mof/LMI_Software.reg +++ b/mof/LMI_Software.reg @@ -89,6 +89,12 @@ namespace: root/cimv2 group: openlmi-software +[LMI_SoftwareJob] + provider: /usr/lib/python2.7/site-packages/openlmi/software/cimom_entry.py + location: pyCmpiProvider + type: instance method + namespace: root/cimv2 + [LMI_SoftwareInstallationJob] provider: /usr/lib/python2.7/site-packages/openlmi/software/cimom_entry.py location: pyCmpiProvider @@ -96,6 +102,12 @@ namespace: root/cimv2 group: openlmi-software +[LMI_SoftwareVerificationJob] + provider: /usr/lib/python2.7/site-packages/openlmi/software/cimom_entry.py + location: pyCmpiProvider + type: instance method + namespace: root/cimv2 + [LMI_SoftwareMethodResult] provider: /usr/lib/python2.7/site-packages/openlmi/software/cimom_entry.py location: pyCmpiProvider diff --git a/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py b/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py index 33c0522..e02fc7a 100644 --- a/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py +++ b/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py @@ -26,7 +26,7 @@ from pywbem.cim_provider2 import CIMProvider2 from openlmi.common import cmpi_logging from openlmi.software.core import AffectedSoftwareJobElement -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.yumdb import YumDB class LMI_AffectedSoftwareJobElement(CIMProvider2): @@ -68,7 +68,7 @@ class LMI_AffectedSoftwareJobElement(CIMProvider2): CIM_ERR_FAILED (some other unspecified error occurred) """ (job, affected) = AffectedSoftwareJobElement.check_path(env, model.path) - model['AffectingElement'] = InstallationJob.job2model(job) + model['AffectingElement'] = Job.job2model(job) ch = env.get_cimom_handle() @@ -90,6 +90,11 @@ class LMI_AffectedSoftwareJobElement(CIMProvider2): AffectedSoftwareJobElement.fill_model_system_collection( model, keys_only=False) + elif ch.is_subclass(affected.namespace, sub=affected.classname, + super='LMI_SoftwareIdentityFileCheck'): + AffectedSoftwareJobElement.fill_model_failed_check( + model, affected) + else: cmpi_logging.logger.error("Unhandled classname: %s", affected.classname) diff --git a/src/software/openlmi/software/LMI_AssociatedSoftwareJobMethodResult.py b/src/software/openlmi/software/LMI_AssociatedSoftwareJobMethodResult.py index ace38b5..c942882 100644 --- a/src/software/openlmi/software/LMI_AssociatedSoftwareJobMethodResult.py +++ b/src/software/openlmi/software/LMI_AssociatedSoftwareJobMethodResult.py @@ -26,7 +26,7 @@ from pywbem.cim_provider2 import CIMProvider2 from openlmi.common import cmpi_logging from openlmi.software.core import generate_references -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.core import MethodResult from openlmi.software.yumdb import YumDB @@ -35,9 +35,9 @@ def generate_job_referents(_env, object_name, model, _keys_only): """ Handler for referents enumeration request. """ - job = InstallationJob.object_path2job(object_name) + job = Job.object_path2job(object_name) - model["Job"] = InstallationJob.job2model(job) + model["Job"] = Job.job2model(job) model["JobParameters"] = MethodResult.job2model(job) yield model @@ -48,7 +48,7 @@ def generate_result_referents(_env, object_name, model, _keys_only): """ job = MethodResult.object_path2job(object_name) - model["Job"] = InstallationJob.job2model(job) + model["Job"] = Job.job2model(job) model["JobParameters"] = MethodResult.job2model(job) yield model @@ -88,13 +88,13 @@ class LMI_AssociatedSoftwareJobMethodResult(CIMProvider2): Instance does not exist in the specified namespace) CIM_ERR_FAILED (some other unspecified error occurred) """ - job = InstallationJob.object_path2job(model['Job']) + job = Job.object_path2job(model['Job']) jobid = MethodResult.object_path2jobid(model['JobParameters']) if job.jobid != jobid: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "Job id of Job(%d) does not match JobParameters(%d)." % (job.jobid, jobid)) - model["Job"] = InstallationJob.job2model(job) + model["Job"] = Job.job2model(job) model["JobParameters"] = MethodResult.job2model(job) return model @@ -123,7 +123,7 @@ class LMI_AssociatedSoftwareJobMethodResult(CIMProvider2): model.path.update({'Job': None, 'JobParameters': None}) for job in YumDB.get_instance().get_job_list(): - model['Job'] = InstallationJob.job2model(job) + model['Job'] = Job.job2model(job) model['JobParameters'] = MethodResult.job2model(job) yield model @@ -237,7 +237,7 @@ class LMI_AssociatedSoftwareJobMethodResult(CIMProvider2): CIM_ERR_FAILED (some other unspecified error occurred) """ handlers = [ - ("Job", "LMI_SoftwareInstallationJob", generate_job_referents), + ("Job", "LMI_SoftwareJob", generate_job_referents), ("JobParameters", "LMI_SoftwareMethodResult", generate_result_referents) ] diff --git a/src/software/openlmi/software/LMI_OwningSoftwareJobElement.py b/src/software/openlmi/software/LMI_OwningSoftwareJobElement.py index 8768c0e..5f15ebe 100644 --- a/src/software/openlmi/software/LMI_OwningSoftwareJobElement.py +++ b/src/software/openlmi/software/LMI_OwningSoftwareJobElement.py @@ -26,7 +26,7 @@ from pywbem.cim_provider2 import CIMProvider2 from openlmi.common import cmpi_logging from openlmi.software.core import InstallationService -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.yumdb import YumDB class LMI_OwningSoftwareJobElement(CIMProvider2): @@ -69,8 +69,8 @@ class LMI_OwningSoftwareJobElement(CIMProvider2): """ InstallationService.check_path_property(env, model, "OwningElement") model['OwningElement'] = InstallationService.get_path() - job = InstallationJob.object_path2job(model['OwnedElement']) - model['OwnedElement'] = InstallationJob.job2model(job) + job = Job.object_path2job(model['OwnedElement']) + model['OwnedElement'] = Job.job2model(job) return model @cmpi_logging.trace_method @@ -98,7 +98,7 @@ class LMI_OwningSoftwareJobElement(CIMProvider2): model.path.update({'OwningElement': None, 'OwnedElement': None}) model['OwningElement'] = InstallationService.get_path() for job in YumDB.get_instance().get_job_list(): - model['OwnedElement'] = InstallationJob.job2model(job) + model['OwnedElement'] = Job.job2model(job) yield model @cmpi_logging.trace_method @@ -218,6 +218,6 @@ class LMI_OwningSoftwareJobElement(CIMProvider2): super='LMI_SoftwareInstallationService') or \ ch.is_subclass(object_name.namespace, sub=object_name.classname, - super='LMI_SoftwareInstallationJob'): + super='LMI_SoftwareJob'): return self.simple_refs(env, object_name, model, result_class_name, role, result_role, keys_only) diff --git a/src/software/openlmi/software/LMI_SoftwareInstallationService.py b/src/software/openlmi/software/LMI_SoftwareInstallationService.py index 8727a14..2b8c6a6 100644 --- a/src/software/openlmi/software/LMI_SoftwareInstallationService.py +++ b/src/software/openlmi/software/LMI_SoftwareInstallationService.py @@ -25,7 +25,7 @@ import pywbem from pywbem.cim_provider2 import CIMProvider2 from openlmi.common import cmpi_logging -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.core import InstallationService class LMI_SoftwareInstallationService(CIMProvider2): @@ -369,12 +369,13 @@ class LMI_SoftwareInstallationService(CIMProvider2): out_params = [pywbem.CIMParameter('Job', type='reference', value=None)] try: jobid = InstallationService.install_or_remove_package( - env, InstallationJob.JOB_METHOD_INSTALL_FROM_URI, + env, Job.JOB_METHOD_INSTALL_FROM_URI, param_uri, param_target, None, param_installoptions, param_installoptionsvalues) rval = self.values.InstallFromURI. \ Method_Parameters_Checked___Job_Started - out_params[0].value = InstallationJob.job2model(jobid) + out_params[0].value = Job.job2model(jobid, + class_name="LMI_SoftwareInstallationJob") except InstallationService.InstallationError as exc: cmpi_logging.logger.error( "installation failed: %s", exc.description) @@ -655,14 +656,14 @@ class LMI_SoftwareInstallationService(CIMProvider2): out_params = [pywbem.CIMParameter('Job', type='reference', value=None)] try: jobid = InstallationService.install_or_remove_package( - env, InstallationJob. \ - JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY, + env, Job.JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY, param_source, param_target, param_collection, param_installoptions, param_installoptionsvalues) rval = self.values.InstallFromSoftwareIdentity. \ Method_Parameters_Checked___Job_Started - out_params[0].value = InstallationJob.job2model(jobid) + out_params[0].value = Job.job2model(jobid, + class_name="LMI_SoftwareInstallationJob") except InstallationService.InstallationError as exc: cmpi_logging.logger.error( "installation failed: %s", exc.description) diff --git a/src/software/openlmi/software/LMI_SoftwareInstallationJob.py b/src/software/openlmi/software/LMI_SoftwareJob.py index a5fc269..b6d7ca5 100644 --- a/src/software/openlmi/software/LMI_SoftwareInstallationJob.py +++ b/src/software/openlmi/software/LMI_SoftwareJob.py @@ -16,20 +16,22 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -"""Python Provider for LMI_SoftwareInstallationJob +"""Python Provider for LMI_SoftwareInstallationJob and +LMI_SoftwareVerificationJob. They will be referred to as LMI_SoftwareJob, +which is their base class. -Instruments the CIM class LMI_SoftwareInstallationJob +Instruments the CIM class LMI_SoftwareJob """ import pywbem from pywbem.cim_provider2 import CIMProvider2 from openlmi.common import cmpi_logging -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.yumdb import errors, YumDB -class LMI_SoftwareInstallationJob(CIMProvider2): - """Instrument the CIM class LMI_SoftwareInstallationJob +class LMI_SoftwareJob(CIMProvider2): + """Instrument the CIM class LMI_SoftwareJob A concrete version of Job. This class represents a generic and instantiable unit of work, such as a batch or a print job. @@ -39,7 +41,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): def __init__ (self, _env): cmpi_logging.logger.debug('Initializing provider %s from %s' \ % (self.__class__.__name__, __file__)) - self.values = InstallationJob.Values + self.values = Job.Values @cmpi_logging.trace_method def get_instance(self, env, model): @@ -63,9 +65,8 @@ class LMI_SoftwareInstallationJob(CIMProvider2): Instance does not exist in the specified namespace) CIM_ERR_FAILED (some other unspecified error occurred) """ - job = InstallationJob.object_path2job(model.path) - return InstallationJob.job2model( - job, keys_only=False, model=model) + job = Job.object_path2job(model.path) + return Job.job2model(job, keys_only=False, model=model) @cmpi_logging.trace_method def enum_instances(self, env, model, keys_only): @@ -94,8 +95,12 @@ class LMI_SoftwareInstallationJob(CIMProvider2): # we set property values on the model. model.path.update({'InstanceID': None}) + ch = env.get_cimom_handle() for job in YumDB.get_instance().get_job_list(): - yield InstallationJob.job2model(job, keys_only, model) + if ch.is_subclass(model.path.namespace, + sub=model.path.classname, + super=Job.job_class2cim_class_name(job.__class__)): + yield Job.job2model(job, keys_only=keys_only, model=model) @cmpi_logging.trace_method def set_instance(self, env, instance, modify_existing): @@ -127,7 +132,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): if not modify_existing: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED, "Can not create new instance.") - return InstallationJob.modify_instance(instance) + return Job.modify_instance(instance) @cmpi_logging.trace_method def delete_instance(self, env, instance_name): @@ -151,7 +156,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): CIM_ERR_FAILED (some other unspecified error occurred) """ with YumDB.get_instance() as ydb: - job = InstallationJob.object_path2job(instance_name) + job = Job.object_path2job(instance_name) try: cmpi_logging.logger.info('deleting job "%s"' % job) ydb.delete_job(job.jobid) @@ -167,7 +172,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): def cim_method_requeststatechange(self, env, object_name, param_requestedstate=None, param_timeoutperiod=None): - """Implements LMI_SoftwareInstallationJob.RequestStateChange() + """Implements LMI_SoftwareJob.RequestStateChange() Requests that the state of the job be changed to the value specified in the RequestedState parameter. Invoking the @@ -225,7 +230,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): the invocation request) CIM_ERR_FAILED (some other unspecified error occurred) """ - job = InstallationJob.object_path2job(object_name) + job = Job.object_path2job(object_name) try: if param_requestedstate not in { self.values.RequestStateChange.RequestedState.Terminate }: @@ -246,7 +251,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): @cmpi_logging.trace_method def cim_method_geterrors(self, env, object_name): - """Implements LMI_SoftwareInstallationJob.GetErrors() + """Implements LMI_SoftwareJob.GetErrors() If JobState is "Completed" and Operational Status is "Completed" then no instance of CIM_Error is returned. If JobState is @@ -283,8 +288,8 @@ class LMI_SoftwareInstallationJob(CIMProvider2): the invocation request) CIM_ERR_FAILED (some other unspecified error occurred) """ - job = InstallationJob.object_path2job(object_name) - error = InstallationJob.job2error(job) + job = Job.object_path2job(object_name) + error = Job.job2error(job) out_params = [] if error is not None: param = pywbem.CIMParameter('Errors', type='instance', @@ -295,7 +300,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): @cmpi_logging.trace_method def cim_method_killjob(self, env, object_name, param_deleteonkill=None): - """Implements LMI_SoftwareInstallationJob.KillJob() + """Implements LMI_SoftwareJob.KillJob() KillJob is being deprecated because there is no distinction made between an orderly shutdown and an immediate kill. @@ -335,7 +340,7 @@ class LMI_SoftwareInstallationJob(CIMProvider2): @cmpi_logging.trace_method def cim_method_geterror(self, env, object_name): - """Implements LMI_SoftwareInstallationJob.GetError() + """Implements LMI_SoftwareJob.GetError() GetError is deprecated because Error should be an array,not a scalar. When the job is executing or has terminated without error, @@ -371,8 +376,8 @@ class LMI_SoftwareInstallationJob(CIMProvider2): the invocation request) CIM_ERR_FAILED (some other unspecified error occurred) """ - job = InstallationJob.object_path2job(object_name) - error = InstallationJob.job2error(job) + job = Job.object_path2job(object_name) + error = Job.job2error(job) out_params = [] if error is not None: param = pywbem.CIMParameter('Error', type='instance', value=error) diff --git a/src/software/openlmi/software/cimom_entry.py b/src/software/openlmi/software/cimom_entry.py index 4dd0d40..7d39a21 100644 --- a/src/software/openlmi/software/cimom_entry.py +++ b/src/software/openlmi/software/cimom_entry.py @@ -28,7 +28,7 @@ from multiprocessing import Queue from openlmi.common import cmpi_logging from openlmi.common import JobManager from openlmi.common.IndicationManager import IndicationManager -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.LMI_SoftwareIdentity import LMI_SoftwareIdentity from openlmi.software.LMI_SystemSoftwareCollection import \ LMI_SystemSoftwareCollection @@ -55,8 +55,7 @@ from openlmi.software.LMI_HostedSoftwareInstallationService import \ LMI_HostedSoftwareInstallationService from openlmi.software.LMI_SoftwareInstallationServiceAffectsElement import \ LMI_SoftwareInstallationServiceAffectsElement -from openlmi.software.LMI_SoftwareInstallationJob import \ - LMI_SoftwareInstallationJob +from openlmi.software.LMI_SoftwareJob import LMI_SoftwareJob from openlmi.software.LMI_SoftwareMethodResult import \ LMI_SoftwareMethodResult from openlmi.software.LMI_AffectedSoftwareJobElement import \ @@ -80,8 +79,7 @@ def get_providers(env): # jobmanager does not understand CIM models, give it a way to transform # job to CIMIndication instance - jobmanager.JOB_TO_MODEL = lambda job: \ - InstallationJob.job2model(job, keys_only=False) + jobmanager.JOB_TO_MODEL = lambda job: Job.job2model(job, keys_only=False) providers = { "LMI_SoftwareIdentity" : LMI_SoftwareIdentity(env), @@ -104,9 +102,11 @@ def get_providers(env): LMI_HostedSoftwareInstallationService(env), "LMI_SoftwareInstallationServiceAffectsElement" : \ LMI_SoftwareInstallationServiceAffectsElement(env), - "LMI_SoftwareInstallationJob" : LMI_SoftwareInstallationJob(env), - "LMI_SoftwareInstCreation" : LMI_SoftwareInstallationJob(env), - "LMI_SoftwareInstModification" : LMI_SoftwareInstallationJob(env), + "LMI_SoftwareJob" : LMI_SoftwareJob(env), + "LMI_SoftwareInstallationJob" : LMI_SoftwareJob(env), + "LMI_SoftwareVerificationJob" : LMI_SoftwareJob(env), + "LMI_SoftwareInstCreation" : LMI_SoftwareJob(env), + "LMI_SoftwareInstModification" : LMI_SoftwareJob(env), "LMI_SoftwareMethodResult" : LMI_SoftwareMethodResult(env), "LMI_AffectedSoftwareJobElement" : LMI_AffectedSoftwareJobElement(env), "LMI_AssociatedSoftwareJobMethodResult" : \ @@ -121,6 +121,7 @@ def get_providers(env): im = IndicationManager.get_instance( env, "Software", "root/cimv2", queue=Queue()) JobManager.register_filters("LMI_SoftwareInstallationJob", im) + JobManager.register_filters("LMI_SoftwareVerificationJob", im) return providers diff --git a/src/software/openlmi/software/core/AffectedSoftwareJobElement.py b/src/software/openlmi/software/core/AffectedSoftwareJobElement.py index 2530104..34c5078 100644 --- a/src/software/openlmi/software/core/AffectedSoftwareJobElement.py +++ b/src/software/openlmi/software/core/AffectedSoftwareJobElement.py @@ -26,7 +26,8 @@ from openlmi.common import cmpi_logging from openlmi.software import util from openlmi.software.core import ComputerSystem from openlmi.software.core import Identity -from openlmi.software.core import InstallationJob +from openlmi.software.core import IdentityFileCheck +from openlmi.software.core import Job from openlmi.software.core import SystemCollection from openlmi.software.yumdb import jobs from openlmi.software.yumdb import PackageInfo @@ -52,14 +53,15 @@ class Values(object): def check_path(env, op): """ Checks, whether object path is valid. - @return affected object path + + Return internal object representing job and object path of affected element + as a pair: ``(job, affected)``. """ if not isinstance(op, pywbem.CIMInstanceName): raise TypeError("op must be a CIMInstanceName") ch = env.get_cimom_handle() - job = op['AffectingElement'] = InstallationJob.object_path2job( - op['AffectingElement']) + job = op['AffectingElement'] = Job.object_path2job(op['AffectingElement']) affected = op['AffectedElement'] if ch.is_subclass(affected.namespace, sub=affected.classname, super='LMI_SoftwareIdentity'): @@ -82,7 +84,7 @@ def check_path(env, op): if job.state == job.COMPLETED: affected = Identity.pkg2model(job.result_data) else: - # TODO: this should be somehow obtained from from downloaded + # TODO: this should be somehow obtained from downloaded # package before installation raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "No SoftwareIdentity is associated to given job.") @@ -98,6 +100,25 @@ def check_path(env, op): super='Linux_ComputerSystem'): ComputerSystem.check_path(env, affected, "AffectedElement") affected = ComputerSystem.get_path() + elif ch.is_subclass(affected.namespace, sub=affected.classname, + super='LMI_SoftwareIdentityFileCheck'): + if not isinstance(job, jobs.YumCheckPackage): + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "Job must point to verification job, not to: \"%s\"" % job) + if job.state != job.COMPLETED: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "Associations to failed file checks for verification job" + " \"%s\" are not yet known, since job has not completed" + " yet." % op["AffectingElement"]["InstanceID"]) + pkg_info, _ = job.result_data + file_check = IdentityFileCheck.object_path2file_check(affected) + if file_check.pkg_info.nevra != pkg_info.nevra: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "Affected element associated to job for another package:" + " \"%s\" != \"%s\"." % (file_check.pkg_info, pkg_info)) + if IdentityFileCheck.file_check_passed(file_check): + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "Given file check reference passed the verification.") else: raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, "Expected an instance of LMI_SoftwareIdentity," @@ -114,7 +135,11 @@ def job2affected_software_identity(job): descriptions = [] if isinstance(job, jobs.YumSpecificPackageJob): if job.state == job.COMPLETED and job.result_data: - affected = Identity.pkg2model(job.result_data) + if isinstance(job, jobs.YumCheckPackage): + # get the first item out of (pkg_info, pkg_check) + affected = Identity.pkg2model(job.result_data[0]) + else: + affected = Identity.pkg2model(job.result_data) else: affected = Identity.pkg2model(job.pkg) if isinstance(job, jobs.YumInstallPackage): @@ -125,7 +150,7 @@ def job2affected_software_identity(job): (jobs.YumUpdatePackage, jobs.YumUpdateToPackage)): descriptions.append("Updating") elif isinstance(job, jobs.YumCheckPackage): - descriptions.append("Checking") + descriptions.append("Verifying") else: descriptions.append("Modifying") cmpi_logging.logger.error("Unhandled job: %s", job) @@ -177,6 +202,36 @@ def fill_model_system_collection(model, keys_only=True): return model @cmpi_logging.trace_function +def fill_model_failed_check(model, failed_check, keys_only=True): + """ + Fills model's AffectedElement and all non-key properties. + + :param failed_check: (``CIMInstanceName``) Is on object path of failed + file check. + """ + if not isinstance(failed_check, pywbem.CIMInstanceName): + raise TypeError("failed_check must be a CIMInstanceName") + model["AffectedElement"] = failed_check + if not keys_only: + model["ElementEffects"] = [Values.ElementEffects.Other] + model["OtherElementEffectsDescriptions"] = [ + "File did not pass the verification." + ] + return model + +@cmpi_logging.trace_function +def generate_failed_checks(model, job, keys_only=True): + """ + Generates associations between LMI_SoftwareVerificationJob and + LMI_SoftwareIdentityFileCheck for files that did not pass the check. + """ + out_params = Job.get_verification_out_params(job) + if not "Failed" in out_params: + return + for failed in out_params["Failed"].value: + yield fill_model_failed_check(model, failed, keys_only) + +@cmpi_logging.trace_function def generate_models_from_job(job, keys_only=True, model=None): """ Generates all associations between job and affected elements. @@ -189,7 +244,7 @@ def generate_models_from_job(job, keys_only=True, model=None): if not keys_only: model = pywbem.CIMInstance("LMI_AffectedSoftwareJobElement", path=model) - model["AffectingElement"] = InstallationJob.job2model(job) + model["AffectingElement"] = Job.job2model(job) (si, element_effects, element_effects_descriptions) = \ job2affected_software_identity(job) model["AffectedElement"] = si @@ -198,8 +253,12 @@ def generate_models_from_job(job, keys_only=True, model=None): model["OtherElementEffectsDescriptions"] = \ element_effects_descriptions yield model - fill_model_system_collection(model, keys_only=keys_only) - yield model + if not isinstance(job, jobs.YumCheckPackage): + fill_model_system_collection(model, keys_only=keys_only) + yield model + else: # package verification - associate to failed file checks + for model in generate_failed_checks(model, job, keys_only=keys_only): + yield model fill_model_computer_system(model, job, keys_only=keys_only) yield model diff --git a/src/software/openlmi/software/core/InstMethodCall.py b/src/software/openlmi/software/core/InstMethodCall.py index 4c7e890..7fc25db 100644 --- a/src/software/openlmi/software/core/InstMethodCall.py +++ b/src/software/openlmi/software/core/InstMethodCall.py @@ -24,7 +24,7 @@ import pywbem import socket from openlmi.common import cmpi_logging -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.core import InstallationService from openlmi.software.yumdb import jobs, errors @@ -107,21 +107,21 @@ def job2model(job, pre=True): host=socket.gethostname(), namespace="root/cimv2") inst = pywbem.CIMInstance(classname="CIM_InstMethodCall", path=path) - src_instance = InstallationJob.job2model(job, False) + src_instance = Job.job2model(job, keys_only=False) inst['SourceInstance'] = pywbem.CIMProperty("SourceInstance", type="instance", value=src_instance) inst['SourceInstanceModelPath'] = \ str(src_instance.path) #pylint: disable=E1103 - inst['MethodName'] = InstallationJob.JOB_METHOD_NAMES[ + inst['MethodName'] = Job.JOB_METHOD_NAMES[ job.metadata["method"]] - inst['MethodParameters'] = InstallationJob.make_method_params( + inst['MethodParameters'] = Job.make_method_params( job, '__MethodParameters', True, not pre) inst['PreCall'] = pre if not pre: inst["Error"] = pywbem.CIMProperty("Error", type="instance", is_array=True, value=[]) - error = InstallationJob.job2error(job) + error = Job.job2error(job) if error is not None: inst["Error"].append(error) inst["ReturnValueType"] = Values.ReturnValueType.uint32 diff --git a/src/software/openlmi/software/core/InstallationService.py b/src/software/openlmi/software/core/InstallationService.py index ccb27a6..9eff44e 100644 --- a/src/software/openlmi/software/core/InstallationService.py +++ b/src/software/openlmi/software/core/InstallationService.py @@ -26,12 +26,12 @@ import pywbem from openlmi.common import cmpi_logging from openlmi.software.core import ComputerSystem from openlmi.software.core import Identity -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.core import SystemCollection from openlmi.software.yumdb import errors from openlmi.software.yumdb import YumDB -JOB_METHOD_SRC_PARAM_NAMES = ["URI", "Source", "Image"] +JOB_METHOD_SRC_PARAM_NAMES = ["URI", "Source", "Image", "Source"] class InstallationError(Exception): """This exception shall be raised upon any error within @@ -302,6 +302,21 @@ class Values(object): 10: 'Starting' } + class VerifyInstalledIdentity(object): + Job_Completed_with_No_Error = pywbem.Uint32(0) + Not_Supported = pywbem.Uint32(1) + Unspecified_Error = pywbem.Uint32(2) + Timeout = pywbem.Uint32(3) + Failed = pywbem.Uint32(4) + Invalid_Parameter = pywbem.Uint32(5) + Target_In_Use = pywbem.Uint32(6) + # DMTF_Reserved = .. + Method_Parameters_Checked___Job_Started = pywbem.Uint32(4096) + Unsupported_TargetType = pywbem.Uint32(4097) + Method_Reserved = pywbem.Uint32(4098) + # Software_Identity_Not_Installed = 4099..32767 + Vendor_Specific = pywbem.Uint32(32768) + class AvailableRequestedStates(object): Enabled = pywbem.Uint16(2) Disabled = pywbem.Uint16(3) @@ -622,10 +637,9 @@ def _check_target_and_collection(env, method, target, collection): " at the same time.") if not target and not collection: raise InstallationError(values.Unspecified_Error, - "Either Target or Collection parameter must be specified." - if method == InstallationJob. \ - JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY else - "Missing Target parameter.") + "Either Target or Collection parameter must be specified." + if method == Job.JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY + else "Missing Target parameter.") @cmpi_logging.trace_function def _install_or_remove_check_params( @@ -639,14 +653,14 @@ def _install_or_remove_check_params( where action is one of Values.InstallFromSoftwareIdentity properties """ if not method in ( - InstallationJob.JOB_METHOD_INSTALL_FROM_URI, - InstallationJob.JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY, - InstallationJob.JOB_METHOD_INSTALL_FROM_BYTE_STREAM): + Job.JOB_METHOD_INSTALL_FROM_URI, + Job.JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY, + Job.JOB_METHOD_INSTALL_FROM_BYTE_STREAM): raise ValueError("unknown method") values = Values.InstallFromSoftwareIdentity supported_options = values.InstallOptions.supported.copy() - if method == InstallationJob.JOB_METHOD_INSTALL_FROM_URI: + if method == Job.JOB_METHOD_INSTALL_FROM_URI: supported_options.remove(values.InstallOptions.Uninstall) if not source: @@ -693,37 +707,44 @@ def _install_or_remove_check_params( @cmpi_logging.trace_function def make_job_input_params(method, source, target, collection, - install_options, - install_options_values): + install_options=None, + install_options_values=None): """ Make dictionary of input parameters, that are stored in job's metadata. This dictionary is used in creation of CIM_ConcreteJob and CIM_InstMethodCall. """ input_params = { - "InstallOptionsValues" : pywbem.CIMProperty( + "Target" : pywbem.CIMProperty( + name="Target", type="reference", value=target), + } + + if method == Job.JOB_METHOD_VERIFY_INSTALLED_IDENTITY: + input_params["Source"] = pywbem.CIMProperty( + name="Source", type="reference", value=source) + return input_params + + input_params["InstallOptionsValues"] = pywbem.CIMProperty( name="InstallOptionsValues", type="string", is_array=True, - value=install_options_values), - "InstallOptions" : pywbem.CIMProperty( + value=install_options_values) + input_params["InstallOptions"] = pywbem.CIMProperty( name="InstallOptions", type="uint16", is_array=True, - value=install_options), - "Target" : pywbem.CIMProperty( - name="Target", type="reference", value=target), - } - if method == InstallationJob.JOB_METHOD_INSTALL_FROM_URI: + value=install_options) + if method == Job.JOB_METHOD_INSTALL_FROM_URI: input_params["URI"] = pywbem.CIMProperty( name="URI", type="string", value=source) - elif method == InstallationJob.JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY: + elif method == Job.JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY: input_params["Source"] = pywbem.CIMProperty( name="Source", type="reference", value=source) input_params["Collection"] = pywbem.CIMProperty( name="Collection", type="reference", value=collection) - elif method == InstallationJob.JOB_METHOD_INSTALL_FROM_BYTE_STREAM: + elif method == Job.JOB_METHOD_INSTALL_FROM_BYTE_STREAM: input_params["Image"] = pywbem.CIMProperty( name="Image", type="reference", value=source) + return input_params @cmpi_logging.trace_function @@ -732,9 +753,8 @@ def install_or_remove_package(env, method, install_options, install_options_values): """ - :param method: (``int``) Identifier of method defined in - ``core.InstallationJob`` module with variables prefixed with - ``JOB_METHOD_``. + :param method: (``int``) Identifier of method defined in ``core.Job`` + module with variables prefixed with ``JOB_METHOD_``. """ values = Values.InstallFromSoftwareIdentity (action, force, repair) = _install_or_remove_check_params( @@ -777,3 +797,30 @@ def install_or_remove_package(env, method, JOB_METHOD_SRC_PARAM_NAMES[method].lower(), str(exc)) raise InstallationError(values.Unspecified_Error, str(exc)) +@cmpi_logging.trace_function +def verify_package(env, method, source, target): + """ + :param method: (``int``) Identifier of method defined in ``core.Job`` + module with variables prefixed with ``JOB_METHOD_``. + """ + values = Values.VerifyInstalledIdentity + + if method != Job.JOB_METHOD_VERIFY_INSTALLED_IDENTITY: + raise ValueError("unknown method") + + if not source: + raise InstallationError(values.Unspecified_Error, + "Missing %s parameter." % (JOB_METHOD_SRC_PARAM_NAMES[method])) + + _check_target_and_collection(env, method, target, None) + + input_params = make_job_input_params(method, source, target, None) + metadata = { "method" : method, "input_params" : input_params } + nevra = Identity.object_path2nevra(source, with_epoch='ALWAYS') + ydb = YumDB.get_instance() + cmpi_logging.logger.info('verifying package "%s"', nevra) + jobid = ydb.check_package(nevra, async=True, **metadata) + cmpi_logging.logger.info('verification job %s for pkg "%s" enqueued', + jobid, nevra) + return jobid + diff --git a/src/software/openlmi/software/core/InstallationJob.py b/src/software/openlmi/software/core/Job.py index 0a3d44a..0a3d44a 100644 --- a/src/software/openlmi/software/core/InstallationJob.py +++ b/src/software/openlmi/software/core/Job.py diff --git a/src/software/openlmi/software/core/MethodResult.py b/src/software/openlmi/software/core/MethodResult.py index 05bcd78..715a554 100644 --- a/src/software/openlmi/software/core/MethodResult.py +++ b/src/software/openlmi/software/core/MethodResult.py @@ -23,7 +23,7 @@ Just a common functionality related to class LMI_SoftwareMethodResult. import pywbem from openlmi.common import cmpi_logging -from openlmi.software.core import InstallationJob +from openlmi.software.core import Job from openlmi.software.core import InstMethodCall from openlmi.software.yumdb import jobs, errors, YumDB @@ -71,7 +71,7 @@ def job2model(job, keys_only=True, model=None): model['InstanceID'] = "LMI:LMI_SoftwareMethodResult:"+str(job.jobid) if not keys_only: model.path['InstanceID'] = model['InstanceID'] #pylint: disable=E1103 - method_name = InstallationJob.JOB_METHOD_NAMES[job.metadata['method']] + method_name = Job.JOB_METHOD_NAMES[job.metadata['method']] model['Caption'] = 'Result of method %s' % method_name model['Description'] = ( 'Result of asynchronous job number %d created upon invocation' diff --git a/src/software/openlmi/software/util/__init__.py b/src/software/openlmi/software/util/__init__.py index 9b0ab01..d92fd7c 100644 --- a/src/software/openlmi/software/util/__init__.py +++ b/src/software/openlmi/software/util/__init__.py @@ -27,6 +27,9 @@ import platform import re import signal +RE_INSTANCE_ID = re.compile(r'LMI:(?P<clsname>[a-z][a-z_0-9]+):(?P<id>\d+)', + re.IGNORECASE) + RE_EVRA = re.compile( r'^(?P<epoch>\d+):(?P<version>[^-]+)-(?P<release>.+)\.(?P<arch>[^.]+)$') RE_NEVRA = re.compile( @@ -165,4 +168,3 @@ def get_signal_name(signal_num): except KeyError: return "UNKNOWN_SIGNAL(%d)" % signal_num - diff --git a/src/software/openlmi/software/yumdb/jobmanager.py b/src/software/openlmi/software/yumdb/jobmanager.py index 977b38f..c2f0202 100644 --- a/src/software/openlmi/software/yumdb/jobmanager.py +++ b/src/software/openlmi/software/yumdb/jobmanager.py @@ -27,8 +27,8 @@ This module uses its own logging facilities because it runs in separeted process not having access to broker logging features. Before using ``JobManager``, module's variable ``JOB_TO_MODEL`` should -be set to callable taking ``YumJob`` instance and returning -``LMI_SoftwareInstallationJob``. +be set to callable taking ``YumJob`` instance and returning its matching +CIM abstraction instance. """ import heapq import inspect @@ -48,7 +48,6 @@ from openlmi.software.yumdb.util import trace_function # It should be a pointer to function, which takes a job and returns # corresponding CIM instance. It's used for sending indications. JOB_TO_MODEL = lambda job: None -JOB_CLASSNAME = "LMI_SoftwareInstallationJob" # Minimum time to keep asynchronous job in cache after completion. In seconds. MINIMUM_TIME_BEFORE_REMOVAL = 10 |