[libvirt] Re: [PATCH 06/12] Domain Events - qemu driver
Daniel P. Berrange
berrange at redhat.com
Sun Oct 19 19:35:26 UTC 2008
On Fri, Oct 17, 2008 at 12:02:52PM -0400, Ben Guthro wrote:
> Register for, and dispatch domain event callbacks
>
> qemu_conf.h | 3 ++
> qemu_driver.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 77 insertions(+), 2 deletions(-)
> diff --git a/src/qemu_conf.h b/src/qemu_conf.h
> index cfd7d35..d06c4d7 100644
> --- a/src/qemu_conf.h
> +++ b/src/qemu_conf.h
> @@ -63,6 +63,9 @@ struct qemud_driver {
> char *vncListen;
>
> virCapsPtr caps;
> +
> + /* An array of callbacks */
> + virDomainEventCallbackListPtr domainEventCallbacks;
> };
>
>
> diff --git a/src/qemu_driver.c b/src/qemu_driver.c
> index a86b787..9792541 100644
> --- a/src/qemu_driver.c
> +++ b/src/qemu_driver.c
> @@ -159,6 +159,10 @@ qemudStartup(void) {
> /* Don't have a dom0 so start from 1 */
> qemu_driver->nextvmid = 1;
>
> + /* Init callback list */
> + if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
> + return -1;
> +
> if (!uid) {
> if (asprintf(&qemu_driver->logDir,
> "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
> @@ -301,6 +305,9 @@ qemudShutdown(void) {
> VIR_FREE(qemu_driver->autostartDir);
> VIR_FREE(qemu_driver->vncTLSx509certdir);
>
> + /* Free domain callback list */
> + virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
> +
> if (qemu_driver->brctl)
> brShutdown(qemu_driver->brctl);
>
> @@ -742,6 +749,8 @@ static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
> return -1;
> }
>
> +static virDomainPtr qemudDomainLookupByName(virConnectPtr conn, const char *name);
> +
> static int qemudStartVMDaemon(virConnectPtr conn,
> struct qemud_driver *driver,
> virDomainObjPtr vm,
> @@ -756,6 +765,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
> unsigned int qemuCmdFlags;
> fd_set keepfd;
> const char *emulator;
> + virDomainPtr dom;
>
> FD_ZERO(&keepfd);
>
> @@ -918,6 +928,11 @@ static int qemudStartVMDaemon(virConnectPtr conn,
> qemudShutdownVMDaemon(conn, driver, vm);
> return -1;
> }
> + dom = qemudDomainLookupByName(conn,vm->def->name);
> + if(dom)
> + virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_STARTED);
> + else
> + DEBUG0("Warning - dom is NULL at domain start");
> }
>
> return ret;
> @@ -1503,6 +1518,7 @@ static int qemudDomainSuspend(virDomainPtr dom) {
> }
> vm->state = VIR_DOMAIN_PAUSED;
> qemudDebug("Reply %s", info);
> + virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_SUSPENDED);
> VIR_FREE(info);
> return 0;
> }
> @@ -1531,6 +1547,7 @@ static int qemudDomainResume(virDomainPtr dom) {
> }
> vm->state = VIR_DOMAIN_RUNNING;
> qemudDebug("Reply %s", info);
> + virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_RESUMED);
> VIR_FREE(info);
> return 0;
> }
> @@ -1572,7 +1589,7 @@ static int qemudDomainDestroy(virDomainPtr dom) {
> if (!vm->persistent)
> virDomainRemoveInactive(&driver->domains,
> vm);
> -
> + virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_STOPPED);
> return 0;
> }
>
> @@ -1903,7 +1920,7 @@ static int qemudDomainSave(virDomainPtr dom,
> if (!vm->persistent)
> virDomainRemoveInactive(&driver->domains,
> vm);
> -
> + virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_SAVED);
> return 0;
> }
>
> @@ -2104,6 +2121,7 @@ static int qemudDomainRestore(virConnectPtr conn,
> struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
> virDomainDefPtr def;
> virDomainObjPtr vm;
> + virDomainPtr dom;
> int fd;
> int ret;
> char *xml;
> @@ -2210,6 +2228,11 @@ static int qemudDomainRestore(virConnectPtr conn,
> vm->state = VIR_DOMAIN_RUNNING;
> }
>
> + dom = virDomainLookupByID(conn, def->id);
> + if(dom) {
> + virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_RESTORED);
> + VIR_FREE(dom);
> + }
> return 0;
> }
>
> @@ -3051,6 +3074,52 @@ done:
> }
>
>
> +static int qemudDomainEventRegister (virConnectPtr conn,
> + void *callback,
> + void *opaque)
> +{
> + struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
> +
> + return virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, callback, opaque);
> +}
> +
> +static int qemudDomainEventDeregister (virConnectPtr conn,
> + void *callback)
> +{
> + struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
> +
> + return virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, callback);
> +}
> +
> +static void qemudDomainEventDispatch (virDomainPtr dom,
> + virDomainEventType evt)
> +{
> + int i;
> + struct qemud_driver *driver;
> + virDomainEventCallbackListPtr cbList;
> +
> + if(!dom->conn) {
> + DEBUG0("Invalid conn");
> + return;
> + }
> + driver = (struct qemud_driver *)dom->conn->privateData;
> +
> + if(!driver) {
> + DEBUG0("Invalid driver");
> + return;
> + }
> + cbList = driver->domainEventCallbacks;
> +
> + for(i=0;i<cbList->count;i++) {
> + if(cbList->callbacks[i] && cbList->callbacks[i]->cb)
> + DEBUG("Dispatching callback %p %p event %d", cbList->callbacks[i], cbList->callbacks[i]->cb, evt);
> + cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
> + dom, evt,
> + cbList->callbacks[i]->opaque);
> + }
> +
> +}
THis all basically works fine, but there's one tiny missing bit. If
a domain shuts down from an external trigger - eg guest admin does a
'shutdown -h', or host admin does 'kill -TERM $qemu', then no STOPPED
event is fired. For this we need to hook into the qemudDispatchVMFailure()
method.
This introduces a small problem though - we don't have a 'virDomainPtr'
object here, so we can't call the generic virDispatchDomainEvent()
method. Of course virDispatchDomainEvent() just delegates back into
the driver - in this case qemudDomainEventDispatch(), which has no
hard requirement to have a 'virDomainPtr' object. Each registered
callback has a 'virConnectPtr' object associated with it, so we can
simply fetch a virDomainPtr as required.
To demonstrate this I'm attching a patch which applies ontop of yours
to make this method call directly. With this, I think we can remove
the 'domainEventDispatch' field in driver.h - though obviously the
other non-QEMU drivers need changing to match too.
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -105,6 +105,10 @@ static int qemudSetNonBlock(int fd) {
return -1;
}
+
+static void qemudDomainEventDispatch (struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainEventType evt);
static void qemudDispatchVMEvent(int fd, int events, void *opaque);
static int qemudStartVMDaemon(virConnectPtr conn,
@@ -930,7 +934,7 @@ static int qemudStartVMDaemon(virConnect
}
dom = qemudDomainLookupByName(conn,vm->def->name);
if(dom)
- virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_STARTED);
+ qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED);
else
DEBUG0("Warning - dom is NULL at domain start");
}
@@ -1027,6 +1031,7 @@ 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);
if (!vm->persistent)
virDomainRemoveInactive(&driver->domains,
vm);
@@ -1518,7 +1523,7 @@ static int qemudDomainSuspend(virDomainP
}
vm->state = VIR_DOMAIN_PAUSED;
qemudDebug("Reply %s", info);
- virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_SUSPENDED);
+ qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_SUSPENDED);
VIR_FREE(info);
return 0;
}
@@ -1547,7 +1552,7 @@ static int qemudDomainResume(virDomainPt
}
vm->state = VIR_DOMAIN_RUNNING;
qemudDebug("Reply %s", info);
- virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_RESUMED);
+ qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_RESUMED);
VIR_FREE(info);
return 0;
}
@@ -1586,10 +1591,10 @@ static int qemudDomainDestroy(virDomainP
}
qemudShutdownVMDaemon(dom->conn, driver, vm);
+ qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STOPPED);
if (!vm->persistent)
virDomainRemoveInactive(&driver->domains,
vm);
- virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_STOPPED);
return 0;
}
@@ -1920,7 +1925,7 @@ static int qemudDomainSave(virDomainPtr
if (!vm->persistent)
virDomainRemoveInactive(&driver->domains,
vm);
- virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_SAVED);
+ qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_SAVED);
return 0;
}
@@ -2230,7 +2235,7 @@ static int qemudDomainRestore(virConnect
dom = virDomainLookupByID(conn, def->id);
if(dom) {
- virDispatchDomainEvent(dom, VIR_DOMAIN_EVENT_RESTORED);
+ qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_RESTORED);
VIR_FREE(dom);
}
return 0;
@@ -3090,31 +3095,28 @@ static int qemudDomainEventDeregister (v
return virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, callback);
}
-static void qemudDomainEventDispatch (virDomainPtr dom,
+static void qemudDomainEventDispatch (struct qemud_driver *driver,
+ virDomainObjPtr vm,
virDomainEventType evt)
{
int i;
- struct qemud_driver *driver;
virDomainEventCallbackListPtr cbList;
- if(!dom->conn) {
- DEBUG0("Invalid conn");
- return;
- }
- driver = (struct qemud_driver *)dom->conn->privateData;
-
- if(!driver) {
- DEBUG0("Invalid driver");
- return;
- }
cbList = driver->domainEventCallbacks;
for(i=0;i<cbList->count;i++) {
- if(cbList->callbacks[i] && cbList->callbacks[i]->cb)
- DEBUG("Dispatching callback %p %p event %d", cbList->callbacks[i], cbList->callbacks[i]->cb, evt);
- cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
- dom, evt,
- cbList->callbacks[i]->opaque);
+ if(cbList->callbacks[i] && cbList->callbacks[i]->cb) {
+ virConnectPtr conn = cbList->callbacks[i]->conn;
+ virDomainPtr dom = virGetDomain(conn, vm->def->name, 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);
+ cbList->callbacks[i]->cb(cbList->callbacks[i]->conn,
+ dom, evt,
+ cbList->callbacks[i]->opaque);
+ virDomainFree(dom);
+ }
+ }
}
}
@@ -3191,7 +3193,7 @@ static virDriver qemuDriver = {
#endif
qemudDomainEventRegister, /* domainEventRegister */
qemudDomainEventDeregister, /* domainEventDeregister */
- qemudDomainEventDispatch, /* domainEventDispatch */
+ NULL,
};
Regards,
Daniel
--
|: 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 :|
More information about the libvir-list
mailing list