6ae9ed
From 6360c62ec2a0ccfb66346daa3566930111685598 Mon Sep 17 00:00:00 2001
6ae9ed
Message-Id: <6360c62ec2a0ccfb66346daa3566930111685598@dist-git>
6ae9ed
From: Peter Krempa <pkrempa@redhat.com>
6ae9ed
Date: Tue, 2 Aug 2016 13:41:44 +0200
6ae9ed
Subject: [PATCH] util: qemu: Allow nested objects in JSON -> commandline
6ae9ed
 generator
6ae9ed
6ae9ed
Move the iterator of objects to the recursive function so that nested
6ae9ed
objects are supported by flattening the structure with '.' delimiters.
6ae9ed
6ae9ed
(cherry picked from commit cd86d6f4656d01894141840531d61595e40e4682)
6ae9ed
6ae9ed
https://bugzilla.redhat.com/show_bug.cgi?id=1134878 [JSON backing]
6ae9ed
https://bugzilla.redhat.com/show_bug.cgi?id=1247521 [gluster multi-host]
6ae9ed
---
6ae9ed
 src/util/virqemu.c          | 70 ++++++++++++++++++++++++++++++++++-----------
6ae9ed
 tests/qemucommandutiltest.c |  8 ++++++
6ae9ed
 2 files changed, 61 insertions(+), 17 deletions(-)
6ae9ed
6ae9ed
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
6ae9ed
index 99c14c2..df665ad 100644
6ae9ed
--- a/src/util/virqemu.c
6ae9ed
+++ b/src/util/virqemu.c
6ae9ed
@@ -26,11 +26,49 @@
6ae9ed
 #include "virerror.h"
6ae9ed
 #include "virlog.h"
6ae9ed
 #include "virqemu.h"
6ae9ed
+#include "virstring.h"
6ae9ed
+#include "viralloc.h"
6ae9ed
 
6ae9ed
 #define VIR_FROM_THIS VIR_FROM_NONE
6ae9ed
 
6ae9ed
 VIR_LOG_INIT("util.qemu");
6ae9ed
 
6ae9ed
+struct virQEMUCommandLineJSONIteratorData {
6ae9ed
+    const char *prefix;
6ae9ed
+    virBufferPtr buf;
6ae9ed
+};
6ae9ed
+
6ae9ed
+
6ae9ed
+static int
6ae9ed
+virQEMUBuildCommandLineJSONRecurse(const char *key,
6ae9ed
+                                   const virJSONValue *value,
6ae9ed
+                                   virBufferPtr buf,
6ae9ed
+                                   bool nested);
6ae9ed
+
6ae9ed
+/* internal iterator to handle nested object formatting */
6ae9ed
+static int
6ae9ed
+virQEMUBuildCommandLineJSONIterate(const char *key,
6ae9ed
+                                   const virJSONValue *value,
6ae9ed
+                                   void *opaque)
6ae9ed
+{
6ae9ed
+    struct virQEMUCommandLineJSONIteratorData *data = opaque;
6ae9ed
+    char *tmpkey = NULL;
6ae9ed
+    int ret = -1;
6ae9ed
+
6ae9ed
+    if (data->prefix) {
6ae9ed
+        if (virAsprintf(&tmpkey, "%s.%s", data->prefix, key) < 0)
6ae9ed
+            return -1;
6ae9ed
+
6ae9ed
+        ret = virQEMUBuildCommandLineJSONRecurse(tmpkey, value, data->buf, false);
6ae9ed
+
6ae9ed
+        VIR_FREE(tmpkey);
6ae9ed
+    } else {
6ae9ed
+        ret = virQEMUBuildCommandLineJSONRecurse(key, value, data->buf, false);
6ae9ed
+    }
6ae9ed
+
6ae9ed
+    return ret;
6ae9ed
+}
6ae9ed
+
6ae9ed
 
6ae9ed
 static int
6ae9ed
 virQEMUBuildCommandLineJSONRecurse(const char *key,
6ae9ed
@@ -38,12 +76,19 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
6ae9ed
                                    virBufferPtr buf,
6ae9ed
                                    bool nested)
6ae9ed
 {
6ae9ed
+    struct virQEMUCommandLineJSONIteratorData data = { key, buf };
6ae9ed
     virJSONValuePtr elem;
6ae9ed
     virBitmapPtr bitmap = NULL;
6ae9ed
     ssize_t pos = -1;
6ae9ed
     ssize_t end;
6ae9ed
     size_t i;
6ae9ed
 
6ae9ed
+    if (!key && value->type != VIR_JSON_TYPE_OBJECT) {
6ae9ed
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6ae9ed
+                       _("only JSON objects can be top level"));
6ae9ed
+        return -1;
6ae9ed
+    }
6ae9ed
+
6ae9ed
     switch ((virJSONType) value->type) {
6ae9ed
     case VIR_JSON_TYPE_STRING:
6ae9ed
         virBufferAsprintf(buf, ",%s=", key);
6ae9ed
@@ -96,10 +141,15 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
6ae9ed
         break;
6ae9ed
 
6ae9ed
     case VIR_JSON_TYPE_OBJECT:
6ae9ed
+        if (virJSONValueObjectForeachKeyValue(value,
6ae9ed
+                                              virQEMUBuildCommandLineJSONIterate,
6ae9ed
+                                              &data) < 0)
6ae9ed
+            return -1;
6ae9ed
+        break;
6ae9ed
+
6ae9ed
     case VIR_JSON_TYPE_NULL:
6ae9ed
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6ae9ed
-                       _("NULL and OBJECT JSON types can't be converted to "
6ae9ed
-                         "commandline string"));
6ae9ed
+                       _("NULL JSON type can't be converted to commandline"));
6ae9ed
         return -1;
6ae9ed
     }
6ae9ed
 
6ae9ed
@@ -108,15 +158,6 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
6ae9ed
 }
6ae9ed
 
6ae9ed
 
6ae9ed
-static int
6ae9ed
-virQEMUBuildCommandLineJSONIterate(const char *key,
6ae9ed
-                                   const virJSONValue *value,
6ae9ed
-                                   void *opaque)
6ae9ed
-{
6ae9ed
-    return virQEMUBuildCommandLineJSONRecurse(key, value, opaque, false);
6ae9ed
-}
6ae9ed
-
6ae9ed
-
6ae9ed
 /**
6ae9ed
  * virQEMUBuildCommandLineJSON:
6ae9ed
  * @value: json object containing the value
6ae9ed
@@ -131,12 +172,7 @@ int
6ae9ed
 virQEMUBuildCommandLineJSON(const virJSONValue *value,
6ae9ed
                             virBufferPtr buf)
6ae9ed
 {
6ae9ed
-    if (virJSONValueObjectForeachKeyValue(value,
6ae9ed
-                                          virQEMUBuildCommandLineJSONIterate,
6ae9ed
-                                          buf) < 0)
6ae9ed
-        return -1;
6ae9ed
-
6ae9ed
-    return 0;
6ae9ed
+    return virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, false);
6ae9ed
 }
6ae9ed
 
6ae9ed
 
6ae9ed
diff --git a/tests/qemucommandutiltest.c b/tests/qemucommandutiltest.c
6ae9ed
index 8299462..4872ea3 100644
6ae9ed
--- a/tests/qemucommandutiltest.c
6ae9ed
+++ b/tests/qemucommandutiltest.c
6ae9ed
@@ -117,6 +117,14 @@ mymain(void)
6ae9ed
                                      "array=bleah,array=qwerty,array=1");
6ae9ed
     DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"boolean\":true,\"hyphen-name\":1234,\"some_string\":\"bleah\"}",
6ae9ed
                                      "boolean=yes,hyphen-name=1234,some_string=bleah");
6ae9ed
+    DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"nest\": {\"boolean\":true,"
6ae9ed
+                                                 "\"hyphen-name\":1234,"
6ae9ed
+                                                 "\"some_string\":\"bleah\","
6ae9ed
+                                                 "\"bleah\":\"bl,eah\""
6ae9ed
+                                                 "}"
6ae9ed
+                                     "}",
6ae9ed
+                                     "nest.boolean=yes,nest.hyphen-name=1234,"
6ae9ed
+                                     "nest.some_string=bleah,nest.bleah=bl,,eah");
6ae9ed
 
6ae9ed
     return ret;
6ae9ed
 
6ae9ed
-- 
6ae9ed
2.9.2
6ae9ed