static void lxcDomainEventQueue(lxc_driver_t *driver,
virDomainEventPtr event);
+static int lxcVmTerminate(lxc_driver_t *driver,
+ virDomainObjPtr vm,
+ virDomainShutoffReason reason);
+static int lxcProcessAutoDestroyInit(lxc_driver_t *driver);
+static void lxcProcessAutoDestroyRun(lxc_driver_t *driver,
+ virConnectPtr conn);
+static void lxcProcessAutoDestroyShutdown(lxc_driver_t *driver);
+static int lxcProcessAutoDestroyAdd(lxc_driver_t *driver,
+ virDomainObjPtr vm,
+ virConnectPtr conn);
+static int lxcProcessAutoDestroyRemove(lxc_driver_t *driver,
+ virDomainObjPtr vm);
+
static virDrvOpenStatus lxcOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
lxcDriverLock(driver);
virDomainEventCallbackListRemoveConn(conn,
driver->domainEventState->callbacks);
+ lxcProcessAutoDestroyRun(driver, conn);
lxcDriverUnlock(driver);
conn->privateData = NULL;
}
+static int lxcProcessAutoDestroyInit(lxc_driver_t *driver)
+{
+ if (!(driver->autodestroy = virHashCreate(5, NULL)))
+ return -1;
+
+ return 0;
+}
+
+struct lxcProcessAutoDestroyData {
+ lxc_driver_t *driver;
+ virConnectPtr conn;
+};
+
+static void lxcProcessAutoDestroyDom(void *payload,
+ const void *name,
+ void *opaque)
+{
+ struct lxcProcessAutoDestroyData *data = opaque;
+ virConnectPtr conn = payload;
+ const char *uuidstr = name;
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ virDomainObjPtr dom;
+ virDomainEventPtr event = NULL;
+
+ VIR_DEBUG("conn=%p uuidstr=%s thisconn=%p", conn, uuidstr, data->conn);
+
+ if (data->conn != conn)
+ return;
+
+ if (virUUIDParse(uuidstr, uuid) < 0) {
+ VIR_WARN("Failed to parse %s", uuidstr);
+ return;
+ }
+
+ if (!(dom = virDomainFindByUUID(&data->driver->domains,
+ uuid))) {
+ VIR_DEBUG("No domain object to kill");
+ return;
+ }
+
+ VIR_DEBUG("Killing domain");
+ lxcVmTerminate(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED);
+ virDomainAuditStop(dom, "destroyed");
+ event = virDomainEventNewFromObj(dom,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
+
+ if (dom && !dom->persistent)
+ virDomainRemoveInactive(&data->driver->domains, dom);
+
+ if (dom)
+ virDomainObjUnlock(dom);
+ if (event)
+ lxcDomainEventQueue(data->driver, event);
+ virHashRemoveEntry(data->driver->autodestroy, uuidstr);
+}
+
+/*
+ * Precondition: driver is locked
+ */
+static void lxcProcessAutoDestroyRun(lxc_driver_t *driver, virConnectPtr conn)
+{
+ struct lxcProcessAutoDestroyData data = {
+ driver, conn
+ };
+ VIR_DEBUG("conn=%p", conn);
+ virHashForEach(driver->autodestroy, lxcProcessAutoDestroyDom, &data);
+}
+
+static void lxcProcessAutoDestroyShutdown(lxc_driver_t *driver)
+{
+ virHashFree(driver->autodestroy);
+}
+
+static int lxcProcessAutoDestroyAdd(lxc_driver_t *driver,
+ virDomainObjPtr vm,
+ virConnectPtr conn)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ VIR_DEBUG("vm=%s uuid=%s conn=%p", vm->def->name, uuidstr, conn);
+ if (virHashAddEntry(driver->autodestroy, uuidstr, conn) < 0)
+ return -1;
+ return 0;
+}
+
+static int lxcProcessAutoDestroyRemove(lxc_driver_t *driver,
+ virDomainObjPtr vm)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr);
+ if (virHashRemoveEntry(driver->autodestroy, uuidstr) < 0)
+ return -1;
+ return 0;
+}
+
+
/**
* lxcVmCleanup:
* @driver: pointer to driver structure
VIR_FREE(xml);
}
+ /* Stop autodestroy in case guest is restarted */
+ lxcProcessAutoDestroyRemove(driver, vm);
+
virEventRemoveHandle(priv->monitorWatch);
VIR_FORCE_CLOSE(priv->monitor);
* @conn: pointer to connection
* @driver: pointer to driver structure
* @vm: pointer to virtual machine structure
+ * @autoDestroy: mark the domain for auto destruction
* @reason: reason for switching vm to running state
*
* Starts a vm
static int lxcVmStart(virConnectPtr conn,
lxc_driver_t * driver,
virDomainObjPtr vm,
+ bool autoDestroy,
virDomainRunningReason reason)
{
int rc = -1, r;
goto cleanup;
}
+ if (autoDestroy &&
+ lxcProcessAutoDestroyAdd(driver, vm, conn) < 0)
+ goto cleanup;
+
/*
* Again, need to save the live configuration, because the function
* requires vm->def->id != -1 to save tty info surely.
virDomainEventPtr event = NULL;
int ret = -1;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
lxcDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
goto cleanup;
}
- ret = lxcVmStart(dom->conn, driver, vm, VIR_DOMAIN_RUNNING_BOOTED);
+ ret = lxcVmStart(dom->conn, driver, vm,
+ (flags & VIR_DOMAIN_START_AUTODESTROY),
+ VIR_DOMAIN_RUNNING_BOOTED);
if (ret == 0) {
event = virDomainEventNewFromObj(vm,
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
- virCheckFlags(0, NULL);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
lxcDriverLock(driver);
if (!(def = virDomainDefParseString(driver->caps, xml,
goto cleanup;
def = NULL;
- if (lxcVmStart(conn, driver, vm, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
+ if (lxcVmStart(conn, driver, vm,
+ (flags & VIR_DOMAIN_START_AUTODESTROY),
+ VIR_DOMAIN_RUNNING_BOOTED) < 0) {
virDomainAuditStart(vm, "booted", false);
virDomainRemoveInactive(&driver->domains, vm);
vm = NULL;
virDomainObjLock(vm);
if (vm->autostart &&
!virDomainObjIsActive(vm)) {
- int ret = lxcVmStart(data->conn, data->driver, vm,
+ int ret = lxcVmStart(data->conn, data->driver, vm, false,
VIR_DOMAIN_RUNNING_BOOTED);
virDomainAuditStart(vm, "booted", ret >= 0);
if (ret < 0) {
lxc_driver->caps->privateDataAllocFunc = lxcDomainObjPrivateAlloc;
lxc_driver->caps->privateDataFreeFunc = lxcDomainObjPrivateFree;
+ if (lxcProcessAutoDestroyInit(lxc_driver) < 0)
+ goto cleanup;
+
/* Get all the running persistent or transient configs first */
if (virDomainLoadAllConfigs(lxc_driver->caps,
&lxc_driver->domains,
virDomainObjListDeinit(&lxc_driver->domains);
virDomainEventStateFree(lxc_driver->domainEventState);
+ lxcProcessAutoDestroyShutdown(lxc_driver);
+
virCapabilitiesFree(lxc_driver->caps);
VIR_FREE(lxc_driver->configDir);
VIR_FREE(lxc_driver->autostartDir);
int monitorWatch;
};
+static int umlProcessAutoDestroyInit(struct uml_driver *driver);
+static void umlProcessAutoDestroyRun(struct uml_driver *driver,
+ virConnectPtr conn);
+static void umlProcessAutoDestroyShutdown(struct uml_driver *driver);
+static int umlProcessAutoDestroyAdd(struct uml_driver *driver,
+ virDomainObjPtr vm,
+ virConnectPtr conn);
+static int umlProcessAutoDestroyRemove(struct uml_driver *driver,
+ virDomainObjPtr vm);
+
static int umlShutdown(void);
static int umlStartVMDaemon(virConnectPtr conn,
struct uml_driver *driver,
- virDomainObjPtr vm);
+ virDomainObjPtr vm,
+ bool autoDestroy);
-static void umlShutdownVMDaemon(virConnectPtr conn,
- struct uml_driver *driver,
+static void umlShutdownVMDaemon(struct uml_driver *driver,
virDomainObjPtr vm,
virDomainShutoffReason reason);
!virDomainObjIsActive(vm)) {
int ret;
virResetLastError();
- ret = umlStartVMDaemon(data->conn, data->driver, vm);
+ ret = umlStartVMDaemon(data->conn, data->driver, vm, false);
virDomainAuditStart(vm, "booted", ret >= 0);
if (ret < 0) {
virErrorPtr err = virGetLastError();
continue;
}
- umlShutdownVMDaemon(NULL, driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+ umlShutdownVMDaemon(driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
virDomainAuditStop(dom, "shutdown");
event = virDomainEventNewFromObj(dom,
VIR_DOMAIN_EVENT_STOPPED,
if (umlOpenMonitor(driver, dom) < 0) {
VIR_WARN("Could not open monitor for new domain");
- umlShutdownVMDaemon(NULL, driver, dom,
+ umlShutdownVMDaemon(driver, dom,
VIR_DOMAIN_SHUTOFF_FAILED);
virDomainAuditStop(dom, "failed");
event = virDomainEventNewFromObj(dom,
}
} else if (umlIdentifyChrPTY(driver, dom) < 0) {
VIR_WARN("Could not identify character devices for new domain");
- umlShutdownVMDaemon(NULL, driver, dom,
+ umlShutdownVMDaemon(driver, dom,
VIR_DOMAIN_SHUTOFF_FAILED);
virDomainAuditStop(dom, "failed");
event = virDomainEventNewFromObj(dom,
umlInotifyEvent, uml_driver, NULL)) < 0)
goto error;
+ if (umlProcessAutoDestroyInit(uml_driver) < 0)
+ goto error;
+
if (virDomainLoadAllConfigs(uml_driver->caps,
¨_driver->domains,
uml_driver->configDir,
virDomainObjLock(dom);
if (virDomainObjIsActive(dom)) {
- umlShutdownVMDaemon(NULL, driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+ umlShutdownVMDaemon(driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
virDomainAuditStop(dom, "shutdown");
}
virDomainObjUnlock(dom);
VIR_FREE(uml_driver->autostartDir);
VIR_FREE(uml_driver->monitorDir);
+ umlProcessAutoDestroyShutdown(uml_driver);
+
if (uml_driver->brctl)
brShutdown(uml_driver->brctl);
}
+static int umlProcessAutoDestroyInit(struct uml_driver *driver)
+{
+ if (!(driver->autodestroy = virHashCreate(5, NULL)))
+ return -1;
+
+ return 0;
+}
+
+struct umlProcessAutoDestroyData {
+ struct uml_driver *driver;
+ virConnectPtr conn;
+};
+
+static void umlProcessAutoDestroyDom(void *payload,
+ const void *name,
+ void *opaque)
+{
+ struct umlProcessAutoDestroyData *data = opaque;
+ virConnectPtr conn = payload;
+ const char *uuidstr = name;
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ virDomainObjPtr dom;
+ virDomainEventPtr event = NULL;
+
+ VIR_DEBUG("conn=%p uuidstr=%s thisconn=%p", conn, uuidstr, data->conn);
+
+ if (data->conn != conn)
+ return;
+
+ if (virUUIDParse(uuidstr, uuid) < 0) {
+ VIR_WARN("Failed to parse %s", uuidstr);
+ return;
+ }
+
+ if (!(dom = virDomainFindByUUID(&data->driver->domains,
+ uuid))) {
+ VIR_DEBUG("No domain object to kill");
+ return;
+ }
+
+ VIR_DEBUG("Killing domain");
+ umlShutdownVMDaemon(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED);
+ virDomainAuditStop(dom, "destroyed");
+ event = virDomainEventNewFromObj(dom,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
+
+ if (dom && !dom->persistent)
+ virDomainRemoveInactive(&data->driver->domains, dom);
+
+ if (dom)
+ virDomainObjUnlock(dom);
+ if (event)
+ umlDomainEventQueue(data->driver, event);
+ virHashRemoveEntry(data->driver->autodestroy, uuidstr);
+}
+
+/*
+ * Precondition: driver is locked
+ */
+static void umlProcessAutoDestroyRun(struct uml_driver *driver, virConnectPtr conn)
+{
+ struct umlProcessAutoDestroyData data = {
+ driver, conn
+ };
+ VIR_DEBUG("conn=%p", conn);
+ virHashForEach(driver->autodestroy, umlProcessAutoDestroyDom, &data);
+}
+
+static void umlProcessAutoDestroyShutdown(struct uml_driver *driver)
+{
+ virHashFree(driver->autodestroy);
+}
+
+static int umlProcessAutoDestroyAdd(struct uml_driver *driver,
+ virDomainObjPtr vm,
+ virConnectPtr conn)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ VIR_DEBUG("vm=%s uuid=%s conn=%p", vm->def->name, uuidstr, conn);
+ if (virHashAddEntry(driver->autodestroy, uuidstr, conn) < 0)
+ return -1;
+ return 0;
+}
+
+static int umlProcessAutoDestroyRemove(struct uml_driver *driver,
+ virDomainObjPtr vm)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr);
+ if (virHashRemoveEntry(driver->autodestroy, uuidstr) < 0)
+ return -1;
+ return 0;
+}
+
+
static int umlReadPidFile(struct uml_driver *driver,
virDomainObjPtr vm)
{
}
-static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainObjPtr vm) {
+static int umlCleanupTapDevices(virDomainObjPtr vm) {
int i;
int err;
int ret = 0;
static int umlStartVMDaemon(virConnectPtr conn,
struct uml_driver *driver,
- virDomainObjPtr vm) {
+ virDomainObjPtr vm,
+ bool autoDestroy) {
int ret;
char *logfile;
int logfd = -1;
if (!(cmd = umlBuildCommandLine(conn, driver, vm))) {
VIR_FORCE_CLOSE(logfd);
virDomainConfVMNWFilterTeardown(vm);
- umlCleanupTapDevices(conn, vm);
+ umlCleanupTapDevices(vm);
return -1;
}
if (ret < 0)
goto cleanup;
+ if (autoDestroy &&
+ umlProcessAutoDestroyAdd(driver, vm, conn) < 0)
+ goto cleanup;
+
ret = virDomainObjSetDefTransient(driver->caps, vm, false);
cleanup:
virCommandFree(cmd);
if (ret < 0) {
virDomainConfVMNWFilterTeardown(vm);
- umlCleanupTapDevices(conn, vm);
+ umlCleanupTapDevices(vm);
}
/* NB we don't mark it running here - we do that async
return ret;
}
-static void umlShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
- struct uml_driver *driver ATTRIBUTE_UNUSED,
+static void umlShutdownVMDaemon(struct uml_driver *driver,
virDomainObjPtr vm,
virDomainShutoffReason reason)
{
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
virDomainConfVMNWFilterTeardown(vm);
- umlCleanupTapDevices(conn, vm);
+ umlCleanupTapDevices(vm);
+
+ /* Stop autodestroy in case guest is restarted */
+ umlProcessAutoDestroyRemove(driver, vm);
if (vm->newDef) {
virDomainDefFree(vm->def);
umlDriverLock(driver);
virDomainEventCallbackListRemoveConn(conn,
driver->domainEventState->callbacks);
+ umlProcessAutoDestroyRun(driver, conn);
umlDriverUnlock(driver);
conn->privateData = NULL;
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
- virCheckFlags(0, NULL);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
umlDriverLock(driver);
if (!(def = virDomainDefParseString(driver->caps, xml,
goto cleanup;
def = NULL;
- if (umlStartVMDaemon(conn, driver, vm) < 0) {
+ if (umlStartVMDaemon(conn, driver, vm,
+ (flags & VIR_DOMAIN_START_AUTODESTROY)) < 0) {
virDomainAuditStart(vm, "booted", false);
virDomainRemoveInactive(&driver->domains,
vm);
goto cleanup;
}
- umlShutdownVMDaemon(dom->conn, driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
+ umlShutdownVMDaemon(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
virDomainAuditStop(vm, "destroyed");
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
virDomainEventPtr event = NULL;
int ret = -1;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
umlDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
goto cleanup;
}
- ret = umlStartVMDaemon(dom->conn, driver, vm);
+ ret = umlStartVMDaemon(dom->conn, driver, vm,
+ (flags & VIR_DOMAIN_START_AUTODESTROY));
virDomainAuditStart(vm, "booted", ret >= 0);
if (ret == 0)
event = virDomainEventNewFromObj(vm,