This copies some of the checks from snapshots regarding testing
when a file already exists. In the process, I noticed a missing
sanity check in snapshots: REUSE_EXT should require the destination
to already be present.
* src/qemu/qemu_driver.c (qemuDomainBlockRebase): Allow REUSE_EXT
flag.
(qemuDomainBlockCopy): Wire up flag, and add some sanity checks.
(qemuDomainSnapshotDiskPrepare): Require destination on REUSE_EXT.
---
src/qemu/qemu_driver.c | 61 +++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1b1c921..0e9ea41 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9812,6 +9812,11 @@ qemuDomainSnapshotDiskPrepare(virDomainObjPtr vm,
virDomainSnapshotDefPtr def,
_("unable to stat for disk %s: %s"),
disk->name, disk->file);
goto cleanup;
+ } else if (allow_reuse) {
+ virReportSystemError(errno,
+ _("missing existing file for disk %s:
%s"),
+ disk->name, disk->file);
+ goto cleanup;
}
} else if (!(S_ISBLK(st.st_mode) || !st.st_size || allow_reuse)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -11881,9 +11886,11 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
int ret = -1;
int idx;
int mode;
+ struct stat st;
/* Preliminaries: find the disk we are editing, sanity checks */
- virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW, -1);
+ virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
+ VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1);
qemuDriverLock(driver);
virUUIDFormat(dom->uuid, uuidstr);
@@ -11928,19 +11935,60 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
goto endjob;
}
+ if ((flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) &&
+ STREQ_NULLABLE(format, "raw") &&
+ STRNEQ_NULLABLE(disk->driverType, "raw")) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("raw shallow copy of non-raw disk '%s' not
possible"),
+ disk->dst);
+ goto endjob;
+ }
+ /* XXX this is pessimistic; we could use 'query-block' or even
+ * keep track of the backing chain ourselves, rather than assuming
+ * that all non-raw source files have a current backing image */
+ if ((flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) &&
+ !(flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) &&
+ STRNEQ_NULLABLE(disk->driverType, "raw")) {
+ qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
+ _("non-shallow copy of non-raw disk '%s' to existing
"
+ "destination not supported"),
+ disk->dst);
+ goto endjob;
+ }
+
/* Prepare the destination file. */
+ if (stat(dest, &st) < 0) {
+ if (errno != ENOENT) {
+ virReportSystemError(errno, _("unable to stat for disk %s: %s"),
+ disk->dst, dest);
+ goto endjob;
+ } else if (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) {
+ virReportSystemError(errno,
+ _("missing destination file for disk %s:
%s"),
+ disk->dst, dest);
+ goto endjob;
+ }
+ } else if (!(S_ISBLK(st.st_mode) || !st.st_size ||
+ (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT))) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("external destination file for disk %s already "
+ "exists and is not a block device: %s"),
+ disk->dst, dest);
+ goto endjob;
+ }
+
/* XXX We also need to add security labeling, lock manager lease,
- * and auditing of those events, as well as to support reuse of
- * existing images, including probing the existing format of an
- * existing image. */
- if (!format)
+ * and auditing of those events. */
+ if (!format && !(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT))
format = disk->driverType;
if ((format && !(disk->mirrorFormat = strdup(format))) ||
!(disk->mirror = strdup(dest))) {
virReportOOMError();
goto endjob;
}
- if (flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW)
+ if (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)
+ mode = QEMU_MONITOR_DRIVE_MIRROR_EXISTING;
+ else if (flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW)
mode = QEMU_MONITOR_DRIVE_MIRROR_ABSOLUTE;
else
mode = QEMU_MONITOR_DRIVE_MIRROR_NO_BACKING;
@@ -11976,6 +12024,7 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const
char *base,
unsigned long bandwidth, unsigned int flags)
{
virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
+ VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
VIR_DOMAIN_BLOCK_REBASE_COPY |
VIR_DOMAIN_BLOCK_REBASE_COPY_RAW, -1);
--
1.7.7.6