
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@linux.vnet.ibm.com> Reviewed-by: John Ferlan <jferlan@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