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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list