QEMU models guestfwd as: 'guestfwd': [ { "str": "tcp:10.0.2.1:4600-chardev:charchannel0" }, { "str": "...."}, ] 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 <pkrempa@xxxxxxxxxx> --- src/util/virqemu.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/util/virqemu.c b/src/util/virqemu.c index 0f8cab29df..f3e9966598 100644 --- a/src/util/virqemu.c +++ b/src/util/virqemu.c @@ -109,6 +109,41 @@ 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": "...."}, + * ] + */ +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 +302,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); -- 2.26.2