[libvirt] [PATCHv2 08/15] blockjob: expose qemu commands for mirrored storage migration

Eric Blake eblake at redhat.com
Fri Apr 6 04:36:54 UTC 2012


The new block copy storage migration sequence requires both the
'drive-mirror' action in 'transaction' (present if the 'drive-mirror'
standalone monitor command also exists) and the 'drive-reopen' monitor
command (it would be nice if that were also part of a 'transaction',
but the initial qemu implementation has it standalone only).

As of this[1] qemu email, both commands have been proposed but not yet
incorporated into the tree, so there is a risk that qemu 1.1 will
not have these commands, or will have something subtly different.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-03/msg01524.html

* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDriveReopen): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDriveReopen): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDriveReopen): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDriveReopen): Declare them.
---
 src/qemu/qemu_capabilities.c |    3 ++
 src/qemu/qemu_capabilities.h |    2 +
 src/qemu/qemu_monitor.c      |   50 ++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.h      |   23 +++++++++++++
 src/qemu/qemu_monitor_json.c |   74 +++++++++++++++++++++++++++++++++++++++--
 src/qemu/qemu_monitor_json.h |   21 +++++++++++-
 6 files changed, 167 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 0e09d6d..1938ae4 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -156,6 +156,9 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
               "scsi-disk.channel",
               "scsi-block",
               "transaction",
+
+              "drive-mirror", /* 90 */
+              "drive-reopen",
     );

 struct qemu_feature_flags {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 78cdbe0..405bf2a 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -124,6 +124,8 @@ enum qemuCapsFlags {
     QEMU_CAPS_SCSI_DISK_CHANNEL  = 87, /* Is scsi-disk.channel available? */
     QEMU_CAPS_SCSI_BLOCK         = 88, /* -device scsi-block */
     QEMU_CAPS_TRANSACTION        = 89, /* transaction monitor command */
+    QEMU_CAPS_DRIVE_MIRROR       = 90, /* drive-mirror monitor command */
+    QEMU_CAPS_DRIVE_REOPEN       = 91, /* drive-reopen monitor command */

     QEMU_CAPS_LAST,                   /* this must always be the last item */
 };
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index e1a8d4c..f33bed8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2685,6 +2685,32 @@ qemuMonitorDiskSnapshot(qemuMonitorPtr mon, virJSONValuePtr actions,
     return ret;
 }

+/* Add the drive-mirror action to a transaction.  */
+int
+qemuMonitorDriveMirror(qemuMonitorPtr mon, virJSONValuePtr actions,
+                       const char *device, const char *file,
+                       const char *format, int mode)
+{
+    int ret;
+
+    VIR_DEBUG("mon=%p, actions=%p, device=%s, file=%s, format=%s, mode=%o",
+              mon, actions, device, file, format, mode);
+
+    if (!mon) {
+        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("monitor must not be NULL"));
+        return -1;
+    }
+
+    if (mon->json)
+        ret = qemuMonitorJSONDriveMirror(mon, actions, device, file, format,
+                                         mode);
+    else
+        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("drive-mirror requires JSON monitor"));
+    return ret;
+}
+
 /* Use the transaction QMP command to run atomic snapshot commands.  */
 int
 qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
@@ -2701,6 +2727,30 @@ qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
     return ret;
 }

+/* Use the drive-reopen monitor command.  */
+int
+qemuMonitorDriveReopen(qemuMonitorPtr mon, const char *device,
+                       const char *file, const char *format)
+{
+    int ret;
+
+    VIR_DEBUG("mon=%p, device=%s, file=%s, format=%s",
+              mon, device, file, format);
+
+    if (!mon) {
+        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("monitor must not be NULL"));
+        return -1;
+    }
+
+    if (mon->json)
+        ret = qemuMonitorJSONDriveReopen(mon, device, file, format);
+    else
+        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("drive-reopen requires JSON monitor"));
+    return ret;
+}
+
 int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
                                 const char *cmd,
                                 char **reply,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 2e6ac79..bbeb330 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -508,8 +508,31 @@ int qemuMonitorDiskSnapshot(qemuMonitorPtr mon,
                             const char *file,
                             const char *format,
                             bool reuse);
+
+typedef enum {
+    QEMU_MONITOR_DRIVE_MIRROR_ABSOLUTE,
+    QEMU_MONITOR_DRIVE_MIRROR_EXISTING,
+    QEMU_MONITOR_DRIVE_MIRROR_NO_BACKING,
+
+    QEMU_MONITOR_DRIVE_MIRROR_LAST
+} qemuMonitorDriveMirrorMode;
+
+int qemuMonitorDriveMirror(qemuMonitorPtr mon,
+                           virJSONValuePtr actions,
+                           const char *device,
+                           const char *file,
+                           const char *format,
+                           int mode)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
 int qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+int qemuMonitorDriveReopen(qemuMonitorPtr mon,
+                           const char *device,
+                           const char *file,
+                           const char *format)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_NONNULL(4);

 int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
                                 const char *cmd,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index d4aca5c..93ebfbf 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -967,12 +967,14 @@ qemuMonitorJSONCheckCommands(qemuMonitorPtr mon,

         if (STREQ(name, "human-monitor-command"))
             *json_hmp = 1;
-
-        if (STREQ(name, "system_wakeup"))
+        else if (STREQ(name, "system_wakeup"))
             qemuCapsSet(qemuCaps, QEMU_CAPS_WAKEUP);
-
-        if (STREQ(name, "transaction"))
+        else if (STREQ(name, "transaction"))
             qemuCapsSet(qemuCaps, QEMU_CAPS_TRANSACTION);
+        else if (STREQ(name, "drive-mirror"))
+            qemuCapsSet(qemuCaps, QEMU_CAPS_DRIVE_MIRROR);
+        else if (STREQ(name, "drive-reopen"))
+            qemuCapsSet(qemuCaps, QEMU_CAPS_DRIVE_REOPEN);
     }

     ret = 0;
@@ -3185,6 +3187,43 @@ cleanup:
     return ret;
 }

+VIR_ENUM_DECL(qemuMonitorDriveMirror)
+VIR_ENUM_IMPL(qemuMonitorDriveMirror, QEMU_MONITOR_DRIVE_MIRROR_LAST,
+              "absolute-paths", "exsisting", "no-backing-file");
+
+int
+qemuMonitorJSONDriveMirror(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+                           virJSONValuePtr actions,
+                           const char *device, const char *file,
+                           const char *format, int mode)
+{
+    int ret = -1;
+    virJSONValuePtr cmd;
+
+    cmd = qemuMonitorJSONMakeCommandRaw(true,
+                                        "drive-mirror",
+                                        "s:device", device,
+                                        "s:target", file,
+                                        "s:format", format,
+                                        "s:mode",
+                                        qemuMonitorDriveMirrorTypeToString(mode),
+                                        NULL);
+    if (!cmd)
+        return -1;
+
+    if (virJSONValueArrayAppend(actions, cmd) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    cmd = NULL;
+    ret = 0;
+
+cleanup:
+    virJSONValueFree(cmd);
+    return ret;
+}
+
 int
 qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
 {
@@ -3214,6 +3253,33 @@ cleanup:
     return ret;
 }

+int
+qemuMonitorJSONDriveReopen(qemuMonitorPtr mon,  const char *device,
+                           const char *file, const char *format)
+{
+    int ret;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+
+    cmd = qemuMonitorJSONMakeCommand("drive-reopen",
+                                     "s:device", device,
+                                     "s:new-image-file", file,
+                                     "s:format", format,
+                                     NULL);
+    if (!cmd)
+        return -1;
+
+    if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
+        goto cleanup;
+
+    ret = qemuMonitorJSONCheckError(cmd, reply);
+
+cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
+
 int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
                                     const char *cmd_str,
                                     char **reply_str,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index a0f67aa..ce23bc1 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -230,8 +230,25 @@ int qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon,
                                 const char *device,
                                 const char *file,
                                 const char *format,
-                                bool reuse);
-int qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions);
+                                bool reuse)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
+int qemuMonitorJSONDriveMirror(qemuMonitorPtr mon,
+                               virJSONValuePtr actions,
+                               const char *device,
+                               const char *file,
+                               const char *format,
+                               int mode)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
+int qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+int qemuMonitorJSONDriveReopen(qemuMonitorPtr mon,
+                               const char *device,
+                               const char *file,
+                               const char *format)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_NONNULL(4);

 int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
                                     const char *cmd_str,
-- 
1.7.7.6




More information about the libvir-list mailing list