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