Blob Blame History Raw
From 4c7c0cbfadf1df719e3236d8ea09e97d2b69cb15 Mon Sep 17 00:00:00 2001
Message-Id: <4c7c0cbfadf1df719e3236d8ea09e97d2b69cb15@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 2 Aug 2016 13:42:02 +0200
Subject: [PATCH] util: qemu: Add support for numbered array members

Add support for converting objects nested in arrays with a numbering
discriminator on the command line. This syntax is used for the
object-based specification of disk source properties.

(cherry picked from commit 74df83a9eba87f81d4190dad0db7e30b9d89c7ea)
https://bugzilla.redhat.com/show_bug.cgi?id=1247521 [gluster multi-host]
---
 src/libvirt_private.syms    |  1 +
 src/util/virqemu.c          | 33 +++++++++++++++++++++++++++++++++
 src/util/virqemu.h          |  3 +++
 tests/qemucommandutiltest.c | 36 +++++++++++++++++++++++++++++++++---
 4 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 27bf269..533cf55 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2195,6 +2195,7 @@ virProcessWait;
 virQEMUBuildBufferEscapeComma;
 virQEMUBuildCommandLineJSON;
 virQEMUBuildCommandLineJSONArrayBitmap;
+virQEMUBuildCommandLineJSONArrayNumbered;
 virQEMUBuildLuksOpts;
 virQEMUBuildObjectCommandlineFromJSON;
 
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
index 8babe36..20410f7 100644
--- a/src/util/virqemu.c
+++ b/src/util/virqemu.c
@@ -79,6 +79,39 @@ virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
 }
 
 
+int
+virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
+                                         const virJSONValue *array,
+                                         virBufferPtr buf)
+{
+    const virJSONValue *member;
+    size_t nelems = virJSONValueArraySize(array);
+    char *prefix = NULL;
+    size_t i;
+    int ret = 0;
+
+    for (i = 0; i < nelems; i++) {
+        member = virJSONValueArrayGet((virJSONValuePtr) array, i);
+
+        if (virAsprintf(&prefix, "%s.%zu", key, i) < 0)
+            goto cleanup;
+
+        if (virQEMUBuildCommandLineJSONRecurse(prefix, member, buf,
+                                               virQEMUBuildCommandLineJSONArrayNumbered,
+                                               true) < 0)
+            goto cleanup;
+
+        VIR_FREE(prefix);
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(prefix);
+    return ret;
+}
+
+
 /* internal iterator to handle nested object formatting */
 static int
 virQEMUBuildCommandLineJSONIterate(const char *key,
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
index 801c35b..40cd9b8 100644
--- a/src/util/virqemu.h
+++ b/src/util/virqemu.h
@@ -35,6 +35,9 @@ typedef int (*virQEMUBuildCommandLineJSONArrayFormatFunc)(const char *key,
 int virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
                                            const virJSONValue *array,
                                            virBufferPtr buf);
+int virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
+                                             const virJSONValue *array,
+                                             virBufferPtr buf);
 
 int virQEMUBuildCommandLineJSON(const virJSONValue *value,
                                 virBufferPtr buf,
diff --git a/tests/qemucommandutiltest.c b/tests/qemucommandutiltest.c
index 0bf0351..1985983 100644
--- a/tests/qemucommandutiltest.c
+++ b/tests/qemucommandutiltest.c
@@ -30,6 +30,7 @@ typedef struct
 {
     const char *props;
     const char *expectprops;
+    virQEMUBuildCommandLineJSONArrayFormatFunc arrayfunc;
 } testQemuCommandBuildObjectFromJSONData;
 
 static int
@@ -46,8 +47,7 @@ testQemuCommandBuildFromJSON(const void *opaque)
         return -1;
     }
 
-    if (virQEMUBuildCommandLineJSON(val, &buf,
-                                    virQEMUBuildCommandLineJSONArrayBitmap) < 0) {
+    if (virQEMUBuildCommandLineJSON(val, &buf, data->arrayfunc) < 0) {
         fprintf(stderr,
                 "\nvirQEMUBuildCommandlineJSON failed process JSON:\n%s\n",
                 data->props);
@@ -83,16 +83,23 @@ mymain(void)
 
     virTestCounterReset("testQemuCommandBuildFromJSON");
 
-#define DO_TEST_COMMAND_OBJECT_FROM_JSON(PROPS, EXPECT)             \
+#define DO_TEST_COMMAND_FROM_JSON(PROPS, ARRAYFUNC, EXPECT)         \
     do {                                                            \
         data1.props = PROPS;                                        \
         data1.expectprops = EXPECT;                                 \
+        data1.arrayfunc = ARRAYFUNC;                                \
         if (virTestRun(virTestCounterNext(),                        \
                        testQemuCommandBuildFromJSON,                \
                        &data1) < 0)                                 \
             ret = -1;                                               \
      } while (0)
 
+#define DO_TEST_COMMAND_OBJECT_FROM_JSON(PROPS, EXPECT)             \
+    DO_TEST_COMMAND_FROM_JSON(PROPS, virQEMUBuildCommandLineJSONArrayBitmap, EXPECT)
+
+#define DO_TEST_COMMAND_DRIVE_FROM_JSON(PROPS, EXPECT)              \
+    DO_TEST_COMMAND_FROM_JSON(PROPS, virQEMUBuildCommandLineJSONArrayNumbered, EXPECT)
+
     DO_TEST_COMMAND_OBJECT_FROM_JSON("{}", NULL);
     DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"string\":\"qwer\"}", "string=qwer");
     DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"string\":\"qw,e,r\"}", "string=qw,,e,,r");
@@ -120,6 +127,29 @@ mymain(void)
                                      "}",
                                      "nest.boolean=yes,nest.hyphen-name=1234,"
                                      "nest.some_string=bleah,nest.bleah=bl,,eah");
+    DO_TEST_COMMAND_DRIVE_FROM_JSON("{\"driver\":\"gluster\","
+                                     "\"volume\":\"test\","
+                                     "\"path\":\"img\","
+                                     "\"server\":[ { \"type\":\"tcp\","
+                                                         "\"host\":\"example.com\","
+                                                         "\"port\":\"1234\""
+                                                        "},"
+                                                        "{ \"type\":\"unix\","
+                                                          "\"socket\":\"/path/socket\""
+                                                        "},"
+                                                        "{ \"type\":\"tcp\","
+                                                          "\"host\":\"example.com\""
+                                                        "}"
+                                                       "]"
+                                     "}",
+                                     "driver=gluster,volume=test,path=img,"
+                                     "server.0.type=tcp,"
+                                     "server.0.host=example.com,"
+                                     "server.0.port=1234,"
+                                     "server.1.type=unix,"
+                                     "server.1.socket=/path/socket,"
+                                     "server.2.type=tcp,"
+                                     "server.2.host=example.com");
 
     return ret;
 
-- 
2.9.2