If an application is using libvirt + KVM as a piece of its
internal infrastructure to perform a specific task, it can
be desirable to guarentee the VM dies when the virConnectPtr
disconnects from libvirtd. This ensures the app can't leak
any VMs it was using. Adding VIR_DOMAIN_START_AUTOKILL as
a flag when starting guests enables this to be done.
* include/libvirt/libvirt.h.in: All VIR_DOMAIN_START_AUTOKILL
* src/qemu/qemu_driver.c: Support automatic killing of guests
upon connection close
* tools/virsh.c: Add --autokill flag to 'start' and 'create'
commands
---
include/libvirt/libvirt.h.in | 1 +
src/qemu/qemu_driver.c | 27 ++++++++++++++++++---------
tools/virsh.c | 6 ++++++
3 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 3f634e6..a827697 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -234,6 +234,7 @@ typedef virDomainInfo *virDomainInfoPtr;
typedef enum {
VIR_DOMAIN_NONE = 0, /* Default behavior */
VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */
+ VIR_DOMAIN_START_AUTOKILL = 1 << 1, /* Automatically kill guest when
virConnectPtr is closed */
} virDomainCreateFlags;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 44e1fba..18701a7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -119,7 +119,8 @@ static int qemudShutdown(void);
static int qemudDomainObjStart(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
- bool start_paused);
+ bool start_paused,
+ bool autokill);
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
@@ -148,7 +149,7 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
void *opaq
} else {
if (vm->autostart &&
!virDomainObjIsActive(vm) &&
- qemudDomainObjStart(data->conn, data->driver, vm, false) < 0) {
+ qemudDomainObjStart(data->conn, data->driver, vm, false, false) < 0)
{
err = virGetLastError();
VIR_ERROR(_("Failed to autostart VM '%s': %s"),
vm->def->name,
@@ -1246,7 +1247,8 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char
*xml,
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
- virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);
+ virCheckFlags(VIR_DOMAIN_START_PAUSED |
+ VIR_DOMAIN_START_AUTOKILL, NULL);
qemuDriverLock(driver);
if (!(def = virDomainDefParseString(driver->caps, xml,
@@ -1277,7 +1279,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char
*xml,
if (qemuProcessStart(conn, driver, vm, NULL,
(flags & VIR_DOMAIN_START_PAUSED) != 0,
- false,
+ (flags & VIR_DOMAIN_START_AUTOKILL) != 0,
-1, NULL, VIR_VM_OP_CREATE) < 0) {
qemuAuditDomainStart(vm, "booted", false);
if (qemuDomainObjEndJob(vm) > 0)
@@ -1295,6 +1297,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char
*xml,
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id;
+endjob:
if (vm &&
qemuDomainObjEndJob(vm) == 0)
vm = NULL;
@@ -3819,7 +3822,8 @@ static int qemudNumDefinedDomains(virConnectPtr conn) {
static int qemudDomainObjStart(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
- bool start_paused)
+ bool start_paused,
+ bool autokill)
{
int ret = -1;
char *managed_save;
@@ -3843,7 +3847,7 @@ static int qemudDomainObjStart(virConnectPtr conn,
}
ret = qemuProcessStart(conn, driver, vm, NULL, start_paused,
- false, -1, NULL, VIR_VM_OP_CREATE);
+ autokill, -1, NULL, VIR_VM_OP_CREATE);
qemuAuditDomainStart(vm, "booted", ret >= 0);
if (ret >= 0) {
virDomainEventPtr event =
@@ -3866,7 +3870,8 @@ qemudDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
virDomainObjPtr vm;
int ret = -1;
- virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);
+ virCheckFlags(VIR_DOMAIN_START_PAUSED |
+ VIR_DOMAIN_START_AUTOKILL, -1);
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -3888,8 +3893,12 @@ qemudDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
goto endjob;
}
- ret = qemudDomainObjStart(dom->conn, driver, vm,
- (flags & VIR_DOMAIN_START_PAUSED) != 0);
+ if (qemudDomainObjStart(dom->conn, driver, vm,
+ (flags & VIR_DOMAIN_START_PAUSED) != 0,
+ (flags & VIR_DOMAIN_START_AUTOKILL) != 0) < 0)
+ goto endjob;
+
+ ret = 0;
endjob:
if (qemuDomainObjEndJob(vm) == 0)
diff --git a/tools/virsh.c b/tools/virsh.c
index fcd254d..dedf883 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -1305,6 +1305,7 @@ static const vshCmdOptDef opts_create[] = {
{"console", VSH_OT_BOOL, 0, N_("attach to console after
creation")},
#endif
{"paused", VSH_OT_BOOL, 0, N_("leave the guest paused after
creation")},
+ {"autokill", VSH_OT_BOOL, 0, N_("automatically kill the guest when
virsh disconnects")},
{NULL, 0, 0, NULL}
};
@@ -1331,6 +1332,8 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd)
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_START_PAUSED;
+ if (vshCommandOptBool(cmd, "autokill"))
+ flags |= VIR_DOMAIN_START_AUTOKILL;
dom = virDomainCreateXML(ctl->conn, buffer, flags);
VIR_FREE(buffer);
@@ -1466,6 +1469,7 @@ static const vshCmdOptDef opts_start[] = {
{"console", VSH_OT_BOOL, 0, N_("attach to console after
creation")},
#endif
{"paused", VSH_OT_BOOL, 0, N_("leave the guest paused after
creation")},
+ {"autokill", VSH_OT_BOOL, 0, N_("automatically kill the guest when
virsh disconnects")},
{NULL, 0, 0, NULL}
};
@@ -1494,6 +1498,8 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_START_PAUSED;
+ if (vshCommandOptBool(cmd, "autokill"))
+ flags |= VIR_DOMAIN_START_AUTOKILL;
/* Prefer older API unless we have to pass a flag. */
if ((flags ? virDomainCreateWithFlags(dom, flags)
--
1.7.4.4