mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-26 14:03:49 +03:00
snapshots: Introduce VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag
With this flag, virDomainSnapshotCreate will use fs-freeze and fs-thaw guest agent commands to quiesce guest's disks.
This commit is contained in:
parent
29bce12ada
commit
109593ecb0
@ -3125,6 +3125,10 @@ typedef enum {
|
||||
system checkpoint */
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT = (1 << 5), /* reuse any existing
|
||||
external files */
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE = (1 << 6), /* use guest agent to
|
||||
quiesce all mounted
|
||||
file systems within
|
||||
the domain */
|
||||
} virDomainSnapshotCreateFlags;
|
||||
|
||||
/* Take a snapshot of the current VM state */
|
||||
|
@ -16602,6 +16602,12 @@ virDomainSnapshotGetConnect(virDomainSnapshotPtr snapshot)
|
||||
* inconsistent (as if power had been pulled), and specifying this
|
||||
* with the VIR_DOMAIN_SNAPSHOT_CREATE_HALT flag risks data loss.
|
||||
*
|
||||
* If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, then the
|
||||
* libvirt will attempt to use guest agent to freeze and thaw all
|
||||
* file systems in use within domain OS. However, if the guest agent
|
||||
* is not present, an error is thrown. Moreover, this flag requires
|
||||
* VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY to be passed as well.
|
||||
*
|
||||
* By default, if the snapshot involves external files, and any of the
|
||||
* destination files already exist as a regular file, the snapshot is
|
||||
* rejected to avoid losing contents of those files. However, if
|
||||
|
@ -9461,6 +9461,56 @@ static int qemuDomainSnapshotIsAllowed(virDomainObjPtr vm)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
qemuDomainSnapshotFSFreeze(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm) {
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
int freezed;
|
||||
|
||||
if (priv->agentError) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("QEMU guest agent is not "
|
||||
"available due to an error"));
|
||||
return -1;
|
||||
}
|
||||
if (!priv->agent) {
|
||||
qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
||||
_("QEMU guest agent is not configured"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qemuDomainObjEnterAgent(driver, vm);
|
||||
freezed = qemuAgentFSFreeze(priv->agent);
|
||||
qemuDomainObjExitAgent(driver, vm);
|
||||
|
||||
return freezed;
|
||||
}
|
||||
|
||||
static int
|
||||
qemuDomainSnapshotFSThaw(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm) {
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
int thawed;
|
||||
|
||||
if (priv->agentError) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("QEMU guest agent is not "
|
||||
"available due to an error"));
|
||||
return -1;
|
||||
}
|
||||
if (!priv->agent) {
|
||||
qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
||||
_("QEMU guest agent is not configured"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qemuDomainObjEnterAgent(driver, vm);
|
||||
thawed = qemuAgentFSThaw(priv->agent);
|
||||
qemuDomainObjExitAgent(driver, vm);
|
||||
|
||||
return thawed;
|
||||
}
|
||||
|
||||
/* The domain is expected to be locked and inactive. */
|
||||
static int
|
||||
qemuDomainSnapshotCreateInactive(struct qemud_driver *driver,
|
||||
@ -9773,6 +9823,12 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
|
||||
|
||||
|
||||
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
|
||||
if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
|
||||
(qemuDomainSnapshotFSFreeze(driver, vm) < 0)) {
|
||||
/* helper reported the error */
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
/* In qemu, snapshot_blkdev on a single disk will pause cpus,
|
||||
* but this confuses libvirt since notifications are not given
|
||||
* when qemu resumes. And for multiple disks, libvirt must
|
||||
@ -9840,13 +9896,20 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (resume && virDomainObjIsActive(vm) &&
|
||||
qemuProcessStartCPUs(driver, vm, conn,
|
||||
VIR_DOMAIN_RUNNING_UNPAUSED,
|
||||
QEMU_ASYNC_JOB_NONE) < 0 &&
|
||||
virGetLastError() == NULL) {
|
||||
qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
||||
_("resuming after snapshot failed"));
|
||||
if (resume && virDomainObjIsActive(vm)) {
|
||||
if (qemuProcessStartCPUs(driver, vm, conn,
|
||||
VIR_DOMAIN_RUNNING_UNPAUSED,
|
||||
QEMU_ASYNC_JOB_NONE) < 0 &&
|
||||
virGetLastError() == NULL) {
|
||||
qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
||||
_("resuming after snapshot failed"));
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
|
||||
qemuDomainSnapshotFSThaw(driver, vm) < 0) {
|
||||
/* helper reported the error */
|
||||
}
|
||||
}
|
||||
|
||||
if (vm) {
|
||||
@ -9888,7 +9951,15 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY |
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT, NULL);
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT |
|
||||
VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, NULL);
|
||||
|
||||
if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
|
||||
!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY)) {
|
||||
qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("quiesce requires disk-only"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
|
||||
!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
|
||||
|
Loading…
x
Reference in New Issue
Block a user