typedef enum {
VIR_DOMAIN_NONE = 0, /* Default behavior */
VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */
+ VIR_DOMAIN_START_AUTODESTROY = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */
} virDomainCreateFlags;
* is destroyed, or if the host is restarted (see virDomainDefineXML() to
* define persistent domains).
*
+ * If the VIR_DOMAIN_START_PAUSED flag is set, the guest domain
+ * will be started, but its CPUs will remain paused. The CPUs
+ * can later be manually started using virDomainResume.
+ *
+ * If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+ * domain will be automatically destroyed when the virConnectPtr
+ * object is finally released. This will also happen if the
+ * client application crashes / looses its connection to the
+ * libvirtd daemon. Any domains marked for auto destroy will
+ * block attempts at migration or save-to-file
+ *
* Returns a new domain object or NULL in case of failure
*/
virDomainPtr
* Launch a defined domain. If the call succeeds the domain moves from the
* defined to the running domains pools.
*
+ * If the VIR_DOMAIN_START_PAUSED flag is set, the guest domain
+ * will be started, but its CPUs will remain paused. The CPUs
+ * can later be manually started using virDomainResume.
+ *
+ * If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+ * domain will be automatically destroyed when the virConnectPtr
+ * object is finally released. This will also happen if the
+ * client application crashes / looses its connection to the
+ * libvirtd daemon. Any domains marked for auto destroy will
+ * block attempts at migration or save-to-file
+ *
* Returns 0 in case of success, -1 in case of error
*/
int
static int qemudDomainObjStart(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
- bool start_paused);
+ bool start_paused,
+ bool autodestroy);
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
} 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,
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
- virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);
+ virCheckFlags(VIR_DOMAIN_START_PAUSED |
+ VIR_DOMAIN_START_AUTODESTROY, NULL);
qemuDriverLock(driver);
if (!(def = virDomainDefParseString(driver->caps, xml,
if (qemuProcessStart(conn, driver, vm, NULL,
(flags & VIR_DOMAIN_START_PAUSED) != 0,
- false,
+ (flags & VIR_DOMAIN_START_AUTODESTROY) != 0,
-1, NULL, VIR_VM_OP_CREATE) < 0) {
qemuAuditDomainStart(vm, "booted", false);
if (qemuDomainObjEndJob(vm) > 0)
goto cleanup;
}
+ if (qemuProcessAutoDestroyActive(driver, vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is marked for auto destroy"));
+ goto cleanup;
+ }
+
priv = vm->privateData;
if (priv->jobActive == QEMU_JOB_MIGRATION_OUT) {
static int qemudDomainObjStart(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
- bool start_paused)
+ bool start_paused,
+ bool autodestroy)
{
int ret = -1;
char *managed_save;
}
ret = qemuProcessStart(conn, driver, vm, NULL, start_paused,
- false, -1, NULL, VIR_VM_OP_CREATE);
+ autodestroy, -1, NULL, VIR_VM_OP_CREATE);
qemuAuditDomainStart(vm, "booted", ret >= 0);
if (ret >= 0) {
virDomainEventPtr event =
virDomainObjPtr vm;
int ret = -1;
- virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);
+ virCheckFlags(VIR_DOMAIN_START_PAUSED |
+ VIR_DOMAIN_START_AUTODESTROY, -1);
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
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_AUTODESTROY) != 0) < 0)
+ goto endjob;
+
+ ret = 0;
endjob:
if (qemuDomainObjEndJob(vm) == 0)
goto cleanup;
}
+ if (qemuProcessAutoDestroyActive(driver, vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is marked for auto destroy"));
+ goto cleanup;
+ }
+
if (!qemuMigrationIsAllowed(vm->def))
goto cleanup;
goto endjob;
}
+ if (qemuProcessAutoDestroyActive(driver, vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is marked for auto destroy"));
+ goto endjob;
+ }
+
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;
return -1;
return 0;
}
+
+bool qemuProcessAutoDestroyActive(struct qemud_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 (virHashLookup(driver->autodestroy, uuidstr) != NULL)
+ return true;
+ return false;
+}
virConnectPtr conn);
int qemuProcessAutoDestroyRemove(struct qemud_driver *driver,
virDomainObjPtr vm);
-
+bool qemuProcessAutoDestroyActive(struct qemud_driver *driver,
+ virDomainObjPtr vm);
#endif /* __QEMU_PROCESS_H__ */
{"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
#endif
{"paused", VSH_OT_BOOL, 0, N_("leave the guest paused after creation")},
+ {"autodestroy", VSH_OT_BOOL, 0, N_("automatically destroy the guest when virsh disconnects")},
{NULL, 0, 0, NULL}
};
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_START_PAUSED;
+ if (vshCommandOptBool(cmd, "autodestroy"))
+ flags |= VIR_DOMAIN_START_AUTODESTROY;
dom = virDomainCreateXML(ctl->conn, buffer, flags);
VIR_FREE(buffer);
{"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
#endif
{"paused", VSH_OT_BOOL, 0, N_("leave the guest paused after creation")},
+ {"autodestroy", VSH_OT_BOOL, 0, N_("automatically destroy the guest when virsh disconnects")},
{NULL, 0, 0, NULL}
};
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_START_PAUSED;
+ if (vshCommandOptBool(cmd, "autodestroy"))
+ flags |= VIR_DOMAIN_START_AUTODESTROY;
/* Prefer older API unless we have to pass a flag. */
if ((flags ? virDomainCreateWithFlags(dom, flags)
console, serial or parallel device configured for the guest.
If omitted, the primary console will be opened.
-=item B<create> I<FILE> optional I<--console> I<--paused>
+=item B<create> I<FILE> optional I<--console> I<--paused> I<--autodestroy>
Create a domain from an XML <file>. An easy way to create the XML
<file> is to use the B<dumpxml> command to obtain the definition of a
pre-existing guest. The domain will be paused if the I<--paused> option
is used and supported by the driver; otherwise it will be running.
If I<--console> is requested, attach to the console after creation.
+If I<--autodestroy> is requested, then the guest will be automatically
+destroyed when virsh closes its connection to libvirt, or otherwise
+exits.
B<Example>
The exact behavior of a domain when it shuts down is set by the
I<on_shutdown> parameter in the domain's XML definition.
-=item B<start> I<domain-name> optional I<--console> I<--paused>
+=item B<start> I<domain-name> optional I<--console> I<--paused> I<--autodestroy>
Start a (previously defined) inactive domain, either from the last
B<managedsave> state, or via a fresh boot if no managedsave state is
present. The domain will be paused if the I<--paused> option is
used and supported by the driver; otherwise it will be running.
If I<--console> is requested, attach to the console after creation.
+If I<--autodestroy> is requested, then the guest will be automatically
+destroyed when virsh closes its connection to libvirt, or otherwise
+exits.
=item B<suspend> I<domain-id>