# -*- 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 LMI_SoftwareInstallationService provider. """ 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 SystemCollection from openlmi.software.yumdb import errors from openlmi.software.yumdb import YumDB #UNSUPPORTED_INSTALL_OPTIONS = { # { "Defer_target_system_reset", "Force_installation", # "Reboot", "Password", "Log", "Silent_Mode", "Administrative_Mode", # "Schedule_Install_At", "DMTF_Reserved" } class InstallationError(Exception): """This exception shall be raised upon any error within install_or_remove_package() function. """ def __init__(self, return_code, description): Exception.__init__(self, return_code, description) @property def return_code(self): """@return return code of CIM method""" return self.args[0] @property def description(self): """@return description of error""" return self.args[1] 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 RequestedState(object): Unknown = pywbem.Uint16(0) Enabled = pywbem.Uint16(2) Disabled = pywbem.Uint16(3) Shut_Down = pywbem.Uint16(4) No_Change = pywbem.Uint16(5) Offline = pywbem.Uint16(6) Test = pywbem.Uint16(7) Deferred = pywbem.Uint16(8) Quiesce = pywbem.Uint16(9) Reboot = pywbem.Uint16(10) Reset = pywbem.Uint16(11) Not_Applicable = pywbem.Uint16(12) # DMTF_Reserved = .. # Vendor_Reserved = 32768..65535 _reverse_map = { 0: 'Unknown', 2: 'Enabled', 3: 'Disabled', 4: 'Shut Down', 5: 'No Change', 6: 'Offline', 7: 'Test', 8: 'Deferred', 9: 'Quiesce', 10: 'Reboot', 11: 'Reset', 12: 'Not Applicable' } 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 InstallFromURI(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) Unattended_silent_installation_not_supported = pywbem.Uint32(4098) Downgrade_reinstall_not_supported = pywbem.Uint32(4099) Not_enough_memory = pywbem.Uint32(4100) Not_enough_swap_space = pywbem.Uint32(4101) Unsupported_version_transition = pywbem.Uint32(4102) Not_enough_disk_space = pywbem.Uint32(4103) Software_and_target_operating_system_mismatch = pywbem.Uint32(4104) Missing_dependencies = pywbem.Uint32(4105) Not_applicable_to_target = pywbem.Uint32(4106) URI_not_accessible = pywbem.Uint32(4107) # Method_Reserved = 4108..32767 # Vendor_Specific = 32768..65535 class InstallOptions(object): Defer_target_system_reset = pywbem.Uint16(2) Force_installation = pywbem.Uint16(3) Install = pywbem.Uint16(4) Update = pywbem.Uint16(5) Repair = pywbem.Uint16(6) Reboot = pywbem.Uint16(7) Password = pywbem.Uint16(8) Uninstall = pywbem.Uint16(9) Log = pywbem.Uint16(10) SilentMode = pywbem.Uint16(11) AdministrativeMode = pywbem.Uint16(12) ScheduleInstallAt = pywbem.Uint16(13) # DMTF_Reserved = .. # Vendor_Specific = 32768..65535 _reverse_map = { 2 : "Defer Target/System Reset", 3 : "Force Installation", 4 : "Install", 5 : "Update", 6 : "Repair", 7 : "Reboot", 8 : "Password", 9 : "Uninstall", 10 : "Log", 11 : "SilentMode", 12 : "AdministrativeMode", 13 : "ScheduleInstallAt", } InstallOptions.supported = { InstallOptions.Install, InstallOptions.Update, InstallOptions.Uninstall, InstallOptions.Force_installation, InstallOptions.Repair, } class CheckSoftwareIdentity(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_Reserved = pywbem.Uint32(4096) Unsupported_TargetType = pywbem.Uint32(4097) Unattended_silent_installation_not_supported = pywbem.Uint32(4098) Downgrade_reinstall_not_supported = pywbem.Uint32(4099) Not_enough_memory = pywbem.Uint32(4100) Not_enough_swap_space = pywbem.Uint32(4101) Unsupported_version_transition = pywbem.Uint32(4102) Not_enough_disk_space = pywbem.Uint32(4103) Software_and_target_operating_system_mismatch = pywbem.Uint32(4104) Missing_dependencies = pywbem.Uint32(4105) Not_applicable_to_target = pywbem.Uint32(4106) No_supported_path_to_image = pywbem.Uint32(4107) Cannot_add_to_Collection = pywbem.Uint32(4108) Asynchronous_Job_already_in_progress = pywbem.Uint32(4109) # Method_Reserved = 4110..32767 # Vendor_Specific = 32768..65535 class InstallCharacteristics(object): Target_automatic_reset = pywbem.Uint16(2) System_automatic_reset = pywbem.Uint16(3) Separate_target_reset_Required = pywbem.Uint16(4) Separate_system_reset_Required = pywbem.Uint16(5) Manual_Reboot_Required = pywbem.Uint16(6) No_Reboot_Required = pywbem.Uint16(7) User_Intervention_recommended = pywbem.Uint16(8) MAY_be_added_to_specified_Collection = pywbem.Uint16(9) # DMTF_Reserved = .. # Vendor_Specific = 0x7FFF..0xFFFF class ChangeAffectedElementsAssignedSequence(object): Completed_with_No_Error = pywbem.Uint32(0) Not_Supported = pywbem.Uint32(1) Error_Occured = pywbem.Uint32(2) Busy = pywbem.Uint32(3) Invalid_Reference = pywbem.Uint32(4) Invalid_Parameter = pywbem.Uint32(5) Access_Denied = pywbem.Uint32(6) # DMTF_Reserved = 7..32767 # Vendor_Specified = 32768..65535 class TransitioningToState(object): Unknown = pywbem.Uint16(0) Enabled = pywbem.Uint16(2) Disabled = pywbem.Uint16(3) Shut_Down = pywbem.Uint16(4) No_Change = pywbem.Uint16(5) Offline = pywbem.Uint16(6) Test = pywbem.Uint16(7) Defer = pywbem.Uint16(8) Quiesce = pywbem.Uint16(9) Reboot = pywbem.Uint16(10) Reset = pywbem.Uint16(11) Not_Applicable = pywbem.Uint16(12) # DMTF_Reserved = .. _reverse_map = { 0: 'Unknown', 2: 'Enabled', 3: 'Disabled', 4: 'Shut Down', 5: 'No Change', 6: 'Offline', 7: 'Test', 8: 'Defer', 9: 'Quiesce', 10: 'Reboot', 11: 'Reset', 12: 'Not Applicable' } class EnabledDefault(object): Enabled = pywbem.Uint16(2) Disabled = pywbem.Uint16(3) Not_Applicable = pywbem.Uint16(5) Enabled_but_Offline = pywbem.Uint16(6) No_Default = pywbem.Uint16(7) Quiesce = pywbem.Uint16(9) # DMTF_Reserved = .. # Vendor_Reserved = 32768..65535 _reverse_map = { 2: 'Enabled', 3: 'Disabled', 5: 'Not Applicable', 6: 'Enabled but Offline', 7: 'No Default', 9: 'Quiesce' } class EnabledState(object): Unknown = pywbem.Uint16(0) Other = pywbem.Uint16(1) Enabled = pywbem.Uint16(2) Disabled = pywbem.Uint16(3) Shutting_Down = pywbem.Uint16(4) Not_Applicable = pywbem.Uint16(5) Enabled_but_Offline = pywbem.Uint16(6) In_Test = pywbem.Uint16(7) Deferred = pywbem.Uint16(8) Quiesce = pywbem.Uint16(9) Starting = pywbem.Uint16(10) # DMTF_Reserved = 11..32767 # Vendor_Reserved = 32768..65535 _reverse_map = { 0: 'Unknown', 1: 'Other', 2: 'Enabled', 3: 'Disabled', 4: 'Shutting Down', 5: 'Not Applicable', 6: 'Enabled but Offline', 7: 'In Test', 8: 'Deferred', 9: 'Quiesce', 10: 'Starting' } class AvailableRequestedStates(object): Enabled = pywbem.Uint16(2) Disabled = pywbem.Uint16(3) Shut_Down = pywbem.Uint16(4) Offline = pywbem.Uint16(6) Test = pywbem.Uint16(7) Defer = pywbem.Uint16(8) Quiesce = pywbem.Uint16(9) Reboot = pywbem.Uint16(10) Reset = pywbem.Uint16(11) # DMTF_Reserved = .. _reverse_map = { 2: 'Enabled', 3: 'Disabled', 4: 'Shut Down', 6: 'Offline', 7: 'Test', 8: 'Defer', 9: 'Quiesce', 10: 'Reboot', 11: 'Reset' } 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 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 RequestStateChange(object): Completed_with_No_Error = pywbem.Uint32(0) Not_Supported = pywbem.Uint32(1) Unknown_or_Unspecified_Error = pywbem.Uint32(2) Cannot_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___Job_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): Enabled = pywbem.Uint16(2) Disabled = pywbem.Uint16(3) Shut_Down = pywbem.Uint16(4) Offline = pywbem.Uint16(6) Test = pywbem.Uint16(7) Defer = pywbem.Uint16(8) Quiesce = pywbem.Uint16(9) Reboot = pywbem.Uint16(10) Reset = pywbem.Uint16(11) # DMTF_Reserved = .. # Vendor_Reserved = 32768..65535 class InstallFromByteStream(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) Unattended_silent_installation_not_supported = pywbem.Uint32(4098) Downgrade_reinstall_not_supported = pywbem.Uint32(4099) Not_enough_memory = pywbem.Uint32(4100) Not_enough_swap_space = pywbem.Uint32(4101) Unsupported_version_transition = pywbem.Uint32(4102) Not_enough_disk_space = pywbem.Uint32(4103) Software_and_target_operating_system_mismatch = pywbem.Uint32(4104) Missing_dependencies = pywbem.Uint32(4105) Not_applicable_to_target = pywbem.Uint32(4106) No_supported_path_to_image = pywbem.Uint32(4107) # Method_Reserved = 4108..32767 # Vendor_Specific = 32768..65535 InstallFromByteStream.InstallOptions = InstallFromURI.InstallOptions class InstallFromSoftwareIdentity(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) Unattended_silent_installation_not_supported = pywbem.Uint32(4098) Downgrade_reinstall_not_supported = pywbem.Uint32(4099) Not_enough_memory = pywbem.Uint32(4100) Not_enough_swap_space = pywbem.Uint32(4101) Unsupported_version_transition = pywbem.Uint32(4102) Not_enough_disk_space = pywbem.Uint32(4103) Software_and_target_operating_system_mismatch = pywbem.Uint32(4104) Missing_dependencies = pywbem.Uint32(4105) Not_applicable_to_target = pywbem.Uint32(4106) No_supported_path_to_image = pywbem.Uint32(4107) Cannot_add_to_Collection = pywbem.Uint32(4108) # Method_Reserved = 4109..32767 # Vendor_Specific = 32768..65535 InstallFromSoftwareIdentity.InstallOptions = InstallFromURI.InstallOptions class StartMode(object): Automatic = 'Automatic' Manual = 'Manual' 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' } def get_path(): """@return instance name with prefilled properties""" op = pywbem.CIMInstanceName( classname="LMI_SoftwareInstallationService", namespace="root/cimv2") op['CreationClassName'] = op.classname systemop = ComputerSystem.get_path() op["SystemCreationClassName"] = systemop.classname op['SystemName'] = systemop["Name"] op["Name"] = "LMI:SoftwareInstallationService" return op def check_path(env, service, prop_name): """ Checks instance name of SoftwareInstallationService. @param prop_name name of object name; used for error descriptions """ if not isinstance(service, pywbem.CIMInstanceName): raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, "\"%s\" must be a CIMInstanceName" % prop_name) our_service = get_path() ch = env.get_cimom_handle() if service.namespace != our_service.namespace: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, 'Namespace of "%s" does not match "%s"' % ( prop_name, our_service.namespace)) if not ch.is_subclass(our_service.namespace, sub=service.classname, super=our_service.classname): raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "Class of \"%s\" must be a sublass of %s" % ( prop_name, our_service.classname)) for key in our_service.keybindings.keys(): if not key in service: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "\"%s\" is missing %s key property" % ( prop_name, key)) if service[key] != our_service[key]: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "\"%s\" key property %s(%s) does not match \"%s\"" %( prop_name, key, service[key], our_service[key])) return True def check_path_property(env, op, prop_name): """ Checks, whether prop_name property of op object path is correct. If not, an exception will be raised. """ if not prop_name in op: raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER, "Missing %s key property!" % prop_name) return check_path(env, op[prop_name], prop_name) def _check_target_and_collection(env, src_type, target, collection): """ Checks Target and Collection parameters of provider's installation methods. """ values = Values.InstallFromSoftwareIdentity if target: try: ComputerSystem.check_path(env, target, "Target") except pywbem.CIMError as exc: raise InstallationError(values.Unspecified_Error, "Target must be either NULL or match managed" " computer system: %s", str(exc)) if collection: try: SystemCollection.check_path(env, collection, "Collection") except pywbem.CIMError as exc: raise InstallationError(values.Unspecified_Error, "Collection does not match system software collection: %s" % str(exc)) if target and collection: raise InstallationError(values.Unspecified_Error, "Only one of Target and Collection parameters can be specified" " at the same time.") if not target and not collection: raise InstallationError(values.Unspecified_Error, "Either Target or Collection parameter must be specified." if src_type == "identity" else "Missing Target parameter.") def _install_or_remove_check_params( env, src_type, source, target, collection, install_options, install_options_values): """ Checks parameters of provider's installation methods. Upon any invalid option an InstallationError will be raised. @return tuple (action, force, repair) where action is one of Values.InstallFromSoftwareIdentity properties """ values = Values.InstallFromSoftwareIdentity supported_options = values.InstallOptions.supported.copy() if src_type == "uri": supported_options.remove(values.InstallOptions.Uninstall) if not src_type in {"uri", "identity"}: raise ValueError('uri must be one of {"uri", "identity"}') if not source: raise InstallationError(values.Unspecified_Error, "Missing %s parameter." % ( "URI" if src_type == "uri" else "Source")) if not install_options: install_options = [] elif not isinstance(install_options, list): raise InstallationError(values.Unspecified_Error, "InstallOptions must be a list of uint16 values.") options = {p for p in install_options} if options - supported_options: raise InstallationError(values.Unspecified_Error, "unsupported install options: {%s}" % ", ".join([ values.InstallOptions._reverse_map[p] for p in options - supported_options])) if install_options_values and len(options) != len(install_options_values): raise InstallationError(values.Unspecified_Error, "InstallOptions array must have the same" " length as InstallOptionsValues: %d != %d" % ( len(options), len(install_options_values))) if install_options_values: for opt, val in zip(install_options, install_options_values): if val: raise InstallationError(values.Unspecified_Error, "install option \"%s\" can not have any" " associated value: %s" % (opt, val)) _check_target_and_collection(env, src_type, target, collection) exclusive = [opt for opt in options if opt in { values.InstallOptions.Install, values.InstallOptions.Update, values.InstallOptions.Uninstall }] if len(exclusive) > 1: raise InstallationError(values.Unspecified_Error, "specified more than one mutually exclusive option at once: {%s}" % ", ".join([ values.InstallOptions._reverse_map[p] for p in exclusive])) if not exclusive: exclusive.append(values.InstallOptions.Install) return ( exclusive[0] , values.InstallOptions.Force_installation in options , values.InstallOptions.Repair in options) def install_or_remove_package(env, src_type, source, target, collection, install_options, install_options_values): """ @param src_type is one of {"uri", "identity"} """ values = Values.InstallFromSoftwareIdentity (action, force, repair) = _install_or_remove_check_params( env, src_type, source, target, collection, install_options, install_options_values) try: ydb = YumDB.get_instance() if action == values.InstallOptions.Uninstall: nevra = Identity.object_path2nevra( source, with_epoch='ALWAYS') cmpi_logging.logger.info('removing package %s', nevra) jobid = ydb.remove_package(nevra, async=True) else: update = action == values.InstallOptions.Update if src_type == "uri": cmpi_logging.logger.info('%s package "%s"', 'updating' if update else 'installing', source) jobid = ydb.install_package_from_uri( source, update_only=update, force=force or repair, async=True) else: # software identity nevra = Identity.object_path2nevra( source, with_epoch='ALWAYS') if update: jobid = ydb.update_package(nevra, force=force or repair, async=True) else: jobid = ydb.install_package( nevra, force=force or repair, async=True) cmpi_logging.logger.info('installation job %s for pkg "%s"' ' enqueued', jobid, nevra) return jobid except (pywbem.CIMError, errors.InvalidURI) as exc: cmpi_logging.logger.error('failed to install/remove package "%s"' ' from %s: %s', source, src_type, str(exc)) raise InstallationError(values.Unspecified_Error, str(exc))