]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Introduce a new event emitted when a virtualization failure occurs
authorDaniel P. Berrange <berrange@redhat.com>
Sun, 29 May 2011 12:21:53 +0000 (20:21 +0800)
committerDaniel Veillard <veillard@redhat.com>
Sun, 29 May 2011 12:21:53 +0000 (20:21 +0800)
This introduces a new domain

  VIR_DOMAIN_EVENT_ID_CONTROL_ERROR

Which uses the existing generic callback

typedef void (*virConnectDomainEventGenericCallback)(virConnectPtr conn,
                                                     virDomainPtr dom,
                                                     void *opaque);

This event is intended to be emitted when there is a failure in
some part of the domain virtualization system. Whether the domain
continues to run/exist after the failure is an implementation
detail specific to the hypervisor.

The idea is that with some types of failure, hypervisors may
prefer to leave the domain running in a "degraded" mode of
operation. For example, if something goes wrong with the QEMU
monitor, it is possible to leave the guest OS running quite
happily. The mgmt app will simply loose the ability todo various
tasks. The mgmt app can then choose how/when to deal with the
failure that occured.
* daemon/remote.c: Dispatch of new event
* examples/domain-events/events-c/event-test.c: Demo catch
  of event
* include/libvirt/libvirt.h.in: Define event ID and callback
* src/conf/domain_event.c, src/conf/domain_event.h: Internal
  event handling
* src/remote/remote_driver.c: Receipt of new event from daemon
* src/remote/remote_protocol.x: Wire protocol for new event
* src/remote_protocol-structs: add new event for checks

daemon/remote.c
examples/domain-events/events-c/event-test.c
include/libvirt/libvirt.h.in
python/libvirt-override.c
src/conf/domain_event.c
src/conf/domain_event.h
src/libvirt_private.syms
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs

index bc9fd3b4172b33dff4fa7ac8416dcc16caa6a527..3f1324791032c5ec9fb0f0e95d75c0941db785f1 100644 (file)
@@ -379,6 +379,34 @@ static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED,
 }
 
 
+static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                              virDomainPtr dom,
+                                              void *opaque)
+{
+    struct qemud_client *client = opaque;
+    remote_domain_event_control_error_msg data;
+
+    if (!client)
+        return -1;
+
+    VIR_DEBUG("Relaying domain control error %s %d", dom->name, dom->id);
+
+    virMutexLock(&client->lock);
+
+    /* build return data */
+    memset(&data, 0, sizeof data);
+    make_nonnull_domain(&data.dom, dom);
+
+    remoteDispatchDomainEventSend(client,
+                                  REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR,
+                                  (xdrproc_t)xdr_remote_domain_event_control_error_msg, &data);
+
+    virMutexUnlock(&client->lock);
+
+    return 0;
+}
+
+
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -387,6 +415,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOErrorReason),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventControlError),
 };
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
index 2da58b8f0a9ac139886eb48cdc02b0af10bbdcb2..4766a0df3de1a840f293b8a2f2d912ac5dae6e75 100644 (file)
@@ -245,6 +245,17 @@ static int myDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
     return 0;
 }
 
+static int myDomainEventControlErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                             virDomainPtr dom,
+                                             void *opaque ATTRIBUTE_UNUSED)
+{
+    printf("%s EVENT: Domain %s(%d) control error\n", __func__, virDomainGetName(dom),
+           virDomainGetID(dom));
+
+    return 0;
+}
+
+
 static void myFreeFunc(void *opaque)
 {
     char *str = opaque;
@@ -278,6 +289,7 @@ int main(int argc, char **argv)
     int callback5ret = -1;
     int callback6ret = -1;
     int callback7ret = -1;
+    int callback8ret = -1;
     struct sigaction action_stop;
 
     memset(&action_stop, 0, sizeof action_stop);
@@ -336,6 +348,11 @@ int main(int argc, char **argv)
                                                     VIR_DOMAIN_EVENT_ID_GRAPHICS,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventGraphicsCallback),
                                                     strdup("callback graphics"), myFreeFunc);
+    callback8ret = virConnectDomainEventRegisterAny(dconn,
+                                                    NULL,
+                                                    VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
+                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventControlErrorCallback),
+                                                    strdup("callback control error"), myFreeFunc);
 
     if ((callback1ret != -1) &&
         (callback2ret != -1) &&
@@ -360,6 +377,8 @@ int main(int argc, char **argv)
         virConnectDomainEventDeregisterAny(dconn, callback5ret);
         virConnectDomainEventDeregisterAny(dconn, callback6ret);
         virConnectDomainEventDeregisterAny(dconn, callback7ret);
+        if (callback8ret != -1)
+            virConnectDomainEventDeregisterAny(dconn, callback8ret);
     }
 
     VIR_DEBUG("Closing connection");
index d304e72b5a16bf2d458880e2ef3029ea9fe903a8..cbd8dbb62e29aff8b437fa72c86b5968d6f52649 100644 (file)
@@ -2443,6 +2443,7 @@ typedef enum {
     VIR_DOMAIN_EVENT_ID_IO_ERROR = 4,        /* virConnectDomainEventIOErrorCallback */
     VIR_DOMAIN_EVENT_ID_GRAPHICS = 5,        /* virConnectDomainEventGraphicsCallback */
     VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON = 6, /* virConnectDomainEventIOErrorReasonCallback */
+    VIR_DOMAIN_EVENT_ID_CONTROL_ERROR = 7,   /* virConnectDomainEventGenericCallback */
 
     /*
      * NB: this enum value will increase over time as new events are
index 8676aba4e515571bc9f34532d0edf436d5bcfba9..763df0028e7cdb70921e001ca8881df852437882 100644 (file)
@@ -3480,6 +3480,9 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
     case VIR_DOMAIN_EVENT_ID_GRAPHICS:
         cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGraphicsCallback);
         break;
+    case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR:
+        cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGenericCallback);
+        break;
     }
 
     if (!cb) {
index b85765ebbaba88c280fd0deffdf7a393ce07a813..34a9d9118b40c8bfa2db77d58faf034640f5e6f9 100644 (file)
@@ -875,6 +875,24 @@ virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj,
 }
 
 
+virDomainEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom)
+{
+    virDomainEventPtr ev =
+        virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
+                                  dom->id, dom->name, dom->uuid);
+    return ev;
+}
+
+
+virDomainEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj)
+{
+    virDomainEventPtr ev =
+        virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
+                                  obj->def->id, obj->def->name, obj->def->uuid);
+    return ev;
+}
+
+
 /**
  * virDomainEventQueuePop:
  * @evtQueue: the queue of events
@@ -1004,6 +1022,11 @@ void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                                     cbopaque);
         break;
 
+    case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR:
+        (cb)(conn, dom,
+             cbopaque);
+        break;
+
     default:
         VIR_WARN("Unexpected event ID %d", event->eventID);
         break;
index efc05f9359466dd0181b4d5ea1b8ae08a3fe07e8..68dc8a8d3d144c6be59b489f9c6ab909e45d0a40 100644 (file)
@@ -167,6 +167,8 @@ virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj,
                                                    virDomainEventGraphicsAddressPtr remote,
                                                    const char *authScheme,
                                                    virDomainEventGraphicsSubjectPtr subject);
+virDomainEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom);
+virDomainEventPtr virDomainEventControlErrorNewFromObj(virDomainObjPtr obj);
 
 
 
index 4bf8277d9f7cc025132665a581dea0c8bc5089c0..321df2a0241eeed75110e15ddf0e828e3e624e35 100644 (file)
@@ -375,6 +375,8 @@ virDomainEventCallbackListPurgeMarked;
 virDomainEventCallbackListRemove;
 virDomainEventCallbackListRemoveConn;
 virDomainEventCallbackListRemoveID;
+virDomainEventControlErrorNewFromDom;
+virDomainEventControlErrorNewFromObj;
 virDomainEventDispatch;
 virDomainEventDispatchDefaultFunc;
 virDomainEventFree;
index 870b3905cd18404ddb031929c674b05ba7b76dab..d6bf7c3c54aa0c483d9f9cb6e36e551a163405cf 100644 (file)
@@ -3962,6 +3962,33 @@ no_memory:
 }
 
 
+static virDomainEventPtr
+remoteDomainReadEventControlError(virConnectPtr conn, XDR *xdr)
+{
+    remote_domain_event_control_error_msg msg;
+    virDomainPtr dom;
+    virDomainEventPtr event = NULL;
+    memset (&msg, 0, sizeof msg);
+
+    /* unmarshall parameters, and process it*/
+    if (! xdr_remote_domain_event_control_error_msg(xdr, &msg) ) {
+        remoteError(VIR_ERR_RPC, "%s",
+                    _("unable to demarshall reboot event"));
+        return NULL;
+    }
+
+    dom = get_nonnull_domain(conn,msg.dom);
+    if (!dom)
+        return NULL;
+
+    event = virDomainEventControlErrorNewFromDom(dom);
+    xdr_free ((xdrproc_t) &xdr_remote_domain_event_control_error_msg, (char *) &msg);
+
+    virDomainFree(dom);
+    return event;
+}
+
+
 static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags)
 {
@@ -5569,6 +5596,10 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
         event = remoteDomainReadEventGraphics(conn, xdr);
         break;
 
+    case REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR:
+        event = remoteDomainReadEventControlError(conn, xdr);
+        break;
+
     default:
         VIR_DEBUG("Unexpected event proc %d", hdr->proc);
         break;
index 89a8cd2e14cbd0a73a17471ab7cb22097fc47707..0602c2766f0880eb42db1734e74ed3b89ac65d78 100644 (file)
@@ -2031,6 +2031,10 @@ struct remote_domain_migrate_confirm3_args {
     int cancelled;
 };
 
+struct remote_domain_event_control_error_msg {
+    remote_nonnull_domain dom;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -2292,7 +2296,9 @@ enum remote_procedure {
 
     REMOTE_PROC_INTERFACE_CHANGE_COMMIT = 221, /* autogen autogen */
     REMOTE_PROC_INTERFACE_CHANGE_ROLLBACK = 222, /* autogen autogen */
-    REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS_FLAGS = 223 /* skipgen skipgen */
+    REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS_FLAGS = 223, /* skipgen skipgen */
+    REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR = 224 /* skipgen skipgen */
+
     /*
      * Notice how the entries are grouped in sets of 10 ?
      * Nice isn't it. Please keep it this way when adding more.
index b428bb207e792c46739298d6bef81ab0100d56fb..1d90dd599d025b6b09ee7dd805f66cd3045ebf26 100644 (file)
@@ -1539,6 +1539,9 @@ struct remote_domain_migrate_confirm3_args {
         uint64_t                   flags;
         int                        cancelled;
 };
+struct remote_domain_event_control_error_msg {
+        remote_nonnull_domain      dom;
+};
 struct remote_message_header {
         u_int                      prog;
         u_int                      vers;