[Libvirt-cim] [PATCH 2 of 3] Raises GuestCrashAlertIndication when QEMU crashes

Richard Maciel rmaciel at linux.vnet.ibm.com
Mon Jan 11 18:16:53 UTC 2010


# HG changeset patch
# User Richard Maciel <rmaciel at linux.vnet.ibm.com>
# Date 1248549583 10800
# Node ID 22540c8901bd5a58a6631c6b449c92a3d0c5fd5b
# Parent  23b104fd6d9cad1416d89c60750c603eef7d3381
Raises GuestCrashAlertIndication when QEMU crashes

Signed-off-by: Richard Maciel <rmaciel at linux.vnet.ibm.com>

diff -r 23b104fd6d9c -r 22540c8901bd src/Makefile.am
--- a/src/Makefile.am	Sat Jul 25 16:19:43 2009 -0300
+++ b/src/Makefile.am	Sat Jul 25 16:19:43 2009 -0300
@@ -76,7 +76,8 @@
                        libVirt_ServiceAffectsElement.la \
                        libVirt_HostedAccessPoint.la \
                        libVirt_ServiceAccessBySAP.la \
-                       libVirt_SAPAvailableForElement.la
+                       libVirt_SAPAvailableForElement.la \
+                       libVirt_GuestCrashAlertIndication.la
 
 libVirt_ComputerSystem_la_SOURCES = Virt_ComputerSystem.c
 libVirt_ComputerSystem_la_DEPENDENCIES = libVirt_VirtualSystemSnapshotService.la
@@ -238,3 +239,7 @@
 libVirt_SAPAvailableForElement_la_SOURCES = Virt_SAPAvailableForElement.c
 libVirt_SAPAvailableForElement_la_LIBADD = -lVirt_ComputerSystem -lVirt_KVMRedirectionSAP
 
+libVirt_GuestCrashAlertIndication_la_DEPENDENCIES = libVirt_ComputerSystem.la
+libVirt_GuestCrashAlertIndication_la_SOURCES = Virt_GuestCrashAlertIndication.c
+libVirt_GuestCrashAlertIndication_la_LIBADD = -lVirt_ComputerSystem
+
diff -r 23b104fd6d9c -r 22540c8901bd src/Virt_GuestCrashAlertIndication.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Virt_GuestCrashAlertIndication.c	Sat Jul 25 16:19:43 2009 -0300
@@ -0,0 +1,524 @@
+/*
+ * Copyright IBM Corp. 2009
+ *
+ * Authors:
+ * Richard Maciel <rmaciel at 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 <stdbool.h>
+#include <pthread.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libvirt/libvirt.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <misc_util.h>
+#include <libcmpiutil/std_indication.h>
+#include <cs_util.h>
+
+#include "config.h"
+#include "infostore.h"
+
+typedef struct cb_info {
+        const CMPIContext *context;
+        const CMPIObjectPath *obj_path;
+} *cb_info_ptr;
+
+static const CMPIBroker *_BROKER;
+
+#define CAI_NUM_PLATFORMS 3
+enum CAI_PLATFORMS {CAI_XEN,
+                    CAI_KVM,
+                    CAI_LXC,
+};
+static int active_filters[CAI_NUM_PLATFORMS];
+
+static pthread_mutex_t cb_reg_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void set_alert_ind_props(const CMPIBroker *broker,
+                                const char *classname,
+                                const CMPIContext *ctx,
+                                const CMPIInstance *ind)
+{
+        CMPIStatus s;
+        CMPIString *str = NULL;
+        CMPIUint16 val;
+        CMPIArray *array = NULL;
+        CMPIDateTime *time = NULL;
+
+        
+        //CMSetProperty(ind, "Description", &str, CMPI_string);
+
+        
+        // val 1
+        val = 1;
+        CMSetProperty(ind, "AlertType", &val, CMPI_uint16);
+
+        str = CMNewString(broker, "Virtual guest crash", &s);
+        CMSetProperty(ind, "OtherAlertType", &str, CMPI_string);
+
+        val = 7;
+        CMSetProperty(ind, "PerceivedSeverity", &val, CMPI_uint16);
+
+        // val 48
+        val = 48;
+        CMSetProperty(ind, "ProbableCause", &val, CMPI_uint16);
+        
+        //CMSetProperty(ind, "ProbableCauseDescription", &str, CMPI_string);
+
+        // val 1
+        val = 1;
+        CMSetProperty(ind, "Trending", &val, CMPI_uint16);
+
+        // This is an array
+        // CMSetProperty(ind, "RecommendedActions", &str, CMPI_string);
+
+        time = CMNewDateTime(broker, &s);
+        CMSetProperty(ind, "EventTime", &time, CMPI_dateTime);
+
+        // Kaitlin, do I need to fill this one?
+        //CMSetProperty(ind, "SystemCreationClassName", &str, CMPI_string);
+
+        // What about this?
+        // CMSetProperty(ind, "SystemName", &str, CMPI_string);
+
+        str = CMNewString(broker, classname, &s);
+        CMSetProperty(ind, "ProviderName", &str, CMPI_string);
+
+        str = CMNewString(broker, "DTMF", &s);
+        CMSetProperty(ind, "OwningEntity", &str, CMPI_string);
+
+        str = CMNewString(broker, "322", &s);
+        CMSetProperty(ind, "MessageID", &str, CMPI_string);
+
+        //CMSetProperty(ind, "Message", &str, CMPI_string);
+
+        // This is an string array
+        array = CMNewArray(broker, 1, CMPI_stringA, &s);
+        str = CMNewString(broker, 
+                          "Virtual machine execution ended "
+                          "unexpectly",
+                          &s);
+        s = CMSetArrayElementAt(array, 0, &str, CMPI_string); 
+        CMSetProperty(ind, "MessageArguments", &array, CMPI_string);
+}
+
+static CMPIStatus create_and_deliver_ind(const CMPIBroker *broker,
+                                         const CMPIContext *ctx,
+                                         struct ind_args *args,
+                                         const CMPIInstance *ind)
+{
+        CMPIStatus s;
+        CMPIObjectPath *ind_op = NULL;
+        
+        set_alert_ind_props(broker, args->classname, ctx, ind);
+
+        ind_op = CMGetObjectPath(ind, NULL);
+        CU_DEBUG("Delivering Indication: %s",
+                 CMGetCharPtr(CMObjectPathToString(ind_op, NULL)));
+
+        s = stdi_deliver(broker, ctx, args, (CMPIInstance *)ind);
+        if (s.rc == CMPI_RC_OK) {
+                CU_DEBUG("Indication delivered");
+        } else {
+                CU_DEBUG("Not delivered: %s", CMGetCharPtr(s.msg));
+        }
+
+        return s;
+}
+
+DECLARE_FILTER(xen_crashed, "Xen_GuestCrashAlertIndication");
+DECLARE_FILTER(kvm_crashed, "KVM_GuestCrashAlertIndication");
+
+static struct std_ind_filter *filters[] = {
+        &xen_crashed,
+        &kvm_crashed,
+        NULL,
+};
+
+static CMPIStatus raise_indication(const CMPIBroker *broker,
+                                   const CMPIContext *ctx,
+                                   const CMPIInstance *ind)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIObjectPath *ref = NULL;
+        struct std_indication_ctx *_ctx = NULL;
+        struct ind_args *args = NULL;
+
+        CU_DEBUG("Guest Crash Raise indication");
+
+        ref = CMGetObjectPath(ind, &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 = true;
+
+        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));
+        args->_ctx = _ctx;
+
+        
+        s = create_and_deliver_ind(broker, ctx, args, ind);
+
+        if (s.rc != CMPI_RC_OK) {
+                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);
+
+        return s;
+}
+
+
+static void free_cb(void *opaque)
+{
+        cb_info_ptr cbinfo = NULL;
+
+        CU_DEBUG("Releasing memory from guest crash callback");
+
+        cbinfo = (cb_info_ptr)opaque;
+        free(cbinfo);
+}
+
+static char * inc_counter(virDomainPtr dom)
+{
+        struct infostore_ctx *store = NULL;
+        char *str = NULL;
+        uint64_t counter = 0;
+        bool ret = false;
+       
+        pthread_mutex_lock(&cb_reg_mutex); 
+
+        store = infostore_open(dom);
+
+        if (store == NULL) {
+                CU_DEBUG("Could not open infostore");
+                goto out;
+        }
+
+        counter = infostore_get_u64(store, "EventID");
+
+        if (counter == 0)
+                CU_DEBUG("No EventID available. Creating...");
+
+        counter++;
+
+        if (asprintf(&str, "%llu", counter) < 0) {
+                CU_DEBUG("Could not alloc memory for counter");
+                goto out;
+        }
+
+        ret = infostore_set_u64(store, "EventID", counter);
+        if (!ret) {
+                CU_DEBUG("Could not save EventID to infostore");
+                free(str);
+        }
+
+ out:
+        if (!ret)
+                str = NULL;
+
+        infostore_close(store);
+
+        pthread_mutex_unlock(&cb_reg_mutex); 
+
+        return str;
+}
+
+static void preset_alert_ind_props(CMPIInstance *ind, virDomainPtr dom)
+{
+        CMPIStatus s;
+        CMPIString *str = NULL;
+        char *dom_name = (char *)virDomainGetName(dom);
+        char *counter = NULL;
+
+        if (dom_name == NULL) {
+                CU_DEBUG("Could not retrieve name of guest responsible for "
+                         "crash");
+                dom_name = "Guest name not available";
+        }
+
+        str = CMNewString(_BROKER, dom_name, &s);
+        CMSetProperty(ind, "AlertingManagedElement", &str, CMPI_string);
+
+        // This property must be unique, retrieve a counter from infostore
+        counter = inc_counter(dom);
+        if (counter == NULL) {
+                CU_DEBUG("Could not retrieve counter");
+        } else {
+                str = CMNewString(_BROKER, counter, &s);
+                CMSetProperty(ind, "EventID", &str, CMPI_string);
+                free(counter);
+        }
+}
+
+static int guest_crashed_cb(virConnectPtr conn,
+                            virDomainPtr dom,
+                            int event,
+                            int detail,
+                            void *opaque)
+{
+        char *type = NULL;
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        const char *ind_name = "GuestCrashAlertIndication";
+        CMPIInstance *ind = NULL;
+        cb_info_ptr cbinfo = NULL;         
+        const CMPIObjectPath *op =  NULL;        
+        const CMPIContext *context = NULL; 
+        
+        CU_DEBUG("Preparing %s", ind_name);
+
+        if (event != VIR_DOMAIN_EVENT_STOPPED_FAILED) {
+                CU_DEBUG("Event not monitored. Ignoring...");
+                return 0;
+        }
+
+        cbinfo = (cb_info_ptr)opaque;
+        op = cbinfo->obj_path;
+        context = cbinfo->context;
+
+        ind = get_typed_instance(_BROKER,
+                                 CLASSNAME(op),
+                                 ind_name,
+                                 NAMESPACE(op));
+
+        preset_alert_ind_props(ind, dom);
+
+        if (ind == NULL) {
+                CU_DEBUG("Failed to create ind '%s'", ind_name);
+                goto out;
+        }
+
+        type = get_typed_class(CLASSNAME(op), ind_name);
+
+        s = stdi_raise_indication(_BROKER, 
+                                  context, 
+                                  type, 
+                                  NAMESPACE(op), 
+                                  ind);
+ 
+ out:
+        free(type);
+ 
+        return s.rc != CMPI_RC_OK;
+}
+
+static int platform_from_class(const char *cn)
+{
+        if (STARTS_WITH(cn, "Xen"))
+                return CAI_XEN;
+        else if (STARTS_WITH(cn, "KVM"))
+                return CAI_KVM;
+        else if (STARTS_WITH(cn, "LXC"))
+                return CAI_LXC;
+        else
+                return -1;
+}
+
+static CMPIStatus ActivateFilter(CMPIIndicationMI* mi,
+                                 const CMPIContext* ctx,
+                                 const CMPISelectExp* se,
+                                 const char *ns,
+                                 const CMPIObjectPath* op,
+                                 CMPIBoolean first)
+{
+        virConnectPtr conn = NULL;
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        cb_info_ptr cbinfo = NULL;
+        int platform;
+        int ret = 0;
+
+        cbinfo = (cb_info_ptr)malloc(sizeof(struct cb_info));
+        cbinfo->context = ctx;
+        cbinfo->obj_path = op;
+
+        CU_DEBUG("ActivateFilter for %s", CLASSNAME(op));
+
+        if (CMIsNullObject(op)) {
+                cu_statusf(_BROKER, &s, 
+                           CMPI_RC_ERR_FAILED,
+                           "No ObjectPath given");
+                goto out;
+        }
+
+        platform = platform_from_class(CLASSNAME(op));
+        if (platform < 0) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Unknown platform");
+                goto out;
+        }
+
+        pthread_mutex_lock(&cb_reg_mutex); 
+
+        active_filters[platform]++;
+
+        if (active_filters[platform] == 1) {
+                conn = connect_by_classname(_BROKER, CLASSNAME(op), &s); 
+
+                CU_DEBUG("Registering callback function");
+                ret = virConnectDomainEventRegister(conn, 
+                                                    guest_crashed_cb, 
+                                                    (void *)cbinfo, 
+                                                    free_cb);
+                CU_DEBUG("ret val: %d\n", ret);
+        }
+
+        pthread_mutex_unlock(&cb_reg_mutex);
+
+ out:
+        return s;
+}
+
+static CMPIStatus DeActivateFilter(CMPIIndicationMI* mi,
+                                   const CMPIContext* ctx,
+                                   const CMPISelectExp* se,
+                                   const  char *ns,
+                                   const CMPIObjectPath* op,
+                                   CMPIBoolean last)
+{
+        virConnectPtr conn = NULL;
+        int platform;
+        int ret = 0;
+
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+
+        pthread_mutex_lock(&cb_reg_mutex);
+
+        platform = platform_from_class(CLASSNAME(op));
+        if (platform < 0) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Unknown platform");
+                goto out;
+        }
+
+        if (active_filters[platform] == 1) {
+                // Unregister callback
+                conn = connect_by_classname(_BROKER, CLASSNAME(op), &s); 
+                
+                CU_DEBUG("De-registering callback function");
+                ret = virConnectDomainEventDeregister(conn, 
+                                                      guest_crashed_cb);
+                CU_DEBUG("ret val: %d\n", ret);
+
+        }
+
+        active_filters[platform]--;
+
+        pthread_mutex_unlock(&cb_reg_mutex);
+
+        CU_DEBUG("DeActivateFilter for %s", CLASSNAME(op));
+
+ out:
+        return s;
+}
+
+static _EI_RTYPE EnableIndications(CMPIIndicationMI* mi,
+                                   const CMPIContext *ctx)
+{
+        CU_DEBUG("EnableIndications");
+
+        _EI_RET();
+
+}
+
+static _EI_RTYPE DisableIndications(CMPIIndicationMI* mi,
+                                    const CMPIContext *ctx)
+{
+        CU_DEBUG("DisableIndications");
+
+        _EI_RET();
+}
+
+
+
+static struct std_indication_handler csi = {
+        .raise_fn = raise_indication,
+        .trigger_fn = NULL,
+        .activate_fn = ActivateFilter,
+        .deactivate_fn = DeActivateFilter,
+        .enable_fn = EnableIndications,
+        .disable_fn = DisableIndications,
+};
+
+DEFAULT_IND_CLEANUP();
+DEFAULT_AF();
+DEFAULT_MP();
+
+STDI_IndicationMIStub(, 
+                      Virt_GuestCrashAlertIndicationProvider,
+                      _BROKER,
+                      libvirt_cim_init(), 
+                      &csi,
+                      filters);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */




More information about the Libvirt-cim mailing list