diff --git a/daemon/remote.c b/daemon/remote.c index aa42d8234a..284e47cf8b 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; -static virConnectDomainEventGenericCallback domainEventCallbacks[VIR_DOMAIN_EVENT_ID_LAST] = { + 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_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 8bbaf6181a..13a853cd5e 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -847,3 +847,8 @@ .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, +}, diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c index ed00fb859c..c7da0c0fe8 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 35c3891a2c..39970da4b1 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -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 diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index d739332113..57fd851651 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 db5ad5b94c..7fb0928d27 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 19918e5a70..471ea1b41a 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 cfd82da17d..6ab170a777 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -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 diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 085e45fd88..17d61138d6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -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; diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 9aaecccdf0..af56c259e4 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -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) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index 59cdc7bdd8..8266294f8b 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -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 (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 12fe67c9a3..0419e7b326 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -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 ?