[libvirt] [PATCH 09/13] Add support for an explicit guest reboot event

Daniel P. Berrange berrange at redhat.com
Fri Mar 19 15:38:57 UTC 2010


The reboot event is not a normal lifecycle event, since the
virtual machine on the host does not change state. Rather the
guest OS is resetting the virtual CPUs. ie, the QEMU process
does not restart. Thus, this does not belong in the current
lifecycle events callback.

This introduces a new event type

    VIR_DOMAIN_EVENT_ID_REBOOT

It takes no parameters, besides the virDomainPtr, so it can
use the generic callback signature.

* daemon/remote.c: Dispatch reboot events to client
* examples/domain-events/events-c/event-test.c: Watch for
  reboot events
* include/libvirt/libvirt.h.in: Define new reboot event ID
* src/conf/domain_event.c, src/conf/domain_event.h,
  src/libvirt_private.syms: Extend API to handle reboot events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
  for reboots and emit a libvirt reboot event
* src/remote/remote_driver.c: Receive and dispatch reboot
  events to application
* src/remote/remote_protocol.x: Wire protocol definition for
  reboot events
---
 daemon/remote.c                              |   30 ++++++++++++++++++++++++-
 daemon/remote_dispatch_table.h               |    5 ++++
 examples/domain-events/events-c/event-test.c |   20 ++++++++++++++++-
 include/libvirt/libvirt.h.in                 |    1 +
 src/conf/domain_event.c                      |   16 +++++++++++++
 src/conf/domain_event.h                      |    3 ++
 src/libvirt_private.syms                     |    2 +
 src/qemu/qemu_driver.c                       |   23 +++++++++++++++++++
 src/remote/remote_driver.c                   |   31 ++++++++++++++++++++++++++
 src/remote/remote_protocol.c                 |    9 +++++++
 src/remote/remote_protocol.h                 |    8 ++++++
 src/remote/remote_protocol.x                 |    6 ++++-
 12 files changed, 151 insertions(+), 3 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index c55331c..f86c102 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -129,9 +129,37 @@ static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED,
     return 0;
 }
 
+static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                        virDomainPtr dom,
+                                        void *opaque)
+{
+    struct qemud_client *client = opaque;
+    remote_domain_event_reboot_msg data;
+
+    if (!client)
+        return -1;
+
+    REMOTE_DEBUG("Relaying domain reboot event %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_REBOOT,
+                                   (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data);
+
+    virMutexUnlock(&client->lock);
+
+    return 0;
+}
+
 
-static virConnectDomainEventGenericCallback domainEventCallbacks[VIR_DOMAIN_EVENT_ID_LAST] = {
+static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
 };
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h
index adfc58b..990e95c 100644
--- a/daemon/remote_dispatch_table.h
+++ b/daemon/remote_dispatch_table.h
@@ -837,3 +837,8 @@
     .args_filter = (xdrproc_t) xdr_remote_domain_events_deregister_any_args,
     .ret_filter = (xdrproc_t) xdr_void,
 },
+{   /* Async event DomainEventReboot => 167 */
+    .fn = NULL,
+    .args_filter = (xdrproc_t) xdr_void,
+    .ret_filter = (xdrproc_t) xdr_void,
+},
diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c
index ed00fb8..c7da0c0 100644
--- a/examples/domain-events/events-c/event-test.c
+++ b/examples/domain-events/events-c/event-test.c
@@ -172,6 +172,16 @@ static int myDomainEventCallback2(virConnectPtr conn ATTRIBUTE_UNUSED,
     return 0;
 }
 
+static int myDomainEventRebootCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                       virDomainPtr dom,
+                                       void *opaque ATTRIBUTE_UNUSED)
+{
+    printf("%s EVENT: Domain %s(%d) rebooted\n", __func__, virDomainGetName(dom),
+           virDomainGetID(dom));
+
+    return 0;
+}
+
 static void myFreeFunc(void *opaque)
 {
     char *str = opaque;
@@ -289,6 +299,7 @@ int main(int argc, char **argv)
     int sts;
     int callback1ret = -1;
     int callback2ret = -1;
+    int callback3ret = -1;
 
     struct sigaction action_stop = {
         .sa_handler = stop
@@ -326,9 +337,15 @@ int main(int argc, char **argv)
                                                     VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventCallback2),
                                                     strdup("callback 2"), myFreeFunc);
+    callback3ret = virConnectDomainEventRegisterAny(dconn,
+                                                    NULL,
+                                                    VIR_DOMAIN_EVENT_ID_REBOOT,
+                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRebootCallback),
+                                                    strdup("callback reboot"), myFreeFunc);
 
     if ((callback1ret != -1) &&
-        (callback2ret != -1)) {
+        (callback2ret != -1) &&
+        (callback3ret != -1)) {
         while(run) {
             struct pollfd pfd = { .fd = h_fd,
                               .events = h_event,
@@ -366,6 +383,7 @@ int main(int argc, char **argv)
         DEBUG0("Deregistering event handlers");
         virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
         virConnectDomainEventDeregisterAny(dconn, callback2ret);
+        virConnectDomainEventDeregisterAny(dconn, callback3ret);
 
     }
 
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 62a51ea..4b55ded 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1850,6 +1850,7 @@ typedef void (*virConnectDomainEventGenericCallback)(virConnectPtr conn,
 
 typedef enum {
     VIR_DOMAIN_EVENT_ID_LIFECYCLE = 0,       /* virConnectDomainEventCallback */
+    VIR_DOMAIN_EVENT_ID_REBOOT = 1,          /* virConnectDomainEventGenericCallback */
 
     /*
      * NB: this enum value will increase over time as new events are
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index 3bd570e..bc16d97 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -523,6 +523,17 @@ virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int de
     return virDomainEventNew(def->id, def->name, def->uuid, type, detail);
 }
 
+virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom)
+{
+    return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT,
+                                     dom->id, dom->name, dom->uuid);
+}
+virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj)
+{
+    return virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_REBOOT,
+                                     obj->def->id, obj->def->name, obj->def->uuid);
+}
+
 /**
  * virDomainEventQueueFree:
  * @queue: pointer to the queue
@@ -628,6 +639,11 @@ void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                             cbopaque);
         break;
 
+    case VIR_DOMAIN_EVENT_ID_REBOOT:
+        (cb)(conn, dom,
+             cbopaque);
+        break;
+
     default:
         VIR_WARN("Unexpected event ID %d", event->eventID);
         break;
diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
index 5578cd9..d9c950d 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -112,6 +112,9 @@ virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detai
 virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail);
 virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail);
 
+virDomainEventPtr virDomainEventRebootNewFromDom(virDomainPtr dom);
+virDomainEventPtr virDomainEventRebootNewFromObj(virDomainObjPtr obj);
+
 int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
                             virDomainEventPtr event);
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2d54fb1..38dc0a4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -214,6 +214,8 @@ virDomainEventNew;
 virDomainEventNewFromDom;
 virDomainEventNewFromObj;
 virDomainEventNewFromDef;
+virDomainEventRebootNewFromDom;
+virDomainEventRebootNewFromObj;
 virDomainEventFree;
 virDomainEventDispatchDefaultFunc;
 virDomainEventDispatch;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a8af7b4..9dfc77e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -855,9 +855,32 @@ cleanup:
     return ret;
 }
 
+
+static int
+qemuHandleDomainReset(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+                      virDomainObjPtr vm)
+{
+    struct qemud_driver *driver = qemu_driver;
+    virDomainEventPtr event;
+
+    virDomainObjLock(vm);
+    event = virDomainEventRebootNewFromObj(vm);
+    virDomainObjUnlock(vm);
+
+    if (event) {
+        qemuDriverLock(driver);
+        qemuDomainEventQueue(driver, event);
+        qemuDriverUnlock(driver);
+    }
+
+    return 0;
+}
+
+
 static qemuMonitorCallbacks monitorCallbacks = {
     .eofNotify = qemuHandleMonitorEOF,
     .diskSecretLookup = findVolumeQcowPassphrase,
+    .domainReset = qemuHandleDomainReset,
 };
 
 static int
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 8b6db9c..1a64749 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6887,6 +6887,33 @@ remoteDomainReadEventLifecycle(virConnectPtr conn, XDR *xdr)
 }
 
 
+static virDomainEventPtr
+remoteDomainReadEventReboot(virConnectPtr conn, XDR *xdr)
+{
+    remote_domain_event_reboot_msg msg;
+    virDomainPtr dom;
+    virDomainEventPtr event = NULL;
+    memset (&msg, 0, sizeof msg);
+
+    /* unmarshall parameters, and process it*/
+    if (! xdr_remote_domain_event_reboot_msg(xdr, &msg) ) {
+        error (conn, VIR_ERR_RPC,
+               _("unable to demarshall reboot event"));
+        return NULL;
+    }
+
+    dom = get_nonnull_domain(conn,msg.dom);
+    if (!dom)
+        return NULL;
+
+    event = virDomainEventRebootNewFromDom(dom);
+    xdr_free ((xdrproc_t) &xdr_remote_domain_event_reboot_msg, (char *) &msg);
+
+    virDomainFree(dom);
+    return event;
+}
+
+
 static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 remoteSecretOpen (virConnectPtr conn,
                   virConnectAuthPtr auth,
@@ -8400,6 +8427,10 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
         event = remoteDomainReadEventLifecycle(conn, xdr);
         break;
 
+    case REMOTE_PROC_DOMAIN_EVENT_REBOOT:
+        event = remoteDomainReadEventReboot(conn, xdr);
+        break;
+
     default:
         DEBUG("Unexpected event proc %d", hdr->proc);
         break;
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
index 3ad8958..f2a59c7 100644
--- a/src/remote/remote_protocol.c
+++ b/src/remote/remote_protocol.c
@@ -3027,6 +3027,15 @@ xdr_remote_domain_events_deregister_any_args (XDR *xdrs, remote_domain_events_de
 }
 
 bool_t
+xdr_remote_domain_event_reboot_msg (XDR *xdrs, remote_domain_event_reboot_msg *objp)
+{
+
+         if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
 xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
 {
 
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index 9005d6f..900a8b8 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -1714,6 +1714,11 @@ struct remote_domain_events_deregister_any_args {
         int eventID;
 };
 typedef struct remote_domain_events_deregister_any_args remote_domain_events_deregister_any_args;
+
+struct remote_domain_event_reboot_msg {
+        remote_nonnull_domain dom;
+};
+typedef struct remote_domain_event_reboot_msg remote_domain_event_reboot_msg;
 #define REMOTE_PROGRAM 0x20008086
 #define REMOTE_PROTOCOL_VERSION 1
 
@@ -1884,6 +1889,7 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_ABORT_JOB = 164,
         REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 165,
         REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 166,
+        REMOTE_PROC_DOMAIN_EVENT_REBOOT = 167,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -2195,6 +2201,7 @@ extern  bool_t xdr_remote_domain_get_job_info_ret (XDR *, remote_domain_get_job_
 extern  bool_t xdr_remote_domain_abort_job_args (XDR *, remote_domain_abort_job_args*);
 extern  bool_t xdr_remote_domain_events_register_any_args (XDR *, remote_domain_events_register_any_args*);
 extern  bool_t xdr_remote_domain_events_deregister_any_args (XDR *, remote_domain_events_deregister_any_args*);
+extern  bool_t xdr_remote_domain_event_reboot_msg (XDR *, remote_domain_event_reboot_msg*);
 extern  bool_t xdr_remote_procedure (XDR *, remote_procedure*);
 extern  bool_t xdr_remote_message_type (XDR *, remote_message_type*);
 extern  bool_t xdr_remote_message_status (XDR *, remote_message_status*);
@@ -2480,6 +2487,7 @@ extern bool_t xdr_remote_domain_get_job_info_ret ();
 extern bool_t xdr_remote_domain_abort_job_args ();
 extern bool_t xdr_remote_domain_events_register_any_args ();
 extern bool_t xdr_remote_domain_events_deregister_any_args ();
+extern bool_t xdr_remote_domain_event_reboot_msg ();
 extern bool_t xdr_remote_procedure ();
 extern bool_t xdr_remote_message_type ();
 extern bool_t xdr_remote_message_status ();
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 2807afa..72fe5b3 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -1525,6 +1525,9 @@ struct remote_domain_events_deregister_any_args {
     int eventID;
 };
 
+struct remote_domain_event_reboot_msg {
+    remote_nonnull_domain dom;
+};
 
 /*----- Protocol. -----*/
 
@@ -1714,7 +1717,8 @@ enum remote_procedure {
     REMOTE_PROC_DOMAIN_GET_JOB_INFO = 163,
     REMOTE_PROC_DOMAIN_ABORT_JOB = 164,
     REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 165,
-    REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 166
+    REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 166,
+    REMOTE_PROC_DOMAIN_EVENT_REBOOT = 167
 
     /*
      * Notice how the entries are grouped in sets of 10 ?
-- 
1.6.6.1




More information about the libvir-list mailing list