As per our earlier discussion today, this patch expands the callback for domain events so that it also gets a event type specific 'detail' field. This is also kept as an int, and we define enumerations for the possible values associated with each type. If a event type has no detail, 0 is passed. The RESTORED and SAVED event types disappear in this patch and just become another piece of 'detail' to the STOPPED and STARTED events. I have also renamed ADDED & REMOVED to DEFINED and UNDEFINED to match terminology we have elsewhere & because the names were confusing me Easiest to just look at the final set: typedef enum { VIR_DOMAIN_EVENT_DEFINED = 0, VIR_DOMAIN_EVENT_UNDEFINED = 1, VIR_DOMAIN_EVENT_STARTED = 2, VIR_DOMAIN_EVENT_SUSPENDED = 3, VIR_DOMAIN_EVENT_RESUMED = 4, VIR_DOMAIN_EVENT_STOPPED = 5, } virDomainEventType; typedef enum { VIR_DOMAIN_EVENT_STARTED_BOOTED = 0, /* Normal startup from boot */ VIR_DOMAIN_EVENT_STARTED_MIGRATED = 1, /* Incoming migration from another host */ VIR_DOMAIN_EVENT_STARTED_RESTORED = 2, /* Restored from a state file */ } virDomainEventStartedDetailType; typedef enum { VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN = 0, /* Normal shutdown */ VIR_DOMAIN_EVENT_STOPPED_DESTROYED = 1, /* Forced poweroff from host */ VIR_DOMAIN_EVENT_STOPPED_CRASHED = 2, /* Guest crashed */ VIR_DOMAIN_EVENT_STOPPED_MIGRATED = 3, /* Migrated off to another host */ VIR_DOMAIN_EVENT_STOPPED_SAVED = 4, /* Saved to a state file */ VIR_DOMAIN_EVENT_STOPPED_FAILED = 5, /* Host emulator/mgmt failed */ } virDomainEventStoppedDetailType; typedef enum { VIR_DOMAIN_EVENT_DEFINED_ADDED = 0, /* Newly created config file */ VIR_DOMAIN_EVENT_DEFINED_UPDATED = 1, /* Changed config file */ } virDomainEventDefinedDetailType; I don't make use of 'CRASHED' in QEMU driver yet. It might be useful in Xen though - when a PV guest crashes, Xen stops the domain running, but leaves it there in a shutoff state, but marked as crashed. Now using the C event-test program you can see the effects: myDomainEventCallback1 EVENT: Domain F9x86_64(2) Started Booted myDomainEventCallback2 EVENT: Domain F9x86_64(2) Started Booted myDomainEventCallback1 EVENT: Domain F9x86_64(-1) Stopped Destroyed myDomainEventCallback2 EVENT: Domain F9x86_64(-1) Stopped Destroyed myDomainEventCallback1 EVENT: Domain F9x86_64(3) Started Booted myDomainEventCallback2 EVENT: Domain F9x86_64(3) Started Booted myDomainEventCallback1 EVENT: Domain F9x86_64(3) Suspended myDomainEventCallback2 EVENT: Domain F9x86_64(3) Suspended myDomainEventCallback1 EVENT: Domain F9x86_64(3) Resumed myDomainEventCallback2 EVENT: Domain F9x86_64(3) Resumed myDomainEventCallback1 EVENT: Domain F9x86_64(-1) Stopped Shutdown myDomainEventCallback2 EVENT: Domain F9x86_64(-1) Stopped Shutdown Of the following sequence of actions virsh start F9x86_64 virsh destroy F9x86_64 virsh start F9x86_64 virsh suspend F9x86_64 virsh resume F9x86_64 virsh shutdown F9x86_64 For the last 'shutdown' operation, you'll see the same if you just run a graceful shutdown inside the guest itself. NB, I've not tested saved/restored because my install of KVM is not new enough to support that correctly, but I expect it to work without trouble. Likewise for migration. A word about migration... - The destination host first gets a STARTED event, with detail MIGRATED when it starts running - The source host then gets a STOPPED event with detail MIGRATED when it completes - The destination host then gets a RESUMED event, on success, and a STOPPED event with detail FAILED if migration aborts. Daniel examples/domain-events/events-c/event-test.c | 78 +++++++++++++++---- examples/domain-events/events-python/event-test.py | 8 +- include/libvirt/libvirt.h | 29 ++++++- include/libvirt/libvirt.h.in | 29 ++++++- python/libvir.c | 6 + qemud/qemud.h | 1 qemud/remote.c | 22 +++-- qemud/remote_protocol.c | 2 qemud/remote_protocol.h | 1 qemud/remote_protocol.x | 1 src/domain_event.c | 4 - src/domain_event.h | 6 + src/qemu_driver.c | 82 +++++++++++++++------ src/remote_internal.c | 29 ++++--- 18 files changed, 366 insertions(+), 118 deletions(-) diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c --- a/examples/domain-events/events-c/event-test.c +++ b/examples/domain-events/events-c/event-test.c @@ -35,9 +35,9 @@ void *t_opaque = NULL; /* Prototypes */ const char *eventToString(int event); int myDomainEventCallback1 (virConnectPtr conn, virDomainPtr dom, - int event, void *opaque); + int event, int detail, void *opaque); int myDomainEventCallback2 (virConnectPtr conn, virDomainPtr dom, - int event, void *opaque); + int event, int detail, void *opaque); int myEventAddHandleFunc (int fd, int event, virEventHandleCallback cb, void *opaque); void myEventUpdateHandleFunc(int fd, int event); @@ -58,11 +58,11 @@ const char *eventToString(int event) { const char *eventToString(int event) { const char *ret = NULL; switch(event) { - case VIR_DOMAIN_EVENT_ADDED: - ret ="Added"; + case VIR_DOMAIN_EVENT_DEFINED: + ret ="Defined"; break; - case VIR_DOMAIN_EVENT_REMOVED: - ret ="Removed"; + case VIR_DOMAIN_EVENT_UNDEFINED: + ret ="Undefined"; break; case VIR_DOMAIN_EVENT_STARTED: ret ="Started"; @@ -76,14 +76,56 @@ const char *eventToString(int event) { case VIR_DOMAIN_EVENT_STOPPED: ret ="Stopped"; break; - case VIR_DOMAIN_EVENT_SAVED: - ret ="Saved"; - break; - case VIR_DOMAIN_EVENT_RESTORED: - ret ="Restored"; - break; default: ret ="Unknown Event"; + } + return ret; +} + +static const char *eventDetailToString(int event, int detail) { + const char *ret = ""; + switch(event) { + case VIR_DOMAIN_EVENT_DEFINED: + if (detail == VIR_DOMAIN_EVENT_DEFINED_ADDED) + ret = "Added"; + else if (detail == VIR_DOMAIN_EVENT_DEFINED_UPDATED) + ret = "Updated"; + break; + case VIR_DOMAIN_EVENT_STARTED: + switch (detail) { + case VIR_DOMAIN_EVENT_STARTED_BOOTED: + ret = "Booted"; + break; + case VIR_DOMAIN_EVENT_STARTED_MIGRATED: + ret = "Migrated"; + break; + case VIR_DOMAIN_EVENT_STARTED_RESTORED: + ret = "Restored"; + break; + } + break; + case VIR_DOMAIN_EVENT_STOPPED: + switch (detail) { + case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN: + ret = "Shutdown"; + break; + case VIR_DOMAIN_EVENT_STOPPED_DESTROYED: + ret = "Destroyed"; + break; + case VIR_DOMAIN_EVENT_STOPPED_CRASHED: + ret = "Crashed"; + break; + case VIR_DOMAIN_EVENT_STOPPED_MIGRATED: + ret = "Migrated"; + break; + case VIR_DOMAIN_EVENT_STOPPED_SAVED: + ret = "Failed"; + break; + case VIR_DOMAIN_EVENT_STOPPED_FAILED: + ret = "Failed"; + break; + } + break; } return ret; } @@ -91,20 +133,24 @@ int myDomainEventCallback1 (virConnectPt int myDomainEventCallback1 (virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int event, + int detail, void *opaque ATTRIBUTE_UNUSED) { - printf("%s EVENT: Domain %s(%d) %s\n", __FUNCTION__, virDomainGetName(dom), - virDomainGetID(dom), eventToString(event)); + printf("%s EVENT: Domain %s(%d) %s %s\n", __FUNCTION__, virDomainGetName(dom), + virDomainGetID(dom), eventToString(event), + eventDetailToString(event, detail)); return 0; } int myDomainEventCallback2 (virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int event, + int detail, void *opaque ATTRIBUTE_UNUSED) { - printf("%s EVENT: Domain %s(%d) %s\n", __FUNCTION__, virDomainGetName(dom), - virDomainGetID(dom), eventToString(event)); + printf("%s EVENT: Domain %s(%d) %s %s\n", __FUNCTION__, virDomainGetName(dom), + virDomainGetID(dom), eventToString(event), + eventDetailToString(event, detail)); return 0; } diff --git a/examples/domain-events/events-python/event-test.py b/examples/domain-events/events-python/event-test.py --- a/examples/domain-events/events-python/event-test.py +++ b/examples/domain-events/events-python/event-test.py @@ -32,11 +32,11 @@ def eventToString(event): "Restored" ); return eventStrings[event]; -def myDomainEventCallback1 (conn, dom, event, opaque): - print "myDomainEventCallback1 EVENT: Domain %s(%s) %s" % (dom.name(), dom.ID(), eventToString(event)) +def myDomainEventCallback1 (conn, dom, event, detail, opaque): + print "myDomainEventCallback1 EVENT: Domain %s(%s) %s %d" % (dom.name(), dom.ID(), eventToString(event), detail) -def myDomainEventCallback2 (conn, dom, event, opaque): - print "myDomainEventCallback2 EVENT: Domain %s(%s) %s" % (dom.name(), dom.ID(), eventToString(event)) +def myDomainEventCallback2 (conn, dom, event, detail, opaque): + print "myDomainEventCallback2 EVENT: Domain %s(%s) %s %d" % (dom.name(), dom.ID(), eventToString(event), detail) ##################################################### # EventImpl Functions diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -1004,21 +1004,41 @@ virDomainPtr virDomainCreateL * a virDomainEventType is emitted during domain lifecycle events */ typedef enum { - VIR_DOMAIN_EVENT_ADDED = 0, - VIR_DOMAIN_EVENT_REMOVED = 1, + VIR_DOMAIN_EVENT_DEFINED = 0, + VIR_DOMAIN_EVENT_UNDEFINED = 1, VIR_DOMAIN_EVENT_STARTED = 2, VIR_DOMAIN_EVENT_SUSPENDED = 3, VIR_DOMAIN_EVENT_RESUMED = 4, VIR_DOMAIN_EVENT_STOPPED = 5, - VIR_DOMAIN_EVENT_SAVED = 6, - VIR_DOMAIN_EVENT_RESTORED = 7, } virDomainEventType; + +typedef enum { + VIR_DOMAIN_EVENT_STARTED_BOOTED = 0, /* Normal startup from boot */ + VIR_DOMAIN_EVENT_STARTED_MIGRATED = 1, /* Incoming migration from another host */ + VIR_DOMAIN_EVENT_STARTED_RESTORED = 2, /* Restored from a state file */ +} virDomainEventStartedDetailType; + +typedef enum { + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN = 0, /* Normal shutdown */ + VIR_DOMAIN_EVENT_STOPPED_DESTROYED = 1, /* Forced poweroff from host */ + VIR_DOMAIN_EVENT_STOPPED_CRASHED = 2, /* Guest crashed */ + VIR_DOMAIN_EVENT_STOPPED_MIGRATED = 3, /* Migrated off to another host */ + VIR_DOMAIN_EVENT_STOPPED_SAVED = 4, /* Saved to a state file */ + VIR_DOMAIN_EVENT_STOPPED_FAILED = 5, /* Host emulator/mgmt failed */ +} virDomainEventStoppedDetailType; + +typedef enum { + VIR_DOMAIN_EVENT_DEFINED_ADDED = 0, /* Newly created config file */ + VIR_DOMAIN_EVENT_DEFINED_UPDATED = 1, /* Changed config file */ +} virDomainEventDefinedDetailType; + /** * virConnectDomainEventCallback: * @conn: virConnect connection * @dom: The domain on which the event occured * @event: The specfic virDomainEventType which occured + * @detail: event specific detail information * @opaque: opaque user data * * A callback function to be registered, and called when a domain event occurs @@ -1026,6 +1046,7 @@ typedef int (*virConnectDomainEventCallb typedef int (*virConnectDomainEventCallback)(virConnectPtr conn, virDomainPtr dom, int event, + int detail, void *opaque); int virConnectDomainEventRegister(virConnectPtr conn, diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1004,21 +1004,41 @@ virDomainPtr virDomainCreateL * a virDomainEventType is emitted during domain lifecycle events */ typedef enum { - VIR_DOMAIN_EVENT_ADDED = 0, - VIR_DOMAIN_EVENT_REMOVED = 1, + VIR_DOMAIN_EVENT_DEFINED = 0, + VIR_DOMAIN_EVENT_UNDEFINED = 1, VIR_DOMAIN_EVENT_STARTED = 2, VIR_DOMAIN_EVENT_SUSPENDED = 3, VIR_DOMAIN_EVENT_RESUMED = 4, VIR_DOMAIN_EVENT_STOPPED = 5, - VIR_DOMAIN_EVENT_SAVED = 6, - VIR_DOMAIN_EVENT_RESTORED = 7, } virDomainEventType; + +typedef enum { + VIR_DOMAIN_EVENT_STARTED_BOOTED = 0, /* Normal startup from boot */ + VIR_DOMAIN_EVENT_STARTED_MIGRATED = 1, /* Incoming migration from another host */ + VIR_DOMAIN_EVENT_STARTED_RESTORED = 2, /* Restored from a state file */ +} virDomainEventStartedDetailType; + +typedef enum { + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN = 0, /* Normal shutdown */ + VIR_DOMAIN_EVENT_STOPPED_DESTROYED = 1, /* Forced poweroff from host */ + VIR_DOMAIN_EVENT_STOPPED_CRASHED = 2, /* Guest crashed */ + VIR_DOMAIN_EVENT_STOPPED_MIGRATED = 3, /* Migrated off to another host */ + VIR_DOMAIN_EVENT_STOPPED_SAVED = 4, /* Saved to a state file */ + VIR_DOMAIN_EVENT_STOPPED_FAILED = 5, /* Host emulator/mgmt failed */ +} virDomainEventStoppedDetailType; + +typedef enum { + VIR_DOMAIN_EVENT_DEFINED_ADDED = 0, /* Newly created config file */ + VIR_DOMAIN_EVENT_DEFINED_UPDATED = 1, /* Changed config file */ +} virDomainEventDefinedDetailType; + /** * virConnectDomainEventCallback: * @conn: virConnect connection * @dom: The domain on which the event occured * @event: The specfic virDomainEventType which occured + * @detail: event specific detail information * @opaque: opaque user data * * A callback function to be registered, and called when a domain event occurs @@ -1026,6 +1046,7 @@ typedef int (*virConnectDomainEventCallb typedef int (*virConnectDomainEventCallback)(virConnectPtr conn, virDomainPtr dom, int event, + int detail, void *opaque); int virConnectDomainEventRegister(virConnectPtr conn, diff --git a/python/libvir.c b/python/libvir.c --- a/python/libvir.c +++ b/python/libvir.c @@ -1538,6 +1538,7 @@ libvirt_virConnectDomainEventCallback(vi libvirt_virConnectDomainEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int event, + int detail, void *opaque) { PyObject *pyobj_ret; @@ -1595,9 +1596,10 @@ libvirt_virConnectDomainEventCallback(vi /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn_inst, (char*)"dispatchDomainEventCallbacks", - (char*)"Oi", + (char*)"Oii", pyobj_dom_inst, - event); + event, + detail); Py_DECREF(pyobj_dom_inst); diff --git a/qemud/qemud.h b/qemud/qemud.h --- a/qemud/qemud.h +++ b/qemud/qemud.h @@ -190,6 +190,7 @@ int remoteRelayDomainEvent (virConnectPt int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int event, + int detail, void *opaque); #endif diff --git a/qemud/remote.c b/qemud/remote.c --- a/qemud/remote.c +++ b/qemud/remote.c @@ -80,7 +80,8 @@ static void static void remoteDispatchDomainEventSend (struct qemud_client *client, virDomainPtr dom, - virDomainEventType event); + int event, + int detail); /* This function gets called from qemud when it detects an incoming * remote protocol message. At this point, client->buffer contains @@ -413,15 +414,16 @@ remoteDispatchError (struct qemud_client } int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int event, - void *opaque) + virDomainPtr dom, + int event, + int detail, + void *opaque) { struct qemud_client *client = opaque; - REMOTE_DEBUG("Relaying domain event %d", event); + REMOTE_DEBUG("Relaying domain event %d %d", event, detail); if(client) { - remoteDispatchDomainEventSend (client, dom, event); + remoteDispatchDomainEventSend (client, dom, event, detail); qemudDispatchClientWrite(client->server,client); } return 0; @@ -3762,8 +3764,9 @@ remoteDispatchDomainEventsDeregister (st static void remoteDispatchDomainEventSend (struct qemud_client *client, - virDomainPtr dom, - virDomainEventType event) + virDomainPtr dom, + int event, + int detail) { remote_message_header rep; XDR xdr; @@ -3799,7 +3802,8 @@ remoteDispatchDomainEventSend (struct qe /* build return data */ make_nonnull_domain (&data.dom, dom); - data.event = (int) event; + data.event = event; + data.detail = detail; if (!xdr_remote_domain_event_ret(&xdr, &data)) { remoteDispatchError (client, NULL, "%s", _("serialise return struct")); diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c --- a/qemud/remote_protocol.c +++ b/qemud/remote_protocol.c @@ -2024,6 +2024,8 @@ xdr_remote_domain_event_ret (XDR *xdrs, return FALSE; if (!xdr_int (xdrs, &objp->event)) return FALSE; + if (!xdr_int (xdrs, &objp->detail)) + return FALSE; return TRUE; } diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h --- a/qemud/remote_protocol.h +++ b/qemud/remote_protocol.h @@ -1130,6 +1130,7 @@ struct remote_domain_event_ret { struct remote_domain_event_ret { remote_nonnull_domain dom; int event; + int detail; }; typedef struct remote_domain_event_ret remote_domain_event_ret; #define REMOTE_PROGRAM 0x20008086 diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x --- a/qemud/remote_protocol.x +++ b/qemud/remote_protocol.x @@ -1007,6 +1007,7 @@ struct remote_domain_event_ret { struct remote_domain_event_ret { remote_nonnull_domain dom; int event; + int detail; }; /*----- Protocol. -----*/ diff --git a/src/domain_event.c b/src/domain_event.c --- a/src/domain_event.c +++ b/src/domain_event.c @@ -198,7 +198,8 @@ int int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, virDomainPtr dom, - virDomainEventType event) + int event, + int detail) { virDomainEventPtr domEvent; @@ -214,6 +215,7 @@ virDomainEventCallbackQueuePush(virDomai } domEvent->dom = dom; domEvent->event = event; + domEvent->detail = detail; /* Make space on queue */ if (VIR_REALLOC_N(evtQueue->events, diff --git a/src/domain_event.h b/src/domain_event.h --- a/src/domain_event.h +++ b/src/domain_event.h @@ -58,7 +58,8 @@ int virDomainEventCallbackListRemove(vir */ struct _virDomainEvent { virDomainPtr dom; - virDomainEventType event; + int event; + int detail; }; typedef struct _virDomainEvent virDomainEvent; typedef virDomainEvent *virDomainEventPtr; @@ -72,7 +73,8 @@ typedef virDomainEventQueue *virDomainEv int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, virDomainPtr dom, - virDomainEventType event); + int event, + int detail); virDomainEventPtr virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue); diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -107,7 +107,8 @@ static int qemudSetNonBlock(int fd) { static void qemudDomainEventDispatch (struct qemud_driver *driver, virDomainObjPtr vm, - virDomainEventType evt); + int event, + int detail); static void qemudDispatchVMEvent(int fd, int events, @@ -137,13 +138,19 @@ qemudAutostartConfigs(struct qemud_drive unsigned int i; for (i = 0 ; i < driver->domains.count ; i++) { - if (driver->domains.objs[i]->autostart && - !virDomainIsActive(driver->domains.objs[i]) && - qemudStartVMDaemon(NULL, driver, driver->domains.objs[i], NULL) < 0) { - virErrorPtr err = virGetLastError(); - qemudLog(QEMUD_ERR, _("Failed to autostart VM '%s': %s\n"), - driver->domains.objs[i]->def->name, - err ? err->message : NULL); + virDomainObjPtr vm = driver->domains.objs[i]; + if (vm->autostart && + !virDomainIsActive(vm)) { + int ret = qemudStartVMDaemon(NULL, driver, vm, NULL); + if (ret < 0) { + virErrorPtr err = virGetLastError(); + qemudLog(QEMUD_ERR, _("Failed to autostart VM '%s': %s\n"), + vm->def->name, + err ? err->message : NULL); + } else { + qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + } } } } @@ -945,7 +952,6 @@ static int qemudStartVMDaemon(virConnect qemudShutdownVMDaemon(conn, driver, vm); return -1; } - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED); } return ret; @@ -1030,6 +1036,9 @@ static int qemudDispatchVMLog(struct qem static int qemudDispatchVMLog(struct qemud_driver *driver, virDomainObjPtr vm, int fd) { if (qemudVMData(driver, vm, fd) < 0) { qemudShutdownVMDaemon(NULL, driver, vm); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_FAILED); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); @@ -1040,7 +1049,9 @@ static int qemudDispatchVMFailure(struct static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr vm, int fd ATTRIBUTE_UNUSED) { qemudShutdownVMDaemon(NULL, driver, vm); - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STOPPED); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); @@ -1513,6 +1524,9 @@ static virDomainPtr qemudDomainCreate(vi vm); return NULL; } + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1543,7 +1557,7 @@ static int qemudDomainSuspend(virDomainP } vm->state = VIR_DOMAIN_PAUSED; qemudDebug("Reply %s", info); - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_SUSPENDED); + qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_SUSPENDED, 0); VIR_FREE(info); return 0; } @@ -1572,7 +1586,7 @@ static int qemudDomainResume(virDomainPt } vm->state = VIR_DOMAIN_RUNNING; qemudDebug("Reply %s", info); - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_RESUMED); + qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_RESUMED, 0); VIR_FREE(info); return 0; } @@ -1611,7 +1625,9 @@ static int qemudDomainDestroy(virDomainP } qemudShutdownVMDaemon(dom->conn, driver, vm); - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STOPPED); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_DESTROYED); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); @@ -1942,10 +1958,12 @@ static int qemudDomainSave(virDomainPtr /* Shut it down */ qemudShutdownVMDaemon(dom->conn, driver, vm); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_SAVED); return 0; } @@ -2240,6 +2258,10 @@ static int qemudDomainRestore(virConnect return -1; } + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_RESTORED); + /* If it was running before, resume it now. */ if (header.was_running) { char *info; @@ -2252,7 +2274,6 @@ static int qemudDomainRestore(virConnect vm->state = VIR_DOMAIN_RUNNING; } - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_RESTORED); return 0; } @@ -2312,6 +2333,7 @@ static int qemudDomainStart(virDomainPtr static int qemudDomainStart(virDomainPtr dom) { struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + int ret; if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2319,7 +2341,13 @@ static int qemudDomainStart(virDomainPtr return -1; } - return qemudStartVMDaemon(dom->conn, driver, vm, NULL); + ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL); + if (ret < 0) + return ret; + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + return 0; } @@ -3340,7 +3368,8 @@ qemudDomainEventDeregister (virConnectPt static void qemudDomainEventDispatch (struct qemud_driver *driver, virDomainObjPtr vm, - virDomainEventType evt) + int event, + int detail) { int i; virDomainEventCallbackListPtr cbList; @@ -3354,11 +3383,11 @@ static void qemudDomainEventDispatch (st vm->def->uuid); if (dom) { dom->id = virDomainIsActive(vm) ? vm->def->id : -1; - DEBUG("Dispatching callback %p %p event %d", - cbList->callbacks[i], - cbList->callbacks[i]->cb, evt); + DEBUG("Dispatching callback %p %p event %d detail %d", + cbList->callbacks[i], + cbList->callbacks[i]->cb, event, detail); cbList->callbacks[i]->cb(cbList->callbacks[i]->conn, - dom, evt, + dom, event, detail, cbList->callbacks[i]->opaque); virDomainFree(dom); } @@ -3507,6 +3536,9 @@ qemudDomainMigratePrepare2 (virConnectPt return -1; } + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_MIGRATED); return 0; } @@ -3578,6 +3610,9 @@ qemudDomainMigratePerform (virDomainPtr /* Clean up the source domain. */ qemudShutdownVMDaemon (dom->conn, driver, vm); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_MIGRATED); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); @@ -3612,9 +3647,14 @@ qemudDomainMigrateFinish2 (virConnectPtr dom = virGetDomain (dconn, vm->def->name, vm->def->uuid); VIR_FREE(info); vm->state = VIR_DOMAIN_RUNNING; + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_RESUMED, 0); return dom; } else { qemudShutdownVMDaemon (dconn, driver, vm); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_FAILED); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); return NULL; diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -5154,7 +5154,7 @@ remoteRegister (void) */ static int remoteDomainReadEvent(virConnectPtr conn, XDR *xdr, - virDomainPtr *dom, int *event) + virDomainPtr *dom, int *event, int *detail) { remote_domain_event_ret ret; memset (&ret, 0, sizeof ret); @@ -5168,6 +5168,7 @@ remoteDomainReadEvent(virConnectPtr conn *dom = get_nonnull_domain(conn,ret.dom); *event = ret.event; + *detail = ret.detail; return 0; } @@ -5176,15 +5177,16 @@ remoteDomainProcessEvent(virConnectPtr c remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr) { virDomainPtr dom; - int event,i; - struct private_data *priv = conn->privateData; - - if(!remoteDomainReadEvent(conn, xdr, &dom, &event)) { + int event, detail, i; + struct private_data *priv = conn->privateData; + + if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) { DEBUG0("Calling domain event callbacks (no queue)"); for(i=0 ; i < priv->callbackList->count ; i++) { - if( priv->callbackList->callbacks[i] ) - priv->callbackList->callbacks[i]->cb(conn, dom, event, - priv->callbackList->callbacks[i]->opaque); + if (priv->callbackList->callbacks[i] ) + priv->callbackList->callbacks[i]->cb( + conn, dom, event, detail, + priv->callbackList->callbacks[i]->opaque); } } } @@ -5193,13 +5195,13 @@ remoteDomainQueueEvent(virConnectPtr con remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr) { virDomainPtr dom; - int event; - struct private_data *priv = conn->privateData; - - if(!remoteDomainReadEvent(conn, xdr, &dom, &event)) + int event, detail; + struct private_data *priv = conn->privateData; + + if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) { if( virDomainEventCallbackQueuePush(priv->domainEvents, - dom, event) < 0 ) { + dom, event, detail) < 0 ) { DEBUG("%s", "Error adding event to queue"); } } @@ -5292,6 +5294,7 @@ remoteDomainEventQueueFlush(int timer AT priv->callbackList->callbacks[i]->cb(domEvent->dom->conn, domEvent->dom, domEvent->event, + domEvent->detail, user_data); } } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list