
# HG changeset patch # User Richard Maciel <rmaciel@linux.vnet.ibm.com> # Date 1248549583 10800 # Node ID a9a9447fc6357f9fd47f40b5a9bc4b97a5541d0f # Parent 0377e5c28fba407e7bf2aae4c5f81d8e521a2adb Raises GuestCrashAlertIndication when QEMU crashes Signed-off-by: Richard Maciel <rmaciel@linux.vnet.ibm.com> diff -r 0377e5c28fba -r a9a9447fc635 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 @@ -75,7 +75,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 @@ -233,3 +234,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 = + diff -r 0377e5c28fba -r a9a9447fc635 src/Virt_ComputerSystemIndication.c --- a/src/Virt_ComputerSystemIndication.c Sat Jul 25 16:19:43 2009 -0300 +++ b/src/Virt_ComputerSystemIndication.c Sat Jul 25 16:19:43 2009 -0300 @@ -692,6 +692,8 @@ char *prefix = NULL; bool rc; + CU_DEBUG("Raise indication"); + if (!lifecycle_enabled) { cu_statusf(_BROKER, &s, CMPI_RC_ERR_FAILED, diff -r 0377e5c28fba -r a9a9447fc635 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,409 @@ +/* + * Copyright IBM Corp. 2009 + * + * Authors: + * Richard Maciel <rmaciel@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 <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" + +typedef struct cb_info { + const CMPIContext *context; + const CMPIObjectPath *ref; +} *cb_info_ptr; + +static const CMPIBroker *_BROKER; + +static CMPIStatus trigger_indication(const CMPIContext *context) +{ + CU_DEBUG("guest crash indication triggered"); + return(CMPIStatus){CMPI_RC_OK, NULL}; +} + +static void set_alert_ind_props(const CMPIBroker *broker, + const char *prefix, + const CMPIContext *ctx, + CMPIInstance *ind) +{ + CMPIStatus s; + CMPIString *str; + CMPIUint16 uint16; + CMPIArray *array; + + + //CMSetProperty(ind, "Description", &str, CMPI_string); + + str = CMNewString(broker, prefix, &s); + CMSetProperty(ind, "AlertingManagedElement", &str, CMPI_string); + + // val 1 + uint16 = 1; + CMSetProperty(ind, "AlertType", &uint16, CMPI_uint16); + + str = CMNewString(broker, "VM Crash", &s); + CMSetProperty(ind, "OtherAlertType", &str, CMPI_string); + + uint16 = 7; + CMSetProperty(ind, "PerceivedSeverity", &uint16, CMPI_uint16); + + // val 48 + uint16 = 48; + CMSetProperty(ind, "ProbableCause", &uint16, CMPI_uint16); + + //CMSetProperty(ind, "ProbableCauseDescription", &str, CMPI_string); + + // val 1 + uint16 = 1; + CMSetProperty(ind, "Trending", &uint16, CMPI_uint16); + + // This is an array + // CMSetProperty(ind, "RecommendedActions", &str, CMPI_string); + + CMSetProperty(ind, "EventID", &str, CMPI_string); + + // Must find how to fill it + //CMSetProperty(ind, "EventTime", &, CMPI_dateTime); + + // Won't use it + //CMSetProperty(ind, "SystemCreationClassName", &str, CMPI_string); + + // Won't use it + // CMSetProperty(ind, "SystemName", &str, CMPI_string); + + // Won't use it + // CMSetProperty(ind, "ProviderName", &str, CMPI_string); + + str = CMNewString(broker, "DTMF", &s); + CMSetProperty(ind, "OwningEntity", &str, CMPI_string); + + str = CMNewString(broker, "PLAT0002", &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, + char *prefix, + struct ind_args *args) +{ + const char *ind_type_name = "GuestCrashAlertIndication"; + CMPIObjectPath *ind_op; + CMPIInstance *ind; + CMPIStatus s; + + ind = get_typed_instance(broker, + prefix, + ind_type_name, + args->ns); + + if (ind == NULL) { + cu_statusf(broker, + &s, + CMPI_RC_ERR_FAILED, + "Failed to create ind, type '%s:%s_%s'", + args->ns, + prefix, + ind_type_name); + goto out; + } + + ind_op = CMGetObjectPath(ind, &s); + if (s.rc != CMPI_RC_OK) { + //CU_DEBUG("Failed to get ind_op. Error: '%s'", s.msg); + goto out; + } + CMSetNameSpace(ind_op, args->ns); + + set_alert_ind_props(broker, prefix, ctx, ind); + + CU_DEBUG("Delivering Indication: %s", + CMGetCharPtr(CMObjectPathToString(ind_op, NULL))); + + s = stdi_deliver(broker, ctx, args, ind); + if (s.rc == CMPI_RC_OK) { + CU_DEBUG("Indication delivered"); + } else { + CU_DEBUG("Not delivered: %s", CMGetCharPtr(s.msg)); + } + + out: + 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; + char *prefix = 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; + + prefix = class_prefix_name(args->classname); + + s = create_and_deliver_ind(broker, ctx, prefix, args); + + 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); + + free(prefix); + 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 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 = "GuestCrashedAlertIndication"; + CMPIInstance *ind = NULL; + cb_info_ptr cbinfo = NULL; + const CMPIObjectPath *ref = NULL; + const CMPIContext *context = NULL; + + CU_DEBUG("Preparing GuestCrashedAlertIndication"); + + if (event != VIR_DOMAIN_EVENT_STOPPED_FAILED) { + CU_DEBUG("Event not monitored. Ignoring..."); + return 0; + } + + cbinfo = (cb_info_ptr)opaque; + ref = cbinfo->ref; + context = cbinfo->context; + + ind = get_typed_instance(_BROKER, + CLASSNAME(ref), + ind_name, + NAMESPACE(ref)); + + if (ind == NULL) { + CU_DEBUG("Failed to create ind '%s'", ind_name); + goto out; + } + + 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; +} + +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 ret = 0; + + cbinfo = (cb_info_ptr)malloc(sizeof(struct cb_info)); + cbinfo->context = ctx; + cbinfo->ref = op; + + CU_DEBUG("ActivateFilter for %s", CLASSNAME(op)); + + 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); + + return s; +} + +static CMPIStatus DeActivateFilter(CMPIIndicationMI* mi, + const CMPIContext* ctx, + const CMPISelectExp* se, + const char *ns, + const CMPIObjectPath* op, + CMPIBoolean last) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + + CU_DEBUG("DeActivateFilter for %s", CLASSNAME(op)); + + 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 = trigger_indication, + .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: + */