Any thoughts on this patch.. Regards, Daniel On Mon, Jul 04, 2011 at 01:32:23PM +0100, Daniel P. Berrange wrote: > * src/uml_conf.h: Add queue for dispatch of domain events > * src/uml_driver.c: Trigger domain events upon important lifecycle transitions > --- > src/uml/uml_conf.h | 4 + > src/uml/uml_driver.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 194 insertions(+), 4 deletions(-) > > diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h > index 1105f84..5401a7e 100644 > --- a/src/uml/uml_conf.h > +++ b/src/uml/uml_conf.h > @@ -29,6 +29,7 @@ > # include "capabilities.h" > # include "network_conf.h" > # include "domain_conf.h" > +# include "domain_event.h" > # include "virterror_internal.h" > # include "threads.h" > # include "command.h" > @@ -60,6 +61,9 @@ struct uml_driver { > int inotifyWatch; > > virCapsPtr caps; > + > + /* Event handling */ > + virDomainEventStatePtr domainEventState; > }; > > > diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c > index 91591f1..d0736df 100644 > --- a/src/uml/uml_driver.c > +++ b/src/uml/uml_driver.c > @@ -113,6 +113,9 @@ static int umlOpenMonitor(struct uml_driver *driver, > virDomainObjPtr vm); > static int umlReadPidFile(struct uml_driver *driver, > virDomainObjPtr vm); > +static void umlDomainEventFlush(int timer, void *opaque); > +static void umlDomainEventQueue(struct uml_driver *driver, > + virDomainEventPtr event); > > static int umlSetCloseExec(int fd) { > int flags; > @@ -166,6 +169,13 @@ umlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaqu > virErrorPtr err = virGetLastError(); > VIR_ERROR(_("Failed to autostart VM '%s': %s"), > vm->def->name, err ? err->message : _("unknown error")); > + } else { > + virDomainEventPtr event = > + virDomainEventNewFromObj(vm, > + VIR_DOMAIN_EVENT_STARTED, > + VIR_DOMAIN_EVENT_STARTED_BOOTED); > + if (event) > + umlDomainEventQueue(data->driver, event); > } > } > virDomainObjUnlock(vm); > @@ -185,7 +195,9 @@ umlAutostartConfigs(struct uml_driver *driver) { > > struct umlAutostartData data = { driver, conn }; > > + umlDriverLock(driver); > virHashForEach(driver->domains.objs, umlAutostartDomain, &data); > + umlDriverUnlock(driver); > > if (conn) > virConnectClose(conn); > @@ -266,6 +278,7 @@ umlInotifyEvent(int watch, > char *tmp, *name; > struct uml_driver *driver = data; > virDomainObjPtr dom; > + virDomainEventPtr event = NULL; > > umlDriverLock(driver); > if (watch != driver->inotifyWatch) > @@ -311,6 +324,9 @@ reread: > > umlShutdownVMDaemon(NULL, driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN); > virDomainAuditStop(dom, "shutdown"); > + event = virDomainEventNewFromObj(dom, > + VIR_DOMAIN_EVENT_STOPPED, > + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); > if (!dom->persistent) { > virDomainRemoveInactive(&driver->domains, > dom); > @@ -337,6 +353,9 @@ reread: > umlShutdownVMDaemon(NULL, driver, dom, > VIR_DOMAIN_SHUTOFF_FAILED); > virDomainAuditStop(dom, "failed"); > + event = virDomainEventNewFromObj(dom, > + VIR_DOMAIN_EVENT_STOPPED, > + VIR_DOMAIN_EVENT_STOPPED_FAILED); > if (!dom->persistent) { > virDomainRemoveInactive(&driver->domains, > dom); > @@ -347,6 +366,9 @@ reread: > umlShutdownVMDaemon(NULL, driver, dom, > VIR_DOMAIN_SHUTOFF_FAILED); > virDomainAuditStop(dom, "failed"); > + event = virDomainEventNewFromObj(dom, > + VIR_DOMAIN_EVENT_STOPPED, > + VIR_DOMAIN_EVENT_STOPPED_FAILED); > if (!dom->persistent) { > virDomainRemoveInactive(&driver->domains, > dom); > @@ -359,6 +381,8 @@ reread: > } > > cleanup: > + if (event) > + umlDomainEventQueue(driver, event); > umlDriverUnlock(driver); > } > > @@ -392,6 +416,13 @@ umlStartup(int privileged) > if (virDomainObjListInit(¨_driver->domains) < 0) > goto error; > > + uml_driver->domainEventState = virDomainEventStateNew(umlDomainEventFlush, > + uml_driver, > + NULL, > + true); > + if (!uml_driver->domainEventState) > + goto error; > + > userdir = virGetUserDirectory(uid); > if (!userdir) > goto error; > @@ -469,9 +500,10 @@ umlStartup(int privileged) > 0, NULL, NULL) < 0) > goto error; > > + umlDriverUnlock(uml_driver); > + > umlAutostartConfigs(uml_driver); > > - umlDriverUnlock(uml_driver); > VIR_FREE(userdir); > > return 0; > @@ -487,6 +519,21 @@ error: > return -1; > } > > +static void umlNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque) > +{ > + struct uml_driver *driver = opaque; > + > + if (newVM) { > + virDomainEventPtr event = > + virDomainEventNewFromObj(vm, > + VIR_DOMAIN_EVENT_DEFINED, > + VIR_DOMAIN_EVENT_DEFINED_ADDED); > + if (event) > + umlDomainEventQueue(driver, event); > + } > +} > + > + > /** > * umlReload: > * > @@ -503,10 +550,10 @@ umlReload(void) { > ¨_driver->domains, > uml_driver->configDir, > uml_driver->autostartDir, > - 0, NULL, NULL); > + 0, umlNotifyLoadDomain, uml_driver); > + umlDriverUnlock(uml_driver); > > umlAutostartConfigs(uml_driver); > - umlDriverUnlock(uml_driver); > > return 0; > } > @@ -569,6 +616,8 @@ umlShutdown(void) { > > virDomainObjListDeinit(¨_driver->domains); > > + virDomainEventStateFree(uml_driver->domainEventState); > + > VIR_FREE(uml_driver->logDir); > VIR_FREE(uml_driver->configDir); > VIR_FREE(uml_driver->autostartDir); > @@ -929,6 +978,7 @@ cleanup: > /* XXX what if someone else tries to start it again > before we get the inotification ? Sounds like > trouble.... */ > + /* XXX this is bad for events too. must fix this better */ > > return ret; > } > @@ -1025,7 +1075,12 @@ static virDrvOpenStatus umlOpen(virConnectPtr conn, > } > > static int umlClose(virConnectPtr conn) { > - /*struct uml_driver *driver = conn->privateData;*/ > + struct uml_driver *driver = conn->privateData; > + > + umlDriverLock(driver); > + virDomainEventCallbackListRemoveConn(conn, > + driver->domainEventState->callbacks); > + umlDriverUnlock(driver); > > conn->privateData = NULL; > > @@ -1293,6 +1348,7 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml, > virDomainDefPtr def; > virDomainObjPtr vm = NULL; > virDomainPtr dom = NULL; > + virDomainEventPtr event = NULL; > > virCheckFlags(0, NULL); > > @@ -1318,6 +1374,9 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml, > goto cleanup; > } > virDomainAuditStart(vm, "booted", true); > + event = virDomainEventNewFromObj(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; > @@ -1326,6 +1385,8 @@ cleanup: > virDomainDefFree(def); > if (vm) > virDomainObjUnlock(vm); > + if (event) > + umlDomainEventQueue(driver, event); > umlDriverUnlock(driver); > return dom; > } > @@ -1366,6 +1427,7 @@ cleanup: > static int umlDomainDestroy(virDomainPtr dom) { > struct uml_driver *driver = dom->conn->privateData; > virDomainObjPtr vm; > + virDomainEventPtr event = NULL; > int ret = -1; > > umlDriverLock(driver); > @@ -1378,6 +1440,9 @@ static int umlDomainDestroy(virDomainPtr dom) { > > umlShutdownVMDaemon(dom->conn, driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED); > virDomainAuditStop(vm, "destroyed"); > + event = virDomainEventNewFromObj(vm, > + VIR_DOMAIN_EVENT_STOPPED, > + VIR_DOMAIN_EVENT_STOPPED_DESTROYED); > if (!vm->persistent) { > virDomainRemoveInactive(&driver->domains, > vm); > @@ -1388,6 +1453,8 @@ static int umlDomainDestroy(virDomainPtr dom) { > cleanup: > if (vm) > virDomainObjUnlock(vm); > + if (event) > + umlDomainEventQueue(driver, event); > umlDriverUnlock(driver); > return ret; > } > @@ -1640,6 +1707,7 @@ static int umlNumDefinedDomains(virConnectPtr conn) { > static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int flags) { > struct uml_driver *driver = dom->conn->privateData; > virDomainObjPtr vm; > + virDomainEventPtr event = NULL; > int ret = -1; > > virCheckFlags(0, -1); > @@ -1655,10 +1723,16 @@ static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int flags) { > > ret = umlStartVMDaemon(dom->conn, driver, vm); > virDomainAuditStart(vm, "booted", ret >= 0); > + if (ret == 0) > + event = virDomainEventNewFromObj(vm, > + VIR_DOMAIN_EVENT_STARTED, > + VIR_DOMAIN_EVENT_STARTED_BOOTED); > > cleanup: > if (vm) > virDomainObjUnlock(vm); > + if (event) > + umlDomainEventQueue(driver, event); > umlDriverUnlock(driver); > return ret; > } > @@ -2208,6 +2282,114 @@ cleanup: > } > > > +static int > +umlDomainEventRegister(virConnectPtr conn, > + virConnectDomainEventCallback callback, > + void *opaque, > + virFreeCallback freecb) > +{ > + struct uml_driver *driver = conn->privateData; > + int ret; > + > + umlDriverLock(driver); > + ret = virDomainEventCallbackListAdd(conn, > + driver->domainEventState->callbacks, > + callback, opaque, freecb); > + umlDriverUnlock(driver); > + > + return ret; > +} > + > +static int > +umlDomainEventDeregister(virConnectPtr conn, > + virConnectDomainEventCallback callback) > +{ > + struct uml_driver *driver = conn->privateData; > + int ret; > + > + umlDriverLock(driver); > + ret = virDomainEventStateDeregister(conn, > + driver->domainEventState, > + callback); > + umlDriverUnlock(driver); > + > + return ret; > +} > +static int > +umlDomainEventRegisterAny(virConnectPtr conn, > + virDomainPtr dom, > + int eventID, > + virConnectDomainEventGenericCallback callback, > + void *opaque, > + virFreeCallback freecb) > +{ > + struct uml_driver *driver = conn->privateData; > + int ret; > + > + umlDriverLock(driver); > + ret = virDomainEventCallbackListAddID(conn, > + driver->domainEventState->callbacks, > + dom, eventID, > + callback, opaque, freecb); > + umlDriverUnlock(driver); > + > + return ret; > +} > + > + > +static int > +umlDomainEventDeregisterAny(virConnectPtr conn, > + int callbackID) > +{ > + struct uml_driver *driver = conn->privateData; > + int ret; > + > + umlDriverLock(driver); > + ret = virDomainEventStateDeregisterAny(conn, > + driver->domainEventState, > + callbackID); > + umlDriverUnlock(driver); > + > + return ret; > +} > + > + > +static void umlDomainEventDispatchFunc(virConnectPtr conn, > + virDomainEventPtr event, > + virConnectDomainEventGenericCallback cb, > + void *cbopaque, > + void *opaque) > +{ > + struct uml_driver *driver = opaque; > + > + /* Drop the lock whle dispatching, for sake of re-entrancy */ > + umlDriverUnlock(driver); > + virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL); > + umlDriverLock(driver); > +} > + > + > +static void umlDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque) > +{ > + struct uml_driver *driver = opaque; > + > + umlDriverLock(driver); > + virDomainEventStateFlush(driver->domainEventState, > + umlDomainEventDispatchFunc, > + driver); > + umlDriverUnlock(driver); > +} > + > + > +/* driver must be locked before calling */ > +static void umlDomainEventQueue(struct uml_driver *driver, > + virDomainEventPtr event) > +{ > + virDomainEventStateQueue(driver->domainEventState, event); > +} > + > + > + > static virDriver umlDriver = { > .no = VIR_DRV_UML, > .name = "UML", > @@ -2250,11 +2432,15 @@ static virDriver umlDriver = { > .nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.3 */ > .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.5.0 */ > .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.5.0 */ > + .domainEventRegister = umlDomainEventRegister, /* 0.9.4 */ > + .domainEventDeregister = umlDomainEventDeregister, /* 0.9.4 */ > .isEncrypted = umlIsEncrypted, /* 0.7.3 */ > .isSecure = umlIsSecure, /* 0.7.3 */ > .domainIsActive = umlDomainIsActive, /* 0.7.3 */ > .domainIsPersistent = umlDomainIsPersistent, /* 0.7.3 */ > .domainIsUpdated = umlDomainIsUpdated, /* 0.8.6 */ > + .domainEventRegisterAny = umlDomainEventRegisterAny, /* 0.9.4 */ > + .domainEventDeregisterAny = umlDomainEventDeregisterAny, /* 0.9.4 */ > .domainOpenConsole = umlDomainOpenConsole, /* 0.8.6 */ > }; > > -- > 1.7.4.4 > -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list