* 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
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,
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
}
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) {
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)) ||