From: "Daniel P. Berrange" <berrange(a)redhat.com>
I wrote this months ago and thought I had already submitted/merged
it. Obviously not. I need this for the virt sandbox tools asap.
We recently added support for VIR_DOMAIN_START_AUTODESTROY and
an impl to the QEMU driver. It is very desirable to support in
other drivers, so this adds it to LXC and UML
* src/lxc/lxc_conf.h, src/lxc/lxc_driver.c,
src/uml/uml_conf.h, src/uml/uml_driver.c: Wire up autodestroy
functions
---
src/lxc/lxc_conf.h | 5 ++
src/lxc/lxc_driver.c | 140 +++++++++++++++++++++++++++++++++++++++++--
src/uml/uml_conf.h | 6 ++
src/uml/uml_driver.c | 164 +++++++++++++++++++++++++++++++++++++++++++-------
4 files changed, 289 insertions(+), 26 deletions(-)
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index 66aa469..b124330 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -56,6 +56,11 @@ struct __lxc_driver {
int have_netns;
virDomainEventStatePtr domainEventState;
+
+ /* Mapping of 'char *uuidstr' -> virConnectPtr
+ * of guests which will be automatically killed
+ * when the virConnectPtr is closed*/
+ virHashTablePtr autodestroy;
};
int lxcLoadDriverConfig(lxc_driver_t *driver);
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index c475887..f08e8d1 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -110,6 +110,19 @@ static void lxcDomainEventFlush(int timer, void *opaque);
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,
@@ -165,6 +178,7 @@ static int lxcClose(virConnectPtr conn)
lxcDriverLock(driver);
virDomainEventCallbackListRemoveConn(conn,
driver->domainEventState->callbacks);
+ lxcProcessAutoDestroyRun(driver, conn);
lxcDriverUnlock(driver);
conn->privateData = NULL;
@@ -1001,6 +1015,104 @@ cleanup:
}
+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
@@ -1028,6 +1140,9 @@ static void lxcVmCleanup(lxc_driver_t *driver,
VIR_FREE(xml);
}
+ /* Stop autodestroy in case guest is restarted */
+ lxcProcessAutoDestroyRemove(driver, vm);
+
virEventRemoveHandle(priv->monitorWatch);
VIR_FORCE_CLOSE(priv->monitor);
@@ -1496,6 +1611,7 @@ cleanup:
* @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
@@ -1505,6 +1621,7 @@ cleanup:
static int lxcVmStart(virConnectPtr conn,
lxc_driver_t * driver,
virDomainObjPtr vm,
+ bool autoDestroy,
virDomainRunningReason reason)
{
int rc = -1, r;
@@ -1665,6 +1782,10 @@ static int lxcVmStart(virConnectPtr conn,
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.
@@ -1719,7 +1840,7 @@ static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int
flags)
virDomainEventPtr event = NULL;
int ret = -1;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
lxcDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -1743,7 +1864,9 @@ static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int
flags)
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,
@@ -1796,7 +1919,7 @@ lxcDomainCreateAndStart(virConnectPtr conn,
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
- virCheckFlags(0, NULL);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
lxcDriverLock(driver);
if (!(def = virDomainDefParseString(driver->caps, xml,
@@ -1819,7 +1942,9 @@ lxcDomainCreateAndStart(virConnectPtr conn,
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;
@@ -2054,7 +2179,7 @@ lxcAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
void *opaqu
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) {
@@ -2205,6 +2330,9 @@ static int lxcStartup(int privileged)
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,
@@ -2285,6 +2413,8 @@ static int lxcShutdown(void)
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);
diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h
index 5401a7e..657f877 100644
--- a/src/uml/uml_conf.h
+++ b/src/uml/uml_conf.h
@@ -33,6 +33,7 @@
# include "virterror_internal.h"
# include "threads.h"
# include "command.h"
+# include "hash.h"
# define umlDebug(fmt, ...) do {} while(0)
@@ -64,6 +65,11 @@ struct uml_driver {
/* Event handling */
virDomainEventStatePtr domainEventState;
+
+ /* Mapping of 'char *uuidstr' -> virConnectPtr
+ * of guests which will be automatically killed
+ * when the virConnectPtr is closed*/
+ virHashTablePtr autodestroy;
};
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 2b7219a..16ab73a 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -75,6 +75,16 @@ struct _umlDomainObjPrivate {
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);
@@ -119,10 +129,10 @@ static void umlDomainEventQueue(struct uml_driver *driver,
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);
@@ -150,7 +160,7 @@ umlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
void *opaqu
!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();
@@ -309,7 +319,7 @@ reread:
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,
@@ -337,7 +347,7 @@ reread:
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,
@@ -350,7 +360,7 @@ reread:
}
} 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,
@@ -480,6 +490,9 @@ umlStartup(int privileged)
umlInotifyEvent, uml_driver, NULL)) < 0)
goto error;
+ if (umlProcessAutoDestroyInit(uml_driver) < 0)
+ goto error;
+
if (virDomainLoadAllConfigs(uml_driver->caps,
¨_driver->domains,
uml_driver->configDir,
@@ -577,7 +590,7 @@ umlShutdownOneVM(void *payload, const void *name ATTRIBUTE_UNUSED,
void *opaque)
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);
@@ -612,6 +625,8 @@ umlShutdown(void) {
VIR_FREE(uml_driver->autostartDir);
VIR_FREE(uml_driver->monitorDir);
+ umlProcessAutoDestroyShutdown(uml_driver);
+
if (uml_driver->brctl)
brShutdown(uml_driver->brctl);
@@ -623,6 +638,104 @@ umlShutdown(void) {
}
+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)
{
@@ -842,8 +955,7 @@ error:
}
-static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainObjPtr vm) {
+static int umlCleanupTapDevices(virDomainObjPtr vm) {
int i;
int err;
int ret = 0;
@@ -873,7 +985,8 @@ static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
static int umlStartVMDaemon(virConnectPtr conn,
struct uml_driver *driver,
- virDomainObjPtr vm) {
+ virDomainObjPtr vm,
+ bool autoDestroy) {
int ret;
char *logfile;
int logfd = -1;
@@ -935,7 +1048,7 @@ static int umlStartVMDaemon(virConnectPtr conn,
if (!(cmd = umlBuildCommandLine(conn, driver, vm))) {
VIR_FORCE_CLOSE(logfd);
virDomainConfVMNWFilterTeardown(vm);
- umlCleanupTapDevices(conn, vm);
+ umlCleanupTapDevices(vm);
return -1;
}
@@ -953,13 +1066,17 @@ static int umlStartVMDaemon(virConnectPtr conn,
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
@@ -972,8 +1089,7 @@ cleanup:
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)
{
@@ -997,7 +1113,10 @@ static void umlShutdownVMDaemon(virConnectPtr conn
ATTRIBUTE_UNUSED,
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);
@@ -1072,6 +1191,7 @@ static int umlClose(virConnectPtr conn) {
umlDriverLock(driver);
virDomainEventCallbackListRemoveConn(conn,
driver->domainEventState->callbacks);
+ umlProcessAutoDestroyRun(driver, conn);
umlDriverUnlock(driver);
conn->privateData = NULL;
@@ -1342,7 +1462,7 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char
*xml,
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
- virCheckFlags(0, NULL);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
umlDriverLock(driver);
if (!(def = virDomainDefParseString(driver->caps, xml,
@@ -1359,7 +1479,8 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char
*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);
@@ -1436,7 +1557,7 @@ umlDomainDestroyFlags(virDomainPtr dom,
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,
@@ -1717,7 +1838,7 @@ static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int
flags) {
virDomainEventPtr event = NULL;
int ret = -1;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
umlDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -1728,7 +1849,8 @@ static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int
flags) {
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,
--
1.7.6.4