Looks pretty much exactly how I pictured it
+1
Daniel P. Berrange wrote on 11/14/2008 12:44 PM:
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);
}
}