]> xenbits.xensource.com Git - libvirt.git/commitdiff
Add support for an explicit guest reboot event
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 18 Mar 2010 15:25:38 +0000 (15:25 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 26 Mar 2010 13:52:43 +0000 (13:52 +0000)
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

12 files changed:
daemon/remote.c
daemon/remote_dispatch_table.h
examples/domain-events/events-c/event-test.c
include/libvirt/libvirt.h.in
src/conf/domain_event.c
src/conf/domain_event.h
src/libvirt_private.syms
src/qemu/qemu_driver.c
src/remote/remote_driver.c
src/remote/remote_protocol.c
src/remote/remote_protocol.h
src/remote/remote_protocol.x

index aa42d8234aa97eb3e2f954a630103adb49c93244..284e47cf8bf9961e4c2add281a7c20deb7ffcea8 100644 (file)
@@ -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);
index 8bbaf6181a03e89ddbea2e6e233b440f5572dab0..13a853cd5eaca3bc29982143e24e460d952fde29 100644 (file)
     .args_filter = (xdrproc_t) xdr_remote_domain_events_deregister_any_args,
     .ret_filter = (xdrproc_t) xdr_void,
 },
+{   /* Async event DomainEventReboot => 169 */
+    .fn = NULL,
+    .args_filter = (xdrproc_t) xdr_void,
+    .ret_filter = (xdrproc_t) xdr_void,
+},
index ed00fb859c707281cb5de6e7aff77f6ab816c277..c7da0c0fe8be9158412b51485130cdb258481910 100644 (file)
@@ -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);
 
     }
 
index 35c3891a2cb622d6dde28e8a10d3c9e0e80ab9c3..39970da4b17b0b9b09b45d84851662b09da989ef 100644 (file)
@@ -1874,6 +1874,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
index d73933211324002a7107398cf3bc765ffafc390f..57fd8516518780218491115ced4ca97f17657ff0 100644 (file)
@@ -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;
index db5ad5b94c6c2feb59175b246e8f88a54a50d02c..7fb0928d27b51867b5980003d86b9ee1e3e449c7 100644 (file)
@@ -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);
 
index 19918e5a701d0a14fe668570071d4fe992bb8280..471ea1b41af6bffefb972c3ab97bd04f3cdac3f1 100644 (file)
@@ -214,6 +214,8 @@ virDomainEventNew;
 virDomainEventNewFromDom;
 virDomainEventNewFromObj;
 virDomainEventNewFromDef;
+virDomainEventRebootNewFromDom;
+virDomainEventRebootNewFromObj;
 virDomainEventFree;
 virDomainEventDispatchDefaultFunc;
 virDomainEventDispatch;
index cfd82da17df70cbdd4f1a6f34ef82a609a424f30..6ab170a7771204288b615dcf9893a9a330940c5c 100644 (file)
@@ -864,9 +864,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
index 085e45fd88f10e1a696656ab8e97060c899bd802..17d61138d65b58abeb1601118f44d41b5b83a839 100644 (file)
@@ -6913,6 +6913,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,
@@ -8456,6 +8483,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;
index 9aaecccdf07ec72633b3cca9cde4a0158dac760e..af56c259e447f889206dbbf27623ba45ee407e52 100644 (file)
@@ -3050,6 +3050,15 @@ xdr_remote_domain_events_deregister_any_args (XDR *xdrs, remote_domain_events_de
         return TRUE;
 }
 
+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)
 {
index 59cdc7bdd8a433b724c692b05eed487884ffdbfb..8266294f8b7d028aa0a06c7a4c130044925abeb7 100644 (file)
@@ -1727,6 +1727,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
 
@@ -1899,6 +1904,7 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME = 166,
         REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167,
         REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168,
+        REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -2212,6 +2218,7 @@ extern  bool_t xdr_remote_domain_abort_job_args (XDR *, remote_domain_abort_job_
 extern  bool_t xdr_remote_domain_migrate_set_max_downtime_args (XDR *, remote_domain_migrate_set_max_downtime_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*);
@@ -2499,6 +2506,7 @@ extern bool_t xdr_remote_domain_abort_job_args ();
 extern bool_t xdr_remote_domain_migrate_set_max_downtime_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 ();
index 12fe67c9a3e503f5ae9046f2df8d297cb73beb4a..0419e7b32622f6bf61380c455765e3c3762466e7 100644 (file)
@@ -1536,6 +1536,9 @@ struct remote_domain_events_deregister_any_args {
     int eventID;
 };
 
+struct remote_domain_event_reboot_msg {
+    remote_nonnull_domain dom;
+};
 
 /*----- Protocol. -----*/
 
@@ -1727,7 +1730,8 @@ enum remote_procedure {
     REMOTE_PROC_STORAGE_VOL_WIPE = 165,
     REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME = 166,
     REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY = 167,
-    REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168
+    REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY = 168,
+    REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169
 
     /*
      * Notice how the entries are grouped in sets of 10 ?