From da820e1c2225bc9944fb72c55e4895021d6881e9 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Fri, 15 May 2020 10:59:40 +0200 Subject: [PATCH] virQEMUBuildNetdevCommandlineFromJSON: Prepare for quirky 'guestfwd' QEMU models guestfwd as: 'guestfwd': [ { "str": "tcp:10.0.2.1:4600-chardev:charchannel0" }, { "str": "...."}, ] but the command line as: guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,guestfwd=... I guess the original idea was to make it extensible while not worrying about adding another object for it. Either way it requires us to add yet another JSON->cmdline convertor for arrays. Signed-off-by: Peter Krempa Reviewed-by: Eric Blake --- src/util/virqemu.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/util/virqemu.c b/src/util/virqemu.c index 0f8cab29df..9823ebc14d 100644 --- a/src/util/virqemu.c +++ b/src/util/virqemu.c @@ -109,6 +109,43 @@ virQEMUBuildCommandLineJSONArrayNumbered(const char *key, } +/** + * This array convertor is for quirky cases where the QMP schema mandates an + * array of objects with only one attribute 'str' which needs to be formatted as + * repeated key-value pairs without the 'str' being printed: + * + * 'guestfwd': [ + * { "str": "tcp:10.0.2.1:4600-chardev:charchannel0" }, + * { "str": "...."}, + * ] + * + * guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,guestfwd=... + */ +static int +virQEMUBuildCommandLineJSONArrayObjectsStr(const char *key, + virJSONValuePtr array, + virBufferPtr buf, + const char *skipKey G_GNUC_UNUSED, + bool onOff G_GNUC_UNUSED) +{ + g_auto(virBuffer) tmp = VIR_BUFFER_INITIALIZER; + size_t i; + + for (i = 0; i < virJSONValueArraySize(array); i++) { + virJSONValuePtr member = virJSONValueArrayGet(array, i); + const char *str = virJSONValueObjectGetString(member, "str"); + + if (!str) + return -1; + + virBufferAsprintf(&tmp, "%s=%s,", key, str); + } + + virBufferAddBuffer(buf, &tmp); + return 0; +} + + /* internal iterator to handle nested object formatting */ static int virQEMUBuildCommandLineJSONIterate(const char *key, @@ -267,7 +304,8 @@ virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props) virBufferAsprintf(&buf, "%s,", type); - if (virQEMUBuildCommandLineJSON(props, &buf, "type", true, NULL) < 0) + if (virQEMUBuildCommandLineJSON(props, &buf, "type", true, + virQEMUBuildCommandLineJSONArrayObjectsStr) < 0) return NULL; return virBufferContentAndReset(&buf);