[libvirt] [PATCH v2 0/3] Use guest agent to quiesce disks

Since we have qemu guest agent support in libvirt, we can start wiring up some things that GA already knows how to do. One of them is file system freeze and thaw. Domain snapshots can profit from this functionality. Michal Privoznik (3): qemu_agent: Create file system freeze and thaw functions snapshots: Introduce VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag virsh: Expose new VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag include/libvirt/libvirt.h.in | 4 ++ src/libvirt.c | 6 +++ src/qemu/qemu_agent.c | 74 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_agent.h | 3 + src/qemu/qemu_driver.c | 87 ++++++++++++++++++++++++++++++++++++++---- tools/virsh.c | 6 +++ tools/virsh.pod | 16 +++++++- 7 files changed, 186 insertions(+), 10 deletions(-) -- 1.7.3.4

These functions simply issue command to guest agent which should freeze or unfreeze all file systems within guest. --- src/qemu/qemu_agent.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_agent.h | 3 ++ 2 files changed, 77 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 6a7c7b3..9df5546 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1110,3 +1110,77 @@ int qemuAgentShutdown(qemuAgentPtr mon, virJSONValueFree(reply); return ret; } + +/* + * qemuAgentFSFreeze: + * @mon: Agent + * + * Issue guest-fsfreeze-freeze command to guest agent, + * which freezes all mounted file systems and returns + * number of frozen file systems on success. + * + * Returns: number of file system frozen on success, + * -1 on error. + */ +int qemuAgentFSFreeze(qemuAgentPtr mon) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + cmd = qemuAgentMakeCommand("guest-fsfreeze-freeze", NULL); + + if (!cmd) + return -1; + + if (qemuAgentCommand(mon, cmd, &reply) < 0 || + qemuAgentCheckError(cmd, reply) < 0) + goto cleanup; + + if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed return value")); + } + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + +/* + * qemuAgentFSThaw: + * @mon: Agent + * + * Issue guest-fsfreeze-thaw command to guest agent, + * which unfreezes all mounted file systems and returns + * number of thawed file systems on success. + * + * Returns: number of file system thawed on success, + * -1 on error. + */ +int qemuAgentFSThaw(qemuAgentPtr mon) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + cmd = qemuAgentMakeCommand("guest-fsfreeze-thaw", NULL); + + if (!cmd) + return -1; + + if (qemuAgentCommand(mon, cmd, &reply) < 0 || + qemuAgentCheckError(cmd, reply) < 0) + goto cleanup; + + if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed return value")); + } + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 93c2ae7..df59ef7 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -66,4 +66,7 @@ typedef enum { int qemuAgentShutdown(qemuAgentPtr mon, qemuAgentShutdownMode mode); +int qemuAgentFSFreeze(qemuAgentPtr mon); +int qemuAgentFSThaw(qemuAgentPtr mon); + #endif /* __QEMU_AGENT_H__ */ -- 1.7.3.4

I am happy that you provide the patches.
These functions simply issue command to guest agent which should freeze or unfreeze all file systems within guest. --- src/qemu/qemu_agent.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_agent.h | 3 ++ 2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 6a7c7b3..9df5546 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1110,3 +1110,77 @@ int qemuAgentShutdown(qemuAgentPtr mon, virJSONValueFree(reply); return ret; } + +/* + * qemuAgentFSFreeze: + * @mon: Agent + * + * Issue guest-fsfreeze-freeze command to guest agent, + * which freezes all mounted file systems and returns + * number of frozen file systems on success. + * + * Returns: number of file system frozen on success, + * -1 on error. + */ +int qemuAgentFSFreeze(qemuAgentPtr mon) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + cmd = qemuAgentMakeCommand("guest-fsfreeze-freeze", NULL); + + if (!cmd) + return -1; + + if (qemuAgentCommand(mon, cmd,&reply)< 0 || + qemuAgentCheckError(cmd, reply)< 0) + goto cleanup; + + if (virJSONValueObjectGetNumberInt(reply, "return",&ret)< 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed return value")); + } + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + +/* + * qemuAgentFSThaw: + * @mon: Agent + * + * Issue guest-fsfreeze-thaw command to guest agent, + * which unfreezes all mounted file systems and returns + * number of thawed file systems on success. + * + * Returns: number of file system thawed on success, + * -1 on error. + */ +int qemuAgentFSThaw(qemuAgentPtr mon) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + cmd = qemuAgentMakeCommand("guest-fsfreeze-thaw", NULL); + + if (!cmd) + return -1; + + if (qemuAgentCommand(mon, cmd,&reply)< 0 || + qemuAgentCheckError(cmd, reply)< 0) + goto cleanup; + + if (virJSONValueObjectGetNumberInt(reply, "return",&ret)< 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed return value")); + } + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +}
But qemuAgentFSFreeze() and qemuAgentFSThaw() are almost same. In addition, qemu guest agent provides status option for FS Freezer. So, could you change to following? VIR_ENUM_DECL(qemuAgentFSFreezeCtlMode); VIR_ENUM_IMPL(qemuAgentFSFreezeCtlMode, QEMU_AGENT_FSFREEZE_LAST, "guest-fsfreeze-freeze", "guest-fsfreeze-thaw", "guest-fsfreeze-status"); int qemuAgentFSFreezeCtl(qemuAGentPtr mon, qemuAgentFSFreezeCtlMode mode){ ... cmd = qemuAgentMakeCommand(qemuAgentFSFreezeCtlModeToString(mode), NULL); ...
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 93c2ae7..df59ef7 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -66,4 +66,7 @@ typedef enum { int qemuAgentShutdown(qemuAgentPtr mon, qemuAgentShutdownMode mode);
+int qemuAgentFSFreeze(qemuAgentPtr mon); +int qemuAgentFSThaw(qemuAgentPtr mon); + #endif /* __QEMU_AGENT_H__ */
Similarly int qemuAgentFSFreezeCtl(qemuAgentPtr mon, qemuAgentFSFreezeCtlMode mode);

On 01/24/2012 04:17 PM, MATSUDA, Daiki wrote:
I am happy that you provide the patches.
These functions simply issue command to guest agent which should freeze or unfreeze all file systems within guest. ---
But qemuAgentFSFreeze() and qemuAgentFSThaw() are almost same. In addition, qemu guest agent provides status option for FS Freezer. So, could you change to following?
VIR_ENUM_DECL(qemuAgentFSFreezeCtlMode);
VIR_ENUM_IMPL(qemuAgentFSFreezeCtlMode, QEMU_AGENT_FSFREEZE_LAST, "guest-fsfreeze-freeze", "guest-fsfreeze-thaw", "guest-fsfreeze-status");
That would make sense if we planned on exposing guest freeze and thaw directly to the user. But right now, we are only planning on using guest freeze and thaw internally as part of our higher-level snapshot create function, where we do freeze and thaw in a balanced pair, and where our command is blocking so that there is no need to call status (that is, if we exposed a libvirt command to query the status, you would only ever be able to call it when we are not in the middle of a snapshot, and thus the fs would always report that it is in a thawed state, unless someone has gone behind libvirt's back, at which point why are you using libvirt). Maybe you can convince me otherwise that we need to expose these three lower-level states to the user, rather than using them internally only for the implementation of the higher-level commands like snapshot-create, but unless we have a reason to expose this much detail, I don't think we need to make your proposed change. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

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 | 87 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 89 insertions(+), 8 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..722a2e2 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 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 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c81289a..ab69dca 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, @@ -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)) || -- 1.7.3.4

On 01/24/2012 01:21 PM, Michal Privoznik wrote:
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 | 87 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 89 insertions(+), 8 deletions(-)
Late review, but I just noticed this since I'm now touching the same area of code:
+++ 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 thrown. Moreover, this flag requires + * VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY to be passed as well.
[note to self - if I ever get disk-only snapshots of offline guests to work by using qemu-img, then quiesce can be ignored, since an offline guest is by definition quiesced]
+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);
Does qemuDomainObjEnterAgent and/or the common code that actually tries to pass a message over the agent socket ensure that the guest is still running? If the guest is online, but paused, then we know for a fact that the guest agent will not respond in a timely manner. Rather than make all callers check for this situation, I'm thinking that it would make sense to check that the vm is running prior to issuing a guest-agent command, and to issue an early error, rather than waiting for a timeout when we finally realize the guest never responded. This is particularly important for the quiesce command. Consider what happens if we don't check for paused first: - guest is paused - we issue the quiesce command which gets buffered up, but it times out without being delivered - we fail the command - the guest is resumed, and now consumes the data that was pending on the monitor - the guest goes into quiesce, but our command is no longer around to thaw the guest. I think we need to ensure that any failure path where we issued a quiesce command, _even if the quiesce command failed due to a timeout_, we _also_ issue a thaw command. If the quiesce command failed, we also expect the thaw command to fail, but if the failure was due to the guest being paused, now when the guest wakes up, it will have two pending commands on the bus, and will temporarily quiesce but then thaw right back. Of course, a paused guest isn't the only reason for a timeout, so we need to make sure of paired calls even if we also teach qemDomainObjEnterAgent to make both freeze and thaw be instant fails on a paused guest.
@@ -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; + }
Note that if the guest is paused instead of running, and the QUIESCE flag is present, we fail to quiesce the disk. That means the snapshot we took is not stable. Okay, we only documented the QUIESCE flag as a best-effort (and anything that relies on the guest agent is inherently best-effort, as we can't trust the guest), but I think it makes more sense to _always_ attempt the FSFreeze on an active guest, and abort the snapshot if quiesce fails (including but not limited to the case where the guest is paused), rather than only attempting the quiesce on a running guest.
+ /* 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 */ + }
Again, we need go guarantee that if qemuDomainSnapshotFSFreeze was called, then this is also called; but that we only pay attention to an error here according to whether the freeze was reported as successful. I'm also worried about the atomic aspect - if we take the snapshot, and it is only the thaw that fails, we
+ + 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; + }
This restriction makes sense for now, but I think that it may be worth lifting someday if I figure out how to do a RAM snapshot with external disk snapshots. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

to cmdSnapshotCreate and cmdSnapshotCreateAs. --- tools/virsh.c | 6 ++++++ tools/virsh.pod | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 5560988..999941c 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -14662,6 +14662,7 @@ static const vshCmdOptDef opts_snapshot_create[] = { {"halt", VSH_OT_BOOL, 0, N_("halt domain after snapshot is created")}, {"disk-only", VSH_OT_BOOL, 0, N_("capture disk state but not vm state")}, {"reuse-external", VSH_OT_BOOL, 0, N_("reuse any existing external files")}, + {"quiesce", VSH_OT_BOOL, 0, N_("quiesce guest's file systems")}, {NULL, 0, 0, NULL} }; @@ -14686,6 +14687,8 @@ cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY; if (vshCommandOptBool(cmd, "reuse-external")) flags |= VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT; + if (vshCommandOptBool(cmd, "quiesce")) + flags |= VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE; if (!vshConnectionUsability(ctl, ctl->conn)) goto cleanup; @@ -14795,6 +14798,7 @@ static const vshCmdOptDef opts_snapshot_create_as[] = { {"halt", VSH_OT_BOOL, 0, N_("halt domain after snapshot is created")}, {"disk-only", VSH_OT_BOOL, 0, N_("capture disk state but not vm state")}, {"reuse-external", VSH_OT_BOOL, 0, N_("reuse any existing external files")}, + {"quiesce", VSH_OT_BOOL, 0, N_("quiesce guest's file systems")}, {"diskspec", VSH_OT_ARGV, 0, N_("disk attributes: disk[,snapshot=type][,driver=type][,file=name]")}, {NULL, 0, 0, NULL} @@ -14820,6 +14824,8 @@ cmdSnapshotCreateAs(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY; if (vshCommandOptBool(cmd, "reuse-external")) flags |= VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT; + if (vshCommandOptBool(cmd, "quiesce")) + flags |= VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE; if (!vshConnectionUsability(ctl, ctl->conn)) goto cleanup; diff --git a/tools/virsh.pod b/tools/virsh.pod index 72c6d8f..b6962cf 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -2046,7 +2046,8 @@ used to represent properties of snapshots. =over 4 =item B<snapshot-create> I<domain> [I<xmlfile>] {[I<--redefine> [I<--current>]] -| [I<--no-metadata>] [I<--halt>] [I<--disk-only>] [I<--reuse-external]} +| [I<--no-metadata>] [I<--halt>] [I<--disk-only>] [I<--reuse-external] +[I<--quiesce>]} Create a snapshot for domain I<domain> with the properties specified in I<xmlfile>. Normally, the only properties settable for a domain snapshot @@ -2088,6 +2089,11 @@ external snapshot with a destination of an existing file, then the existing file is truncated and reused; otherwise, a snapshot is refused to avoid losing contents of the existing files. +If I<--quiesce> is specified, libvirt will try to use guest agent +to freeze and unfreeze domain's mounted file systems. However, +if domain has no guest agent, snapshot creation will fail. +Currently, this requires I<--disk-only> to be passed as well. + Existence of snapshot metadata will prevent attempts to B<undefine> a persistent domain. However, for transient domains, snapshot metadata is silently lost when the domain quits running (whether @@ -2095,7 +2101,8 @@ by command such as B<destroy> or by internal guest action). =item B<snapshot-create-as> I<domain> {[I<--print-xml>] | [I<--no-metadata>] [I<--halt>] [I<--reuse-existing>]} [I<name>] -[I<description>] [I<--disk-only> [[I<--diskspec>] B<diskspec>]...] +[I<description>] [I<--disk-only> [I<--quiesce>] +[[I<--diskspec>] B<diskspec>]...] Create a snapshot for domain I<domain> with the given <name> and <description>; if either value is omitted, libvirt will choose a @@ -2123,6 +2130,11 @@ option requests an external snapshot with a destination of an existing file, then the existing file is truncated and reused; otherwise, a snapshot is refused to avoid losing contents of the existing files. +If I<--quiesce> is specified, libvirt will try to use guest agent +to freeze and unfreeze domain's mounted file systems. However, +if domain has no guest agent, snapshot creation will fail. +Currently, this requires I<--disk-only> to be passed as well. + If I<--no-metadata> is specified, then the snapshot data is created, but any metadata is immediately discarded (that is, libvirt does not treat the snapshot as current, and cannot revert to the snapshot -- 1.7.3.4

On Tue, Jan 24, 2012 at 21:21:32 +0100, Michal Privoznik wrote:
Since we have qemu guest agent support in libvirt, we can start wiring up some things that GA already knows how to do. One of them is file system freeze and thaw. Domain snapshots can profit from this functionality.
Michal Privoznik (3): qemu_agent: Create file system freeze and thaw functions snapshots: Introduce VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag virsh: Expose new VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag
ACK series. Jirka

On 25.01.2012 11:02, Jiri Denemark wrote:
On Tue, Jan 24, 2012 at 21:21:32 +0100, Michal Privoznik wrote:
Since we have qemu guest agent support in libvirt, we can start wiring up some things that GA already knows how to do. One of them is file system freeze and thaw. Domain snapshots can profit from this functionality.
Michal Privoznik (3): qemu_agent: Create file system freeze and thaw functions snapshots: Introduce VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag virsh: Expose new VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag
ACK series.
Jirka
Thanks, pushed. Michal
participants (4)
-
Eric Blake
-
Jiri Denemark
-
MATSUDA, Daiki
-
Michal Privoznik