RHEL-only
drive-mirror and drive-reopen are still under upstream qemu
discussion; as a result, RHEL decided to backport things under
a downstream name. Accommodate these differences.
There are a few differences between the upstream proposal[1]
and the RHEL build. The RHEL build uses the __com.redhat_ prefix
to make the differences obvious. Upstream has a mandatory 'full'
argument for 'drive-mirror', and 'drive-mirror' cannot be used
as part of a transaction (that is, upstream only supports streaming
block copy). Downstream treates 'full' as optional (defaulting
to false), and can combine 'blockdev-snapshot-sync' and 'drive-mirror'
in a single 'transaction' in order to support snapshot+mirror in
addition to streaming block copy.
[
1]https://lists.gnu.org/archive/html/qemu-devel/2012-04/msg01630.html
I don't think it's worth trying to support both spellings at once:
if you build upstream libvirt on RHEL, you lose out on the ability
to control the RHEL-specific block copy naming, but then you are also
capable of building upstream qemu to get the upstream spelling of
the same feature (that is, if you use RHEL, you should either stick
to the distro patches across the entire virt stack, or you are assumed
to be capable of building the entire virt stack yourself).
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands):
Check for alternate spelling.
(qemuMonitorJSONDriveReopen): Use that spelling.
(qemuMonitorJSONDriveMirror): Likewise, and add an argument for
snapshot+mirror.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror): Update.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror): Likewise.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror): Likewise.
* src/qemu/qemu_driver.c (qemuDomainBlockCopy): Likewise.
---
was 15/18 in v4
v5: a lot more invasive, now that qemu 1.1 has a firmer proposal
that differs from RHEL's desire to still provide snapshot+mirror
mode in contrast to streaming mirror mode.
src/qemu/qemu_driver.c | 2 +-
src/qemu/qemu_monitor.c | 9 +++---
src/qemu/qemu_monitor.h | 3 +-
src/qemu/qemu_monitor_json.c | 57 +++++++++++++++++++++++++++++++-----------
src/qemu/qemu_monitor_json.h | 3 +-
5 files changed, 52 insertions(+), 22 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a27f6c2..dd49cb9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12055,7 +12055,7 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
/* Actually start the mirroring */
qemuDomainObjEnterMonitorWithDriver(driver, vm);
- ret = qemuMonitorDriveMirror(priv->mon, device, dest, format, flags);
+ ret = qemuMonitorDriveMirror(priv->mon, NULL, device, dest, format, flags);
virDomainAuditDisk(vm, NULL, dest, "mirror", ret >= 0);
if (ret == 0 && bandwidth != 0) {
/* Setting speed now is best-effort. */
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 34c7926..6a050e1 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2687,14 +2687,14 @@ qemuMonitorDiskSnapshot(qemuMonitorPtr mon, virJSONValuePtr
actions,
/* Add the drive-mirror action to a transaction. */
int
-qemuMonitorDriveMirror(qemuMonitorPtr mon,
+qemuMonitorDriveMirror(qemuMonitorPtr mon, virJSONValuePtr actions,
const char *device, const char *file,
const char *format, unsigned int flags)
{
int ret = -1;
- VIR_DEBUG("mon=%p, device=%s, file=%s, format=%s, flags=%x",
- mon, device, file, format, flags);
+ VIR_DEBUG("mon=%p, actions=%p, device=%s, file=%s, format=%s, flags=%x",
+ mon, actions, device, file, format, flags);
if (!mon) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -2703,7 +2703,8 @@ qemuMonitorDriveMirror(qemuMonitorPtr mon,
}
if (mon->json)
- ret = qemuMonitorJSONDriveMirror(mon, device, file, format, flags);
+ ret = qemuMonitorJSONDriveMirror(mon, actions, device, file, format,
+ flags);
else
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("drive-mirror requires JSON monitor"));
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 1b4b130..c8a834b 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -511,11 +511,12 @@ int qemuMonitorDiskSnapshot(qemuMonitorPtr mon,
int qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorDriveMirror(qemuMonitorPtr mon,
+ virJSONValuePtr actions,
const char *device,
const char *file,
const char *format,
unsigned int flags)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
int qemuMonitorDriveReopen(qemuMonitorPtr mon,
const char *device,
const char *file,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 6bce701..8ff1501 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -989,9 +989,9 @@ qemuMonitorJSONCheckCommands(qemuMonitorPtr mon,
qemuCapsSet(qemuCaps, QEMU_CAPS_BLOCKJOB_SYNC);
else if (STREQ(name, "block-job-cancel"))
qemuCapsSet(qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC);
- else if (STREQ(name, "drive-mirror"))
+ else if (STREQ(name, "__com.redhat_drive-mirror"))
qemuCapsSet(qemuCaps, QEMU_CAPS_DRIVE_MIRROR);
- else if (STREQ(name, "drive-reopen"))
+ else if (STREQ(name, "__com.redhat_drive-reopen"))
qemuCapsSet(qemuCaps, QEMU_CAPS_DRIVE_REOPEN);
}
@@ -3205,7 +3205,7 @@ cleanup:
}
int
-qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
+qemuMonitorJSONDriveMirror(qemuMonitorPtr mon, virJSONValuePtr actions,
const char *device, const char *file,
const char *format, unsigned int flags)
{
@@ -3215,20 +3215,47 @@ qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
bool shallow = (flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) != 0;
bool reuse = (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) != 0;
- cmd = qemuMonitorJSONMakeCommand("drive-mirror",
- "s:device", device,
- "s:target", file,
- "b:full", !shallow,
- "s:mode",
- reuse ? "existing" :
"absolute-paths",
- format ? "s:format" : NULL, format,
- NULL);
+ /* In the RHEL build, '__com.redhat_drive-mirror' is also a part
+ * of 'transaction', but when used there, the 'full' argument must
+ * not be given; as a result, the standalone command made 'full'
+ * optional, defaulting to false. */
+ if (actions && !shallow)
+ return -1;
+ if (shallow) {
+ cmd = qemuMonitorJSONMakeCommandRaw(actions != NULL,
+ "__com.redhat_drive-mirror",
+ "s:device", device,
+ "s:target", file,
+ "s:mode",
+ reuse ? "existing" :
"absolute-paths",
+ format ? "s:format" : NULL,
format,
+ NULL);
+ } else {
+ cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive-mirror",
+ "s:device", device,
+ "s:target", file,
+ "b:full", true,
+ "s:mode",
+ reuse ? "existing" :
"absolute-paths",
+ format ? "s:format" : NULL, format,
+ NULL);
+ }
+
if (!cmd)
return -1;
- if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
- goto cleanup;
- ret = qemuMonitorJSONCheckError(cmd, reply);
+ if (actions) {
+ if (virJSONValueArrayAppend(actions, cmd) < 0) {
+ virReportOOMError();
+ } else {
+ cmd = NULL;
+ ret = 0;
+ }
+ } else {
+ if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
+ goto cleanup;
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+ }
cleanup:
virJSONValueFree(cmd);
@@ -3272,7 +3299,7 @@ qemuMonitorJSONDriveReopen(qemuMonitorPtr mon, const char *device,
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
- cmd = qemuMonitorJSONMakeCommand("drive-reopen",
+ cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive-reopen",
"s:device", device,
"s:new-image-file", file,
format ? "s:format" : NULL, format,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index d93c37d..6306e99 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -236,11 +236,12 @@ int qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon,
int qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
+ virJSONValuePtr actions,
const char *device,
const char *file,
const char *format,
unsigned int flags)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
int qemuMonitorJSONDriveReopen(qemuMonitorPtr mon,
const char *device,
const char *file,
--
1.7.7.6