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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list