Re: [libvirt PATCH v6 07/30] nodedev: add ability to parse mdevs from mdevctl

2021-03-29 Thread Erik Skultety
On Fri, Mar 26, 2021 at 11:48:03AM -0500, Jonathon Jongsma wrote:
> This function will parse the list of mediated devices that are returned
> by mdevctl and convert it into our internal node device representation.
> 
> Signed-off-by: Jonathon Jongsma 
> ---

...

> @@ -265,13 +312,13 @@ mymain(void)
>  }
>  
>  #define DO_TEST_FULL(desc, func, info) \
> -if (virTestRun(desc, func, ) < 0) \
> +if (virTestRun(desc, func, info) < 0) \
>  ret = -1;
>  
>  #define DO_TEST_START_FULL(virt_type, create, filename) \
>  do { \
>  struct startTestInfo info = { virt_type, create, filename }; \
> -DO_TEST_FULL("mdevctl start " filename, testMdevctlStartHelper, 
> info); \
> +DO_TEST_FULL("mdevctl start " filename, testMdevctlStartHelper, 
> ); \
> } \
>  while (0)

^This IMO deserves a trivial standalone patch.

As for the rest of the code - per the discussion that happened in v4:
Reviewed-by: Erik Skultety 

>  
> @@ -281,6 +328,9 @@ mymain(void)
>  #define DO_TEST_STOP(uuid) \
>  DO_TEST_FULL("mdevctl stop " uuid, testMdevctlStop, uuid)
>  
> +#define DO_TEST_PARSE_JSON(filename) \
> +DO_TEST_FULL("parse mdevctl json " filename, testMdevctlParse, filename)
> +
>  /* Test mdevctl start commands */
>  DO_TEST_START("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366");
>  DO_TEST_START("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
> @@ -289,6 +339,8 @@ mymain(void)
>  /* Test mdevctl stop command, pass an arbitrary uuid */
>  DO_TEST_STOP("e2451f73-c95b-4124-b900-e008af37c576");
>  
> +DO_TEST_PARSE_JSON("mdevctl-list-multiple");
> +
>   done:
>  nodedevTestDriverFree(driver);
>  
> -- 
> 2.26.3
> 



[libvirt PATCH v6 07/30] nodedev: add ability to parse mdevs from mdevctl

2021-03-26 Thread Jonathon Jongsma
This function will parse the list of mediated devices that are returned
by mdevctl and convert it into our internal node device representation.

Signed-off-by: Jonathon Jongsma 
---
 src/node_device/node_device_driver.c  | 143 ++
 src/node_device/node_device_driver.h  |   4 +
 .../mdevctl-list-multiple.json|  59 
 .../mdevctl-list-multiple.out.xml |  39 +
 tests/nodedevmdevctltest.c|  56 ++-
 5 files changed, 299 insertions(+), 2 deletions(-)
 create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple.json
 create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple.out.xml

diff --git a/src/node_device/node_device_driver.c 
b/src/node_device/node_device_driver.c
index bada5bbf00..a646692870 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -860,6 +860,149 @@ virMdevctlStop(virNodeDeviceDefPtr def, char **errmsg)
 }
 
 
+static void mdevGenerateDeviceName(virNodeDeviceDef *dev)
+{
+nodeDeviceGenerateName(dev, "mdev", dev->caps->data.mdev.uuid, NULL);
+}
+
+
+static virNodeDeviceDef*
+nodeDeviceParseMdevctlChildDevice(const char *parent,
+  virJSONValue *json)
+{
+virNodeDevCapMdev *mdev;
+const char *uuid;
+virJSONValue *props;
+virJSONValue *attrs;
+g_autoptr(virNodeDeviceDef) child = g_new0(virNodeDeviceDef, 1);
+
+/* the child object should have a single key equal to its uuid.
+ * The value is an object describing the properties of the mdev */
+if (virJSONValueObjectKeysNumber(json) != 1)
+return NULL;
+
+uuid = virJSONValueObjectGetKey(json, 0);
+props = virJSONValueObjectGetValue(json, 0);
+
+child->parent = g_strdup(parent);
+child->caps = g_new0(virNodeDevCapsDef, 1);
+child->caps->data.type = VIR_NODE_DEV_CAP_MDEV;
+
+mdev = >caps->data.mdev;
+mdev->uuid = g_strdup(uuid);
+mdev->type =
+g_strdup(virJSONValueObjectGetString(props, "mdev_type"));
+
+attrs = virJSONValueObjectGet(props, "attrs");
+
+if (attrs && virJSONValueIsArray(attrs)) {
+size_t i;
+int nattrs = virJSONValueArraySize(attrs);
+
+mdev->attributes = g_new0(virMediatedDeviceAttr*, nattrs);
+mdev->nattributes = nattrs;
+
+for (i = 0; i < nattrs; i++) {
+virJSONValue *attr = virJSONValueArrayGet(attrs, i);
+virMediatedDeviceAttr *attribute;
+virJSONValue *value;
+
+if (!virJSONValueIsObject(attr) ||
+virJSONValueObjectKeysNumber(attr) != 1)
+return NULL;
+
+attribute = g_new0(virMediatedDeviceAttr, 1);
+attribute->name = g_strdup(virJSONValueObjectGetKey(attr, 0));
+value = virJSONValueObjectGetValue(attr, 0);
+attribute->value = g_strdup(virJSONValueGetString(value));
+mdev->attributes[i] = attribute;
+}
+}
+mdevGenerateDeviceName(child);
+
+return g_steal_pointer();
+}
+
+
+int
+nodeDeviceParseMdevctlJSON(const char *jsonstring,
+   virNodeDeviceDef ***devs)
+{
+int n;
+g_autoptr(virJSONValue) json_devicelist = NULL;
+virNodeDeviceDef **outdevs = NULL;
+size_t noutdevs = 0;
+size_t i;
+size_t j;
+
+json_devicelist = virJSONValueFromString(jsonstring);
+
+if (!json_devicelist || !virJSONValueIsArray(json_devicelist)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("mdevctl JSON response contains no devices"));
+goto error;
+}
+
+n = virJSONValueArraySize(json_devicelist);
+
+for (i = 0; i < n; i++) {
+virJSONValue *obj = virJSONValueArrayGet(json_devicelist, i);
+const char *parent;
+virJSONValue *child_array;
+int nchildren;
+
+if (!virJSONValueIsObject(obj)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Parent device is not an object"));
+goto error;
+}
+
+/* mdevctl returns an array of objects.  Each object is a parent device
+ * object containing a single key-value pair which maps from the name
+ * of the parent device to an array of child devices */
+if (virJSONValueObjectKeysNumber(obj) != 1) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Unexpected format for parent device object"));
+goto error;
+}
+
+parent = virJSONValueObjectGetKey(obj, 0);
+child_array = virJSONValueObjectGetValue(obj, 0);
+
+if (!virJSONValueIsArray(child_array)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Parent device's JSON object data is not an 
array"));
+goto error;
+}
+
+nchildren = virJSONValueArraySize(child_array);
+
+for (j = 0; j < nchildren; j++) {
+