With this flag, virDomainSnapshotCreate will use fs-freeze and fs-thaw guest agent commands to quiesce guest's disks. --- include/libvirt/libvirt.h.in | 4 ++ src/libvirt.c | 6 ++ src/qemu/qemu_driver.c | 118 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 113 insertions(+), 15 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5e6e488..182065d 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -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 */ diff --git a/src/libvirt.c b/src/libvirt.c index 96ad3d5..d9b8d88 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -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 trowed. Moreover, this flags 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 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c81289a..14ad30b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -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, @@ -9493,6 +9543,13 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn, } if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { + if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) && + (qemuDomainSnapshotFSFreeze(driver, vm) < 0)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to freeze domain's file systems")); + goto endjob; + } + /* savevm monitor command pauses the domain emitting an event which * confuses libvirt since it's not notified when qemu resumes the * domain. Thus we stop and start CPUs ourselves. @@ -9532,13 +9589,21 @@ qemuDomainSnapshotCreateActive(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) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to thaw domain's file systems")); + } } endjob: @@ -9773,6 +9838,13 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn, if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { + if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) && + (qemuDomainSnapshotFSFreeze(driver, vm) < 0)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to freeze domain's file systems")); + 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 +9912,21 @@ 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) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to thaw domain's file systems")); + } } if (vm) { @@ -9888,7 +9968,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)) || -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list