[PATCH 15/21] virQEMUBuildNetdevCommandlineFromJSON: Prepare for quirky 'guestfwd'

Peter Krempa posted 21 patches 5 years, 8 months ago
[PATCH 15/21] virQEMUBuildNetdevCommandlineFromJSON: Prepare for quirky 'guestfwd'
Posted by Peter Krempa 5 years, 8 months ago
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@redhat.com>
---
 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

Re: [PATCH 15/21] virQEMUBuildNetdevCommandlineFromJSON: Prepare for quirky 'guestfwd'
Posted by Eric Blake 5 years, 8 months ago
On 5/15/20 10:28 AM, Peter Krempa wrote:
> 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.

I would have found it easier to mention both the JSON (which you did) 
and the corresponding CLI (which you did not):

-netdev ...,guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,guestfwd=...

But the idea makes sense - the QMP form uses quite a bit of nesting 
(although actual qapfication of netdev occurred late, the hand-rolled 
parser for netdev predated many of the best practices learned for other 
interfaces, and the CLI does not reflect that nesting).

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org