start: allow discarding managed save

There have been several instances of people having problems with
a broken managed save file, and not aware that they could use
'virsh managedsave-remove dom' to fix things.  Making it possible
to do this as part of starting a domain makes the same functionality
easier to find, and one less API call.

* include/libvirt/libvirt.h.in (VIR_DOMAIN_START_FORCE_BOOT): New
flag.
* src/libvirt.c (virDomainCreateWithFlags): Document it.
* src/qemu/qemu_driver.c (qemuDomainObjStart): Alter signature.
(qemuAutostartDomain, qemuDomainStartWithFlags): Update callers.
* tools/virsh.c (cmdStart): Expose it in virsh.
* tools/virsh.pod (start): Document it.
This commit is contained in:
Eric Blake 2011-08-27 17:07:18 -06:00
parent 71a0beaf3a
commit 27c8526053
5 changed files with 43 additions and 23 deletions

View File

@ -236,6 +236,7 @@ typedef enum {
VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */ VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */
VIR_DOMAIN_START_AUTODESTROY = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */ VIR_DOMAIN_START_AUTODESTROY = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */
VIR_DOMAIN_START_BYPASS_CACHE = 1 << 2, /* Avoid file system cache pollution */ VIR_DOMAIN_START_BYPASS_CACHE = 1 << 2, /* Avoid file system cache pollution */
VIR_DOMAIN_START_FORCE_BOOT = 1 << 3, /* Boot, discarding any managed save */
} virDomainCreateFlags; } virDomainCreateFlags;

View File

@ -7081,6 +7081,9 @@ error:
* the file, or fail if it cannot do so for the given system; this can allow * the file, or fail if it cannot do so for the given system; this can allow
* less pressure on file system cache, but also risks slowing loads from NFS. * less pressure on file system cache, but also risks slowing loads from NFS.
* *
* If the VIR_DOMAIN_START_FORCE_BOOT flag is set, then any managed save
* file for this domain is discarded, and the domain boots from scratch.
*
* Returns 0 in case of success, -1 in case of error * Returns 0 in case of success, -1 in case of error
*/ */
int int

View File

@ -120,9 +120,7 @@ static int qemudShutdown(void);
static int qemuDomainObjStart(virConnectPtr conn, static int qemuDomainObjStart(virConnectPtr conn,
struct qemud_driver *driver, struct qemud_driver *driver,
virDomainObjPtr vm, virDomainObjPtr vm,
bool start_paused, unsigned int flags);
bool autodestroy,
bool bypass_cache);
static int qemudDomainGetMaxVcpus(virDomainPtr dom); static int qemudDomainGetMaxVcpus(virDomainPtr dom);
@ -135,11 +133,16 @@ struct qemuAutostartData {
}; };
static void static void
qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
void *opaque)
{ {
virDomainObjPtr vm = payload; virDomainObjPtr vm = payload;
struct qemuAutostartData *data = opaque; struct qemuAutostartData *data = opaque;
virErrorPtr err; virErrorPtr err;
int flags = 0;
if (data->driver->autoStartBypassCache)
flags |= VIR_DOMAIN_START_BYPASS_CACHE;
virDomainObjLock(vm); virDomainObjLock(vm);
virResetLastError(); virResetLastError();
@ -152,9 +155,7 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq
} else { } else {
if (vm->autostart && if (vm->autostart &&
!virDomainObjIsActive(vm) && !virDomainObjIsActive(vm) &&
qemuDomainObjStart(data->conn, data->driver, vm, qemuDomainObjStart(data->conn, data->driver, vm, flags) < 0) {
false, false,
data->driver->autoStartBypassCache) < 0) {
err = virGetLastError(); err = virGetLastError();
VIR_ERROR(_("Failed to autostart VM '%s': %s"), VIR_ERROR(_("Failed to autostart VM '%s': %s"),
vm->def->name, vm->def->name,
@ -4441,12 +4442,14 @@ static int
qemuDomainObjStart(virConnectPtr conn, qemuDomainObjStart(virConnectPtr conn,
struct qemud_driver *driver, struct qemud_driver *driver,
virDomainObjPtr vm, virDomainObjPtr vm,
bool start_paused, unsigned int flags)
bool autodestroy,
bool bypass_cache)
{ {
int ret = -1; int ret = -1;
char *managed_save; char *managed_save;
bool start_paused = (flags & VIR_DOMAIN_START_PAUSED) != 0;
bool autodestroy = (flags & VIR_DOMAIN_START_AUTODESTROY) != 0;
bool bypass_cache = (flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0;
bool force_boot = (flags & VIR_DOMAIN_START_FORCE_BOOT) != 0;
/* /*
* If there is a managed saved state restore it instead of starting * If there is a managed saved state restore it instead of starting
@ -4458,13 +4461,22 @@ qemuDomainObjStart(virConnectPtr conn,
goto cleanup; goto cleanup;
if (virFileExists(managed_save)) { if (virFileExists(managed_save)) {
ret = qemuDomainObjRestore(conn, driver, vm, managed_save, if (force_boot) {
bypass_cache); if (unlink(managed_save) < 0) {
virReportSystemError(errno,
_("cannot remove managed save file %s"),
managed_save);
goto cleanup;
}
} else {
ret = qemuDomainObjRestore(conn, driver, vm, managed_save,
bypass_cache);
if ((ret == 0) && (unlink(managed_save) < 0)) if ((ret == 0) && (unlink(managed_save) < 0))
VIR_WARN("Failed to remove the managed state %s", managed_save); VIR_WARN("Failed to remove the managed state %s", managed_save);
goto cleanup; goto cleanup;
}
} }
ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, ret = qemuProcessStart(conn, driver, vm, NULL, start_paused,
@ -4493,7 +4505,8 @@ qemuDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
virCheckFlags(VIR_DOMAIN_START_PAUSED | virCheckFlags(VIR_DOMAIN_START_PAUSED |
VIR_DOMAIN_START_AUTODESTROY | VIR_DOMAIN_START_AUTODESTROY |
VIR_DOMAIN_START_BYPASS_CACHE, -1); VIR_DOMAIN_START_BYPASS_CACHE |
VIR_DOMAIN_START_FORCE_BOOT, -1);
qemuDriverLock(driver); qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid); vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@ -4515,10 +4528,7 @@ qemuDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
goto endjob; goto endjob;
} }
if (qemuDomainObjStart(dom->conn, driver, vm, if (qemuDomainObjStart(dom->conn, driver, vm, flags) < 0)
(flags & VIR_DOMAIN_START_PAUSED) != 0,
(flags & VIR_DOMAIN_START_AUTODESTROY) != 0,
(flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0) < 0)
goto endjob; goto endjob;
ret = 0; ret = 0;

View File

@ -1537,9 +1537,12 @@ static const vshCmdOptDef opts_start[] = {
{"console", VSH_OT_BOOL, 0, N_("attach to console after creation")}, {"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
#endif #endif
{"paused", VSH_OT_BOOL, 0, N_("leave the guest paused after creation")}, {"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")}, {"autodestroy", VSH_OT_BOOL, 0,
N_("automatically destroy the guest when virsh disconnects")},
{"bypass-cache", VSH_OT_BOOL, 0, {"bypass-cache", VSH_OT_BOOL, 0,
N_("avoid file system cache when loading")}, N_("avoid file system cache when loading")},
{"force-boot", VSH_OT_BOOL, 0,
N_("force fresh boot by discarding any managed save")},
{NULL, 0, 0, NULL} {NULL, 0, 0, NULL}
}; };
@ -1572,6 +1575,8 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
flags |= VIR_DOMAIN_START_AUTODESTROY; flags |= VIR_DOMAIN_START_AUTODESTROY;
if (vshCommandOptBool(cmd, "bypass-cache")) if (vshCommandOptBool(cmd, "bypass-cache"))
flags |= VIR_DOMAIN_START_BYPASS_CACHE; flags |= VIR_DOMAIN_START_BYPASS_CACHE;
if (vshCommandOptBool(cmd, "force-boot"))
flags |= VIR_DOMAIN_START_FORCE_BOOT;
/* Prefer older API unless we have to pass a flag. */ /* Prefer older API unless we have to pass a flag. */
if ((flags ? virDomainCreateWithFlags(dom, flags) if ((flags ? virDomainCreateWithFlags(dom, flags)

View File

@ -890,7 +890,7 @@ The exact behavior of a domain when it shuts down is set by the
I<on_shutdown> parameter in the domain's XML definition. I<on_shutdown> parameter in the domain's XML definition.
=item B<start> I<domain-name> [I<--console>] [I<--paused>] [I<--autodestroy>] =item B<start> I<domain-name> [I<--console>] [I<--paused>] [I<--autodestroy>]
[I<--bypass-cache>] [I<--bypass-cache>] [I<--force-boot>]
Start a (previously defined) inactive domain, either from the last Start a (previously defined) inactive domain, either from the last
B<managedsave> state, or via a fresh boot if no managedsave state is B<managedsave> state, or via a fresh boot if no managedsave state is
@ -901,7 +901,8 @@ If I<--autodestroy> is requested, then the guest will be automatically
destroyed when virsh closes its connection to libvirt, or otherwise destroyed when virsh closes its connection to libvirt, or otherwise
exits. If I<--bypass-cache> is specified, and managedsave state exists, exits. If I<--bypass-cache> is specified, and managedsave state exists,
the restore will avoid the file system cache, although this may slow the restore will avoid the file system cache, although this may slow
down the operation. down the operation. If I<--force-boot> is specified, then any
managedsave state is discarded and a fresh boot occurs.
=item B<suspend> I<domain-id> =item B<suspend> I<domain-id>