6ae9ed
From 4c7c0cbfadf1df719e3236d8ea09e97d2b69cb15 Mon Sep 17 00:00:00 2001
6ae9ed
Message-Id: <4c7c0cbfadf1df719e3236d8ea09e97d2b69cb15@dist-git>
6ae9ed
From: Peter Krempa <pkrempa@redhat.com>
6ae9ed
Date: Tue, 2 Aug 2016 13:42:02 +0200
6ae9ed
Subject: [PATCH] util: qemu: Add support for numbered array members
6ae9ed
6ae9ed
Add support for converting objects nested in arrays with a numbering
6ae9ed
discriminator on the command line. This syntax is used for the
6ae9ed
object-based specification of disk source properties.
6ae9ed
6ae9ed
(cherry picked from commit 74df83a9eba87f81d4190dad0db7e30b9d89c7ea)
6ae9ed
https://bugzilla.redhat.com/show_bug.cgi?id=1247521 [gluster multi-host]
6ae9ed
---
6ae9ed
 src/libvirt_private.syms    |  1 +
6ae9ed
 src/util/virqemu.c          | 33 +++++++++++++++++++++++++++++++++
6ae9ed
 src/util/virqemu.h          |  3 +++
6ae9ed
 tests/qemucommandutiltest.c | 36 +++++++++++++++++++++++++++++++++---
6ae9ed
 4 files changed, 70 insertions(+), 3 deletions(-)
6ae9ed
6ae9ed
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
6ae9ed
index 27bf269..533cf55 100644
6ae9ed
--- a/src/libvirt_private.syms
6ae9ed
+++ b/src/libvirt_private.syms
6ae9ed
@@ -2195,6 +2195,7 @@ virProcessWait;
6ae9ed
 virQEMUBuildBufferEscapeComma;
6ae9ed
 virQEMUBuildCommandLineJSON;
6ae9ed
 virQEMUBuildCommandLineJSONArrayBitmap;
6ae9ed
+virQEMUBuildCommandLineJSONArrayNumbered;
6ae9ed
 virQEMUBuildLuksOpts;
6ae9ed
 virQEMUBuildObjectCommandlineFromJSON;
6ae9ed
 
6ae9ed
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
6ae9ed
index 8babe36..20410f7 100644
6ae9ed
--- a/src/util/virqemu.c
6ae9ed
+++ b/src/util/virqemu.c
6ae9ed
@@ -79,6 +79,39 @@ virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
6ae9ed
 }
6ae9ed
 
6ae9ed
 
6ae9ed
+int
6ae9ed
+virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
6ae9ed
+                                         const virJSONValue *array,
6ae9ed
+                                         virBufferPtr buf)
6ae9ed
+{
6ae9ed
+    const virJSONValue *member;
6ae9ed
+    size_t nelems = virJSONValueArraySize(array);
6ae9ed
+    char *prefix = NULL;
6ae9ed
+    size_t i;
6ae9ed
+    int ret = 0;
6ae9ed
+
6ae9ed
+    for (i = 0; i < nelems; i++) {
6ae9ed
+        member = virJSONValueArrayGet((virJSONValuePtr) array, i);
6ae9ed
+
6ae9ed
+        if (virAsprintf(&prefix, "%s.%zu", key, i) < 0)
6ae9ed
+            goto cleanup;
6ae9ed
+
6ae9ed
+        if (virQEMUBuildCommandLineJSONRecurse(prefix, member, buf,
6ae9ed
+                                               virQEMUBuildCommandLineJSONArrayNumbered,
6ae9ed
+                                               true) < 0)
6ae9ed
+            goto cleanup;
6ae9ed
+
6ae9ed
+        VIR_FREE(prefix);
6ae9ed
+    }
6ae9ed
+
6ae9ed
+    ret = 0;
6ae9ed
+
6ae9ed
+ cleanup:
6ae9ed
+    VIR_FREE(prefix);
6ae9ed
+    return ret;
6ae9ed
+}
6ae9ed
+
6ae9ed
+
6ae9ed
 /* internal iterator to handle nested object formatting */
6ae9ed
 static int
6ae9ed
 virQEMUBuildCommandLineJSONIterate(const char *key,
6ae9ed
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
6ae9ed
index 801c35b..40cd9b8 100644
6ae9ed
--- a/src/util/virqemu.h
6ae9ed
+++ b/src/util/virqemu.h
6ae9ed
@@ -35,6 +35,9 @@ typedef int (*virQEMUBuildCommandLineJSONArrayFormatFunc)(const char *key,
6ae9ed
 int virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
6ae9ed
                                            const virJSONValue *array,
6ae9ed
                                            virBufferPtr buf);
6ae9ed
+int virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
6ae9ed
+                                             const virJSONValue *array,
6ae9ed
+                                             virBufferPtr buf);
6ae9ed
 
6ae9ed
 int virQEMUBuildCommandLineJSON(const virJSONValue *value,
6ae9ed
                                 virBufferPtr buf,
6ae9ed
diff --git a/tests/qemucommandutiltest.c b/tests/qemucommandutiltest.c
6ae9ed
index 0bf0351..1985983 100644
6ae9ed
--- a/tests/qemucommandutiltest.c
6ae9ed
+++ b/tests/qemucommandutiltest.c
6ae9ed
@@ -30,6 +30,7 @@ typedef struct
6ae9ed
 {
6ae9ed
     const char *props;
6ae9ed
     const char *expectprops;
6ae9ed
+    virQEMUBuildCommandLineJSONArrayFormatFunc arrayfunc;
6ae9ed
 } testQemuCommandBuildObjectFromJSONData;
6ae9ed
 
6ae9ed
 static int
6ae9ed
@@ -46,8 +47,7 @@ testQemuCommandBuildFromJSON(const void *opaque)
6ae9ed
         return -1;
6ae9ed
     }
6ae9ed
 
6ae9ed
-    if (virQEMUBuildCommandLineJSON(val, &buf,
6ae9ed
-                                    virQEMUBuildCommandLineJSONArrayBitmap) < 0) {
6ae9ed
+    if (virQEMUBuildCommandLineJSON(val, &buf, data->arrayfunc) < 0) {
6ae9ed
         fprintf(stderr,
6ae9ed
                 "\nvirQEMUBuildCommandlineJSON failed process JSON:\n%s\n",
6ae9ed
                 data->props);
6ae9ed
@@ -83,16 +83,23 @@ mymain(void)
6ae9ed
 
6ae9ed
     virTestCounterReset("testQemuCommandBuildFromJSON");
6ae9ed
 
6ae9ed
-#define DO_TEST_COMMAND_OBJECT_FROM_JSON(PROPS, EXPECT)             \
6ae9ed
+#define DO_TEST_COMMAND_FROM_JSON(PROPS, ARRAYFUNC, EXPECT)         \
6ae9ed
     do {                                                            \
6ae9ed
         data1.props = PROPS;                                        \
6ae9ed
         data1.expectprops = EXPECT;                                 \
6ae9ed
+        data1.arrayfunc = ARRAYFUNC;                                \
6ae9ed
         if (virTestRun(virTestCounterNext(),                        \
6ae9ed
                        testQemuCommandBuildFromJSON,                \
6ae9ed
                        &data1) < 0)                                 \
6ae9ed
             ret = -1;                                               \
6ae9ed
      } while (0)
6ae9ed
 
6ae9ed
+#define DO_TEST_COMMAND_OBJECT_FROM_JSON(PROPS, EXPECT)             \
6ae9ed
+    DO_TEST_COMMAND_FROM_JSON(PROPS, virQEMUBuildCommandLineJSONArrayBitmap, EXPECT)
6ae9ed
+
6ae9ed
+#define DO_TEST_COMMAND_DRIVE_FROM_JSON(PROPS, EXPECT)              \
6ae9ed
+    DO_TEST_COMMAND_FROM_JSON(PROPS, virQEMUBuildCommandLineJSONArrayNumbered, EXPECT)
6ae9ed
+
6ae9ed
     DO_TEST_COMMAND_OBJECT_FROM_JSON("{}", NULL);
6ae9ed
     DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"string\":\"qwer\"}", "string=qwer");
6ae9ed
     DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"string\":\"qw,e,r\"}", "string=qw,,e,,r");
6ae9ed
@@ -120,6 +127,29 @@ mymain(void)
6ae9ed
                                      "}",
6ae9ed
                                      "nest.boolean=yes,nest.hyphen-name=1234,"
6ae9ed
                                      "nest.some_string=bleah,nest.bleah=bl,,eah");
6ae9ed
+    DO_TEST_COMMAND_DRIVE_FROM_JSON("{\"driver\":\"gluster\","
6ae9ed
+                                     "\"volume\":\"test\","
6ae9ed
+                                     "\"path\":\"img\","
6ae9ed
+                                     "\"server\":[ { \"type\":\"tcp\","
6ae9ed
+                                                         "\"host\":\"example.com\","
6ae9ed
+                                                         "\"port\":\"1234\""
6ae9ed
+                                                        "},"
6ae9ed
+                                                        "{ \"type\":\"unix\","
6ae9ed
+                                                          "\"socket\":\"/path/socket\""
6ae9ed
+                                                        "},"
6ae9ed
+                                                        "{ \"type\":\"tcp\","
6ae9ed
+                                                          "\"host\":\"example.com\""
6ae9ed
+                                                        "}"
6ae9ed
+                                                       "]"
6ae9ed
+                                     "}",
6ae9ed
+                                     "driver=gluster,volume=test,path=img,"
6ae9ed
+                                     "server.0.type=tcp,"
6ae9ed
+                                     "server.0.host=example.com,"
6ae9ed
+                                     "server.0.port=1234,"
6ae9ed
+                                     "server.1.type=unix,"
6ae9ed
+                                     "server.1.socket=/path/socket,"
6ae9ed
+                                     "server.2.type=tcp,"
6ae9ed
+                                     "server.2.host=example.com");
6ae9ed
 
6ae9ed
     return ret;
6ae9ed
 
6ae9ed
-- 
6ae9ed
2.9.2
6ae9ed