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.
---
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 9937200..296b036 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2208,6 +2208,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.0