Add domain events support to UML driver

* src/uml_conf.h: Add queue for dispatch of domain events
* src/uml_driver.c: Trigger domain events upon important lifecycle transitions
This commit is contained in:
Daniel P. Berrange 2009-07-06 16:06:11 +01:00
parent 71d3026077
commit cf81318cb7
2 changed files with 195 additions and 4 deletions

View File

@ -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;
};

View File

@ -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 umlStartVMDaemon(virConnectPtr conn,
struct uml_driver *driver,
@ -153,6 +156,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);
@ -172,7 +182,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);
@ -253,6 +265,7 @@ umlInotifyEvent(int watch,
char *tmp, *name;
struct uml_driver *driver = data;
virDomainObjPtr dom;
virDomainEventPtr event = NULL;
umlDriverLock(driver);
if (watch != driver->inotifyWatch)
@ -298,6 +311,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);
@ -324,6 +340,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);
@ -334,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);
@ -346,6 +368,8 @@ reread:
}
cleanup:
if (event)
umlDomainEventQueue(driver, event);
umlDriverUnlock(driver);
}
@ -379,6 +403,13 @@ umlStartup(int privileged)
if (virDomainObjListInit(&uml_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;
@ -457,9 +488,10 @@ umlStartup(int privileged)
NULL, NULL) < 0)
goto error;
umlDriverUnlock(uml_driver);
umlAutostartConfigs(uml_driver);
umlDriverUnlock(uml_driver);
VIR_FREE(userdir);
return 0;
@ -475,6 +507,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:
*
@ -492,10 +539,10 @@ umlReload(void) {
uml_driver->configDir,
uml_driver->autostartDir,
0, 1 << VIR_DOMAIN_VIRT_UML,
NULL, NULL);
umlNotifyLoadDomain, uml_driver);
umlDriverUnlock(uml_driver);
umlAutostartConfigs(uml_driver);
umlDriverUnlock(uml_driver);
return 0;
}
@ -558,6 +605,8 @@ umlShutdown(void) {
virDomainObjListDeinit(&uml_driver->domains);
virDomainEventStateFree(uml_driver->domainEventState);
VIR_FREE(uml_driver->logDir);
VIR_FREE(uml_driver->configDir);
VIR_FREE(uml_driver->autostartDir);
@ -918,6 +967,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;
}
@ -1017,7 +1067,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;
@ -1285,6 +1340,7 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
virDomainDefPtr def;
virDomainObjPtr vm = NULL;
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
virCheckFlags(0, NULL);
@ -1311,6 +1367,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;
@ -1319,6 +1378,8 @@ cleanup:
virDomainDefFree(def);
if (vm)
virDomainObjUnlock(vm);
if (event)
umlDomainEventQueue(driver, event);
umlDriverUnlock(driver);
return dom;
}
@ -1359,6 +1420,7 @@ cleanup:
static int umlDomainDestroy(virDomainPtr dom) {
struct uml_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
virDomainEventPtr event = NULL;
int ret = -1;
umlDriverLock(driver);
@ -1371,6 +1433,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);
@ -1381,6 +1446,8 @@ static int umlDomainDestroy(virDomainPtr dom) {
cleanup:
if (vm)
virDomainObjUnlock(vm);
if (event)
umlDomainEventQueue(driver, event);
umlDriverUnlock(driver);
return ret;
}
@ -1638,6 +1705,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);
@ -1653,10 +1721,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;
}
@ -2207,6 +2281,115 @@ 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",
@ -2249,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 */
};