From cimtest, Calling to virEventRegisterDefaultImpl() of libvirt API,
resulting random fail in cases, which seems most likely tog-pegasus's
internal data is damaged. The root cause may be:
1 libvirt event API have a bug, we called it from thread A and then
do other things in thread B, maybe it did not handle this well.
2 tog-pegasus have confilict with libvirt's event.
3 Potential requirement in libvirt event API or tog-pegasus's thread,
which is not document so we used them in a wrong way.
Most possible is that tog-pegasus tries to manage all threads
resulting the error.
This patch bring back libvirt-cim's own old event implemention, which
is by default used now. CSI from libvirt can still be activated with
a macro.
This patch also have changed some buglike code of old libvirt-cim's event
implemention.
Tested with cimtest on following Env, no more strange error found:
RH6.3
libvirt-0.9.10-21.el6.x86_64
tog-pegasus-2.11.0-3.el6.x86_64
Note that to make review easy, this patch try move the code
as little as possible, a following "clean up" patch will
move the code together.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
Reviewed-by: John Ferlan <jferlan(a)redhat.com>
---
src/Virt_ComputerSystem.c | 60 +++-
src/Virt_ComputerSystemIndication.c | 663 ++++++++++++++++++++++++++++-
src/Virt_VirtualSystemManagementService.c | 57 +++-
3 files changed, 777 insertions(+), 3 deletions(-)
diff --git a/src/Virt_ComputerSystem.c b/src/Virt_ComputerSystem.c
index 4a9b26d..d37159f 100644
--- a/src/Virt_ComputerSystem.c
+++ b/src/Virt_ComputerSystem.c
@@ -45,8 +45,58 @@
#include "Virt_HostSystem.h"
#include "Virt_VirtualSystemSnapshotService.h"
+#include "config.h"
+
const static CMPIBroker *_BROKER;
+#ifndef USE_LIBVIRT_EVENT
+static bool trigger_mod_indication(const CMPIBroker *broker,
+ const CMPIContext *context,
+ CMPIInstance *prev_inst,
+ const CMPIObjectPath *ref)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *ind_name = "ComputerSystemModifiedIndication";
+ CMPIInstance *ind = NULL;
+ char *type = NULL;
+
+ CU_DEBUG("Preparing libvirt-cim native ComputerSystem indication");
+
+ ind = get_typed_instance(broker,
+ CLASSNAME(ref),
+ ind_name,
+ NAMESPACE(ref),
+ false);
+ if (ind == NULL) {
+ CU_DEBUG("Failed to create ind '%s'", ind_name);
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to create ind '%s'", ind_name);
+ goto out;
+ }
+
+ CU_DEBUG("Setting PreviousInstance");
+ CMSetProperty(ind, "PreviousInstance",
+ (CMPIValue *)&prev_inst, CMPI_instance);
+
+ type = get_typed_class(CLASSNAME(ref), ind_name);
+
+ s = stdi_raise_indication(broker, context, type, NAMESPACE(ref), ind);
+
+ out:
+ free(type);
+ return s.rc == CMPI_RC_OK;
+}
+#else
+static bool trigger_mod_indication(const CMPIBroker *broker,
+ const CMPIContext *context,
+ CMPIInstance *prev_inst,
+ const CMPIObjectPath *ref)
+{
+ return true;
+}
+#endif
+
/* Set the "Name" property of an instance from a domain */
static int set_name_from_dom(virDomainPtr dom, CMPIInstance *instance)
{
@@ -1258,8 +1308,16 @@ static CMPIStatus state_change(CMPIMethodMI *self,
s = __state_change(name, state, reference);
- if (s.rc == CMPI_RC_OK)
+ if (s.rc == CMPI_RC_OK) {
rc = 0;
+ /* try trigger indication */
+ bool ind_rc = trigger_mod_indication(_BROKER, context,
+ prev_inst, reference);
+ if (!ind_rc) {
+ CU_DEBUG("Unable to trigger indication for "
+ "state change, dom is '%s'", name);
+ }
+ }
out:
CMReturnData(results, &rc, CMPI_uint32);
diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c
index 3df47fa..ef449ff 100644
--- a/src/Virt_ComputerSystemIndication.c
+++ b/src/Virt_ComputerSystemIndication.c
@@ -48,7 +48,6 @@
#include "Virt_ComputerSystemIndication.h"
#include "Virt_HostSystem.h"
-
#define CSI_NUM_PLATFORMS 3
enum CSI_PLATFORMS {
CSI_XEN,
@@ -84,6 +83,8 @@ static pthread_mutex_t lifecycle_mutex = PTHREAD_MUTEX_INITIALIZER;
static bool lifecycle_enabled = false;
static csi_thread_data_t csi_thread_data[CSI_NUM_PLATFORMS] = {{0}, {0}, {0}};
+#ifndef USE_LIBVIRT_EVENT
+#else
/*
* Domain manipulation
*/
@@ -180,6 +181,7 @@ static void csi_free_thread_data(void *data)
stdi_free_ind_args(&thread->args);
pthread_mutex_unlock(&lifecycle_mutex);
}
+#endif
void set_source_inst_props(const CMPIBroker *broker,
const CMPIContext *context,
@@ -386,6 +388,394 @@ static bool create_deleted_guest_inst(const char *xml,
return rc;
}
+#ifndef USE_LIBVIRT_EVENT
+/* libvirt-cim's private CSI implement */
+
+#define WAIT_TIME 60
+#define FAIL_WAIT_TIME 2
+
+static pthread_cond_t lifecycle_cond = PTHREAD_COND_INITIALIZER;
+
+struct dom_xml {
+ char uuid[VIR_UUID_STRING_BUFLEN];
+ char *xml;
+ enum {DOM_OFFLINE,
+ DOM_ONLINE,
+ DOM_PAUSED,
+ DOM_CRASHED,
+ DOM_GONE,
+ } state;
+};
+
+static void free_dom_xml(struct dom_xml dom)
+{
+ free(dom.xml);
+ dom.xml = NULL;
+}
+
+static char *sys_name_from_xml(char *xml)
+{
+ char *tmp = NULL;
+ char *name = NULL;
+ int rc;
+
+ tmp = strstr(xml, "<name>");
+ if (tmp == NULL) {
+ goto out;
+ }
+
+ rc = sscanf(tmp, "<name>%a[^<]s</name>", &name);
+ if (rc != 1) {
+ name = NULL;
+ }
+
+ out:
+ return name;
+}
+
+static int dom_state(virDomainPtr dom)
+{
+ virDomainInfo info;
+ int ret;
+
+ ret = virDomainGetInfo(dom, &info);
+ if (ret != 0) {
+ return DOM_GONE;
+ }
+
+ switch (info.state) {
+ case VIR_DOMAIN_NOSTATE:
+ case VIR_DOMAIN_RUNNING:
+ case VIR_DOMAIN_BLOCKED:
+ return DOM_ONLINE;
+
+ case VIR_DOMAIN_PAUSED:
+ return DOM_PAUSED;
+
+ case VIR_DOMAIN_SHUTOFF:
+ return DOM_OFFLINE;
+
+ case VIR_DOMAIN_CRASHED:
+ return DOM_CRASHED;
+
+ default:
+ return DOM_GONE;
+ };
+}
+
+static CMPIStatus doms_to_xml(struct dom_xml **dom_xml_list,
+ virDomainPtr *dom_ptr_list,
+ int dom_ptr_count)
+{
+ int i;
+ int rc;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ if (dom_ptr_count <= 0) {
+ *dom_xml_list = NULL;
+ return s;
+ }
+ *dom_xml_list = calloc(dom_ptr_count, sizeof(struct dom_xml));
+ if (!dom_xml_list) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed calloc %d dom_xml.", dom_ptr_count);
+ return s;
+ }
+ for (i = 0; i < dom_ptr_count; i++) {
+ rc = virDomainGetUUIDString(dom_ptr_list[i],
+ (*dom_xml_list)[i].uuid);
+ if (rc == -1) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to get UUID");
+ /* If any domain fails, we fail. */
+ break;
+ }
+
+ (*dom_xml_list)[i].xml = virDomainGetXMLDesc(dom_ptr_list[i],
+ VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE);
+ if ((*dom_xml_list)[i].xml == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to get xml desc");
+ break;
+ }
+
+ (*dom_xml_list)[i].state = dom_state(dom_ptr_list[i]);
+ }
+
+ return s;
+}
+
+static bool dom_changed(struct dom_xml prev_dom,
+ struct dom_xml *cur_xml,
+ int cur_count)
+{
+ int i;
+ bool ret = false;
+
+ for (i = 0; i < cur_count; i++) {
+ if (strcmp(cur_xml[i].uuid, prev_dom.uuid) != 0) {
+ continue;
+ }
+
+ if (strcmp(cur_xml[i].xml, prev_dom.xml) != 0) {
+ CU_DEBUG("Domain config changed");
+ ret = true;
+ }
+
+ if (prev_dom.state != cur_xml[i].state) {
+ CU_DEBUG("Domain state changed");
+ ret = true;
+ }
+
+ break;
+ }
+
+ return ret;
+}
+
+static bool wait_for_event(int wait_time)
+{
+ struct timespec timeout;
+ int ret;
+
+
+ clock_gettime(CLOCK_REALTIME, &timeout);
+ timeout.tv_sec += wait_time;
+
+ ret = pthread_cond_timedwait(&lifecycle_cond,
+ &lifecycle_mutex,
+ &timeout);
+ return !ret;
+}
+
+static bool dom_in_list(char *uuid, int count, struct dom_xml *list)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (STREQ(uuid, list[i].uuid)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool async_ind_native(CMPIContext *context,
+ int ind_type,
+ struct dom_xml prev_dom,
+ char *prefix,
+ struct ind_args *args)
+{
+ bool rc = false;
+ char *name = NULL;
+ char *cn = NULL;
+ CMPIObjectPath *op;
+ CMPIInstance *prev_inst;
+ CMPIInstance *affected_inst;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ CU_DEBUG("Entering native indication dilivery with type %d.",
ind_type)
+ if (!lifecycle_enabled) {
+ CU_DEBUG("CSI not enabled, skipping indication delivery");
+ return false;
+ }
+
+ name = sys_name_from_xml(prev_dom.xml);
+ CU_DEBUG("Name for system: '%s'", name);
+ if (name == NULL) {
+ rc = false;
+ goto out;
+ }
+
+ cn = get_typed_class(prefix, "ComputerSystem");
+
+ op = CMNewObjectPath(_BROKER, args->ns, cn, &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullObject(op)) {
+ CU_DEBUG("op error");
+ goto out;
+ }
+
+ if (ind_type == CS_CREATED || ind_type == CS_MODIFIED) {
+ s = get_domain_by_name(_BROKER, op, name, &affected_inst);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("domain by name error");
+ goto out;
+ }
+ } else if (ind_type == CS_DELETED) {
+ rc = create_deleted_guest_inst(prev_dom.xml,
+ args->ns,
+ prefix,
+ &affected_inst);
+ if (!rc) {
+ CU_DEBUG("Could not recreate guest instance");
+ goto out;
+ }
+ } else {
+ CU_DEBUG("Unrecognized indication type %d", ind_type);
+ goto out;
+ }
+
+ /* FIXME: We are unable to get the previous CS instance after it has
+ been modified. Consider keeping track of the previous
+ state in the place we keep track of the requested state */
+ prev_inst = affected_inst;
+
+ CMSetProperty(affected_inst, "Name",
+ (CMPIValue *)name, CMPI_chars);
+ CMSetProperty(affected_inst, "UUID",
+ (CMPIValue *)prev_dom.uuid, CMPI_chars);
+
+ rc = _do_indication(_BROKER, context, prev_inst, affected_inst,
+ ind_type, prefix, args);
+
+ out:
+ free(cn);
+ free(name);
+ return rc;
+}
+
+static CMPI_THREAD_RETURN lifecycle_thread_native(void *params)
+{
+ CU_DEBUG("Entering libvirtc-cim native CSI thread.");
+ csi_thread_data_t *thread = (csi_thread_data_t *) params;
+ struct ind_args *args = thread->args;
+ CMPIContext *context = args->context;
+ char *prefix = class_prefix_name(args->classname);
+ virConnectPtr conn;
+ CMPIStatus s;
+ int retry_time = FAIL_WAIT_TIME;
+
+ struct dom_xml *cur_xml = NULL;
+ struct dom_xml *prev_xml = NULL;
+ int prev_count = 0;
+ int cur_count = 0;
+ virDomainPtr *tmp_list = NULL;
+ int CBAttached = 0;
+
+ if (prefix == NULL) {
+ goto init_out;
+ }
+
+ pthread_mutex_lock(&lifecycle_mutex);
+ conn = connect_by_classname(_BROKER, args->classname, &s);
+ if (conn == NULL) {
+ CU_DEBUG("Unable to start lifecycle thread: "
+ "Failed to connect (cn: %s)", args->classname);
+ pthread_mutex_unlock(&lifecycle_mutex);
+ goto conn_out;
+ }
+
+ CBAttachThread(_BROKER, args->context);
+ CBAttached = 1;
+ prev_count = get_domain_list(conn, &tmp_list);
+ s = doms_to_xml(&prev_xml, tmp_list, prev_count);
+ free_domain_list(tmp_list, prev_count);
+ free(tmp_list);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("doms_to_xml failed. Attempting to continue.");
+ }
+
+ CU_DEBUG("Entering libvirt-cim native CSI event loop (%s)", prefix);
+
+ int i;
+ while (1) {
+ if (thread->active_filters <= 0) {
+ break;
+ }
+
+ bool res;
+ bool failure = false;
+
+ cur_count = get_domain_list(conn, &tmp_list);
+ s = doms_to_xml(&cur_xml, tmp_list, cur_count);
+ free_domain_list(tmp_list, cur_count);
+ free(tmp_list);
+ if (s.rc != CMPI_RC_OK) {
+ CU_DEBUG("doms_to_xml failed. retry in %d seconds",
+ retry_time);
+ failure = true;
+ goto fail;
+ }
+
+ /* CU_DEBUG("cur_count %d, prev_count %d.",
+ cur_count, prev_count); */
+ for (i = 0; i < cur_count; i++) {
+ res = dom_in_list(cur_xml[i].uuid,
+ prev_count, prev_xml);
+ if (!res) {
+ async_ind_native(context, CS_CREATED,
+ cur_xml[i], prefix, args);
+ }
+
+ }
+
+ for (i = 0; i < prev_count; i++) {
+ res = dom_in_list(prev_xml[i].uuid,
+ cur_count, cur_xml);
+ if (!res) {
+ async_ind_native(context, CS_DELETED,
+ prev_xml[i], prefix, args);
+ } else if (dom_changed(prev_xml[i],
+ cur_xml, cur_count)) {
+ async_ind_native(context, CS_MODIFIED,
+ prev_xml[i], prefix, args);
+ }
+ free_dom_xml(prev_xml[i]);
+ }
+
+ fail:
+ if (failure) {
+ wait_for_event(FAIL_WAIT_TIME);
+ } else {
+ free(prev_xml);
+ prev_xml = cur_xml;
+ cur_xml = NULL;
+ prev_count = cur_count;
+ cur_count = 0;
+ wait_for_event(WAIT_TIME);
+ }
+ }
+
+ CU_DEBUG("Exiting libvirt-cim native CSI event loop (%s)", prefix);
+
+ if (prev_xml != NULL) {
+ for (i = 0; i < prev_count; i++) {
+ free_dom_xml(prev_xml[i]);
+ }
+ free(prev_xml);
+ prev_xml = NULL;
+ }
+
+ pthread_mutex_unlock(&lifecycle_mutex);
+
+ virConnectClose(conn);
+
+ conn_out:
+ free(prefix);
+
+ init_out:
+ pthread_mutex_lock(&lifecycle_mutex);
+ thread->id = 0;
+ thread->active_filters = 0;
+
+ /* it seems tog-pegasus try kill this thread after detached, use this
+ flag to delay detach as much as possible. */
+ if (CBAttached > 0) {
+ CBDetachThread(_BROKER, args->context);
+ }
+ if (thread->args != NULL) {
+ stdi_free_ind_args(&thread->args);
+ }
+
+ pthread_mutex_unlock(&lifecycle_mutex);
+
+ return (CMPI_THREAD_RETURN) 0;
+}
+#else
static bool async_ind(struct ind_args *args,
int ind_type,
csi_dom_xml_t *dom,
@@ -669,6 +1059,7 @@ static CMPI_THREAD_RETURN lifecycle_thread(void *params)
free(prefix);
return (CMPI_THREAD_RETURN) 0;
}
+#endif
static int platform_from_class(const char *cn)
{
@@ -682,6 +1073,162 @@ static int platform_from_class(const char *cn)
return -1;
}
+#ifndef USE_LIBVIRT_EVENT
+static CMPIStatus ActivateFilter(CMPIIndicationMI *mi,
+ const CMPIContext *ctx,
+ const CMPISelectExp *se,
+ const char *ns,
+ const CMPIObjectPath *op,
+ CMPIBoolean first)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct std_indication_ctx *_ctx;
+ struct ind_args *args = NULL;
+ int platform;
+ bool error = false;
+ csi_thread_data_t *thread = NULL;
+
+ CU_DEBUG("ActivateFilter for %s", CLASSNAME(op));
+
+ pthread_mutex_lock(&lifecycle_mutex);
+
+ CU_DEBUG("Using libvirt-cim's event implemention.");
+
+ _ctx = (struct std_indication_ctx *)mi->hdl;
+
+ if (CMIsNullObject(op)) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "No ObjectPath given");
+ goto out;
+ }
+
+ /* FIXME: op is stale the second time around, for some reason */
+ platform = platform_from_class(CLASSNAME(op));
+ if (platform < 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unknown platform");
+ goto out;
+ }
+
+ thread = &csi_thread_data[platform];
+ thread->active_filters += 1;
+
+ /* Check if thread is already running */
+ if (thread->id > 0) {
+ goto out;
+ }
+
+ args = malloc(sizeof(*args));
+ if (args == NULL) {
+ CU_DEBUG("Failed to allocate ind_args");
+ cu_statusf(_BROKER, &s, CMPI_RC_ERR_FAILED,
+ "Unable to allocate ind_args");
+ error = true;
+ goto out;
+ }
+
+ args->context = CBPrepareAttachThread(_BROKER, ctx);
+ if (args->context == NULL) {
+ CU_DEBUG("Failed to create thread context");
+ cu_statusf(_BROKER, &s, CMPI_RC_ERR_FAILED,
+ "Unable to create thread context");
+ error = true;
+ goto out;
+ }
+
+ args->ns = strdup(NAMESPACE(op));
+ args->classname = strdup(CLASSNAME(op));
+ args->_ctx = _ctx;
+
+ thread->args = args;
+
+ thread->id = _BROKER->xft->newThread(lifecycle_thread_native,
+ thread, 0);
+
+ if (thread->id <= 0) {
+ CU_DEBUG("Error, failed to create new thread.");
+ error = true;
+ }
+
+ out:
+ if (error == true) {
+ thread->active_filters -= 1;
+ free(args);
+ }
+
+ pthread_mutex_unlock(&lifecycle_mutex);
+
+ return s;
+}
+
+static CMPIStatus DeActivateFilter(CMPIIndicationMI *mi,
+ const CMPIContext *ctx,
+ const CMPISelectExp *se,
+ const char *ns,
+ const CMPIObjectPath *op,
+ CMPIBoolean last)
+{
+ int platform;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ CU_DEBUG("DeActivateFilter for %s", CLASSNAME(op));
+
+ platform = platform_from_class(CLASSNAME(op));
+ if (platform < 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unknown platform");
+ goto out;
+ }
+
+
+ pthread_mutex_lock(&lifecycle_mutex);
+ csi_thread_data[platform].active_filters -= 1;
+ pthread_mutex_unlock(&lifecycle_mutex);
+
+ pthread_cond_signal(&lifecycle_cond);
+
+ out:
+ return s;
+}
+
+static CMPIStatus trigger_indication(const CMPIContext *context)
+{
+ CU_DEBUG("triggered");
+ pthread_cond_signal(&lifecycle_cond);
+ return (CMPIStatus){CMPI_RC_OK, NULL};
+}
+
+static CMPIInstance *get_prev_inst(const CMPIBroker *broker,
+ const CMPIInstance *ind,
+ CMPIStatus *s)
+{
+ CMPIData data;
+ CMPIInstance *prev_inst = NULL;
+
+ data = CMGetProperty(ind, "PreviousInstance", s);
+ if (s->rc != CMPI_RC_OK || CMIsNullValue(data)) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_NO_SUCH_PROPERTY,
+ "Unable to get PreviousInstance of the
indication");
+ goto out;
+ }
+
+ if (data.type != CMPI_instance) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_TYPE_MISMATCH,
+ "Indication SourceInstance is of unexpected type");
+ goto out;
+ }
+
+ prev_inst = data.value.inst;
+
+ out:
+ return prev_inst;
+}
+#else
static CMPIStatus ActivateFilter(CMPIIndicationMI* mi,
const CMPIContext* ctx,
const CMPISelectExp* se,
@@ -703,6 +1250,7 @@ static CMPIStatus ActivateFilter(CMPIIndicationMI* mi,
if (events_registered == 0) {
events_registered = 1;
+ CU_DEBUG("Registering libvirt event.");
virEventRegisterDefaultImpl();
}
@@ -756,6 +1304,11 @@ static CMPIStatus ActivateFilter(CMPIIndicationMI* mi,
thread->args = args;
thread->id = _BROKER->xft->newThread(lifecycle_thread, thread, 0);
+ if (thread->id <= 0) {
+ CU_DEBUG("Error, failed to create new thread.");
+ error = true;
+ }
+
out:
if (error == true) {
thread->active_filters -= 1;
@@ -795,6 +1348,7 @@ static CMPIStatus DeActivateFilter(CMPIIndicationMI* mi,
out:
return s;
}
+#endif
static _EI_RTYPE EnableIndications(CMPIIndicationMI* mi,
const CMPIContext *ctx)
@@ -841,7 +1395,114 @@ static struct std_ind_filter *filters[] = {
NULL,
};
+#ifndef USE_LIBVIRT_EVENT
+static CMPIStatus raise_indication(const CMPIBroker *broker,
+ const CMPIContext *ctx,
+ const CMPIObjectPath *ref,
+ const CMPIInstance *ind)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *prev_inst;
+ CMPIInstance *src_inst;
+ CMPIObjectPath *_ref = NULL;
+ struct std_indication_ctx *_ctx = NULL;
+ struct ind_args *args = NULL;
+ char *prefix = NULL;
+ bool rc;
+
+ if (!lifecycle_enabled) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "CSI not enabled, skipping indication delivery");
+ goto out;
+ }
+
+ prev_inst = get_prev_inst(broker, ind, &s);
+ if (s.rc != CMPI_RC_OK || CMIsNullObject(prev_inst)) {
+ goto out;
+ }
+
+ _ref = CMGetObjectPath(prev_inst, &s);
+ if (s.rc != CMPI_RC_OK) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get a reference to the guest");
+ goto out;
+ }
+
+ /* FIXME: This is a Pegasus work around. Pegsus loses the namespace
+ when an ObjectPath is pulled from an instance */
+ if (STREQ(NAMESPACE(_ref), "")) {
+ CMSetNameSpace(_ref, "root/virt");
+ }
+
+ s = get_domain_by_ref(broker, _ref, &src_inst);
+ if (s.rc != CMPI_RC_OK || CMIsNullObject(src_inst)) {
+ goto out;
+ }
+
+ _ctx = malloc(sizeof(struct std_indication_ctx));
+ if (_ctx == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to allocate indication context");
+ goto out;
+ }
+
+ _ctx->brkr = broker;
+ _ctx->handler = NULL;
+ _ctx->filters = filters;
+ _ctx->enabled = lifecycle_enabled;
+
+ args = malloc(sizeof(struct ind_args));
+ if (args == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to allocate ind_args");
+ goto out;
+ }
+
+ args->ns = strdup(NAMESPACE(_ref));
+ args->classname = strdup(CLASSNAME(_ref));
+ if (!args->classname || !args->ns) {
+ CU_DEBUG("Failed in strdup");
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed in strdup in indication raising");
+ goto out;
+ }
+ args->_ctx = _ctx;
+
+ prefix = class_prefix_name(args->classname);
+
+ rc = _do_indication(broker, ctx, prev_inst, src_inst,
+ CS_MODIFIED, prefix, args);
+
+ if (!rc) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to generate indication");
+ }
+
+ out:
+ if (args != NULL) {
+ stdi_free_ind_args(&args);
+ }
+
+ if (_ctx != NULL) {
+ free(_ctx);
+ }
+
+ free(prefix);
+ return s;
+}
+#endif
+
static struct std_indication_handler csi = {
+#ifndef USE_LIBVIRT_EVENT
+ .raise_fn = raise_indication,
+ .trigger_fn = trigger_indication,
+#endif
.activate_fn = ActivateFilter,
.deactivate_fn = DeActivateFilter,
.enable_fn = EnableIndications,
diff --git a/src/Virt_VirtualSystemManagementService.c
b/src/Virt_VirtualSystemManagementService.c
index 6322daf..cbb646d 100644
--- a/src/Virt_VirtualSystemManagementService.c
+++ b/src/Virt_VirtualSystemManagementService.c
@@ -107,6 +107,33 @@ enum ResourceAction {
RESOURCE_MOD,
};
+#ifndef USE_LIBVIRT_EVENT
+static bool trigger_indication(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const char *base_type,
+ const CMPIObjectPath *ref)
+{
+ char *type;
+ CMPIStatus s;
+
+ type = get_typed_class(CLASSNAME(ref), base_type);
+
+ s = stdi_trigger_indication(broker, context, type, NAMESPACE(ref));
+
+ free(type);
+
+ return s.rc == CMPI_RC_OK;
+}
+#else
+static bool trigger_indication(const CMPIBroker *broker;
+ const CMPIContext *context,
+ const char *base_type,
+ const CMPIObjectPath *ref)
+{
+ return true;
+}
+#endif
+
#if LIBVIR_VERSION_NUMBER < 9000
/* Network QoS support */
static CMPIStatus add_qos_for_mac(const uint64_t qos,
@@ -2167,6 +2194,16 @@ static CMPIStatus define_system(CMPIMethodMI *self,
CMAddArg(argsout, "ResultingSystem", &result, CMPI_ref);
}
+ /* try trigger indication */
+ bool ind_rc = trigger_indication(_BROKER, context,
+ "ComputerSystemCreatedIndication",
reference);
+ if (!ind_rc) {
+ const char *dom_name = NULL;
+ cu_get_str_prop(vssd, "VirtualSystemIdentifier",
&dom_name);
+ CU_DEBUG("Unable to trigger indication for "
+ "system create, dom is '%s'", dom_name);
+ }
+
out:
if (s.rc == CMPI_RC_OK)
rc = CIM_SVPC_RETURN_COMPLETED;
@@ -2269,6 +2306,15 @@ error:
NULL,
reference,
&list);
+
+ /* try trigger indication */
+ bool ind_rc = trigger_indication(_BROKER, context,
+ "ComputerSystemDeletedIndication",
reference);
+ if (!ind_rc) {
+ CU_DEBUG("Unable to trigger indication for "
+ "system delete, dom is '%s'",
dom_name);
+ }
+
}
virDomainFree(dom);
@@ -2350,8 +2396,17 @@ static CMPIStatus update_system_settings(const CMPIContext
*context,
connect_and_create(xml, ref, &s);
}
- if (s.rc == CMPI_RC_OK)
+ if (s.rc == CMPI_RC_OK) {
set_autostart(vssd, ref, dom);
+ /* try trigger indication */
+ bool ind_rc = trigger_indication(_BROKER, context,
+ "ComputerSystemModifiedIndication",
ref);
+ if (!ind_rc) {
+ CU_DEBUG("Unable to trigger indication for "
+ "system modify, dom is '%s'", name);
+ }
+
+ }
out:
free(xml);
--
1.7.1