Currently qemuDomainBlockCopy only support local file. This patch make the rbd external destination file could be passed to qemu driver_mirror. If the flag VIR_DOMAIN_BLOCK_COPY_REUSE_EXT is not set for rbd protocol, qemuDomainBlockCopy will report an error. Signed-off-by: Liu Qing <liuqing@xxxxxxxxxx> --- src/qemu/qemu_driver.c | 119 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 37 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a82e58b..c0b7fda 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -16609,6 +16609,12 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, virQEMUDriverConfigPtr cfg = NULL; const char *format = NULL; int desttype = virStorageSourceGetActualType(mirror); + char *mirr_path = NULL; + qemuDomainSecretInfoPtr tmp_secinfo = NULL; + qemuDomainSecretInfoPtr mirr_secinfo = NULL; + qemuDomainSecretInfoPtr tmp_encinfo = NULL; + virStorageSourcePtr tmp_src = NULL; + qemuDomainDiskPrivatePtr diskPriv = NULL; /* Preliminaries: find the disk we are editing, sanity checks */ virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW | @@ -16629,6 +16635,8 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, if (!(disk = qemuDomainDiskByName(vm->def, path))) goto endjob; + diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + if (!(device = qemuAliasFromDisk(disk))) goto endjob; @@ -16675,51 +16683,67 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, } /* Prepare the destination file. */ - /* XXX Allow non-file mirror destinations */ - if (!virStorageSourceIsLocalStorage(mirror)) { + if (!virStorageSourceIsLocalStorage(mirror) && + (mirror->type != VIR_STORAGE_TYPE_NETWORK || + mirror->protocol != VIR_STORAGE_NET_PROTOCOL_RBD)) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("non-file destination not supported yet")); goto endjob; } - if (stat(mirror->path, &st) < 0) { - if (errno != ENOENT) { - virReportSystemError(errno, _("unable to stat for disk %s: %s"), - disk->dst, mirror->path); - goto endjob; - } else if (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT || - desttype == VIR_STORAGE_TYPE_BLOCK) { - virReportSystemError(errno, - _("missing destination file for disk %s: %s"), - disk->dst, mirror->path); - goto endjob; - } - } else if (!S_ISBLK(st.st_mode)) { - if (st.st_size && !(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("external destination file for disk %s already " - "exists and is not a block device: %s"), - disk->dst, mirror->path); - goto endjob; - } - if (desttype == VIR_STORAGE_TYPE_BLOCK) { - virReportError(VIR_ERR_INVALID_ARG, - _("blockdev flag requested for disk %s, but file " - "'%s' is not a block device"), - disk->dst, mirror->path); - goto endjob; + if (virStorageSourceIsLocalStorage(mirror)) { + if (stat(mirror->path, &st) < 0) { + if (errno != ENOENT) { + virReportSystemError(errno, _("unable to stat for disk %s: %s"), + disk->dst, mirror->path); + goto endjob; + } else if (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT || + desttype == VIR_STORAGE_TYPE_BLOCK) { + virReportSystemError(errno, + _("missing destination file for disk %s: %s"), + disk->dst, mirror->path); + goto endjob; + } + } else if (!S_ISBLK(st.st_mode)) { + if (st.st_size && !(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("external destination file for disk %s already " + "exists and is not a block device: %s"), + disk->dst, mirror->path); + goto endjob; + } + if (desttype == VIR_STORAGE_TYPE_BLOCK) { + virReportError(VIR_ERR_INVALID_ARG, + _("blockdev flag requested for disk %s, but file " + "'%s' is not a block device"), + disk->dst, mirror->path); + goto endjob; + } } + } else if (!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) { + virReportError(VIR_ERR_INVALID_ARG, + "%s", + _("only external destination file is supported for " + "rbd protocol")); + goto endjob; } if (!mirror->format) { - if (!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) { - mirror->format = disk->src->format; - } else { - /* If the user passed the REUSE_EXT flag, then either they - * can also pass the RAW flag or use XML to tell us the format. - * So if we get here, we assume it is safe for us to probe the - * format from the file that we will be using. */ - mirror->format = virStorageFileProbeFormat(mirror->path, cfg->user, + if (virStorageSourceIsLocalStorage(mirror)) { + if (!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) { + mirror->format = disk->src->format; + } else { + /* If the user passed the REUSE_EXT flag, then either they + * can also pass the RAW flag or use XML to tell us the format. + * So if we get here, we assume it is safe for us to probe the + * format from the file that we will be using. */ + mirror->format = virStorageFileProbeFormat(mirror->path, cfg->user, cfg->group); + } + } else { + virReportError(VIR_ERR_INVALID_ARG, + _("format is required for %s"), + mirror->path); + goto endjob; } } @@ -16745,9 +16769,29 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, goto endjob; } + tmp_secinfo = diskPriv->secinfo; + tmp_encinfo = diskPriv->encinfo; + tmp_src = disk->src; + disk->src = mirror; + + if (qemuDomainSecretDiskPrepare(conn, priv, disk) < 0) { + disk->src = tmp_src; + diskPriv->secinfo = tmp_secinfo; + diskPriv->encinfo = tmp_encinfo; + goto endjob; + } + + disk->src = tmp_src; + mirr_secinfo = diskPriv->secinfo; + diskPriv->secinfo = tmp_secinfo; + diskPriv->encinfo = tmp_encinfo; + + if (qemuGetDriveSourceString(mirror, mirr_secinfo, &mirr_path) < 0) + goto endjob; + /* Actually start the mirroring */ qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorDriveMirror(priv->mon, device, mirror->path, format, + ret = qemuMonitorDriveMirror(priv->mon, device, mirr_path, format, bandwidth, granularity, buf_size, flags); virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0); if (qemuDomainObjExitMonitor(driver, vm) < 0) @@ -16775,6 +16819,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, qemuDomainObjEndJob(driver, vm); cleanup: + VIR_FREE(mirr_path); VIR_FREE(device); virObjectUnref(cfg); return ret; -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list