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,
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);
struct umlAutostartData data = { driver, conn };
+ umlDriverLock(driver);
virHashForEach(driver->domains.objs, umlAutostartDomain, &data);
+ umlDriverUnlock(driver);
if (conn)
virConnectClose(conn);
char *tmp, *name;
struct uml_driver *driver = data;
virDomainObjPtr dom;
+ virDomainEventPtr event = NULL;
umlDriverLock(driver);
if (watch != driver->inotifyWatch)
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);
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);
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);
}
cleanup:
+ if (event)
+ umlDomainEventQueue(driver, event);
umlDriverUnlock(driver);
}
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;
NULL, NULL) < 0)
goto error;
+ umlDriverUnlock(uml_driver);
+
umlAutostartConfigs(uml_driver);
- umlDriverUnlock(uml_driver);
VIR_FREE(userdir);
return 0;
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:
*
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;
}
virDomainObjListDeinit(¨_driver->domains);
+ virDomainEventStateFree(uml_driver->domainEventState);
+
VIR_FREE(uml_driver->logDir);
VIR_FREE(uml_driver->configDir);
VIR_FREE(uml_driver->autostartDir);
/* 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;
}
}
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;
virDomainDefPtr def;
virDomainObjPtr vm = NULL;
virDomainPtr dom = NULL;
+ virDomainEventPtr event = NULL;
virCheckFlags(0, NULL);
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;
virDomainDefFree(def);
if (vm)
virDomainObjUnlock(vm);
+ if (event)
+ umlDomainEventQueue(driver, event);
umlDriverUnlock(driver);
return dom;
}
static int umlDomainDestroy(virDomainPtr dom) {
struct uml_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
+ virDomainEventPtr event = NULL;
int ret = -1;
umlDriverLock(driver);
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);
cleanup:
if (vm)
virDomainObjUnlock(vm);
+ if (event)
+ umlDomainEventQueue(driver, event);
umlDriverUnlock(driver);
return ret;
}
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);
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;
}
}
+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",
.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 */
};