[PATCH 0 of 2] ComputerSystemModifiedIndication, not an RFC anymore

Looks like it's finally something that is ready for the tree. The first patch basically just takes what I had before and puts it in with ComputerSystemIndication, then the second patch does some actual integration work.

# HG changeset patch # User Jay Gagnon <grendel@linux.vnet.ibm.com> # Date 1200514576 18000 # Node ID e4000f4735b6e90b0b0acc4fd40d8d9c06800032 # Parent ca8dc23eacc44970a2d79978bc9de65aaa600b92 Add Modified to the list of available indications in ComputerSystemIndication. This is the integration of the previously discussed CSMI provider into the existing CSI provider. Most of the integration changes are actually done to how CSI works, as CSMI featured several improvements. The schema changes are in here too because they're just so small and simple compared to everything else that I didn't bother to break them out this time. If keeping them separate is preferred I can do that. Signed-off-by: Jay Gagnon <grendel@linux.vnet.ibm.com> diff -r ca8dc23eacc4 -r e4000f4735b6 schema/ComputerSystemIndication.mof --- a/schema/ComputerSystemIndication.mof Wed Jan 09 13:08:17 2008 +0100 +++ b/schema/ComputerSystemIndication.mof Wed Jan 16 15:16:16 2008 -0500 @@ -14,6 +14,13 @@ class Xen_ComputerSystemDeletedIndicatio { }; +[Description ("Xen_ComputerSystem modified"), + Provider("cmpi::Virt_ComputerSystemIndication") +] +class Xen_ComputerSystemModifiedIndication : CIM_InstModification +{ +}; + [Description ("KVM_ComputerSystem lifecycle"), Provider("cmpi::Virt_ComputerSystemIndication") ] @@ -27,3 +34,10 @@ class KVM_ComputerSystemDeletedIndicatio class KVM_ComputerSystemDeletedIndication : CIM_InstDeletion { }; + +[Description ("KVM_ComputerSystem modified"), + Provider("cmpi::Virt_ComputerSystemIndication") +] +class KVM_ComputerSystemModifiedIndication : CIM_InstModification +{ +}; diff -r ca8dc23eacc4 -r e4000f4735b6 schema/ComputerSystemIndication.registration --- a/schema/ComputerSystemIndication.registration Wed Jan 09 13:08:17 2008 +0100 +++ b/schema/ComputerSystemIndication.registration Wed Jan 16 15:16:16 2008 -0500 @@ -2,5 +2,7 @@ # Classname Namespace ProviderName ProviderModule ProviderTypes Xen_ComputerSystemCreatedIndication root/virt Virt_ComputerSystemIndication Virt_ComputerSystemIndication indication method Xen_ComputerSystemDeletedIndication root/virt Virt_ComputerSystemIndication Virt_ComputerSystemIndication indication method +Xen_ComputerSystemModifiedIndication root/virt Virt_ComputerSystemIndication Virt_ComputerSystemIndication indication method KVM_ComputerSystemCreatedIndication root/virt Virt_ComputerSystemIndication Virt_ComputerSystemIndication indication method KVM_ComputerSystemDeletedIndication root/virt Virt_ComputerSystemIndication Virt_ComputerSystemIndication indication method +KVM_ComputerSystemModifiedIndication root/virt Virt_ComputerSystemIndication Virt_ComputerSystemIndication indication method diff -r ca8dc23eacc4 -r e4000f4735b6 src/Virt_ComputerSystemIndication.c --- a/src/Virt_ComputerSystemIndication.c Wed Jan 09 13:08:17 2008 +0100 +++ b/src/Virt_ComputerSystemIndication.c Wed Jan 16 15:16:16 2008 -0500 @@ -62,6 +62,107 @@ static bool lifecycle_enabled = 0; # define _EI_RET() return (CMPIStatus){CMPI_RC_OK, NULL} #endif +struct dom_xml { + char uuid[VIR_UUID_STRING_BUFLEN]; + char *xml; +}; + +struct ind_args { + CMPIContext *context; + const CMPIObjectPath *ref; +}; + +static void free_dom_xml (struct dom_xml dom) +{ + free(dom.xml); +} + +static void free_ind_args (struct ind_args args) +{ + /* Nothing to do right now, but if this ends up with + something that does need to be freed I want everything in place. */ +} + +static void cleanup_domain_list(virDomainPtr *list, int size) +{ + int i; + + for (i = 0; i < size; i++) { + virDomainFree(list[i]); + } +} + +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 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}; + + *dom_xml_list = calloc(dom_ptr_count, sizeof(struct dom_xml)); + 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], + 0); + if ((*dom_xml_list)[i].xml == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to get xml desc"); + break; + } + } + + 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) + ret = true; + + break; + } + + return ret; +} + static bool _lifecycle_indication(const CMPIBroker *broker, const CMPIContext *ctx, const CMPIObjectPath *newsystem, @@ -97,6 +198,45 @@ static bool _lifecycle_indication(const NAMESPACE(newsystem), ind); + + return true; +} + +static bool _do_modified_indication(const CMPIBroker *broker, + const CMPIContext *ctx, + CMPIInstance *mod_inst, + char *prefix, + char *ns) +{ + CMPIObjectPath *ind_op; + CMPIInstance *ind; + CMPIStatus s; + + ind = get_typed_instance(broker, + prefix, + "ComputerSystemModifiedIndication", + ns); + if (ind == NULL) { + CU_DEBUG("Failed to create ind"); + return false; + } + + ind_op = CMGetObjectPath(ind, &s); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Failed to get ind_op"); + return false; + } + + CMSetProperty(ind, "PreviousInstance", + (CMPIValue *)&mod_inst, CMPI_instance); + + CU_DEBUG("Delivering Indication: %s\n", + CMGetCharPtr(CMObjectPathToString(ind_op, NULL))); + + CBDeliverIndication(_BROKER, + ctx, + CIM_VIRT_NS, + ind); return true; } @@ -177,17 +317,57 @@ static bool async_ind(CMPIContext *conte return _lifecycle_indication(_BROKER, context, op, type_name); } +static bool mod_ind(CMPIContext *context, + virConnectPtr conn, + struct dom_xml prev_dom, + char *prefix, + char *ns) +{ + bool rc; + char *name = NULL; + CMPIInstance *mod_inst; + + mod_inst = get_typed_instance(_BROKER, + prefix, + "ComputerSystem", + ns); + + name = sys_name_from_xml(prev_dom.xml); + CU_DEBUG("Name for system: '%s'", name); + if (name == NULL) { + rc = false; + goto out; + } + + CMSetProperty(mod_inst, "Name", + (CMPIValue *)name, CMPI_chars); + CMSetProperty(mod_inst, "UUID", + (CMPIValue *)prev_dom.uuid, CMPI_chars); + + rc = _do_modified_indication(_BROKER, context, mod_inst, prefix, ns); + + out: + free(name); + return rc; +} + static CMPI_THREAD_RETURN lifecycle_thread(void *params) { - CMPIContext *context = (CMPIContext *)params; + CU_DEBUG("lifecycle_thread"); + struct ind_args *args = (struct ind_args *)params; + CMPIContext *context = args->context; CMPIStatus s; int prev_count; int cur_count; virDomainPtr *prev_list; virDomainPtr *cur_list; + struct dom_xml *cur_xml = NULL; + struct dom_xml *prev_xml = NULL; virConnectPtr conn; + char *prefix = class_prefix_name(CLASSNAME(args->ref)); + char *ns = NAMESPACE(args->ref); - conn = lv_connect(_BROKER, &s); + conn = connect_by_classname(_BROKER, CLASSNAME(args->ref), &s); if (conn == NULL) { CU_DEBUG("Failed to connect: %s", CMGetCharPtr(s.msg)); return NULL; @@ -198,12 +378,20 @@ static CMPI_THREAD_RETURN lifecycle_thre CBAttachThread(_BROKER, context); prev_count = get_domain_list(conn, &prev_list); + s = doms_to_xml(&prev_xml, prev_list, prev_count); + if (s.rc != CMPI_RC_OK) + CU_DEBUG("doms_to_xml failed. Attempting to continue."); + + CU_DEBUG("entering event loop"); while (lifecycle_enabled) { int i; bool res; cur_count = get_domain_list(conn, &cur_list); + s = doms_to_xml(&cur_xml, cur_list, cur_count); + if (s.rc != CMPI_RC_OK) + CU_DEBUG("doms_to_xml failed."); for (i = 0; i < cur_count; i++) { res = dom_in_list(cur_list[i], prev_count, prev_list); @@ -221,15 +409,32 @@ static CMPI_THREAD_RETURN lifecycle_thre conn, virDomainGetName(prev_list[i]), CS_DELETED); - virDomainFree(prev_list[i]); } + for (i = 0; i < prev_count; i++) { + res = dom_changed(prev_xml[i], cur_xml, cur_count); + if (res) { + CU_DEBUG("Domain '%s' modified.", prev_xml[i].uuid); + mod_ind(context, conn, prev_xml[i], prefix, ns); + } + free_dom_xml(prev_xml[i]); + } + + cleanup_domain_list(prev_list, prev_count); + free(prev_list); + free(prev_xml); prev_list = cur_list; + prev_xml = cur_xml; prev_count = cur_count; wait_for_event(); } + pthread_mutex_unlock(&lifecycle_mutex); + free_ind_args(*args); + free(prefix); + virConnectClose(conn); + /* Should I free args as well here, since it's malloced in activate? */ return NULL; } @@ -241,17 +446,28 @@ static CMPIStatus ActivateFilter(CMPIInd const CMPIObjectPath* op, CMPIBoolean first) { + CU_DEBUG("ActivateFilter"); + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct ind_args *args = malloc(sizeof(struct ind_args)); + + if (CMIsNullObject(op)) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "No ObjectPath given"); + goto out; + } + args->ref = op; + if (lifecycle_thread_id == 0) { - CMPIContext *thread_context; - - thread_context = CBPrepareAttachThread(_BROKER, ctx); + args->context = CBPrepareAttachThread(_BROKER, ctx); lifecycle_thread_id = _BROKER->xft->newThread(lifecycle_thread, - thread_context, + args, 0); } - return (CMPIStatus){CMPI_RC_OK, NULL}; + out: + return s; } static CMPIStatus DeActivateFilter(CMPIIndicationMI* mi,

Jay Gagnon wrote:
}
+ for (i = 0; i < prev_count; i++) { + res = dom_changed(prev_xml[i], cur_xml, cur_count); + if (res) { + CU_DEBUG("Domain '%s' modified.", prev_xml[i].uuid); + mod_ind(context, conn, prev_xml[i], prefix, ns); + } + free_dom_xml(prev_xml[i]); + }
Would it be worth while to add the contents of this loop with delete indication loop just above? for (i = 0; i < prev_count; i++) { //Handle delete indication } This would prevent us from looping through another time. However, it might make the loop too complex / hard to read... -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

Kaitlin Rupert wrote:
Jay Gagnon wrote:
}
+ for (i = 0; i < prev_count; i++) { + res = dom_changed(prev_xml[i], cur_xml, cur_count); + if (res) { + CU_DEBUG("Domain '%s' modified.", prev_xml[i].uuid); + mod_ind(context, conn, prev_xml[i], prefix, ns); + } + free_dom_xml(prev_xml[i]); + }
Would it be worth while to add the contents of this loop with delete indication loop just above?
for (i = 0; i < prev_count; i++) { //Handle delete indication }
This would prevent us from looping through another time. However, it might make the loop too complex / hard to read...
I think with that one I'd fall on the "makes the loop more complex" side of things. If it saved us from hitting libvirt an additional time or something like that it would be worth it, but I think the total cycles saved will be pretty small and I like how each indication has a distinct section right now. -- -Jay

Jay Gagnon wrote:
Kaitlin Rupert wrote:
Jay Gagnon wrote:
}
+ for (i = 0; i < prev_count; i++) { + res = dom_changed(prev_xml[i], cur_xml, cur_count); + if (res) { + CU_DEBUG("Domain '%s' modified.", prev_xml[i].uuid); + mod_ind(context, conn, prev_xml[i], prefix, ns); + } + free_dom_xml(prev_xml[i]); + }
Would it be worth while to add the contents of this loop with delete indication loop just above?
for (i = 0; i < prev_count; i++) { //Handle delete indication }
This would prevent us from looping through another time. However, it might make the loop too complex / hard to read...
I think with that one I'd fall on the "makes the loop more complex" side of things. If it saved us from hitting libvirt an additional time or something like that it would be worth it, but I think the total cycles saved will be pretty small and I like how each indication has a distinct section right now.
Sure that makes sense and is fine by me. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

# HG changeset patch # User Jay Gagnon <grendel@linux.vnet.ibm.com> # Date 1200514883 18000 # Node ID dd91142f9b502f4c3f134fe3c51c105c4a290cb1 # Parent e4000f4735b6e90b0b0acc4fd40d8d9c06800032 Clean up CSI/CSMI integration The functions responsible for actually firing the indication weren't really integrated in the first patch, so much as co-existing. This one attempts to reconcile the two approaches, although there is still probably more that can be done. Signed-off-by: Jay Gagnon <grendel@linux.vnet.ibm.com> diff -r e4000f4735b6 -r dd91142f9b50 src/Virt_ComputerSystemIndication.c --- a/src/Virt_ComputerSystemIndication.c Wed Jan 16 15:16:16 2008 -0500 +++ b/src/Virt_ComputerSystemIndication.c Wed Jan 16 15:21:23 2008 -0500 @@ -48,6 +48,7 @@ static CMPI_THREAD_TYPE lifecycle_thread enum CS_EVENTS {CS_CREATED, CS_DELETED, + CS_MODIFIED, }; static pthread_cond_t lifecycle_cond = PTHREAD_COND_INITIALIZER; @@ -163,82 +164,57 @@ static bool dom_changed(struct dom_xml p return ret; } -static bool _lifecycle_indication(const CMPIBroker *broker, - const CMPIContext *ctx, - const CMPIObjectPath *newsystem, - const char *type) +static bool _do_indication(const CMPIBroker *broker, + const CMPIContext *ctx, + CMPIInstance *affected_inst, + int ind_type, + const char *ind_type_name, + char *prefix, + char *ns) { + CMPIObjectPath *affected_op; CMPIObjectPath *ind_op; CMPIInstance *ind; CMPIStatus s; + bool ret = true; ind = get_typed_instance(broker, - "Xen", /* Temporary hack */ - type, - NAMESPACE(newsystem)); + prefix, + ind_type_name, + ns); if (ind == NULL) { CU_DEBUG("Failed to create ind"); - return false; + ret = false; } ind_op = CMGetObjectPath(ind, &s); if (s.rc != CMPI_RC_OK) { CU_DEBUG("Failed to get ind_op"); - return false; + ret = false; } - CMSetProperty(ind, "AffectedSystem", - (CMPIValue *)&newsystem, CMPI_ref); + switch(ind_type) { + case CS_CREATED: + case CS_DELETED: + affected_op = CMGetObjectPath(affected_inst, NULL); + CMSetProperty(ind, "AffectedSystem", + (CMPIValue *)&affected_op, CMPI_ref); + break; + case CS_MODIFIED: + CMSetProperty(ind, "PreviousInstance", + (CMPIValue *)&affected_inst, CMPI_instance); + break; + } CU_DEBUG("Delivering Indication: %s", - CMGetCharPtr(CMObjectPathToString(ind_op, NULL))); + CMGetCharPtr(CMObjectPathToString(ind_op, NULL))); - CBDeliverIndication(_BROKER, + CBDeliverIndication(broker, ctx, - NAMESPACE(newsystem), + ns, ind); - - return true; -} - -static bool _do_modified_indication(const CMPIBroker *broker, - const CMPIContext *ctx, - CMPIInstance *mod_inst, - char *prefix, - char *ns) -{ - CMPIObjectPath *ind_op; - CMPIInstance *ind; - CMPIStatus s; - - ind = get_typed_instance(broker, - prefix, - "ComputerSystemModifiedIndication", - ns); - if (ind == NULL) { - CU_DEBUG("Failed to create ind"); - return false; - } - - ind_op = CMGetObjectPath(ind, &s); - if (s.rc != CMPI_RC_OK) { - CU_DEBUG("Failed to get ind_op"); - return false; - } - - CMSetProperty(ind, "PreviousInstance", - (CMPIValue *)&mod_inst, CMPI_instance); - - CU_DEBUG("Delivering Indication: %s\n", - CMGetCharPtr(CMObjectPathToString(ind_op, NULL))); - - CBDeliverIndication(_BROKER, - ctx, - CIM_VIRT_NS, - ind); - - return true; + return ret; } static bool wait_for_event(void) @@ -278,16 +254,15 @@ static bool async_ind(CMPIContext *conte static bool async_ind(CMPIContext *context, virConnectPtr conn, const char *name, - int type) + int type, + char *prefix, + char *ns) { CMPIInstance *newinst; CMPIObjectPath *op; CMPIStatus s; const char *type_name; char *type_cn = NULL; - const char *ns = CIM_VIRT_NS; - - /* FIXME: Hmm, need to get the namespace a better way */ if (type == CS_CREATED) { type_name = "ComputerSystemCreatedIndication"; @@ -310,11 +285,10 @@ static bool async_ind(CMPIContext *conte /* A deleted domain will have no instance to lookup */ newinst = CMNewInstance(_BROKER, op, &s); - op = CMGetObjectPath(newinst, NULL); - free(type_cn); - return _lifecycle_indication(_BROKER, context, op, type_name); + return _do_indication(_BROKER, context, newinst, type, type_name, + prefix, ns); } static bool mod_ind(CMPIContext *context, @@ -344,7 +318,9 @@ static bool mod_ind(CMPIContext *context CMSetProperty(mod_inst, "UUID", (CMPIValue *)prev_dom.uuid, CMPI_chars); - rc = _do_modified_indication(_BROKER, context, mod_inst, prefix, ns); + rc = _do_indication(_BROKER, context, mod_inst, + CS_MODIFIED, "ComputerSystemModifiedIndication", + prefix, ns); out: free(name); @@ -399,7 +375,9 @@ static CMPI_THREAD_RETURN lifecycle_thre async_ind(context, conn, virDomainGetName(cur_list[i]), - CS_CREATED); + CS_CREATED, + prefix, + ns); } for (i = 0; i < prev_count; i++) { @@ -408,7 +386,9 @@ static CMPI_THREAD_RETURN lifecycle_thre async_ind(context, conn, virDomainGetName(prev_list[i]), - CS_DELETED); + CS_DELETED, + prefix, + ns); } for (i = 0; i < prev_count; i++) {

Jay Gagnon wrote:
# HG changeset patch # User Jay Gagnon <grendel@linux.vnet.ibm.com> # Date 1200514883 18000 # Node ID dd91142f9b502f4c3f134fe3c51c105c4a290cb1 # Parent e4000f4735b6e90b0b0acc4fd40d8d9c06800032 Clean up CSI/CSMI integration
The functions responsible for actually firing the indication weren't really integrated in the first patch, so much as co-existing. This one attempts to reconcile the two approaches, although there is still probably more that can be done.
Signed-off-by: Jay Gagnon <grendel@linux.vnet.ibm.com>
@@ -310,11 +285,10 @@ static bool async_ind(CMPIContext *conte /* A deleted domain will have no instance to lookup */ newinst = CMNewInstance(_BROKER, op, &s);
- op = CMGetObjectPath(newinst, NULL); - free(type_cn);
- return _lifecycle_indication(_BROKER, context, op, type_name); + return _do_indication(_BROKER, context, newinst, type, type_name, + prefix, ns); }
static bool mod_ind(CMPIContext *context, @@ -344,7 +318,9 @@ static bool mod_ind(CMPIContext *context CMSetProperty(mod_inst, "UUID", (CMPIValue *)prev_dom.uuid, CMPI_chars);
- rc = _do_modified_indication(_BROKER, context, mod_inst, prefix, ns); + rc = _do_indication(_BROKER, context, mod_inst, + CS_MODIFIED, "ComputerSystemModifiedIndication", + prefix, ns);
Is it possible to merge async_ind() and mod_ind() ? For me it looks like, that async_ind() can be updated to also handle the modification case. -- Regards Heidi Eckhart Software Engineer IBM Linux Technology Center - Open Hypervisor

Heidi Eckhart wrote:
Jay Gagnon wrote:
# HG changeset patch # User Jay Gagnon <grendel@linux.vnet.ibm.com> # Date 1200514883 18000 # Node ID dd91142f9b502f4c3f134fe3c51c105c4a290cb1 # Parent e4000f4735b6e90b0b0acc4fd40d8d9c06800032 Clean up CSI/CSMI integration
The functions responsible for actually firing the indication weren't really integrated in the first patch, so much as co-existing. This one attempts to reconcile the two approaches, although there is still probably more that can be done.
Signed-off-by: Jay Gagnon <grendel@linux.vnet.ibm.com> @@ -310,11 +285,10 @@ static bool async_ind(CMPIContext *conte /* A deleted domain will have no instance to lookup */ newinst = CMNewInstance(_BROKER, op, &s);
- op = CMGetObjectPath(newinst, NULL); - free(type_cn);
- return _lifecycle_indication(_BROKER, context, op, type_name); + return _do_indication(_BROKER, context, newinst, type, type_name, + prefix, ns); }
static bool mod_ind(CMPIContext *context, @@ -344,7 +318,9 @@ static bool mod_ind(CMPIContext *context CMSetProperty(mod_inst, "UUID", (CMPIValue *)prev_dom.uuid, CMPI_chars);
- rc = _do_modified_indication(_BROKER, context, mod_inst, prefix, ns); + rc = _do_indication(_BROKER, context, mod_inst, + CS_MODIFIED, "ComputerSystemModifiedIndication", + prefix, ns);
Is it possible to merge async_ind() and mod_ind() ? For me it looks like, that async_ind() can be updated to also handle the modification case.
I made an early attempt to do that before I sent the patch out, but found that there were so many if-else blocks to handle the differences that it wasn't worth it. I was also operating under the assumption that I would lose some of the original functionality (information content really), because I would need to switch Created and Deleted over to use a struct dom_xml instead of a virDomainPtr. But it appears that I may have been wrong there, and all of them can use the list of dom_xml structs that Modified requires, which would allow for considerable consolidation. I will give that a shot right now and see how it turns out. -- -Jay
participants (3)
-
Heidi Eckhart
-
Jay Gagnon
-
Kaitlin Rupert