summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Schiffer <pschiffe@redhat.com>2013-05-13 13:00:29 +0200
committerPeter Schiffer <pschiffe@redhat.com>2013-05-13 13:00:29 +0200
commitafc343e81566c7707d2ee67c1f47a9ca23b8cd9f (patch)
tree4319416383cf36235f89b0a2365afc7c6cd63300
parent1c3bd366f82d4f53c76b89f8fff9359356781622 (diff)
parent9a690650d5ba4cdf432091c4a095452cfa4faa37 (diff)
downloadopenlmi-providers-afc343e81566c7707d2ee67c1f47a9ca23b8cd9f.tar.gz
openlmi-providers-afc343e81566c7707d2ee67c1f47a9ca23b8cd9f.tar.xz
openlmi-providers-afc343e81566c7707d2ee67c1f47a9ca23b8cd9f.zip
Merge branch 'master' of ssh://git.fedorahosted.org/git/openlmi-providers
-rw-r--r--.reviewboardrc2
-rw-r--r--mof/60_LMI_Software.mof165
-rw-r--r--src/python/openlmi/common/JobManager.py36
-rw-r--r--src/python/openlmi/common/__init__.py18
-rw-r--r--src/realmd/LMI_HostedRealmdServiceProvider.c2
-rw-r--r--src/realmd/LMI_RealmdKerberosRealmProvider.c2
-rw-r--r--src/realmd/LMI_RealmdRealmProvider.c2
-rw-r--r--src/realmd/LMI_RealmdServiceProvider.c2
-rw-r--r--src/realmd/LMI_ServiceAffectsRealmdRealmProvider.c2
-rw-r--r--src/realmd/rdcp_dbus.c137
-rw-r--r--src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py2
-rw-r--r--src/software/openlmi/software/LMI_SoftwareInstallationService.py10
-rw-r--r--src/software/openlmi/software/core/Error.py4
-rw-r--r--src/software/openlmi/software/core/InstMethodCall.py144
-rw-r--r--src/software/openlmi/software/core/InstallationJob.py60
-rw-r--r--src/software/openlmi/software/core/InstallationService.py104
-rw-r--r--src/software/openlmi/software/core/MethodResult.py18
-rw-r--r--src/software/openlmi/software/yumdb/__init__.py48
-rw-r--r--src/software/openlmi/software/yumdb/jobs.py2
19 files changed, 430 insertions, 330 deletions
diff --git a/.reviewboardrc b/.reviewboardrc
new file mode 100644
index 0000000..b95918c
--- /dev/null
+++ b/.reviewboardrc
@@ -0,0 +1,2 @@
+REVIEWBOARD_URL = 'https://reviewboard-openlmi.rhcloud.com'
+REPOSITORY = 'openlmi-providers'
diff --git a/mof/60_LMI_Software.mof b/mof/60_LMI_Software.mof
index 9f2f2ce..12b4f9d 100644
--- a/mof/60_LMI_Software.mof
+++ b/mof/60_LMI_Software.mof
@@ -21,6 +21,9 @@
#pragma locale ("en_US")
//#pragma namespace ("root/cimv2")
+/* ****************************************************************************
+ * Central class of Software Inventory and Update profiles
+ */
class LMI_SoftwareIdentity : CIM_SoftwareIdentity {
[Implemented(true), Override("InstanceID"), Description(
@@ -78,6 +81,9 @@ class LMI_SoftwareIdentity : CIM_SoftwareIdentity {
};
+/******************************************************************************
+ * Software inventory classes
+ */
class LMI_SystemSoftwareCollection : CIM_SystemSpecificCollection {
[Implemented(true), Override("InstanceID")]
@@ -88,39 +94,6 @@ class LMI_SystemSoftwareCollection : CIM_SystemSpecificCollection {
};
-[Association]
-class LMI_HostedSoftwareCollection : CIM_HostedCollection {
-
- [Override("Antecedent")]
- Linux_ComputerSystem REF Antecedent;
-
- [Override("Dependent")]
- LMI_SystemSoftwareCollection REF Dependent;
-
-};
-
-[Association]
-class LMI_MemberOfSoftwareCollection : CIM_MemberOfCollection {
-
- [Override("Collection")]
- LMI_SystemSoftwareCollection REF Collection;
-
- [Override("Member")]
- LMI_SoftwareIdentity REF Member;
-
-};
-
-[Association]
-class LMI_InstalledSoftwareIdentity : CIM_InstalledSoftwareIdentity {
-
- [Override("InstalledSoftware")]
- LMI_SoftwareIdentity REF InstalledSoftware;
-
- [Override("System")]
- Linux_ComputerSystem REF System;
-
-};
-
class LMI_SoftwareIdentityResource : CIM_SoftwareIdentityResource {
[Implemented(true), Override("CreationClassName")]
@@ -272,6 +245,42 @@ class LMI_SoftwareIdentityResource : CIM_SoftwareIdentityResource {
};
+/******************************************************************************
+ * Software inventory associations
+ */
+[Association]
+class LMI_HostedSoftwareCollection : CIM_HostedCollection {
+
+ [Override("Antecedent")]
+ Linux_ComputerSystem REF Antecedent;
+
+ [Override("Dependent")]
+ LMI_SystemSoftwareCollection REF Dependent;
+
+};
+
+[Association]
+class LMI_MemberOfSoftwareCollection : CIM_MemberOfCollection {
+
+ [Override("Collection")]
+ LMI_SystemSoftwareCollection REF Collection;
+
+ [Override("Member")]
+ LMI_SoftwareIdentity REF Member;
+
+};
+
+[Association]
+class LMI_InstalledSoftwareIdentity : CIM_InstalledSoftwareIdentity {
+
+ [Override("InstalledSoftware")]
+ LMI_SoftwareIdentity REF InstalledSoftware;
+
+ [Override("System")]
+ Linux_ComputerSystem REF System;
+
+};
+
[Association]
class LMI_ResourceForSoftwareIdentity : CIM_SAPAvailableForElement {
@@ -294,6 +303,9 @@ class LMI_HostedSoftwareIdentityResource : CIM_HostedAccessPoint {
};
+/******************************************************************************
+ * Software update profile classes
+ */
class LMI_SoftwareInstallationService : CIM_SoftwareInstallationService {
[Implemented(true), Override("CreationClassName")]
@@ -576,47 +588,6 @@ class LMI_SoftwareInstallationServiceCapabilities :
};
-[Association]
-class LMI_AssociatedSoftwareInstallationServiceCapabilities :
- CIM_ElementCapabilities {
-
- [Override("Capabilities")]
- LMI_SoftwareInstallationServiceCapabilities REF Capabilities;
-
- [Override("ManagedElement")]
- LMI_SoftwareInstallationService REF ManagedElement;
-
- [Implemented(true), Override("Characteristics")]
- uint16 Characteristics[];
-
-};
-
-[Association]
-class LMI_HostedSoftwareInstallationService : CIM_HostedService {
-
- [Override("Antecedent")]
- Linux_ComputerSystem REF Antecedent;
-
- [Override("Dependent")]
- LMI_SoftwareInstallationService REF Dependent;
-
-};
-
-[Association]
-class LMI_SoftwareInstallationServiceAffectsElement :
- CIM_ServiceAffectsElement {
-
- [Override("AffectingElement")]
- LMI_SoftwareInstallationService REF AffectingElement;
-
- [Implemented(true), Override("ElementEffects")]
- uint16 ElementEffects[];
-
- [Implemented(true), Override("OtherElementEffectsDescriptions")]
- string OtherElementEffectsDescriptions[];
-
-};
-
class LMI_SoftwareInstallationJob : LMI_ConcreteJob {
[Implemented(true), Override("InstanceID")]
@@ -651,6 +622,9 @@ class LMI_SoftwareInstallationJob : LMI_ConcreteJob {
class LMI_SoftwareMethodResult : LMI_MethodResult {
};
+/******************************************************************************
+ * Software update associations
+ */
[Association]
class LMI_AssociatedSoftwareJobMethodResult : LMI_AssociatedJobMethodResult {
@@ -681,6 +655,49 @@ class LMI_AffectedSoftwareJobElement : LMI_AffectedJobElement {
};
+[Association]
+class LMI_AssociatedSoftwareInstallationServiceCapabilities :
+ CIM_ElementCapabilities {
+
+ [Override("Capabilities")]
+ LMI_SoftwareInstallationServiceCapabilities REF Capabilities;
+
+ [Override("ManagedElement")]
+ LMI_SoftwareInstallationService REF ManagedElement;
+
+ [Implemented(true), Override("Characteristics")]
+ uint16 Characteristics[];
+
+};
+
+[Association]
+class LMI_HostedSoftwareInstallationService : CIM_HostedService {
+
+ [Override("Antecedent")]
+ Linux_ComputerSystem REF Antecedent;
+
+ [Override("Dependent")]
+ LMI_SoftwareInstallationService REF Dependent;
+
+};
+
+[Association]
+class LMI_SoftwareInstallationServiceAffectsElement :
+ CIM_ServiceAffectsElement {
+
+ [Override("AffectingElement")]
+ LMI_SoftwareInstallationService REF AffectingElement;
+
+ [Implemented(true), Override("ElementEffects")]
+ uint16 ElementEffects[];
+
+ [Implemented(true), Override("OtherElementEffectsDescriptions")]
+ string OtherElementEffectsDescriptions[];
+
+};
+
+/******************************************************************************
+ * Software update indications
[Indication]
class LMI_SoftwareInstCreation : CIM_InstCreation {
};
diff --git a/src/python/openlmi/common/JobManager.py b/src/python/openlmi/common/JobManager.py
index d7939cc..fc12d7e 100644
--- a/src/python/openlmi/common/JobManager.py
+++ b/src/python/openlmi/common/JobManager.py
@@ -47,6 +47,7 @@ import threading
from Queue import Queue
import pywbem
import openlmi.common.cmpi_logging as cmpi_logging
+import openlmi.common
from openlmi.common.IndicationManager import IndicationManager
from pywbem.cim_provider2 import CIMProvider2
import socket
@@ -464,34 +465,6 @@ class Job(object):
classname = self.job_manager.job_classname
return 'LMI:' + classname + ':' + str(self.the_id)
- @staticmethod
- def parse_instance_id(instance_id, job_manager, classname=None):
- """
- Return the last part of instance_id.
-
- :param instance_id: (``string``) InstanceID to parse.
- :param job_manager: (``JobManager``) JobManager to query for Job's
- classname.
- :param classname: (``string``) Optional classname. If not given,
- JobManager's job_classname will be used for parsing. Other
- classnames may be used to parse e.g. LMI_<name>MethodResult
- InstanceIDs.
-
- :rtype: ``string`` or None if the ``instance_id`` has wrong format.
- """
- if classname is None:
- classname = job_manager.job_classname
- parts = instance_id.split(":")
- if len(parts) != 3:
- return None
- if parts[0] != 'LMI':
- return None
- if parts[1] != classname:
- return None
- if not parts[2].isdigit():
- return None
- return parts[2]
-
@cmpi_logging.trace_method
def get_pre_call(self):
"""
@@ -871,11 +844,10 @@ class JobManager(object):
"""
if classname is None:
classname = self.job_classname
- the_id = Job.parse_instance_id(instance_id, self, classname)
- if the_id:
- return self.jobs.get(the_id, None)
- else:
+ the_id = openlmi.common.parse_instance_id(instance_id, classname)
+ if not the_id.isdigit():
return None
+ return self.jobs.get(the_id, None)
@cmpi_logging.trace_method
def _worker_main(self):
diff --git a/src/python/openlmi/common/__init__.py b/src/python/openlmi/common/__init__.py
index 2d19515..baebcdb 100644
--- a/src/python/openlmi/common/__init__.py
+++ b/src/python/openlmi/common/__init__.py
@@ -22,3 +22,21 @@
"""
Common utilities for OpenLMI python providers.
"""
+def parse_instance_id(instance_id, classname=None):
+ """
+ Parse InstanceID, check it has LMI:<classname>:<ID> format and return
+ the ID. Return None if the format is bad.
+ :param instance_id: (``string``) String to parse.
+ :param classname: (``string``) Name of class, whose InstanceID we parse.
+ If the classname is None, it won't be checked.
+ :returns: ``string`` with the ID.
+ """
+ parts = instance_id.split(":", 2)
+ if len(parts) != 3:
+ return None
+ if parts[0] != "LMI":
+ return None
+ real_classname = parts[1]
+ if classname and real_classname.lower() != classname.lower():
+ return None
+ return parts[2]
diff --git a/src/realmd/LMI_HostedRealmdServiceProvider.c b/src/realmd/LMI_HostedRealmdServiceProvider.c
index 08732c1..1a9f399 100644
--- a/src/realmd/LMI_HostedRealmdServiceProvider.c
+++ b/src/realmd/LMI_HostedRealmdServiceProvider.c
@@ -230,4 +230,4 @@ KONKRET_REGISTRATION(
"root/cimv2",
"LMI_HostedRealmdService",
"LMI_HostedRealmdService",
- "instance association");
+ "instance association")
diff --git a/src/realmd/LMI_RealmdKerberosRealmProvider.c b/src/realmd/LMI_RealmdKerberosRealmProvider.c
index 5dc90d2..aa43ba1 100644
--- a/src/realmd/LMI_RealmdKerberosRealmProvider.c
+++ b/src/realmd/LMI_RealmdKerberosRealmProvider.c
@@ -624,4 +624,4 @@ KONKRET_REGISTRATION(
"root/cimv2",
"LMI_RealmdKerberosRealm",
"LMI_RealmdKerberosRealm",
- "instance method");
+ "instance method")
diff --git a/src/realmd/LMI_RealmdRealmProvider.c b/src/realmd/LMI_RealmdRealmProvider.c
index d8e0a18..13e0471 100644
--- a/src/realmd/LMI_RealmdRealmProvider.c
+++ b/src/realmd/LMI_RealmdRealmProvider.c
@@ -323,4 +323,4 @@ KONKRET_REGISTRATION(
"root/cimv2",
"LMI_RealmdRealm",
"LMI_RealmdRealm",
- "instance method");
+ "instance method")
diff --git a/src/realmd/LMI_RealmdServiceProvider.c b/src/realmd/LMI_RealmdServiceProvider.c
index 01fc0b8..8bc1b79 100644
--- a/src/realmd/LMI_RealmdServiceProvider.c
+++ b/src/realmd/LMI_RealmdServiceProvider.c
@@ -628,4 +628,4 @@ KONKRET_REGISTRATION(
"root/cimv2",
"LMI_RealmdService",
"LMI_RealmdService",
- "instance method");
+ "instance method")
diff --git a/src/realmd/LMI_ServiceAffectsRealmdRealmProvider.c b/src/realmd/LMI_ServiceAffectsRealmdRealmProvider.c
index 70d65f4..a80ab01 100644
--- a/src/realmd/LMI_ServiceAffectsRealmdRealmProvider.c
+++ b/src/realmd/LMI_ServiceAffectsRealmdRealmProvider.c
@@ -249,4 +249,4 @@ KONKRET_REGISTRATION(
"root/cimv2",
"LMI_ServiceAffectsRealmdRealm",
"LMI_ServiceAffectsRealmdRealm",
- "instance association");
+ "instance association")
diff --git a/src/realmd/rdcp_dbus.c b/src/realmd/rdcp_dbus.c
index b05e5c9..75ee439 100644
--- a/src/realmd/rdcp_dbus.c
+++ b/src/realmd/rdcp_dbus.c
@@ -47,15 +47,6 @@ static gboolean
append_g_variant_to_dbus_message(DBusMessage *message, GVariant *g_variant, GError **g_error);
static gboolean
-dbus_method_append_args_tuple(DBusMessage *message, GVariant *args, GError **g_error);
-
-static gboolean
-marshal_dbus_string_variant(DBusMessageIter *iter, const char *value, GError **g_error);
-
-static gboolean
-marshal_dbus_dict_string_entry(DBusMessageIter *array, const char *name, const char *value, GError **g_error);
-
-static gboolean
dbus_iter_to_variant(DBusMessageIter *iter, GVariant **g_variant_return, GError **g_error);
static gboolean
@@ -681,134 +672,6 @@ append_g_variant_to_dbus_message(DBusMessage *message, GVariant *g_variant, GEr
return TRUE;
}
-/**
- * dbus_method_append_args_tuple:
- * @message DBus message currently being built
- * @args A GVariant tuple containing the method parameters to
- * be appended to @message
- * @g_error initialized to error info when FALSE is returned.
- *
- * Append the method parameters to a DBus method message. @args
- * is a GVariant tuple representing the parameter list.
- *
- * Returns: return TRUE if successful, FALSE if error with @g_error initialized.
- */
-static gboolean
-dbus_method_append_args_tuple(DBusMessage *message, GVariant *args, GError **g_error)
-{
- DBusMessageIter iter;
- gsize n, i;
- GVariant *arg;
-
- g_return_val_if_fail (message != NULL, FALSE);
- g_return_val_if_fail (args != NULL && g_variant_is_of_type(args, G_VARIANT_TYPE_TUPLE), FALSE);
- g_return_val_if_fail (g_error == NULL || *g_error == NULL, FALSE);
-
- if ((n = g_variant_n_children(args))) {
-
- dbus_message_iter_init_append(message, &iter);
-
- for (i = 0; i < n; i++) {
- arg = g_variant_get_child_value(args, i);
- if (!append_g_variant_to_dbus_msg_iter(&iter, arg, g_error)) {
- G_VARIANT_FREE(arg);
- return FALSE;
- }
- G_VARIANT_FREE(arg);
- }
- }
-
- return TRUE;
-}
-
-/**
- * marshal_dbus_string_variant:
- * @iter iterator into which the string variant will be inserted
- * @value string value to insert as variant
- * @g_error initialized to error info when FALSE is returned.
- *
- * Add a string variant while marshaling DBus protocol.
- *
- * Returns: return TRUE if successful, FALSE if error with @g_error initialized.
- */
-static gboolean
-marshal_dbus_string_variant(DBusMessageIter *iter, const char *value, GError **g_error)
-{
- DBusMessageIter variant;
-
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (value != NULL, FALSE);
- g_return_val_if_fail (g_error == NULL || *g_error == NULL, FALSE);
-
- if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &variant)) {
- g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
- "cannot open dbus variant string container, value=\"%s\"", value);
- return FALSE;
- }
-
- if (!dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &value)) {
- g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
- "cannot append dbus variant string value, value=\"%s\"", value);
- return FALSE;
- }
-
- if (!dbus_message_iter_close_container(iter, &variant)) {
- g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
- "cannot close dbus variant container, value=\"%s\"", value);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * marshal_dbus_dict_string_entry:
- * @array dictionary array into which entry is inserted
- * @name entry's key
- * @value entry's value
- * @g_error initialized to error info when FALSE is returned.
- *
- * Adds a dictionary entry into an dictionary array whose key is a
- * string and whose value is also a string while marshaling DBus protocol.
- *
- * Returns: return TRUE if successful, FALSE if error with @g_error initialized.
- */
-static gboolean
-marshal_dbus_dict_string_entry(DBusMessageIter *array, const char *name, const char *value, GError **g_error)
-{
- DBusMessageIter entry;
-
- g_return_val_if_fail (array != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
- g_return_val_if_fail (value != NULL, FALSE);
- g_return_val_if_fail (g_error == NULL || *g_error == NULL, FALSE);
-
- if (!dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL, &entry)) {
- g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
- "cannot open dbus dict entry container for option <%s=%s>", name, value);
- return FALSE;
- }
-
- if (!dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name)) {
- g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
- "cannot append option name for option <%s=%s>", name, value);
- return FALSE;
- }
-
- if (!marshal_dbus_string_variant(&entry, value, g_error)) {
- return FALSE;
- }
-
- if (!dbus_message_iter_close_container(array, &entry)) {
- g_set_error(g_error, RDCP_ERROR, RDCP_ERROR_DBUS,
- "cannot close dbus dict entry container for option <%s=%s>", name, value);
- return FALSE;
- }
-
- return TRUE;
-}
-
-
/*----------------------------------------------------------------------------*/
diff --git a/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py b/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py
index 601b1c3..33c0522 100644
--- a/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py
+++ b/src/software/openlmi/software/LMI_AffectedSoftwareJobElement.py
@@ -83,7 +83,7 @@ class LMI_AffectedSoftwareJobElement(CIMProvider2):
elif ch.is_subclass(affected.namespace,
sub=affected.classname, super='Linux_ComputerSystem'):
AffectedSoftwareJobElement.fill_model_computer_system(
- model, env, keys_only=False)
+ model, job, keys_only=False)
elif ch.is_subclass(affected.namespace,
sub=affected.classname, super='LMI_SystemSoftwareCollection'):
diff --git a/src/software/openlmi/software/LMI_SoftwareInstallationService.py b/src/software/openlmi/software/LMI_SoftwareInstallationService.py
index f1e0ea7..8727a14 100644
--- a/src/software/openlmi/software/LMI_SoftwareInstallationService.py
+++ b/src/software/openlmi/software/LMI_SoftwareInstallationService.py
@@ -369,8 +369,8 @@ class LMI_SoftwareInstallationService(CIMProvider2):
out_params = [pywbem.CIMParameter('Job', type='reference', value=None)]
try:
jobid = InstallationService.install_or_remove_package(
- env, "uri", param_uri,
- param_target, None, param_installoptions,
+ env, InstallationJob.JOB_METHOD_INSTALL_FROM_URI,
+ param_uri, param_target, None, param_installoptions,
param_installoptionsvalues)
rval = self.values.InstallFromURI. \
Method_Parameters_Checked___Job_Started
@@ -655,8 +655,10 @@ class LMI_SoftwareInstallationService(CIMProvider2):
out_params = [pywbem.CIMParameter('Job', type='reference', value=None)]
try:
jobid = InstallationService.install_or_remove_package(
- env, "identity", param_source,
- param_target, param_collection, param_installoptions,
+ env, InstallationJob. \
+ 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
diff --git a/src/software/openlmi/software/core/Error.py b/src/software/openlmi/software/core/Error.py
index 210c00e..92b71d5 100644
--- a/src/software/openlmi/software/core/Error.py
+++ b/src/software/openlmi/software/core/Error.py
@@ -23,7 +23,6 @@ Just a common functionality related to class CIM_Error.
import pywbem
from openlmi.common import cmpi_logging
-from openlmi.software.core import InstallationService
class Values(object):
class ErrorSourceFormat(object):
@@ -430,6 +429,8 @@ def make_instance(
if not isinstance(locals()[param], (int, long)):
raise TypeError('%s must be integer'%param)
if error_source is None:
+ # this is a cyclic dependency
+ from openlmi.software.core import InstallationService
error_source = InstallationService.get_path()
if not isinstance(error_source, pywbem.CIMInstanceName):
raise TypeError('error_source must be a CIMInstanceName')
@@ -448,7 +449,6 @@ def make_instance(
if message_arguments is not None:
inst['MessageArguments'] = message_arguments
inst['ProbableCause'] = pywbem.Uint16(probable_cause)
- #inst['PerceivedSeverity'] = pywbem.Uint16(perceived_severity)
if probable_cause_description is not None:
inst['ProbableCauseDescription'] = probable_cause_description
if recommended_actions is not None:
diff --git a/src/software/openlmi/software/core/InstMethodCall.py b/src/software/openlmi/software/core/InstMethodCall.py
new file mode 100644
index 0000000..4c7e890
--- /dev/null
+++ b/src/software/openlmi/software/core/InstMethodCall.py
@@ -0,0 +1,144 @@
+# -*- 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 <http://www.gnu.org/licenses/>.
+
+"""
+CIM values for enumeration types of CIM_InstMethodCall indication class.
+"""
+
+import pywbem
+import socket
+
+from openlmi.common import cmpi_logging
+from openlmi.software.core import InstallationJob
+from openlmi.software.core import InstallationService
+from openlmi.software.yumdb import jobs, errors
+
+class Values(object):
+ class ReturnValueType(object):
+ boolean = pywbem.Uint16(2)
+ string = pywbem.Uint16(3)
+ char16 = pywbem.Uint16(4)
+ uint8 = pywbem.Uint16(5)
+ sint8 = pywbem.Uint16(6)
+ uint16 = pywbem.Uint16(7)
+ sint16 = pywbem.Uint16(8)
+ uint32 = pywbem.Uint16(9)
+ sint32 = pywbem.Uint16(10)
+ uint64 = pywbem.Uint16(11)
+ sint64 = pywbem.Uint16(12)
+ datetime = pywbem.Uint16(13)
+ real32 = pywbem.Uint16(14)
+ real64 = pywbem.Uint16(15)
+ reference = pywbem.Uint16(16)
+ # DMTF_Reserved = ..
+ _reverse_map = {
+ 2: 'boolean',
+ 3: 'string',
+ 4: 'char16',
+ 5: 'uint8',
+ 6: 'sint8',
+ 7: 'uint16',
+ 8: 'sint16',
+ 9: 'uint32',
+ 10: 'sint32',
+ 11: 'uint64',
+ 12: 'sint64',
+ 13: 'datetime',
+ 14: 'real32',
+ 15: 'real64',
+ 16: 'reference'
+ }
+
+ class PerceivedSeverity(object):
+ Unknown = pywbem.Uint16(0)
+ Other = pywbem.Uint16(1)
+ Information = pywbem.Uint16(2)
+ Degraded_Warning = pywbem.Uint16(3)
+ Minor = pywbem.Uint16(4)
+ Major = pywbem.Uint16(5)
+ Critical = pywbem.Uint16(6)
+ Fatal_NonRecoverable = pywbem.Uint16(7)
+ # DMTF_Reserved = ..
+ _reverse_map = {
+ 0: 'Unknown',
+ 1: 'Other',
+ 2: 'Information',
+ 3: 'Degraded/Warning',
+ 4: 'Minor',
+ 5: 'Major',
+ 6: 'Critical',
+ 7: 'Fatal/NonRecoverable'
+ }
+
+@cmpi_logging.trace_function
+def job2model(job, pre=True):
+ """
+ Create post or pre indication instance used by clients to subscribe
+ to job's state changes.
+
+ :param job: (``YumJob``) Instance of job created as a result of method
+ invocation.
+ :param pre: (``bool``) says, whether to make pre or post indication
+ instance.
+ :rtype CIMInstance of CIM_InstMethodCall.
+ """
+ if not isinstance(job, jobs.YumJob):
+ raise TypeError("job must be a YumJob")
+ if not pre and job.state == job.NEW or job.state == job.RUNNING:
+ raise ValueError("job must be finished to make a post indication"
+ " instance")
+ path = pywbem.CIMInstanceName(
+ classname="CIM_InstMethodCall",
+ host=socket.gethostname(),
+ namespace="root/cimv2")
+ inst = pywbem.CIMInstance(classname="CIM_InstMethodCall", path=path)
+ src_instance = InstallationJob.job2model(job, 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[
+ job.metadata["method"]]
+ inst['MethodParameters'] = InstallationJob.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)
+ if error is not None:
+ inst["Error"].append(error)
+ inst["ReturnValueType"] = Values.ReturnValueType.uint32
+ if job.state == job.COMPLETED:
+ inst["ReturnValue"] = str(InstallationService. \
+ Values.InstallFromURI.Job_Completed_with_No_Error)
+ elif job.state == job.EXCEPTION:
+ if issubclass(job.result_data[0], (
+ errors.InvalidNevra, errors.InvalidURI,
+ errors.PackageNotFound)):
+ inst["ReturnValue"] = str(InstallationService.Values. \
+ InstallFromURI.Invalid_Parameter)
+ else:
+ inst["ReturnValue"] = str(InstallationService.Values. \
+ InstallFromURI.Failed)
+ else:
+ inst["ReturnValue"] = str(InstallationService.Values. \
+ InstallFromURI.Unspecified_Error)
+ return inst
+
diff --git a/src/software/openlmi/software/core/InstallationJob.py b/src/software/openlmi/software/core/InstallationJob.py
index 7b06be2..e90ad1b 100644
--- a/src/software/openlmi/software/core/InstallationJob.py
+++ b/src/software/openlmi/software/core/InstallationJob.py
@@ -44,6 +44,18 @@ JOB_DESCRIPTIONS = {
'Software package installation job %(jobid)d from uri: "%(uri)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) = range(3)
+
+# above identificators point to this array to their description
+JOB_METHOD_NAMES = (
+ "InstallFromSoftwareIdentity",
+ "InstallFromURI",
+ "InstallFromByteStream")
+
class Values(object):
class DetailedStatus(object):
Not_Available = pywbem.Uint16(0)
@@ -386,6 +398,37 @@ class Values(object):
}
@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 and "output_params" in job.metadata:
+ # overwrite any input parameter
+ for (name, value) in job.metadata["output_params"].iteritems():
+ inst[name] = value
+ return inst
+
+@cmpi_logging.trace_function
def _fill_nonkeys(job, model):
"""
Fills into the model of instance all non-key properties.
@@ -436,8 +479,12 @@ def _fill_nonkeys(job, model):
type='uint16', value=None)
model['OperationalStatus'] = [Values.OperationalStatus.Unknown]
model['JobStatus'] = 'Unknown'
- if 'method_name' in job.metadata:
- model['MethodName'] = job.metadata['method_name']
+ 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)
@@ -502,7 +549,8 @@ def object_path2job(op):
instid = op['InstanceID']
if not instid.lower().startswith("lmi:lmi_softwareinstallationjob:"):
raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER,
- "InstanceID must start with LMI:LMI_SoftwareInstallationJob: prefix.")
+ "InstanceID must start with LMI:LMI_SoftwareInstallationJob:"
+ " prefix.")
try:
instid = int(instid[len("LMI:LMI_SoftwareInstallationJob:"):])
except ValueError:
@@ -596,11 +644,9 @@ def job2error(job):
kwargs['status_code'] = Error.Values. \
CIMStatusCode.CIM_ERR_NOT_FOUND
if issubclass(errortup[0], errors.PackageNotFound):
- kwargs['status_code_description'] = \
- "Package not found"
+ kwargs['status_code_description'] = "Package not found"
else:
- kwargs['status_code_description'] = \
- "Repository not found"
+ kwargs['status_code_description'] = "Repository not found"
elif issubclass(errortup[0], errors.PackageAlreadyInstalled):
kwargs['status_code'] = Error.Values. \
CIMStatusCode.CIM_ERR_ALREADY_EXISTS
diff --git a/src/software/openlmi/software/core/InstallationService.py b/src/software/openlmi/software/core/InstallationService.py
index acc7ca6..ccb27a6 100644
--- a/src/software/openlmi/software/core/InstallationService.py
+++ b/src/software/openlmi/software/core/InstallationService.py
@@ -26,10 +26,13 @@ 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 SystemCollection
from openlmi.software.yumdb import errors
from openlmi.software.yumdb import YumDB
+JOB_METHOD_SRC_PARAM_NAMES = ["URI", "Source", "Image"]
+
class InstallationError(Exception):
"""This exception shall be raised upon any error within
install_or_remove_package() function.
@@ -593,7 +596,7 @@ def check_path_property(env, op, prop_name):
return check_path(env, op[prop_name], prop_name)
@cmpi_logging.trace_function
-def _check_target_and_collection(env, src_type, target, collection):
+def _check_target_and_collection(env, method, target, collection):
"""
Checks Target and Collection parameters of provider's installation
methods.
@@ -620,12 +623,13 @@ def _check_target_and_collection(env, src_type, target, collection):
if not target and not collection:
raise InstallationError(values.Unspecified_Error,
"Either Target or Collection parameter must be specified."
- if src_type == "identity" else
+ if method == InstallationJob. \
+ JOB_METHOD_INSTALL_FROM_SOFTWARE_IDENTITY else
"Missing Target parameter.")
@cmpi_logging.trace_function
def _install_or_remove_check_params(
- env, src_type, source, target, collection,
+ env, method, source, target, collection,
install_options,
install_options_values):
"""
@@ -634,17 +638,20 @@ def _install_or_remove_check_params(
@return tuple (action, force, repair)
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):
+ raise ValueError("unknown method")
+
values = Values.InstallFromSoftwareIdentity
supported_options = values.InstallOptions.supported.copy()
- if src_type == "uri":
+ if method == InstallationJob.JOB_METHOD_INSTALL_FROM_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"))
+ "Missing %s parameter." % (JOB_METHOD_SRC_PARAM_NAMES[method]))
if not install_options:
install_options = []
elif not isinstance(install_options, list):
@@ -668,7 +675,7 @@ def _install_or_remove_check_params(
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)
+ _check_target_and_collection(env, method, target, collection)
exclusive = [opt for opt in options if opt in {
values.InstallOptions.Install,
values.InstallOptions.Update,
@@ -685,45 +692,88 @@ def _install_or_remove_check_params(
, values.InstallOptions.Repair in options)
@cmpi_logging.trace_function
-def install_or_remove_package(env, src_type, source, target, collection,
+def make_job_input_params(method, source, target, collection,
install_options,
install_options_values):
"""
- @param src_type is one of {"uri", "identity"}
+ 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(
+ name="InstallOptionsValues",
+ type="string",
+ is_array=True,
+ value=install_options_values),
+ "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:
+ input_params["URI"] = pywbem.CIMProperty(
+ name="URI", type="string", value=source)
+ elif method == InstallationJob.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:
+ input_params["Image"] = pywbem.CIMProperty(
+ name="Image", type="reference", value=source)
+ return input_params
+
+@cmpi_logging.trace_function
+def install_or_remove_package(env, method,
+ source, target, collection,
+ install_options,
+ install_options_values):
+ """
+ :param method: (``int``) Identifier of method defined in
+ ``core.InstallationJob`` module with variables prefixed with
+ ``JOB_METHOD_``.
"""
values = Values.InstallFromSoftwareIdentity
(action, force, repair) = _install_or_remove_check_params(
- env, src_type, source, target, collection,
+ env, method, source, target, collection,
install_options, install_options_values)
+ input_params = make_job_input_params(method,
+ source, target, collection, install_options,
+ install_options_values)
+ metadata = { "method" : method, "input_params" : input_params }
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)
+ src = Identity.object_path2nevra(source, with_epoch='ALWAYS')
+ cmpi_logging.logger.info('removing package %s', src)
+ jobid = ydb.remove_package(src, async=True, **metadata)
else:
update = action == values.InstallOptions.Update
- if src_type == "uri":
+ if method == Job.JOB_METHOD_INSTALL_FROM_URI:
cmpi_logging.logger.info('%s package "%s"',
'updating' if update else 'installing', source)
+ src = source
jobid = ydb.install_package_from_uri(
source, update_only=update, force=force or repair,
- async=True)
+ async=True, **metadata)
else: # software identity
- nevra = Identity.object_path2nevra(
- source, with_epoch='ALWAYS')
+ src = Identity.object_path2nevra(source, with_epoch='ALWAYS')
if update:
- jobid = ydb.update_package(nevra,
- force=force or repair, async=True)
+ jobid = ydb.update_package(src,
+ force=force or repair, async=True, **metadata)
else:
- jobid = ydb.install_package(
- nevra, force=force or repair, async=True)
+ jobid = ydb.install_package(src,
+ force=force or repair, async=True, **metadata)
cmpi_logging.logger.info('installation job %s for pkg "%s"'
- ' enqueued', jobid, nevra)
+ ' enqueued', jobid, src)
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))
+ cmpi_logging.logger.exception('failed to install/remove package "%s"'
+ ' from %s: %s', source,
+ JOB_METHOD_SRC_PARAM_NAMES[method].lower(), str(exc))
raise InstallationError(values.Unspecified_Error, str(exc))
diff --git a/src/software/openlmi/software/core/MethodResult.py b/src/software/openlmi/software/core/MethodResult.py
index 723edbb..05bcd78 100644
--- a/src/software/openlmi/software/core/MethodResult.py
+++ b/src/software/openlmi/software/core/MethodResult.py
@@ -23,6 +23,8 @@ 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 InstMethodCall
from openlmi.software.yumdb import jobs, errors, YumDB
@cmpi_logging.trace_function
@@ -69,16 +71,18 @@ 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
- model['Caption'] = 'Result of method %s' % job.metadata['method_name']
+ method_name = InstallationJob.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'
" of %s's %s method." % (job.jobid,
- "LMI_SoftwareInstallationService",
- job.metadata['method_name']))
+ "LMI_SoftwareInstallationService", method_name))
model['ElementName'] = 'MethodResult-%d' % job.jobid
- #model['PostCallIndication'] = \ # TODO
- #pywbem.CIMInstance(classname='CIM_InstMethodCall', ...)
- #model['PreCallIndication'] = \ # TODO
- #pywbem.CIMInstance(classname='CIM_InstMethodCall', ...)
+ model['PostCallIndication'] = pywbem.CIMProperty("PostCallIndication",
+ type="instance",
+ value=InstMethodCall.job2model(job, pre=False))
+ model['PreCallIndication'] = pywbem.CIMProperty("PreCallIndication",
+ type="instance",
+ value=InstMethodCall.job2model(job))
return model
diff --git a/src/software/openlmi/software/yumdb/__init__.py b/src/software/openlmi/software/yumdb/__init__.py
index 04f2191..ccb4360 100644
--- a/src/software/openlmi/software/yumdb/__init__.py
+++ b/src/software/openlmi/software/yumdb/__init__.py
@@ -136,26 +136,6 @@ def _make_async_job(jobcls, *args, **kwargs):
job.metadata = {}
job.metadata['name'] = \
type(job).__name__[len('Yum'):] + ('-%d' % job.jobid)
- frm = inspect.currentframe()
- method_name = None
- while ( frm is not None
- and ( not 'self' in frm.f_locals
- or not isinstance(frm.f_locals['self'], CIMProvider2))):
- frm = frm.f_back
- if frm is not None:
- prov = frm.f_locals['self']
- method_name = frm.f_code.co_name.lower()
- if method_name.startswith('cim_method_'):
- method_name = method_name[len('cim_method_'):]
- if hasattr(prov, 'values'):
- lowertocorrectcase = {
- k.lower(): k for k in prov.values.__dict__ }
- try:
- method_name = lowertocorrectcase[method_name]
- except KeyError:
- pass
- if method_name is not None:
- job.metadata['method_name'] = method_name
return job
# *****************************************************************************
@@ -526,7 +506,7 @@ class YumDB(singletonmixin.Singleton):
# Asynchronous jobs
# *************************************************************************
@job_request(async=True)
- def install_package(self, pkg, async=False, force=False):
+ def install_package(self, pkg, async=False, force=False, **metadata):
"""
Install package.
@param pkg is an instance of PackageInfo obtained with
@@ -534,25 +514,25 @@ class YumDB(singletonmixin.Singleton):
Package must not be installed if force is False.
"""
return self._do_job(_make_async_job(jobs.YumInstallPackage,
- pkg, force=force, async=async))
+ pkg, force=force, async=async, metadata=metadata))
@job_request(async=True)
- def remove_package(self, pkg, async=False):
+ def remove_package(self, pkg, async=False, **metadata):
"""
@param pkg is an instance of PackageInfo obtained with
get_package_list() or filter_packages(), which must be installed
"""
return self._do_job(_make_async_job(jobs.YumRemovePackage,
- pkg, async=async))
+ pkg, async=async, metadata=metadata))
@job_request(async=True)
- def update_to_package(self, desired_pkg, async=False):
+ def update_to_package(self, desired_pkg, async=False, **metadata):
"""
@param desired_pkg is an instance of PackageInfo,
which must be available
"""
return self._do_job(_make_async_job(jobs.YumUpdateToPackage,
- desired_pkg, async=async))
+ desired_pkg, async=async, metadata=metadata))
@job_request(async=True)
def update_package(self, pkg,
@@ -560,33 +540,35 @@ class YumDB(singletonmixin.Singleton):
to_epoch=None,
to_version=None,
to_release=None,
- force=False):
+ force=False,
+ **metadata):
"""
@param pkg is an instance of PackageInfo, which must be installed
The other parameters filter candidate available packages for update.
"""
return self._do_job(_make_async_job(jobs.YumUpdatePackage,
- pkg, async, to_epoch, to_version, to_release, force=force))
+ pkg, async, to_epoch, to_version, to_release, force=force,
+ metadata=metadata))
@job_request(async=True)
- def check_package(self, pkg, async=False):
+ def check_package(self, pkg, async=False, **metadata):
"""
@param pkg is an instance of PackageInfo representing installed package
@return instance of yumdb.PackageCheck
"""
return self._do_job(_make_async_job(jobs.YumCheckPackage,
- pkg, async=async))
+ pkg, async=async, metadata=metadata))
@job_request(async=True)
def install_package_from_uri(self, uri,
- async=False, update_only=False, force=False):
+ async=False, update_only=False, force=False, **metadata):
"""
Install package from uri.
@param uri is either remote url or local path.
"""
- return self._do_job(jobs.YumInstallPackageFromURI(
- uri, async, update_only, force=force))
+ return self._do_job(_make_async_job(jobs.YumInstallPackageFromURI,
+ uri, async, update_only, force=force, metadata=metadata))
# *************************************************************************
# Control of asynchronous jobs
diff --git a/src/software/openlmi/software/yumdb/jobs.py b/src/software/openlmi/software/yumdb/jobs.py
index 84fd3ed..5195f50 100644
--- a/src/software/openlmi/software/yumdb/jobs.py
+++ b/src/software/openlmi/software/yumdb/jobs.py
@@ -45,7 +45,7 @@ class YumJob(object): #pylint: disable=R0903
metadata attribute typically contain:
name - name of job, that is modifiable by user
- method_name - name of provider's method, that lead to creation of job
+ method - identificator of method, that lead to creation of job
"""
__slots__ = ( 'jobid', 'created', 'started', 'finished', 'last_change'
, 'priority', 'result', 'result_data')