# HG changeset patch
# User Jay Gagnon <grendel(a)linux.vnet.ibm.com>
# Date 1199982797 18000
# Node ID 6f3a50557ab0648b1fa0bde747914d6e58027eef
# Parent ca8dc23eacc44970a2d79978bc9de65aaa600b92
Add Virt_ComputerSystemModifiedIndication, which watches for changes in our guests.
Signed-off-by: Jay Gagnon <grendel(a)linux.vnet.ibm.com>
diff -r ca8dc23eacc4 -r 6f3a50557ab0 src/Virt_ComputerSystemModifiedIndication.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Virt_ComputerSystemModifiedIndication.c Thu Jan 10 11:33:17 2008 -0500
@@ -0,0 +1,379 @@
+/*
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ * Jay Gagnon <grendel(a)linux.vnet.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <time.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libvirt/libvirt.h>
+
+#include <libcmpiutil.h>
+#include <misc_util.h>
+#include <std_indication.h>
+#include <cs_util.h>
+
+#include "config.h"
+
+#include "Virt_ComputerSystem.h"
+#include "Virt_ComputerSystemModifiedIndication.h"
+
+static const CMPIBroker *_BROKER;
+
+static CMPI_THREAD_TYPE lifecycle_thread_id = 0;
+
+enum CS_EVENTS {
+ CS_MODIFIED,
+};
+
+static pthread_cond_t lifecycle_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t lifecycle_mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool lifecycle_enabled = 0;
+
+#ifdef CMPI_EI_VOID
+# define _EI_RTYPE void
+# define _EI_RET() return
+#else
+# define _EI_RTYPE CMPIStatus
+# define _EI_RET() return (CMPIStatus){CMPI_RC_OK, NULL}
+#endif
+
+int free_dom_xml (struct dom_xml dom)
+{
+ free(dom.uuid);
+ free(dom.xml);
+ return 0;
+}
+
+static bool _lifecycle_indication(const CMPIBroker *broker,
+ const CMPIContext *ctx,
+ CMPIInstance *mod_inst)
+{
+ CMPIObjectPath *ind_op;
+ CMPIInstance *ind;
+ CMPIStatus s;
+
+ ind = get_typed_instance(broker,
+ "Xen", /* Temporary hack */
+ "ComputerSystemModifiedIndication",
+ CIM_VIRT_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);
+
+ printf("Delivering Indication: %s\n",
+ CMGetCharPtr(CMObjectPathToString(ind_op, NULL)));
+
+ CBDeliverIndication(_BROKER,
+ ctx,
+ CIM_VIRT_NS,
+ ind);
+
+
+ return true;
+}
+
+static bool wait_for_event(void)
+{
+ struct timespec timeout;
+ int ret;
+
+
+ clock_gettime(CLOCK_REALTIME, &timeout);
+ timeout.tv_sec += 3;
+
+ ret = pthread_cond_timedwait(&lifecycle_cond,
+ &lifecycle_mutex,
+ &timeout);
+
+ return true;
+}
+
+static char *sys_name_from_xml(char *xml)
+{
+ char *tmp;
+ char *start;
+ char *end;
+ char *name;
+
+ /* Has to be a better way. */
+ tmp = strdup(xml);
+ start = strstr(tmp, "<name>");
+ start += 6;
+ end = strstr(start, "</name>");
+ end[0] = '\0';
+
+ name = strdup(start);
+ free(tmp);
+
+ return name;
+}
+
+static bool async_ind(CMPIContext *context,
+ virConnectPtr conn,
+ struct dom_xml prev_dom)
+{
+ bool rc;
+ char *name = NULL;
+ CMPIInstance *mod_inst;
+ const char *ns = CIM_VIRT_NS;
+
+ /* Where should we be getting the namespace and classname? */
+ mod_inst = get_typed_instance(_BROKER,
+ "Xen",
+ "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 = _lifecycle_indication(_BROKER, context, mod_inst);
+
+ out:
+ free(name);
+ return rc;
+}
+
+static CMPIStatus doms_to_xml(struct dom_xml **dom_xml_list,
+ virDomainPtr *dom_ptr_list,
+ int dom_ptr_count)
+{
+ int i;
+ int rc;
+ char *xml = NULL;
+ char uuid[VIR_UUID_STRING_BUFLEN];
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ *dom_xml_list = malloc(dom_ptr_count * sizeof(struct dom_xml));
+ for (i = 0; i < dom_ptr_count; i++) {
+ rc = virDomainGetUUIDString(dom_ptr_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;
+ }
+
+ xml = virDomainGetXMLDesc(dom_ptr_list[i], 0);
+ if (xml == NULL) {
+ cu_statusf(broker, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to get xml desc");
+ break;
+ }
+
+ (*dom_xml_list)[i].xml = strdup(xml);
+ (*dom_xml_list)[i].uuid = strdup(uuid);
+
+ free(xml);
+ }
+
+ 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 CMPI_THREAD_RETURN lifecycle_thread(void *params)
+{
+ int i;
+ int cur_count;
+ int prev_count;
+ virConnectPtr conn;
+ virDomainPtr *tmp_list;
+ struct dom_xml *cur_xml = NULL;
+ struct dom_xml *prev_xml = NULL;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIContext *context = (CMPIContext *)params;
+
+ /* We can't use this anymore, can we? */
+ conn = lv_connect(_BROKER, &s);
+
+ pthread_mutex_lock(&lifecycle_mutex);
+
+ CBAttachThread(_BROKER, context);
+
+ prev_count = get_domain_list(conn, &tmp_list);
+ s = doms_to_xml(&prev_xml, tmp_list, prev_count);
+ /* TODO: status check */
+ for (i = 0; i < prev_count; i++) {
+ virDomainFree(tmp_list[i]);
+ }
+
+ CU_DEBUG("entering event loop");
+ while (lifecycle_enabled) {
+ bool modified;
+
+ cur_count = get_domain_list(conn, &tmp_list);
+ s = doms_to_xml(&cur_xml, tmp_list, cur_count);
+ /* TODO: status check */
+ for (i = 0; i < cur_count; i++) {
+ virDomainFree(tmp_list[i]);
+ }
+
+ for (i = 0; i < prev_count; i++) {
+ modified = dom_changed(prev_xml[i], cur_xml, cur_count);
+ if (modified) {
+ CU_DEBUG("Domain '%s' modified.",
+ prev_xml[i].uuid);
+ async_ind(context, conn, prev_xml[i]);
+ }
+
+ free_dom_xml(prev_xml[i]);
+ }
+
+ free(prev_xml);
+ prev_xml = cur_xml;
+ wait_for_event();
+ }
+ CU_DEBUG("exiting event loop");
+
+ pthread_mutex_unlock(&lifecycle_mutex);
+
+ return NULL;
+}
+
+static CMPIStatus ActivateFilter(CMPIIndicationMI* mi,
+ const CMPIContext* ctx,
+ const CMPISelectExp* se,
+ const char *ns,
+ const CMPIObjectPath* op,
+ CMPIBoolean first)
+{
+ CU_DEBUG("ActivateFilter");
+ if (lifecycle_thread_id == 0) {
+ CMPIContext *thread_context;
+
+ thread_context = CBPrepareAttachThread(_BROKER, ctx);
+
+ lifecycle_thread_id = _BROKER->xft->newThread(lifecycle_thread,
+ thread_context,
+ 0);
+ }
+
+ return (CMPIStatus){CMPI_RC_OK, NULL};
+}
+
+static CMPIStatus DeActivateFilter(CMPIIndicationMI* mi,
+ const CMPIContext* ctx,
+ const CMPISelectExp* se,
+ const char *ns,
+ const CMPIObjectPath* op,
+ CMPIBoolean last)
+{
+ return (CMPIStatus){CMPI_RC_OK, NULL};
+}
+
+static _EI_RTYPE EnableIndications(CMPIIndicationMI* mi,
+ const CMPIContext *ctx)
+{
+ pthread_mutex_lock(&lifecycle_mutex);
+ lifecycle_enabled = true;
+ pthread_mutex_unlock(&lifecycle_mutex);
+
+ CU_DEBUG("ComputerSystemModifiedIndication enabled");
+
+ _EI_RET();
+}
+
+static _EI_RTYPE DisableIndications(CMPIIndicationMI* mi,
+ const CMPIContext *ctx)
+{
+ pthread_mutex_lock(&lifecycle_mutex);
+ lifecycle_enabled = false;
+ pthread_mutex_unlock(&lifecycle_mutex);
+
+ CU_DEBUG("ComputerSystemModifiedIndication disabled");
+
+ _EI_RET();
+}
+
+static CMPIStatus trigger_indication(const CMPIContext *context)
+{
+ pthread_cond_signal(&lifecycle_cond);
+ CU_DEBUG("CSMI triggered");
+ return(CMPIStatus){CMPI_RC_OK, NULL};
+}
+
+static struct std_indication_handler csmi = {
+ .raise_fn = NULL,
+ .trigger_fn = trigger_indication,
+};
+
+DEFAULT_IND_CLEANUP();
+DEFAULT_AF();
+DEFAULT_MP();
+
+STDI_IndicationMIStub(, Virt_ComputerSystemModifiedIndicationProvider,
+ _BROKER, libvirt_cim_init(), &csmi);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r ca8dc23eacc4 -r 6f3a50557ab0 src/Virt_ComputerSystemModifiedIndication.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Virt_ComputerSystemModifiedIndication.h Thu Jan 10 11:33:17 2008 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright IBM Corp. 2007
+ *
+ * Authors:
+ * Jay Gagnon <grendel(a)linux.vnet.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+struct dom_xml {
+ char *uuid;
+ char *xml;
+};
+
+int free_dom_xml(struct dom_xml dom);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */