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