* 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