From 6e8736fd571767a74c334a6a112a337917519cb7 Mon Sep 17 00:00:00 2001 From: Michal Minar Date: Fri, 10 May 2013 15:52:04 +0200 Subject: 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. --- mof/60_LMI_Software.mof | 76 ++- mof/70_LMI_SoftwareIndicationFilters.mof | 78 +++ mof/LMI_Software.reg | 12 + .../software/LMI_AffectedSoftwareJobElement.py | 9 +- .../LMI_AssociatedSoftwareJobMethodResult.py | 16 +- .../software/LMI_OwningSoftwareJobElement.py | 10 +- .../software/LMI_SoftwareInstallationJob.py | 380 ----------- .../software/LMI_SoftwareInstallationService.py | 13 +- src/software/openlmi/software/LMI_SoftwareJob.py | 385 +++++++++++ src/software/openlmi/software/cimom_entry.py | 17 +- .../software/core/AffectedSoftwareJobElement.py | 79 ++- .../openlmi/software/core/InstMethodCall.py | 10 +- .../openlmi/software/core/InstallationJob.py | 754 --------------------- .../openlmi/software/core/InstallationService.py | 97 ++- src/software/openlmi/software/core/Job.py | 754 +++++++++++++++++++++ src/software/openlmi/software/core/MethodResult.py | 4 +- src/software/openlmi/software/util/__init__.py | 4 +- src/software/openlmi/software/yumdb/jobmanager.py | 5 +- 18 files changed, 1459 insertions(+), 1244 deletions(-) delete mode 100644 src/software/openlmi/software/LMI_SoftwareInstallationJob.py create mode 100644 src/software/openlmi/software/LMI_SoftwareJob.py delete mode 100644 src/software/openlmi/software/core/InstallationJob.py create mode 100644 src/software/openlmi/software/core/Job.py 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_SoftwareInstallationJob.py b/src/software/openlmi/software/LMI_SoftwareInstallationJob.py deleted file mode 100644 index a5fc269..0000000 --- a/src/software/openlmi/software/LMI_SoftwareInstallationJob.py +++ /dev/null @@ -1,380 +0,0 @@ -# -*- encoding: utf-8 -*- -# Software Management Providers -# -# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Python Provider for LMI_SoftwareInstallationJob - -Instruments the CIM class LMI_SoftwareInstallationJob -""" - -import pywbem -from pywbem.cim_provider2 import CIMProvider2 - -from openlmi.common import cmpi_logging -from openlmi.software.core import InstallationJob -from openlmi.software.yumdb import errors, YumDB - -class LMI_SoftwareInstallationJob(CIMProvider2): - """Instrument the CIM class LMI_SoftwareInstallationJob - - A concrete version of Job. This class represents a generic and - instantiable unit of work, such as a batch or a print job. - - """ - - def __init__ (self, _env): - cmpi_logging.logger.debug('Initializing provider %s from %s' \ - % (self.__class__.__name__, __file__)) - self.values = InstallationJob.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) - """ - job = InstallationJob.object_path2job(model.path) - return InstallationJob.job2model( - job, 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) - """ - # Prime model.path with knowledge of the keys, so key values on - # the CIMInstanceName (model.path) will automatically be set when - # we set property values on the model. - model.path.update({'InstanceID': None}) - - for job in YumDB.get_instance().get_job_list(): - yield InstallationJob.job2model(job, keys_only, model) - - @cmpi_logging.trace_method - def set_instance(self, env, instance, modify_existing): - """Return a newly created or modified instance. - - Keyword arguments: - env -- Provider Environment (pycimmb.ProviderEnvironment) - instance -- The new pywbem.CIMInstance. If modifying an existing - instance, the properties on this instance have been filtered by - the PropertyList from the request. - modify_existing -- True if ModifyInstance, False if CreateInstance - - Return the new instance. The keys must be set on the new instance. - - Possible Errors: - CIM_ERR_ACCESS_DENIED - CIM_ERR_NOT_SUPPORTED - CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized - or otherwise incorrect parameters) - CIM_ERR_ALREADY_EXISTS (the CIM Instance already exists -- only - valid if modify_existing is False, indicating that the operation - was CreateInstance) - CIM_ERR_NOT_FOUND (the CIM Instance does not exist -- only valid - if modify_existing is True, indicating that the operation - was ModifyInstance) - CIM_ERR_FAILED (some other unspecified error occurred) - - """ - if not modify_existing: - raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED, - "Can not create new instance.") - return InstallationJob.modify_instance(instance) - - @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) - """ - with YumDB.get_instance() as ydb: - job = InstallationJob.object_path2job(instance_name) - try: - cmpi_logging.logger.info('deleting job "%s"' % job) - ydb.delete_job(job.jobid) - cmpi_logging.logger.info('job "%s" removed' % job) - except errors.JobNotFound as exc: - raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, - getattr(exc, 'message', str(exc))) - except errors.JobControlError as exc: - raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, - getattr(exc, 'message', str(exc))) - - @cmpi_logging.trace_method - def cim_method_requeststatechange(self, env, object_name, - param_requestedstate=None, - param_timeoutperiod=None): - """Implements LMI_SoftwareInstallationJob.RequestStateChange() - - Requests that the state of the job be changed to the value - specified in the RequestedState parameter. Invoking the - RequestStateChange method multiple times could result in earlier - requests being overwritten or lost. If 0 is returned, then the - task completed successfully. Any other return code indicates an - error condition. - - Keyword arguments: - env -- Provider Environment (pycimmb.ProviderEnvironment) - object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName - specifying the object on which the method RequestStateChange() - should be invoked. - param_requestedstate -- The input parameter RequestedState ( - type pywbem.Uint16 - self.Values.RequestStateChange.RequestedState) - RequestStateChange changes the state of a job. The possible - values are as follows: Start (2) changes the state to - 'Running'. Suspend (3) stops the job temporarily. The - intention is to subsequently restart the job with 'Start'. It - might be possible to enter the 'Service' state while - suspended. (This is job-specific.) Terminate (4) stops the - job cleanly, saving data, preserving the state, and shutting - down all underlying processes in an orderly manner. Kill (5) - terminates the job immediately with no requirement to save - data or preserve the state. Service (6) puts the job into a - vendor-specific service state. It might be possible to restart - the job. - - param_timeoutperiod -- The input parameter TimeoutPeriod ( - type pywbem.CIMDateTime) - A timeout period that specifies the maximum amount of time that - the client expects the transition to the new state to take. - The interval format must be used to specify the TimeoutPeriod. - A value of 0 or a null parameter indicates that the client has - no time requirements for the transition. If this property - does not contain 0 or null and the implementation does not - support this parameter, a return code of 'Use Of Timeout - Parameter Not Supported' must be returned. - - - Returns a two-tuple containing the return value ( - type pywbem.Uint32 self.Values.RequestStateChange) - 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) - """ - job = InstallationJob.object_path2job(object_name) - try: - if param_requestedstate not in { - self.values.RequestStateChange.RequestedState.Terminate }: - raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, - "Valid RequestedState can by only Terminate (%d)" % - self.values.RequestStateChange.RequestedState.Terminate) - if param_timeoutperiod: - raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, - "Timeout period is not supported.") - YumDB.get_instance().terminate_job(job.jobid) - except errors.JobNotFound as exc: - raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, - getattr(exc, 'message', str(exc))) - except errors.JobControlError as exc: - raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, - getattr(exc, 'message', str(exc))) - return (self.values.GetErrors.Success, []) - - @cmpi_logging.trace_method - def cim_method_geterrors(self, env, object_name): - """Implements LMI_SoftwareInstallationJob.GetErrors() - - If JobState is "Completed" and Operational Status is "Completed" - then no instance of CIM_Error is returned. If JobState is - "Exception" then GetErrors may return intances of CIM_Error - related to the execution of the procedure or method invoked by the - job. If Operatational Status is not "OK" or "Completed"then - GetErrors may return CIM_Error instances related to the running of - the job. - - Keyword arguments: - env -- Provider Environment (pycimmb.ProviderEnvironment) - object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName - specifying the object on which the method GetErrors() - should be invoked. - - Returns a two-tuple containing the return value ( - type pywbem.Uint32 self.Values.GetErrors) - and a list of CIMParameter objects representing the output parameters - - Output parameters: - Errors -- (type pywbem.CIMInstance(classname='CIM_Error', ...)) - If the OperationalStatus on the Job is not "OK", then this - method will return one or more CIM Error instance(s). - Otherwise, when the Job is "OK", null is returned. - - - 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) - """ - job = InstallationJob.object_path2job(object_name) - error = InstallationJob.job2error(job) - out_params = [] - if error is not None: - param = pywbem.CIMParameter('Errors', type='instance', - is_array=True, array_size=1, value=[error]) - out_params.append(param) - return (self.values.GetErrors.Success, out_params) - - @cmpi_logging.trace_method - def cim_method_killjob(self, env, object_name, - param_deleteonkill=None): - """Implements LMI_SoftwareInstallationJob.KillJob() - - KillJob is being deprecated because there is no distinction made - between an orderly shutdown and an immediate kill. - CIM_ConcreteJob.RequestStateChange() provides 'Terminate' and - 'Kill' options to allow this distinction. A method to kill this - job and any underlying processes, and to remove any 'dangling' - associations. - - Keyword arguments: - env -- Provider Environment (pycimmb.ProviderEnvironment) - object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName - specifying the object on which the method KillJob() - should be invoked. - param_deleteonkill -- The input parameter DeleteOnKill (type bool) - Indicates whether or not the Job should be automatically - deleted upon termination. This parameter takes precedence over - the property, DeleteOnCompletion. - - - Returns a two-tuple containing the return value ( - type pywbem.Uint32 self.Values.KillJob) - 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) - """ - raise pywbem.CIMError(pywbem.CIM_ERR_METHOD_NOT_AVAILABLE) - - @cmpi_logging.trace_method - def cim_method_geterror(self, env, object_name): - """Implements LMI_SoftwareInstallationJob.GetError() - - GetError is deprecated because Error should be an array,not a - scalar. When the job is executing or has terminated without error, - then this method returns no CIM_Error instance. However, if the - job has failed because of some internal problem or because the job - has been terminated by a client, then a CIM_Error instance is - returned. - - Keyword arguments: - env -- Provider Environment (pycimmb.ProviderEnvironment) - object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName - specifying the object on which the method GetError() - should be invoked. - - Returns a two-tuple containing the return value ( - type pywbem.Uint32 self.Values.GetError) - and a list of CIMParameter objects representing the output parameters - - Output parameters: - Error -- (type pywbem.CIMInstance(classname='CIM_Error', ...)) - If the OperationalStatus on the Job is not "OK", then this - method will return a CIM Error instance. Otherwise, when the - Job is "OK", null is returned. - - - 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) - """ - job = InstallationJob.object_path2job(object_name) - error = InstallationJob.job2error(job) - out_params = [] - if error is not None: - param = pywbem.CIMParameter('Error', type='instance', value=error) - out_params.append(param) - return (self.values.GetErrors.Success, out_params) 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_SoftwareJob.py b/src/software/openlmi/software/LMI_SoftwareJob.py new file mode 100644 index 0000000..b6d7ca5 --- /dev/null +++ b/src/software/openlmi/software/LMI_SoftwareJob.py @@ -0,0 +1,385 @@ +# -*- encoding: utf-8 -*- +# Software Management Providers +# +# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""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_SoftwareJob +""" + +import pywbem +from pywbem.cim_provider2 import CIMProvider2 + +from openlmi.common import cmpi_logging +from openlmi.software.core import Job +from openlmi.software.yumdb import errors, YumDB + +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. + + """ + + def __init__ (self, _env): + cmpi_logging.logger.debug('Initializing provider %s from %s' \ + % (self.__class__.__name__, __file__)) + self.values = Job.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) + """ + 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): + """Enumerate instances. + + The WBEM operations EnumerateInstances and EnumerateInstanceNames + are both mapped to this method. + This method is a python generator + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + model -- A template of the pywbem.CIMInstances to be generated. + The properties of the model are already filtered according to + the PropertyList from the request. Only properties present in + the model need to be given values. If you prefer, you can + always set all of the values, and the instance will be filtered + for you. + keys_only -- A boolean. True if only the key properties should be + set on the generated instances. + + Possible Errors: + CIM_ERR_FAILED (some other unspecified error occurred) + """ + # Prime model.path with knowledge of the keys, so key values on + # the CIMInstanceName (model.path) will automatically be set when + # we set property values on the model. + model.path.update({'InstanceID': None}) + + ch = env.get_cimom_handle() + for job in YumDB.get_instance().get_job_list(): + 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): + """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) + + """ + if not modify_existing: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED, + "Can not create new instance.") + return Job.modify_instance(instance) + + @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) + """ + with YumDB.get_instance() as ydb: + job = Job.object_path2job(instance_name) + try: + cmpi_logging.logger.info('deleting job "%s"' % job) + ydb.delete_job(job.jobid) + cmpi_logging.logger.info('job "%s" removed' % job) + except errors.JobNotFound as exc: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + getattr(exc, 'message', str(exc))) + except errors.JobControlError as exc: + raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, + getattr(exc, 'message', str(exc))) + + @cmpi_logging.trace_method + def cim_method_requeststatechange(self, env, object_name, + param_requestedstate=None, + param_timeoutperiod=None): + """Implements LMI_SoftwareJob.RequestStateChange() + + Requests that the state of the job be changed to the value + specified in the RequestedState parameter. Invoking the + RequestStateChange method multiple times could result in earlier + requests being overwritten or lost. If 0 is returned, then the + task completed successfully. Any other return code indicates an + error condition. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName + specifying the object on which the method RequestStateChange() + should be invoked. + param_requestedstate -- The input parameter RequestedState ( + type pywbem.Uint16 + self.Values.RequestStateChange.RequestedState) + RequestStateChange changes the state of a job. The possible + values are as follows: Start (2) changes the state to + 'Running'. Suspend (3) stops the job temporarily. The + intention is to subsequently restart the job with 'Start'. It + might be possible to enter the 'Service' state while + suspended. (This is job-specific.) Terminate (4) stops the + job cleanly, saving data, preserving the state, and shutting + down all underlying processes in an orderly manner. Kill (5) + terminates the job immediately with no requirement to save + data or preserve the state. Service (6) puts the job into a + vendor-specific service state. It might be possible to restart + the job. + + param_timeoutperiod -- The input parameter TimeoutPeriod ( + type pywbem.CIMDateTime) + A timeout period that specifies the maximum amount of time that + the client expects the transition to the new state to take. + The interval format must be used to specify the TimeoutPeriod. + A value of 0 or a null parameter indicates that the client has + no time requirements for the transition. If this property + does not contain 0 or null and the implementation does not + support this parameter, a return code of 'Use Of Timeout + Parameter Not Supported' must be returned. + + + Returns a two-tuple containing the return value ( + type pywbem.Uint32 self.Values.RequestStateChange) + 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) + """ + job = Job.object_path2job(object_name) + try: + if param_requestedstate not in { + self.values.RequestStateChange.RequestedState.Terminate }: + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "Valid RequestedState can by only Terminate (%d)" % + self.values.RequestStateChange.RequestedState.Terminate) + if param_timeoutperiod: + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "Timeout period is not supported.") + YumDB.get_instance().terminate_job(job.jobid) + except errors.JobNotFound as exc: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + getattr(exc, 'message', str(exc))) + except errors.JobControlError as exc: + raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, + getattr(exc, 'message', str(exc))) + return (self.values.GetErrors.Success, []) + + @cmpi_logging.trace_method + def cim_method_geterrors(self, env, object_name): + """Implements LMI_SoftwareJob.GetErrors() + + If JobState is "Completed" and Operational Status is "Completed" + then no instance of CIM_Error is returned. If JobState is + "Exception" then GetErrors may return intances of CIM_Error + related to the execution of the procedure or method invoked by the + job. If Operatational Status is not "OK" or "Completed"then + GetErrors may return CIM_Error instances related to the running of + the job. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName + specifying the object on which the method GetErrors() + should be invoked. + + Returns a two-tuple containing the return value ( + type pywbem.Uint32 self.Values.GetErrors) + and a list of CIMParameter objects representing the output parameters + + Output parameters: + Errors -- (type pywbem.CIMInstance(classname='CIM_Error', ...)) + If the OperationalStatus on the Job is not "OK", then this + method will return one or more CIM Error instance(s). + Otherwise, when the Job is "OK", null is returned. + + + 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) + """ + job = Job.object_path2job(object_name) + error = Job.job2error(job) + out_params = [] + if error is not None: + param = pywbem.CIMParameter('Errors', type='instance', + is_array=True, array_size=1, value=[error]) + out_params.append(param) + return (self.values.GetErrors.Success, out_params) + + @cmpi_logging.trace_method + def cim_method_killjob(self, env, object_name, + param_deleteonkill=None): + """Implements LMI_SoftwareJob.KillJob() + + KillJob is being deprecated because there is no distinction made + between an orderly shutdown and an immediate kill. + CIM_ConcreteJob.RequestStateChange() provides 'Terminate' and + 'Kill' options to allow this distinction. A method to kill this + job and any underlying processes, and to remove any 'dangling' + associations. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName + specifying the object on which the method KillJob() + should be invoked. + param_deleteonkill -- The input parameter DeleteOnKill (type bool) + Indicates whether or not the Job should be automatically + deleted upon termination. This parameter takes precedence over + the property, DeleteOnCompletion. + + + Returns a two-tuple containing the return value ( + type pywbem.Uint32 self.Values.KillJob) + 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) + """ + raise pywbem.CIMError(pywbem.CIM_ERR_METHOD_NOT_AVAILABLE) + + @cmpi_logging.trace_method + def cim_method_geterror(self, env, object_name): + """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, + then this method returns no CIM_Error instance. However, if the + job has failed because of some internal problem or because the job + has been terminated by a client, then a CIM_Error instance is + returned. + + Keyword arguments: + env -- Provider Environment (pycimmb.ProviderEnvironment) + object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName + specifying the object on which the method GetError() + should be invoked. + + Returns a two-tuple containing the return value ( + type pywbem.Uint32 self.Values.GetError) + and a list of CIMParameter objects representing the output parameters + + Output parameters: + Error -- (type pywbem.CIMInstance(classname='CIM_Error', ...)) + If the OperationalStatus on the Job is not "OK", then this + method will return a CIM Error instance. Otherwise, when the + Job is "OK", null is returned. + + + 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) + """ + 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) + out_params.append(param) + return (self.values.GetErrors.Success, out_params) 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) @@ -176,6 +201,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): """ @@ -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/InstallationJob.py b/src/software/openlmi/software/core/InstallationJob.py deleted file mode 100644 index 0a3d44a..0000000 --- a/src/software/openlmi/software/core/InstallationJob.py +++ /dev/null @@ -1,754 +0,0 @@ -# -*- encoding: utf-8 -*- -# Software Management Providers -# -# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -""" -Just a common functionality related to SoftwareInstallationJob -and SoftwareVerificationJob. -""" - -from datetime import datetime, timedelta -import pywbem -import time - -from openlmi.common import cmpi_logging -from openlmi.software import util -from openlmi.software.core import Error -from openlmi.software.yumdb import errors, jobs -from openlmi.software.yumdb import YumDB - -JOB_CLASS_NAMES = ( - "LMI_SoftwareInstallationJob", - "LMI_SoftwareVerificationJob" -) - -JOB_DESCRIPTIONS = { - jobs.YumInstallPackage : - 'Software package installation job %(jobid)d for "%(pkg)s".', - jobs.YumRemovePackage : - 'Software package removal job %(jobid)d for "%(pkg)s".', - jobs.YumUpdateToPackage : - 'Software package update job %(jobid)d for "%(pkg)s".', - jobs.YumUpdatePackage : - 'Software package update job %(jobid)d for "%(pkg)s".', - jobs.YumInstallPackageFromURI : - 'Software package installation job %(jobid)d from uri: "%(uri)s".', - jobs.YumCheckPackage : - 'Software package check job %(jobid)d for "%(pkg)s".', - jobs.YumCheckPackageFile : - 'File verification job %(jobid)d for package "%(pkg)s".', -} - -# identificators of InstallationService method, which may trigger -# creation of asynchronous job -( JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY -, JOB_METHOD_INSTALL_FROM_URI -, JOB_METHOD_INSTALL_FROM_BYTE_STREAM -, JOB_METHOD_VERIFY_INSTALLED_IDENTITY) = range(4) - -# above identificators point to this array to their description -JOB_METHOD_NAMES = ( - "InstallFromSoftwareIdentity", - "InstallFromURI", - "InstallFromByteStream", - "VerifyInstalledIdentity") - -class Values(object): - class DetailedStatus(object): - Not_Available = pywbem.Uint16(0) - No_Additional_Information = pywbem.Uint16(1) - Stressed = pywbem.Uint16(2) - Predictive_Failure = pywbem.Uint16(3) - Non_Recoverable_Error = pywbem.Uint16(4) - Supporting_Entity_in_Error = pywbem.Uint16(5) - # DMTF_Reserved = .. - # Vendor_Reserved = 0x8000.. - _reverse_map = { - 0: 'Not Available', - 1: 'No Additional Information', - 2: 'Stressed', - 3: 'Predictive Failure', - 4: 'Non-Recoverable Error', - 5: 'Supporting Entity in Error' - } - - class Status(object): - OK = 'OK' - Error = 'Error' - Degraded = 'Degraded' - Unknown = 'Unknown' - Pred_Fail = 'Pred Fail' - Starting = 'Starting' - Stopping = 'Stopping' - Service = 'Service' - Stressed = 'Stressed' - NonRecover = 'NonRecover' - No_Contact = 'No Contact' - Lost_Comm = 'Lost Comm' - Stopped = 'Stopped' - - class HealthState(object): - Unknown = pywbem.Uint16(0) - OK = pywbem.Uint16(5) - Degraded_Warning = pywbem.Uint16(10) - Minor_failure = pywbem.Uint16(15) - Major_failure = pywbem.Uint16(20) - Critical_failure = pywbem.Uint16(25) - Non_recoverable_error = pywbem.Uint16(30) - # DMTF_Reserved = .. - # Vendor_Specific = 32768..65535 - _reverse_map = { - 0: 'Unknown', - 5: 'OK', - 10: 'Degraded/Warning', - 15: 'Minor failure', - 20: 'Major failure', - 25: 'Critical failure', - 30: 'Non-recoverable error' - } - - class JobState(object): - New = pywbem.Uint16(2) - Starting = pywbem.Uint16(3) - Running = pywbem.Uint16(4) - Suspended = pywbem.Uint16(5) - Shutting_Down = pywbem.Uint16(6) - Completed = pywbem.Uint16(7) - Terminated = pywbem.Uint16(8) - Killed = pywbem.Uint16(9) - Exception = pywbem.Uint16(10) - Service = pywbem.Uint16(11) - Query_Pending = pywbem.Uint16(12) - # DMTF_Reserved = 13..32767 - # Vendor_Reserved = 32768..65535 - _reverse_map = { - 2: 'New', - 3: 'Starting', - 4: 'Running', - 5: 'Suspended', - 6: 'Shutting Down', - 7: 'Completed', - 8: 'Terminated', - 9: 'Killed', - 10: 'Exception', - 11: 'Service', - 12: 'Query Pending' - } - - class GetError(object): - Success = 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) - Access_Denied = pywbem.Uint32(6) - # DMTF_Reserved = .. - # Vendor_Specific = 32768..65535 - - class KillJob(object): - Success = pywbem.Uint32(0) - Not_Supported = pywbem.Uint32(1) - Unknown = pywbem.Uint32(2) - Timeout = pywbem.Uint32(3) - Failed = pywbem.Uint32(4) - Access_Denied = pywbem.Uint32(6) - Not_Found = pywbem.Uint32(7) - # DMTF_Reserved = .. - # Vendor_Specific = 32768..65535 - - class RecoveryAction(object): - Unknown = pywbem.Uint16(0) - Other = pywbem.Uint16(1) - Do_Not_Continue = pywbem.Uint16(2) - Continue_With_Next_Job = pywbem.Uint16(3) - Re_run_Job = pywbem.Uint16(4) - Run_Recovery_Job = pywbem.Uint16(5) - _reverse_map = { - 0: 'Unknown', - 1: 'Other', - 2: 'Do Not Continue', - 3: 'Continue With Next Job', - 4: 'Re-run Job', - 5: 'Run Recovery Job' - } - - class RunDayOfWeek(object): - _Saturday = pywbem.Sint8(-7) - _Friday = pywbem.Sint8(-6) - _Thursday = pywbem.Sint8(-5) - _Wednesday = pywbem.Sint8(-4) - _Tuesday = pywbem.Sint8(-3) - _Monday = pywbem.Sint8(-2) - _Sunday = pywbem.Sint8(-1) - ExactDayOfMonth = pywbem.Sint8(0) - Sunday = pywbem.Sint8(1) - Monday = pywbem.Sint8(2) - Tuesday = pywbem.Sint8(3) - Wednesday = pywbem.Sint8(4) - Thursday = pywbem.Sint8(5) - Friday = pywbem.Sint8(6) - Saturday = pywbem.Sint8(7) - _reverse_map = { - 0: 'ExactDayOfMonth', - 1: 'Sunday', - 2: 'Monday', - 3: 'Tuesday', - 4: 'Wednesday', - 5: 'Thursday', - 6: 'Friday', - 7: 'Saturday', - -1: '-Sunday', - -7: '-Saturday', - -6: '-Friday', - -5: '-Thursday', - -4: '-Wednesday', - -3: '-Tuesday', - -2: '-Monday' - } - - class RunMonth(object): - January = pywbem.Uint8(0) - February = pywbem.Uint8(1) - March = pywbem.Uint8(2) - April = pywbem.Uint8(3) - May = pywbem.Uint8(4) - June = pywbem.Uint8(5) - July = pywbem.Uint8(6) - August = pywbem.Uint8(7) - September = pywbem.Uint8(8) - October = pywbem.Uint8(9) - November = pywbem.Uint8(10) - December = pywbem.Uint8(11) - _reverse_map = { - 0: 'January', - 1: 'February', - 2: 'March', - 3: 'April', - 4: 'May', - 5: 'June', - 6: 'July', - 7: 'August', - 8: 'September', - 9: 'October', - 10: 'November', - 11: 'December' - } - - class GetErrors(object): - Success = 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) - Access_Denied = pywbem.Uint32(6) - # DMTF_Reserved = .. - # Vendor_Specific = 32768..65535 - - class CommunicationStatus(object): - Unknown = pywbem.Uint16(0) - Not_Available = pywbem.Uint16(1) - Communication_OK = pywbem.Uint16(2) - Lost_Communication = pywbem.Uint16(3) - No_Contact = pywbem.Uint16(4) - # DMTF_Reserved = .. - # Vendor_Reserved = 0x8000.. - _reverse_map = { - 0: 'Unknown', - 1: 'Not Available', - 2: 'Communication OK', - 3: 'Lost Communication', - 4: 'No Contact' - } - - class OperationalStatus(object): - Unknown = pywbem.Uint16(0) - Other = pywbem.Uint16(1) - OK = pywbem.Uint16(2) - Degraded = pywbem.Uint16(3) - Stressed = pywbem.Uint16(4) - Predictive_Failure = pywbem.Uint16(5) - Error = pywbem.Uint16(6) - Non_Recoverable_Error = pywbem.Uint16(7) - Starting = pywbem.Uint16(8) - Stopping = pywbem.Uint16(9) - Stopped = pywbem.Uint16(10) - In_Service = pywbem.Uint16(11) - No_Contact = pywbem.Uint16(12) - Lost_Communication = pywbem.Uint16(13) - Aborted = pywbem.Uint16(14) - Dormant = pywbem.Uint16(15) - Supporting_Entity_in_Error = pywbem.Uint16(16) - Completed = pywbem.Uint16(17) - Power_Mode = pywbem.Uint16(18) - Relocating = pywbem.Uint16(19) - # DMTF_Reserved = .. - # Vendor_Reserved = 0x8000.. - _reverse_map = { - 0: 'Unknown', - 1: 'Other', - 2: 'OK', - 3: 'Degraded', - 4: 'Stressed', - 5: 'Predictive Failure', - 6: 'Error', - 7: 'Non-Recoverable Error', - 8: 'Starting', - 9: 'Stopping', - 10: 'Stopped', - 11: 'In Service', - 12: 'No Contact', - 13: 'Lost Communication', - 14: 'Aborted', - 15: 'Dormant', - 16: 'Supporting Entity in Error', - 17: 'Completed', - 18: 'Power Mode', - 19: 'Relocating' - } - - class OperatingStatus(object): - Unknown = pywbem.Uint16(0) - Not_Available = pywbem.Uint16(1) - Servicing = pywbem.Uint16(2) - Starting = pywbem.Uint16(3) - Stopping = pywbem.Uint16(4) - Stopped = pywbem.Uint16(5) - Aborted = pywbem.Uint16(6) - Dormant = pywbem.Uint16(7) - Completed = pywbem.Uint16(8) - Migrating = pywbem.Uint16(9) - Emigrating = pywbem.Uint16(10) - Immigrating = pywbem.Uint16(11) - Snapshotting = pywbem.Uint16(12) - Shutting_Down = pywbem.Uint16(13) - In_Test = pywbem.Uint16(14) - Transitioning = pywbem.Uint16(15) - In_Service = pywbem.Uint16(16) - # DMTF_Reserved = .. - # Vendor_Reserved = 0x8000.. - _reverse_map = { - 0: 'Unknown', - 1: 'Not Available', - 2: 'Servicing', - 3: 'Starting', - 4: 'Stopping', - 5: 'Stopped', - 6: 'Aborted', - 7: 'Dormant', - 8: 'Completed', - 9: 'Migrating', - 10: 'Emigrating', - 11: 'Immigrating', - 12: 'Snapshotting', - 13: 'Shutting Down', - 14: 'In Test', - 15: 'Transitioning', - 16: 'In Service' - } - - class LocalOrUtcTime(object): - Local_Time = pywbem.Uint16(1) - UTC_Time = pywbem.Uint16(2) - _reverse_map = { - 1: 'Local Time', - 2: 'UTC Time' - } - - class RequestStateChange(object): - Completed_with_No_Error = pywbem.Uint32(0) - Not_Supported = pywbem.Uint32(1) - Unknown_Unspecified_Error = pywbem.Uint32(2) - Can_NOT_complete_within_Timeout_Period = pywbem.Uint32(3) - Failed = pywbem.Uint32(4) - Invalid_Parameter = pywbem.Uint32(5) - In_Use = pywbem.Uint32(6) - # DMTF_Reserved = .. - Method_Parameters_Checked___Transition_Started = pywbem.Uint32(4096) - Invalid_State_Transition = pywbem.Uint32(4097) - Use_of_Timeout_Parameter_Not_Supported = pywbem.Uint32(4098) - Busy = pywbem.Uint32(4099) - # Method_Reserved = 4100..32767 - # Vendor_Specific = 32768..65535 - class RequestedState(object): - Start = pywbem.Uint16(2) - Suspend = pywbem.Uint16(3) - Terminate = pywbem.Uint16(4) - Kill = pywbem.Uint16(5) - Service = pywbem.Uint16(6) - # DMTF_Reserved = 7..32767 - # Vendor_Reserved = 32768..65535 - - class PrimaryStatus(object): - Unknown = pywbem.Uint16(0) - OK = pywbem.Uint16(1) - Degraded = pywbem.Uint16(2) - Error = pywbem.Uint16(3) - # DMTF_Reserved = .. - # Vendor_Reserved = 0x8000.. - _reverse_map = { - 0: 'Unknown', - 1: 'OK', - 2: 'Degraded', - 3: 'Error' - } - -@cmpi_logging.trace_function -def get_verification_out_params(job): - """ - Get the output parameters for verification job. They may not be computed - yet. In that case compute them a update the job in YumWorker process. - - :param job: (``jobs.YumCheckPackage``) - :rtype: (``dict``) Dictionary of output parameters with pywbem values. - """ - if not isinstance(job, jobs.YumCheckPackage): - raise TypeError("job must be a YumCheckPackage instance") - if ( not job.metadata.get("output_params", []) - and job.state == job.COMPLETED): - from openlmi.software.core import IdentityFileCheck - failed = [] - pkg_info, pkg_check = job.result_data - for file_name in pkg_check: - pkg_file = pkg_check[file_name] - file_check = IdentityFileCheck.test_file(pkg_info, - pkg_check.file_checksum_type, pkg_file) - if not IdentityFileCheck.file_check_passed(file_check): - failed.append(IdentityFileCheck.file_check2model( - file_check, job=job)) - metadata = { - 'output_params' : { - 'Failed' : pywbem.CIMProperty("Failed", - type="reference", is_array=True, value=failed) - } - } - # update local instance - job.update(metadata=metadata) - if YumDB.RUNNING_UNDER_CIMOM_PROCESS: - # update instance on server - YumDB.get_instance().update_job(job.jobid, metadata=metadata) - # else: we are called from YumWorker process; - # (update on server already occured) - # moreover YumWorker blocks on us - we can not wait for another job - # to finish - return job.metadata.get('output_params', []) - -@cmpi_logging.trace_function -def make_method_params(job, class_name, include_input, include_output): - """ - Create a class of given name with all input or output parameters - of the asynchronous method. Typically used to assemble - CIM_ConcreteJob.JobInParameters or CIM_InstMethodCall.MethodParameters - values. - - :param job: (``YumJob``) Instance of job created as a result of method - invocation. It carries method parameters. - :param class_name: (``str``) Name of the class to create. - :param include_input: (``bool``) Whether input parameters should be - included in the returned class. - :param include_output: (``bool``) Whether output parameters should be - included in the returned class. - :rtype: CIMInstance of the created class. - """ - # TODO: this is workaround for bug #920763, use class_name - # when it's fixed - clsname = "CIM_ManagedElement" - path = pywbem.CIMInstanceName(classname=clsname, namespace="root/cimv2") - inst = pywbem.CIMInstance(classname=clsname, path=path) - if include_input and "input_params" in job.metadata: - for (name, value) in job.metadata["input_params"].items(): - inst[name] = value - if include_output: - if isinstance(job, jobs.YumCheckPackage): - # make sure, that output parameters are computed - get_verification_out_params(job) - if "output_params" in job.metadata: - # overwrite any input parameter - for (name, value) in job.metadata["output_params"].iteritems(): - inst[name] = value - return inst - -def job_class2cim_class_name(jobcls): - """ - Here we map classes of job objects to their corresponding CIM class - name. - - :param jobcls: (``type``) Subclass of jobs.YumJob. - """ - if not issubclass(jobcls, ( - jobs.YumInstallPackageFromURI, - jobs.YumSpecificPackageJob)): - raise ValueError("Job class \"%s\" does not have any associated" - " CIM class." % jobcls.__name__) - if issubclass(jobcls, (jobs.YumCheckPackage, jobs.YumCheckPackageFile)): - return "LMI_SoftwareVerificationJob" - return "LMI_SoftwareInstallationJob" - -@cmpi_logging.trace_function -def _fill_nonkeys(job, model): - """ - Fills into the model of instance all non-key properties. - """ - model['Caption'] = 'Software installation job with id=%d' % job.jobid - model['CommunicationStatus'] = Values.CommunicationStatus.Not_Available - model['DeleteOnCompletion'] = job.delete_on_completion - try: - description = JOB_DESCRIPTIONS[job.__class__] - kwargs = job.job_kwargs - kwargs['jobid'] = job.jobid - model['Description'] = description % kwargs - except KeyError: - cmpi_logging.logger.error( - 'no description string found for job class %s' % - job.__class__.__name__) - model['Description'] = pywbem.CIMProperty('Description', - type='string', value=None) - if job.started: - if job.finished: - elapsed = job.finished - job.started - else: - elapsed = time.time() - job.started - model['ElapsedTime'] = pywbem.CIMDateTime(timedelta(seconds=elapsed)) - else: - model["ElapsedTime"] = pywbem.CIMProperty('ElapsedTime', - type='datetime', value=None) - model['ErrorCode'] = pywbem.Uint16(0 if job.state != job.EXCEPTION else 1) - try: - model['JobState'], model['OperationalStatus'], model['JobStatus'] = { - jobs.YumJob.NEW : (Values.JobState.New, - [Values.OperationalStatus.Dormant], 'Enqueued'), - jobs.YumJob.RUNNING : (Values.JobState.Running, - [Values.OperationalStatus.OK], 'Running'), - jobs.YumJob.TERMINATED : (Values.JobState.Terminated, - [Values.OperationalStatus.Stopped], 'Terminated'), - jobs.YumJob.EXCEPTION : (Values.JobState.Exception - , [Values.OperationalStatus.Error] - , 'Failed'), - jobs.YumJob.COMPLETED : (Values.JobState.Completed - , [ Values.OperationalStatus.OK - , Values.OperationalStatus.Completed] - , 'Finished successfully') - }[job.state] - except KeyError: - cmpi_logging.logger.error('unknown job state: %s' % job.state) - model['JobState'] = pywbem.CIMProperty('JobState', - type='uint16', value=None) - model['OperationalStatus'] = [Values.OperationalStatus.Unknown] - model['JobStatus'] = 'Unknown' - model["JobInParameters"] = make_method_params( - job, "__JobInParameters", True, False) - model["JobOutParameters"] = make_method_params( - job, "__JobOutParameters", False, True) - if 'method' in job.metadata: - model['MethodName'] = JOB_METHOD_NAMES[job.metadata["method"]] - else: - model["MethodName"] = pywbem.CIMProperty('MethodName', - type='string', value=None) - model['Name'] = job.metadata['name'] - model['LocalOrUtcTime'] = Values.LocalOrUtcTime.UTC_Time - model['PercentComplete'] = pywbem.Uint16( - 100 if job.state == job.COMPLETED else ( - 50 if job.state == job.RUNNING else - 0)) - model['Priority'] = pywbem.Uint32(job.priority) - if job.started: - model['StartTime'] = pywbem.CIMDateTime(datetime.fromtimestamp( - job.started)) - model['TimeBeforeRemoval'] = pywbem.CIMDateTime(timedelta( - seconds=job.time_before_removal)) - model['TimeOfLastStateChange'] = pywbem.CIMDateTime(datetime.fromtimestamp( - job.last_change)) - model['TimeSubmitted'] = pywbem.CIMDateTime(datetime.fromtimestamp( - job.created)) - -@cmpi_logging.trace_function -def job2model(job, class_name=None, keys_only=True, model=None): - """ - Makes LMI_SoftwareJob out of job object or job id. - - :param job: (``int`` | ``YumAsyncJob``) Job identifier. - In case of integer, caller should also provide class_name of resulting - CIM instance. Otherwise generic LMI_SoftwareJob will be returned. - :param class_name: (``str``) Determines CIM class name of resulting - instance. This should be given when ``job`` is an integer. - :param model: (``CIMInstance`` | ``CIMInstanceName``) If not None, - will be filled with properties, otherwise - a new instance of CIMInstance or CIMObjectPath is created. - :param keys_only: (``bool``) Says whether to fill only key properties. - Also if ``model`` is not given, it determines, whether to make - ``CIMInstanceName`` or ``CIMInstance``. - :rtype: (``CIMInstance`` | ``CIMInstanceName``) - """ - if not isinstance(job, (int, long, jobs.YumAsyncJob)): - raise TypeError("job must be an instance of YumAsyncJob") - if isinstance(job, jobs.YumAsyncJob) and not job.async: - raise ValueError("job must be asynchronous") - if not keys_only and isinstance(job, (int, long)): - raise TypeError("job must be an instance of YumAsyncJob" - " filling non-key properties") - - if class_name is None: - if model is not None: - class_name = model.classname - elif isinstance(job, jobs.YumJob): - class_name = job_class2cim_class_name(job.__class__) - else: - class_name = "LMI_SoftwareJob" - cmpi_logging.logger.warn( - "class_name not supplied for jobid=%d, using general" - " LMI_SoftwareJob as CIM class name") - if model is None: - model = pywbem.CIMInstanceName(class_name, namespace="root/cimv2") - if not keys_only: - model = pywbem.CIMInstance(class_name, path=model) - - jobid = job.jobid if isinstance(job, jobs.YumAsyncJob) else job - model['InstanceID'] = 'LMI:%s:%d' % (class_name, jobid) - if isinstance(model, pywbem.CIMInstance): - model.path['InstanceID'] = model['InstanceID'] #pylint: disable=E1103 - if not keys_only: - _fill_nonkeys(job, model) - return model - -@cmpi_logging.trace_function -def object_path2job(op): - """ - @param op must contain precise InstanceID of job - """ - if not isinstance(op, pywbem.CIMInstanceName): - raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, - "op must be an instance of CIMInstanceName") - - if (not "InstanceID" in op or not op['InstanceID']): - raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, - "Missing InstanceID key property.") - instid = op['InstanceID'] - match = util.RE_INSTANCE_ID.match(instid) - if not match or match.group('clsname').lower() not in { - c.lower() for c in JOB_CLASS_NAMES}: - raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, - "InstanceID must start with one of {%s} prefixes." - " And end with positive integer." % ( - ", ".join(("LMI:%s:" % cn) for cn in JOB_CLASS_NAMES))) - - instid = int(match.group('id')) - try: - job = YumDB.get_instance().get_job(instid) - clsname = job_class2cim_class_name(job.__class__) - if ( clsname.lower() != op.classname.lower() - and op.classname.lower() != 'LMI_SoftwareJob'.lower()): - raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, - "Classname \"%s\" does not belong to job with given id." - " \"%s\" is the correct one." % (op.classname, clsname)) - return job - except errors.JobNotFound: - raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, - 'No such job "%s".' % op['InstanceID']) - -@cmpi_logging.trace_function -def modify_instance(instance): - """ - This call modifies the job's parameters according to given instance. - """ - job = object_path2job(instance.path) - ydb = YumDB.get_instance() - update_kwargs = {} - reschedule_kwargs = {} - # all modifiable properties - prop_name_map = { - "name" : "name", - "priority" : "priority", - "deleteoncompletion" : "delete_on_completion", - "timebeforeremoval" : "time_before_removal" - } - metadata_props = {"name"} - reschedule_props = {"delete_on_completion", "time_before_removal"} - for name, prop in instance.properties.items(): - if prop is None: - cmpi_logging.logger.warn('property "%s" is None') - continue - name = name.lower() - try: - pname = prop_name_map[name] - if pname == "priority" and job.priority != prop.value: - cmpi_logging.logger.info( - 'changing priority of job %s to %d', job, prop.value) - job = ydb.set_job_priority(job.jobid, prop.value) - elif pname in reschedule_props: - if getattr(job, pname) == prop.value: - continue - if pname == "time_before_removal": - value = prop.value.timedelta.total_seconds() - else: - value = prop.value - reschedule_kwargs[pname] = value - else: - if pname in metadata_props: - if not 'metadata' in update_kwargs: - update_kwargs['metadata'] = {} - update_kwargs['metadata'][pname] = prop.value - else: - update_kwargs[pname] = prop.value - except KeyError: - if name == 'instanceid': - continue - cmpi_logging.logger.warn("skipping property %s: %s", name, prop) - - if reschedule_kwargs: - for prop in ('delete_on_completion', 'time_before_removal'): - if prop not in reschedule_kwargs: - reschedule_kwargs[prop] = getattr(job, prop) - cmpi_logging.logger.info('rescheduling job %s to: %s', - job, ", ".join("%s=%s"%(k, v) for k, v in - reschedule_kwargs.items())) - job = ydb.reschedule_job(job.jobid, **reschedule_kwargs) - - if update_kwargs: - cmpi_logging.logger.info('changing atributes of job %s to: %s', - job, ", ".join("%s=%s"%(k, v) for k, v in - update_kwargs.items())) - job = ydb.update_job(job.jobid, **update_kwargs) - - return job2model(job, keys_only=False, model=instance) - -@cmpi_logging.trace_function -def job2error(job): - """ - @return instance of CIM_Error if job is in EXCEPTION state, - None otherwise - """ - if not isinstance(job, jobs.YumJob): - raise TypeError("job must be isntance of YumJob") - if job.state == job.EXCEPTION: - errortup = job.result_data - kwargs = {} - if issubclass(errortup[0], - (errors.RepositoryNotFound, errors.PackageNotFound)): - kwargs['status_code'] = Error.Values. \ - CIMStatusCode.CIM_ERR_NOT_FOUND - if issubclass(errortup[0], errors.PackageNotFound): - kwargs['status_code_description'] = "Package not found" - else: - kwargs['status_code_description'] = "Repository not found" - elif issubclass(errortup[0], errors.PackageAlreadyInstalled): - kwargs['status_code'] = Error.Values. \ - CIMStatusCode.CIM_ERR_ALREADY_EXISTS - kwargs['message'] = getattr(errortup[1], 'message', - str(errortup[1])) - value = Error.make_instance(**kwargs) - return value 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/Job.py b/src/software/openlmi/software/core/Job.py new file mode 100644 index 0000000..0a3d44a --- /dev/null +++ b/src/software/openlmi/software/core/Job.py @@ -0,0 +1,754 @@ +# -*- encoding: utf-8 -*- +# Software Management Providers +# +# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Just a common functionality related to SoftwareInstallationJob +and SoftwareVerificationJob. +""" + +from datetime import datetime, timedelta +import pywbem +import time + +from openlmi.common import cmpi_logging +from openlmi.software import util +from openlmi.software.core import Error +from openlmi.software.yumdb import errors, jobs +from openlmi.software.yumdb import YumDB + +JOB_CLASS_NAMES = ( + "LMI_SoftwareInstallationJob", + "LMI_SoftwareVerificationJob" +) + +JOB_DESCRIPTIONS = { + jobs.YumInstallPackage : + 'Software package installation job %(jobid)d for "%(pkg)s".', + jobs.YumRemovePackage : + 'Software package removal job %(jobid)d for "%(pkg)s".', + jobs.YumUpdateToPackage : + 'Software package update job %(jobid)d for "%(pkg)s".', + jobs.YumUpdatePackage : + 'Software package update job %(jobid)d for "%(pkg)s".', + jobs.YumInstallPackageFromURI : + 'Software package installation job %(jobid)d from uri: "%(uri)s".', + jobs.YumCheckPackage : + 'Software package check job %(jobid)d for "%(pkg)s".', + jobs.YumCheckPackageFile : + 'File verification job %(jobid)d for package "%(pkg)s".', +} + +# identificators of InstallationService method, which may trigger +# creation of asynchronous job +( JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY +, JOB_METHOD_INSTALL_FROM_URI +, JOB_METHOD_INSTALL_FROM_BYTE_STREAM +, JOB_METHOD_VERIFY_INSTALLED_IDENTITY) = range(4) + +# above identificators point to this array to their description +JOB_METHOD_NAMES = ( + "InstallFromSoftwareIdentity", + "InstallFromURI", + "InstallFromByteStream", + "VerifyInstalledIdentity") + +class Values(object): + class DetailedStatus(object): + Not_Available = pywbem.Uint16(0) + No_Additional_Information = pywbem.Uint16(1) + Stressed = pywbem.Uint16(2) + Predictive_Failure = pywbem.Uint16(3) + Non_Recoverable_Error = pywbem.Uint16(4) + Supporting_Entity_in_Error = pywbem.Uint16(5) + # DMTF_Reserved = .. + # Vendor_Reserved = 0x8000.. + _reverse_map = { + 0: 'Not Available', + 1: 'No Additional Information', + 2: 'Stressed', + 3: 'Predictive Failure', + 4: 'Non-Recoverable Error', + 5: 'Supporting Entity in Error' + } + + class Status(object): + OK = 'OK' + Error = 'Error' + Degraded = 'Degraded' + Unknown = 'Unknown' + Pred_Fail = 'Pred Fail' + Starting = 'Starting' + Stopping = 'Stopping' + Service = 'Service' + Stressed = 'Stressed' + NonRecover = 'NonRecover' + No_Contact = 'No Contact' + Lost_Comm = 'Lost Comm' + Stopped = 'Stopped' + + class HealthState(object): + Unknown = pywbem.Uint16(0) + OK = pywbem.Uint16(5) + Degraded_Warning = pywbem.Uint16(10) + Minor_failure = pywbem.Uint16(15) + Major_failure = pywbem.Uint16(20) + Critical_failure = pywbem.Uint16(25) + Non_recoverable_error = pywbem.Uint16(30) + # DMTF_Reserved = .. + # Vendor_Specific = 32768..65535 + _reverse_map = { + 0: 'Unknown', + 5: 'OK', + 10: 'Degraded/Warning', + 15: 'Minor failure', + 20: 'Major failure', + 25: 'Critical failure', + 30: 'Non-recoverable error' + } + + class JobState(object): + New = pywbem.Uint16(2) + Starting = pywbem.Uint16(3) + Running = pywbem.Uint16(4) + Suspended = pywbem.Uint16(5) + Shutting_Down = pywbem.Uint16(6) + Completed = pywbem.Uint16(7) + Terminated = pywbem.Uint16(8) + Killed = pywbem.Uint16(9) + Exception = pywbem.Uint16(10) + Service = pywbem.Uint16(11) + Query_Pending = pywbem.Uint16(12) + # DMTF_Reserved = 13..32767 + # Vendor_Reserved = 32768..65535 + _reverse_map = { + 2: 'New', + 3: 'Starting', + 4: 'Running', + 5: 'Suspended', + 6: 'Shutting Down', + 7: 'Completed', + 8: 'Terminated', + 9: 'Killed', + 10: 'Exception', + 11: 'Service', + 12: 'Query Pending' + } + + class GetError(object): + Success = 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) + Access_Denied = pywbem.Uint32(6) + # DMTF_Reserved = .. + # Vendor_Specific = 32768..65535 + + class KillJob(object): + Success = pywbem.Uint32(0) + Not_Supported = pywbem.Uint32(1) + Unknown = pywbem.Uint32(2) + Timeout = pywbem.Uint32(3) + Failed = pywbem.Uint32(4) + Access_Denied = pywbem.Uint32(6) + Not_Found = pywbem.Uint32(7) + # DMTF_Reserved = .. + # Vendor_Specific = 32768..65535 + + class RecoveryAction(object): + Unknown = pywbem.Uint16(0) + Other = pywbem.Uint16(1) + Do_Not_Continue = pywbem.Uint16(2) + Continue_With_Next_Job = pywbem.Uint16(3) + Re_run_Job = pywbem.Uint16(4) + Run_Recovery_Job = pywbem.Uint16(5) + _reverse_map = { + 0: 'Unknown', + 1: 'Other', + 2: 'Do Not Continue', + 3: 'Continue With Next Job', + 4: 'Re-run Job', + 5: 'Run Recovery Job' + } + + class RunDayOfWeek(object): + _Saturday = pywbem.Sint8(-7) + _Friday = pywbem.Sint8(-6) + _Thursday = pywbem.Sint8(-5) + _Wednesday = pywbem.Sint8(-4) + _Tuesday = pywbem.Sint8(-3) + _Monday = pywbem.Sint8(-2) + _Sunday = pywbem.Sint8(-1) + ExactDayOfMonth = pywbem.Sint8(0) + Sunday = pywbem.Sint8(1) + Monday = pywbem.Sint8(2) + Tuesday = pywbem.Sint8(3) + Wednesday = pywbem.Sint8(4) + Thursday = pywbem.Sint8(5) + Friday = pywbem.Sint8(6) + Saturday = pywbem.Sint8(7) + _reverse_map = { + 0: 'ExactDayOfMonth', + 1: 'Sunday', + 2: 'Monday', + 3: 'Tuesday', + 4: 'Wednesday', + 5: 'Thursday', + 6: 'Friday', + 7: 'Saturday', + -1: '-Sunday', + -7: '-Saturday', + -6: '-Friday', + -5: '-Thursday', + -4: '-Wednesday', + -3: '-Tuesday', + -2: '-Monday' + } + + class RunMonth(object): + January = pywbem.Uint8(0) + February = pywbem.Uint8(1) + March = pywbem.Uint8(2) + April = pywbem.Uint8(3) + May = pywbem.Uint8(4) + June = pywbem.Uint8(5) + July = pywbem.Uint8(6) + August = pywbem.Uint8(7) + September = pywbem.Uint8(8) + October = pywbem.Uint8(9) + November = pywbem.Uint8(10) + December = pywbem.Uint8(11) + _reverse_map = { + 0: 'January', + 1: 'February', + 2: 'March', + 3: 'April', + 4: 'May', + 5: 'June', + 6: 'July', + 7: 'August', + 8: 'September', + 9: 'October', + 10: 'November', + 11: 'December' + } + + class GetErrors(object): + Success = 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) + Access_Denied = pywbem.Uint32(6) + # DMTF_Reserved = .. + # Vendor_Specific = 32768..65535 + + class CommunicationStatus(object): + Unknown = pywbem.Uint16(0) + Not_Available = pywbem.Uint16(1) + Communication_OK = pywbem.Uint16(2) + Lost_Communication = pywbem.Uint16(3) + No_Contact = pywbem.Uint16(4) + # DMTF_Reserved = .. + # Vendor_Reserved = 0x8000.. + _reverse_map = { + 0: 'Unknown', + 1: 'Not Available', + 2: 'Communication OK', + 3: 'Lost Communication', + 4: 'No Contact' + } + + class OperationalStatus(object): + Unknown = pywbem.Uint16(0) + Other = pywbem.Uint16(1) + OK = pywbem.Uint16(2) + Degraded = pywbem.Uint16(3) + Stressed = pywbem.Uint16(4) + Predictive_Failure = pywbem.Uint16(5) + Error = pywbem.Uint16(6) + Non_Recoverable_Error = pywbem.Uint16(7) + Starting = pywbem.Uint16(8) + Stopping = pywbem.Uint16(9) + Stopped = pywbem.Uint16(10) + In_Service = pywbem.Uint16(11) + No_Contact = pywbem.Uint16(12) + Lost_Communication = pywbem.Uint16(13) + Aborted = pywbem.Uint16(14) + Dormant = pywbem.Uint16(15) + Supporting_Entity_in_Error = pywbem.Uint16(16) + Completed = pywbem.Uint16(17) + Power_Mode = pywbem.Uint16(18) + Relocating = pywbem.Uint16(19) + # DMTF_Reserved = .. + # Vendor_Reserved = 0x8000.. + _reverse_map = { + 0: 'Unknown', + 1: 'Other', + 2: 'OK', + 3: 'Degraded', + 4: 'Stressed', + 5: 'Predictive Failure', + 6: 'Error', + 7: 'Non-Recoverable Error', + 8: 'Starting', + 9: 'Stopping', + 10: 'Stopped', + 11: 'In Service', + 12: 'No Contact', + 13: 'Lost Communication', + 14: 'Aborted', + 15: 'Dormant', + 16: 'Supporting Entity in Error', + 17: 'Completed', + 18: 'Power Mode', + 19: 'Relocating' + } + + class OperatingStatus(object): + Unknown = pywbem.Uint16(0) + Not_Available = pywbem.Uint16(1) + Servicing = pywbem.Uint16(2) + Starting = pywbem.Uint16(3) + Stopping = pywbem.Uint16(4) + Stopped = pywbem.Uint16(5) + Aborted = pywbem.Uint16(6) + Dormant = pywbem.Uint16(7) + Completed = pywbem.Uint16(8) + Migrating = pywbem.Uint16(9) + Emigrating = pywbem.Uint16(10) + Immigrating = pywbem.Uint16(11) + Snapshotting = pywbem.Uint16(12) + Shutting_Down = pywbem.Uint16(13) + In_Test = pywbem.Uint16(14) + Transitioning = pywbem.Uint16(15) + In_Service = pywbem.Uint16(16) + # DMTF_Reserved = .. + # Vendor_Reserved = 0x8000.. + _reverse_map = { + 0: 'Unknown', + 1: 'Not Available', + 2: 'Servicing', + 3: 'Starting', + 4: 'Stopping', + 5: 'Stopped', + 6: 'Aborted', + 7: 'Dormant', + 8: 'Completed', + 9: 'Migrating', + 10: 'Emigrating', + 11: 'Immigrating', + 12: 'Snapshotting', + 13: 'Shutting Down', + 14: 'In Test', + 15: 'Transitioning', + 16: 'In Service' + } + + class LocalOrUtcTime(object): + Local_Time = pywbem.Uint16(1) + UTC_Time = pywbem.Uint16(2) + _reverse_map = { + 1: 'Local Time', + 2: 'UTC Time' + } + + class RequestStateChange(object): + Completed_with_No_Error = pywbem.Uint32(0) + Not_Supported = pywbem.Uint32(1) + Unknown_Unspecified_Error = pywbem.Uint32(2) + Can_NOT_complete_within_Timeout_Period = pywbem.Uint32(3) + Failed = pywbem.Uint32(4) + Invalid_Parameter = pywbem.Uint32(5) + In_Use = pywbem.Uint32(6) + # DMTF_Reserved = .. + Method_Parameters_Checked___Transition_Started = pywbem.Uint32(4096) + Invalid_State_Transition = pywbem.Uint32(4097) + Use_of_Timeout_Parameter_Not_Supported = pywbem.Uint32(4098) + Busy = pywbem.Uint32(4099) + # Method_Reserved = 4100..32767 + # Vendor_Specific = 32768..65535 + class RequestedState(object): + Start = pywbem.Uint16(2) + Suspend = pywbem.Uint16(3) + Terminate = pywbem.Uint16(4) + Kill = pywbem.Uint16(5) + Service = pywbem.Uint16(6) + # DMTF_Reserved = 7..32767 + # Vendor_Reserved = 32768..65535 + + class PrimaryStatus(object): + Unknown = pywbem.Uint16(0) + OK = pywbem.Uint16(1) + Degraded = pywbem.Uint16(2) + Error = pywbem.Uint16(3) + # DMTF_Reserved = .. + # Vendor_Reserved = 0x8000.. + _reverse_map = { + 0: 'Unknown', + 1: 'OK', + 2: 'Degraded', + 3: 'Error' + } + +@cmpi_logging.trace_function +def get_verification_out_params(job): + """ + Get the output parameters for verification job. They may not be computed + yet. In that case compute them a update the job in YumWorker process. + + :param job: (``jobs.YumCheckPackage``) + :rtype: (``dict``) Dictionary of output parameters with pywbem values. + """ + if not isinstance(job, jobs.YumCheckPackage): + raise TypeError("job must be a YumCheckPackage instance") + if ( not job.metadata.get("output_params", []) + and job.state == job.COMPLETED): + from openlmi.software.core import IdentityFileCheck + failed = [] + pkg_info, pkg_check = job.result_data + for file_name in pkg_check: + pkg_file = pkg_check[file_name] + file_check = IdentityFileCheck.test_file(pkg_info, + pkg_check.file_checksum_type, pkg_file) + if not IdentityFileCheck.file_check_passed(file_check): + failed.append(IdentityFileCheck.file_check2model( + file_check, job=job)) + metadata = { + 'output_params' : { + 'Failed' : pywbem.CIMProperty("Failed", + type="reference", is_array=True, value=failed) + } + } + # update local instance + job.update(metadata=metadata) + if YumDB.RUNNING_UNDER_CIMOM_PROCESS: + # update instance on server + YumDB.get_instance().update_job(job.jobid, metadata=metadata) + # else: we are called from YumWorker process; + # (update on server already occured) + # moreover YumWorker blocks on us - we can not wait for another job + # to finish + return job.metadata.get('output_params', []) + +@cmpi_logging.trace_function +def make_method_params(job, class_name, include_input, include_output): + """ + Create a class of given name with all input or output parameters + of the asynchronous method. Typically used to assemble + CIM_ConcreteJob.JobInParameters or CIM_InstMethodCall.MethodParameters + values. + + :param job: (``YumJob``) Instance of job created as a result of method + invocation. It carries method parameters. + :param class_name: (``str``) Name of the class to create. + :param include_input: (``bool``) Whether input parameters should be + included in the returned class. + :param include_output: (``bool``) Whether output parameters should be + included in the returned class. + :rtype: CIMInstance of the created class. + """ + # TODO: this is workaround for bug #920763, use class_name + # when it's fixed + clsname = "CIM_ManagedElement" + path = pywbem.CIMInstanceName(classname=clsname, namespace="root/cimv2") + inst = pywbem.CIMInstance(classname=clsname, path=path) + if include_input and "input_params" in job.metadata: + for (name, value) in job.metadata["input_params"].items(): + inst[name] = value + if include_output: + if isinstance(job, jobs.YumCheckPackage): + # make sure, that output parameters are computed + get_verification_out_params(job) + if "output_params" in job.metadata: + # overwrite any input parameter + for (name, value) in job.metadata["output_params"].iteritems(): + inst[name] = value + return inst + +def job_class2cim_class_name(jobcls): + """ + Here we map classes of job objects to their corresponding CIM class + name. + + :param jobcls: (``type``) Subclass of jobs.YumJob. + """ + if not issubclass(jobcls, ( + jobs.YumInstallPackageFromURI, + jobs.YumSpecificPackageJob)): + raise ValueError("Job class \"%s\" does not have any associated" + " CIM class." % jobcls.__name__) + if issubclass(jobcls, (jobs.YumCheckPackage, jobs.YumCheckPackageFile)): + return "LMI_SoftwareVerificationJob" + return "LMI_SoftwareInstallationJob" + +@cmpi_logging.trace_function +def _fill_nonkeys(job, model): + """ + Fills into the model of instance all non-key properties. + """ + model['Caption'] = 'Software installation job with id=%d' % job.jobid + model['CommunicationStatus'] = Values.CommunicationStatus.Not_Available + model['DeleteOnCompletion'] = job.delete_on_completion + try: + description = JOB_DESCRIPTIONS[job.__class__] + kwargs = job.job_kwargs + kwargs['jobid'] = job.jobid + model['Description'] = description % kwargs + except KeyError: + cmpi_logging.logger.error( + 'no description string found for job class %s' % + job.__class__.__name__) + model['Description'] = pywbem.CIMProperty('Description', + type='string', value=None) + if job.started: + if job.finished: + elapsed = job.finished - job.started + else: + elapsed = time.time() - job.started + model['ElapsedTime'] = pywbem.CIMDateTime(timedelta(seconds=elapsed)) + else: + model["ElapsedTime"] = pywbem.CIMProperty('ElapsedTime', + type='datetime', value=None) + model['ErrorCode'] = pywbem.Uint16(0 if job.state != job.EXCEPTION else 1) + try: + model['JobState'], model['OperationalStatus'], model['JobStatus'] = { + jobs.YumJob.NEW : (Values.JobState.New, + [Values.OperationalStatus.Dormant], 'Enqueued'), + jobs.YumJob.RUNNING : (Values.JobState.Running, + [Values.OperationalStatus.OK], 'Running'), + jobs.YumJob.TERMINATED : (Values.JobState.Terminated, + [Values.OperationalStatus.Stopped], 'Terminated'), + jobs.YumJob.EXCEPTION : (Values.JobState.Exception + , [Values.OperationalStatus.Error] + , 'Failed'), + jobs.YumJob.COMPLETED : (Values.JobState.Completed + , [ Values.OperationalStatus.OK + , Values.OperationalStatus.Completed] + , 'Finished successfully') + }[job.state] + except KeyError: + cmpi_logging.logger.error('unknown job state: %s' % job.state) + model['JobState'] = pywbem.CIMProperty('JobState', + type='uint16', value=None) + model['OperationalStatus'] = [Values.OperationalStatus.Unknown] + model['JobStatus'] = 'Unknown' + model["JobInParameters"] = make_method_params( + job, "__JobInParameters", True, False) + model["JobOutParameters"] = make_method_params( + job, "__JobOutParameters", False, True) + if 'method' in job.metadata: + model['MethodName'] = JOB_METHOD_NAMES[job.metadata["method"]] + else: + model["MethodName"] = pywbem.CIMProperty('MethodName', + type='string', value=None) + model['Name'] = job.metadata['name'] + model['LocalOrUtcTime'] = Values.LocalOrUtcTime.UTC_Time + model['PercentComplete'] = pywbem.Uint16( + 100 if job.state == job.COMPLETED else ( + 50 if job.state == job.RUNNING else + 0)) + model['Priority'] = pywbem.Uint32(job.priority) + if job.started: + model['StartTime'] = pywbem.CIMDateTime(datetime.fromtimestamp( + job.started)) + model['TimeBeforeRemoval'] = pywbem.CIMDateTime(timedelta( + seconds=job.time_before_removal)) + model['TimeOfLastStateChange'] = pywbem.CIMDateTime(datetime.fromtimestamp( + job.last_change)) + model['TimeSubmitted'] = pywbem.CIMDateTime(datetime.fromtimestamp( + job.created)) + +@cmpi_logging.trace_function +def job2model(job, class_name=None, keys_only=True, model=None): + """ + Makes LMI_SoftwareJob out of job object or job id. + + :param job: (``int`` | ``YumAsyncJob``) Job identifier. + In case of integer, caller should also provide class_name of resulting + CIM instance. Otherwise generic LMI_SoftwareJob will be returned. + :param class_name: (``str``) Determines CIM class name of resulting + instance. This should be given when ``job`` is an integer. + :param model: (``CIMInstance`` | ``CIMInstanceName``) If not None, + will be filled with properties, otherwise + a new instance of CIMInstance or CIMObjectPath is created. + :param keys_only: (``bool``) Says whether to fill only key properties. + Also if ``model`` is not given, it determines, whether to make + ``CIMInstanceName`` or ``CIMInstance``. + :rtype: (``CIMInstance`` | ``CIMInstanceName``) + """ + if not isinstance(job, (int, long, jobs.YumAsyncJob)): + raise TypeError("job must be an instance of YumAsyncJob") + if isinstance(job, jobs.YumAsyncJob) and not job.async: + raise ValueError("job must be asynchronous") + if not keys_only and isinstance(job, (int, long)): + raise TypeError("job must be an instance of YumAsyncJob" + " filling non-key properties") + + if class_name is None: + if model is not None: + class_name = model.classname + elif isinstance(job, jobs.YumJob): + class_name = job_class2cim_class_name(job.__class__) + else: + class_name = "LMI_SoftwareJob" + cmpi_logging.logger.warn( + "class_name not supplied for jobid=%d, using general" + " LMI_SoftwareJob as CIM class name") + if model is None: + model = pywbem.CIMInstanceName(class_name, namespace="root/cimv2") + if not keys_only: + model = pywbem.CIMInstance(class_name, path=model) + + jobid = job.jobid if isinstance(job, jobs.YumAsyncJob) else job + model['InstanceID'] = 'LMI:%s:%d' % (class_name, jobid) + if isinstance(model, pywbem.CIMInstance): + model.path['InstanceID'] = model['InstanceID'] #pylint: disable=E1103 + if not keys_only: + _fill_nonkeys(job, model) + return model + +@cmpi_logging.trace_function +def object_path2job(op): + """ + @param op must contain precise InstanceID of job + """ + if not isinstance(op, pywbem.CIMInstanceName): + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "op must be an instance of CIMInstanceName") + + if (not "InstanceID" in op or not op['InstanceID']): + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "Missing InstanceID key property.") + instid = op['InstanceID'] + match = util.RE_INSTANCE_ID.match(instid) + if not match or match.group('clsname').lower() not in { + c.lower() for c in JOB_CLASS_NAMES}: + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "InstanceID must start with one of {%s} prefixes." + " And end with positive integer." % ( + ", ".join(("LMI:%s:" % cn) for cn in JOB_CLASS_NAMES))) + + instid = int(match.group('id')) + try: + job = YumDB.get_instance().get_job(instid) + clsname = job_class2cim_class_name(job.__class__) + if ( clsname.lower() != op.classname.lower() + and op.classname.lower() != 'LMI_SoftwareJob'.lower()): + raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, + "Classname \"%s\" does not belong to job with given id." + " \"%s\" is the correct one." % (op.classname, clsname)) + return job + except errors.JobNotFound: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + 'No such job "%s".' % op['InstanceID']) + +@cmpi_logging.trace_function +def modify_instance(instance): + """ + This call modifies the job's parameters according to given instance. + """ + job = object_path2job(instance.path) + ydb = YumDB.get_instance() + update_kwargs = {} + reschedule_kwargs = {} + # all modifiable properties + prop_name_map = { + "name" : "name", + "priority" : "priority", + "deleteoncompletion" : "delete_on_completion", + "timebeforeremoval" : "time_before_removal" + } + metadata_props = {"name"} + reschedule_props = {"delete_on_completion", "time_before_removal"} + for name, prop in instance.properties.items(): + if prop is None: + cmpi_logging.logger.warn('property "%s" is None') + continue + name = name.lower() + try: + pname = prop_name_map[name] + if pname == "priority" and job.priority != prop.value: + cmpi_logging.logger.info( + 'changing priority of job %s to %d', job, prop.value) + job = ydb.set_job_priority(job.jobid, prop.value) + elif pname in reschedule_props: + if getattr(job, pname) == prop.value: + continue + if pname == "time_before_removal": + value = prop.value.timedelta.total_seconds() + else: + value = prop.value + reschedule_kwargs[pname] = value + else: + if pname in metadata_props: + if not 'metadata' in update_kwargs: + update_kwargs['metadata'] = {} + update_kwargs['metadata'][pname] = prop.value + else: + update_kwargs[pname] = prop.value + except KeyError: + if name == 'instanceid': + continue + cmpi_logging.logger.warn("skipping property %s: %s", name, prop) + + if reschedule_kwargs: + for prop in ('delete_on_completion', 'time_before_removal'): + if prop not in reschedule_kwargs: + reschedule_kwargs[prop] = getattr(job, prop) + cmpi_logging.logger.info('rescheduling job %s to: %s', + job, ", ".join("%s=%s"%(k, v) for k, v in + reschedule_kwargs.items())) + job = ydb.reschedule_job(job.jobid, **reschedule_kwargs) + + if update_kwargs: + cmpi_logging.logger.info('changing atributes of job %s to: %s', + job, ", ".join("%s=%s"%(k, v) for k, v in + update_kwargs.items())) + job = ydb.update_job(job.jobid, **update_kwargs) + + return job2model(job, keys_only=False, model=instance) + +@cmpi_logging.trace_function +def job2error(job): + """ + @return instance of CIM_Error if job is in EXCEPTION state, + None otherwise + """ + if not isinstance(job, jobs.YumJob): + raise TypeError("job must be isntance of YumJob") + if job.state == job.EXCEPTION: + errortup = job.result_data + kwargs = {} + if issubclass(errortup[0], + (errors.RepositoryNotFound, errors.PackageNotFound)): + kwargs['status_code'] = Error.Values. \ + CIMStatusCode.CIM_ERR_NOT_FOUND + if issubclass(errortup[0], errors.PackageNotFound): + kwargs['status_code_description'] = "Package not found" + else: + kwargs['status_code_description'] = "Repository not found" + elif issubclass(errortup[0], errors.PackageAlreadyInstalled): + kwargs['status_code'] = Error.Values. \ + CIMStatusCode.CIM_ERR_ALREADY_EXISTS + kwargs['message'] = getattr(errortup[1], 'message', + str(errortup[1])) + value = Error.make_instance(**kwargs) + return value 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[a-z][a-z_0-9]+):(?P\d+)', + re.IGNORECASE) + RE_EVRA = re.compile( r'^(?P\d+):(?P[^-]+)-(?P.+)\.(?P[^.]+)$') 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 -- cgit