From nobody Mon Feb 9 17:35:18 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) client-ip=205.139.110.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1594938141; cv=none; d=zohomail.com; s=zohoarc; b=UqCJIryoBAOrpaXE53gI2PniJ8SDAXSCiC0fxMFAjVaivU/3VfjFR5ZnEXFsEn3IeOIOyzBv7jAGao2VMZala5/cbAMq/CrlhAyUeDaT6Ahz6rusPl4G4+5x/UmHuVcb50fMT/DFtn8N8iJAspMjOfrn28nzYfa0AU1VqMHUGrg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594938141; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+sKOi4jebnbwzR4M6hYwC4yo6dwPGStnonAOFHIpeUk=; b=Sp1CPbBimld0oYvOSJJOKFKZW5LoehjEDtDW9r8fCJIQHAIJxVQVvRfCEwyswhWqbIuGBqnRlVl+NtBMUU2HRhXZe8eW8ArKOKQ4f5GMxgP5owBRBtjVqOUt/7XT6rYtDy4LoXv99SPAheCGDB853nssZrPnZga9x4xV9ap5rd8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by mx.zohomail.com with SMTPS id 1594938141363815.9989015071029; Thu, 16 Jul 2020 15:22:21 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-226-XsvvlxttOrqOObYMKRQFWA-1; Thu, 16 Jul 2020 18:22:17 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 508DD800468; Thu, 16 Jul 2020 22:22:11 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2472D75540; Thu, 16 Jul 2020 22:22:11 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id DE6341806B0D; Thu, 16 Jul 2020 22:22:10 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 06GMLpvf022289 for ; Thu, 16 Jul 2020 18:21:51 -0400 Received: by smtp.corp.redhat.com (Postfix) id D8ADB6FED1; Thu, 16 Jul 2020 22:21:51 +0000 (UTC) Received: from himantopus.redhat.com (ovpn-112-38.phx2.redhat.com [10.3.112.38]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8ECB0724B8 for ; Thu, 16 Jul 2020 22:21:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594938140; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=+sKOi4jebnbwzR4M6hYwC4yo6dwPGStnonAOFHIpeUk=; b=ZCTxEblYpMpW6EQZNnbJ+BEiQJwYS7rK+YHexlRGbzchmKgXRQGc0AL9RRcCWg38cAY0V6 ByHaJ72QAcK+jsMTcOxs3u3eb3S82dL5ih1pwcojSgITzQ47lP63vj6aUDACBmeF3QGYsp VXEFk7L7LvdZNvbo0avshkQdPFMwOPs= X-MC-Unique: XsvvlxttOrqOObYMKRQFWA-1 From: Jonathon Jongsma To: libvir-list@redhat.com Subject: [libvirt PATCH 05/16] nodedev: add ability to list and parse defined mdevs Date: Thu, 16 Jul 2020 17:21:35 -0500 Message-Id: <20200716222146.1241-6-jjongsma@redhat.com> In-Reply-To: <20200716222146.1241-1-jjongsma@redhat.com> References: <20200716222146.1241-1-jjongsma@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" This adds some internal API to query for persistent mediated devices that are defined by mdevctl. Following commits will make use of this information. This just provides the infrastructure and tests for this feature. One test verifies that we are executing mdevctl with the proper arguments, and other tests verify that we can parse the returned JSON and convert it to our own internal node device representations. Signed-off-by: Jonathon Jongsma --- src/node_device/node_device_driver.c | 154 ++++++++++++++++++ src/node_device/node_device_driver.h | 13 ++ src/node_device/node_device_udev.c | 19 +-- .../mdevctl-list-defined.argv | 1 + .../mdevctl-list-multiple-parents.json | 59 +++++++ .../mdevctl-list-multiple-parents.out.xml | 39 +++++ .../mdevctl-list-multiple.json | 59 +++++++ .../mdevctl-list-multiple.out.xml | 39 +++++ .../mdevctl-list-single-noattr.json | 11 ++ .../mdevctl-list-single-noattr.out.xml | 8 + .../mdevctl-list-single.json | 31 ++++ .../mdevctl-list-single.out.xml | 14 ++ tests/nodedevmdevctltest.c | 97 +++++++++++ 13 files changed, 528 insertions(+), 16 deletions(-) create mode 100644 tests/nodedevmdevctldata/mdevctl-list-defined.argv create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple-parents.= json create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple-parents.= out.xml create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple.json create mode 100644 tests/nodedevmdevctldata/mdevctl-list-multiple.out.xml create mode 100644 tests/nodedevmdevctldata/mdevctl-list-single-noattr.json create mode 100644 tests/nodedevmdevctldata/mdevctl-list-single-noattr.out= .xml create mode 100644 tests/nodedevmdevctldata/mdevctl-list-single.json create mode 100644 tests/nodedevmdevctldata/mdevctl-list-single.out.xml diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_de= vice_driver.c index f766fd9f32..cb8965a6d9 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -812,6 +812,135 @@ virMdevctlStop(virNodeDeviceDefPtr def) } =20 =20 +virCommandPtr +nodeDeviceGetMdevctlListCommand(bool defined, + char **output) +{ + virCommandPtr cmd =3D virCommandNewArgList(MDEVCTL, + "list", + "--dumpjson", + NULL); + + if (defined) + virCommandAddArg(cmd, "--defined"); + + virCommandSetOutputBuffer(cmd, output); + + return cmd; +} + + +static void mdevGenerateDeviceName(virNodeDeviceDefPtr dev) +{ + nodeDeviceGenerateName(dev, "mdev", dev->caps->data.mdev.uuid, NULL); +} + +int +nodeDeviceParseMdevctlJSON(const char *jsonstring, + virNodeDeviceDefPtr **devs) +{ + int n; + g_autoptr(virJSONValue) json_devicelist =3D NULL; + virNodeDeviceDefPtr *outdevs =3D NULL; + size_t noutdevs =3D 0; + + json_devicelist =3D virJSONValueFromString(jsonstring); + + if (!json_devicelist) + goto parsefailure; + + if (!virJSONValueIsArray(json_devicelist)) + goto parsefailure; + + n =3D virJSONValueArraySize(json_devicelist); + + for (int i =3D 0; i < n; i++) { + virJSONValuePtr obj =3D virJSONValueArrayGet(json_devicelist, i); + int nparents; + + if (!virJSONValueIsObject(obj)) + goto parsefailure; + + nparents =3D virJSONValueObjectKeysNumber(obj); + + for (int j =3D 0; j < nparents; j++) { + const char *parent =3D virJSONValueObjectGetKey(obj, j); + virJSONValuePtr child_array =3D virJSONValueObjectGetValue(obj= , j); + int nchildren; + + if (!virJSONValueIsArray(child_array)) + goto parsefailure; + + nchildren =3D virJSONValueArraySize(child_array); + + for (int k =3D 0; k < nchildren; k++) { + virNodeDevCapMdevPtr mdev; + const char *uuid; + virJSONValuePtr props; + g_autoptr(virNodeDeviceDef) child =3D g_new0(virNodeDevice= Def, 1); + virJSONValuePtr child_obj =3D virJSONValueArrayGet(child_a= rray, k); + + /* 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(child_obj) !=3D 1) + goto parsefailure; + + uuid =3D virJSONValueObjectGetKey(child_obj, 0); + props =3D virJSONValueObjectGetValue(child_obj, 0); + + child->parent =3D g_strdup(parent); + child->caps =3D g_new0(virNodeDevCapsDef, 1); + child->caps->data.type =3D VIR_NODE_DEV_CAP_MDEV; + + mdev =3D &child->caps->data.mdev; + mdev->uuid =3D g_strdup(uuid); + mdev->type =3D + g_strdup(virJSONValueObjectGetString(props, "mdev_type= ")); + + virJSONValuePtr attrs =3D virJSONValueObjectGet(props, "at= trs"); + + if (attrs && virJSONValueIsArray(attrs)) { + int nattrs =3D virJSONValueArraySize(attrs); + + mdev->attributes =3D g_new0(virMediatedDeviceAttrPtr, = nattrs); + mdev->nattributes =3D nattrs; + + for (int m =3D 0; m < nattrs; m++) { + virJSONValuePtr attr =3D virJSONValueArrayGet(attr= s, m); + virMediatedDeviceAttrPtr attribute; + + if (!virJSONValueIsObject(attr) || + virJSONValueObjectKeysNumber(attr) !=3D 1) + goto parsefailure; + + attribute =3D g_new0(virMediatedDeviceAttr, 1); + attribute->name =3D g_strdup(virJSONValueObjectGet= Key(attr, 0)); + virJSONValuePtr value =3D virJSONValueObjectGetVal= ue(attr, 0); + attribute->value =3D g_strdup(virJSONValueGetStrin= g(value)); + mdev->attributes[m] =3D attribute; + } + } + mdevGenerateDeviceName(child); + + if (VIR_APPEND_ELEMENT(outdevs, noutdevs, child) < 0) + child =3D NULL; + } + } + } + + *devs =3D outdevs; + return noutdevs; + + parsefailure: + for (int i =3D 0; i < noutdevs; i++) + virNodeDeviceDefFree(outdevs[i]); + VIR_FREE(outdevs); + + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", "unable to parse JSON res= ponse"); + return -1; +} + + int nodeDeviceDestroy(virNodeDevicePtr device) { @@ -931,3 +1060,28 @@ nodedevRegister(void) # endif #endif } + + +void +nodeDeviceGenerateName(virNodeDeviceDefPtr def, + const char *subsystem, + const char *sysname, + const char *s) +{ + size_t i; + g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; + + virBufferAsprintf(&buf, "%s_%s", + subsystem, + sysname); + + if (s !=3D NULL) + virBufferAsprintf(&buf, "_%s", s); + + def->name =3D virBufferContentAndReset(&buf); + + for (i =3D 0; i < strlen(def->name); i++) { + if (!(g_ascii_isalnum(*(def->name + i)))) + *(def->name + i) =3D '_'; + } +} diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_de= vice_driver.h index be5d397828..e7317fd67a 100644 --- a/src/node_device/node_device_driver.h +++ b/src/node_device/node_device_driver.h @@ -123,3 +123,16 @@ nodeDeviceGetMdevctlStartCommand(virNodeDeviceDefPtr d= ef, char **uuid_out); virCommandPtr nodeDeviceGetMdevctlStopCommand(const char *uuid); + +virCommandPtr +nodeDeviceGetMdevctlListCommand(bool defined, char **output); + +int +nodeDeviceParseMdevctlJSON(const char *jsonstring, + virNodeDeviceDefPtr **devs); + +void +nodeDeviceGenerateName(virNodeDeviceDefPtr def, + const char *subsystem, + const char *sysname, + const char *s); diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi= ce_udev.c index bce5466131..93b74b1f24 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -293,22 +293,9 @@ udevGenerateDeviceName(struct udev_device *device, virNodeDeviceDefPtr def, const char *s) { - size_t i; - g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; - - virBufferAsprintf(&buf, "%s_%s", - udev_device_get_subsystem(device), - udev_device_get_sysname(device)); - - if (s !=3D NULL) - virBufferAsprintf(&buf, "_%s", s); - - def->name =3D virBufferContentAndReset(&buf); - - for (i =3D 0; i < strlen(def->name); i++) { - if (!(g_ascii_isalnum(*(def->name + i)))) - *(def->name + i) =3D '_'; - } + nodeDeviceGenerateName(def, + udev_device_get_subsystem(device), + udev_device_get_sysname(device), s); =20 return 0; } diff --git a/tests/nodedevmdevctldata/mdevctl-list-defined.argv b/tests/nod= edevmdevctldata/mdevctl-list-defined.argv new file mode 100644 index 0000000000..72b5906e9e --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-defined.argv @@ -0,0 +1 @@ +$MDEVCTL_BINARY$ list --dumpjson --defined diff --git a/tests/nodedevmdevctldata/mdevctl-list-multiple-parents.json b/= tests/nodedevmdevctldata/mdevctl-list-multiple-parents.json new file mode 100644 index 0000000000..eefcd90c62 --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-multiple-parents.json @@ -0,0 +1,59 @@ +[ + { + "0000:00:02.0": [ + { + "200f228a-c80a-4d50-bfb7-f5a0e4e34045": { + "mdev_type": "i915-GVTg_V5_4", + "start": "manual" + } + }, + { + "de807ffc-1923-4d5f-b6c9-b20ecebc6d4b": { + "mdev_type": "i915-GVTg_V5_4", + "start": "auto" + } + }, + { + "435722ea-5f43-468a-874f-da34f1217f13": { + "mdev_type": "i915-GVTg_V5_8", + "start": "manual", + "attrs": [ + { + "testattr": "42" + } + ] + } + } + ] + }, + { + "matrix": [ + { "783e6dbb-ea0e-411f-94e2-717eaad438bf": { + "mdev_type": "vfio_ap-passthrough", + "start": "manual", + "attrs": [ + { + "assign_adapter": "5" + }, + { + "assign_adapter": "6" + }, + { + "assign_domain": "0xab" + }, + { + "assign_control_domain": "0xab" + }, + { + "assign_domain": "4" + }, + { + "assign_control_domain": "4" + } + ] + } + } + ] + } +] + diff --git a/tests/nodedevmdevctldata/mdevctl-list-multiple-parents.out.xml= b/tests/nodedevmdevctldata/mdevctl-list-multiple-parents.out.xml new file mode 100644 index 0000000000..543ad916b7 --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-multiple-parents.out.xml @@ -0,0 +1,39 @@ + + mdev_200f228a_c80a_4d50_bfb7_f5a0e4e34045 + 0000:00:02.0 + + + + + + + mdev_de807ffc_1923_4d5f_b6c9_b20ecebc6d4b + 0000:00:02.0 + + + + + + + mdev_435722ea_5f43_468a_874f_da34f1217f13 + 0000:00:02.0 + + + + + + + + mdev_783e6dbb_ea0e_411f_94e2_717eaad438bf + matrix + + + + + + + + + + + diff --git a/tests/nodedevmdevctldata/mdevctl-list-multiple.json b/tests/no= dedevmdevctldata/mdevctl-list-multiple.json new file mode 100644 index 0000000000..eefcd90c62 --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-multiple.json @@ -0,0 +1,59 @@ +[ + { + "0000:00:02.0": [ + { + "200f228a-c80a-4d50-bfb7-f5a0e4e34045": { + "mdev_type": "i915-GVTg_V5_4", + "start": "manual" + } + }, + { + "de807ffc-1923-4d5f-b6c9-b20ecebc6d4b": { + "mdev_type": "i915-GVTg_V5_4", + "start": "auto" + } + }, + { + "435722ea-5f43-468a-874f-da34f1217f13": { + "mdev_type": "i915-GVTg_V5_8", + "start": "manual", + "attrs": [ + { + "testattr": "42" + } + ] + } + } + ] + }, + { + "matrix": [ + { "783e6dbb-ea0e-411f-94e2-717eaad438bf": { + "mdev_type": "vfio_ap-passthrough", + "start": "manual", + "attrs": [ + { + "assign_adapter": "5" + }, + { + "assign_adapter": "6" + }, + { + "assign_domain": "0xab" + }, + { + "assign_control_domain": "0xab" + }, + { + "assign_domain": "4" + }, + { + "assign_control_domain": "4" + } + ] + } + } + ] + } +] + diff --git a/tests/nodedevmdevctldata/mdevctl-list-multiple.out.xml b/tests= /nodedevmdevctldata/mdevctl-list-multiple.out.xml new file mode 100644 index 0000000000..543ad916b7 --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-multiple.out.xml @@ -0,0 +1,39 @@ + + mdev_200f228a_c80a_4d50_bfb7_f5a0e4e34045 + 0000:00:02.0 + + + + + + + mdev_de807ffc_1923_4d5f_b6c9_b20ecebc6d4b + 0000:00:02.0 + + + + + + + mdev_435722ea_5f43_468a_874f_da34f1217f13 + 0000:00:02.0 + + + + + + + + mdev_783e6dbb_ea0e_411f_94e2_717eaad438bf + matrix + + + + + + + + + + + diff --git a/tests/nodedevmdevctldata/mdevctl-list-single-noattr.json b/tes= ts/nodedevmdevctldata/mdevctl-list-single-noattr.json new file mode 100644 index 0000000000..acee3eb628 --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-single-noattr.json @@ -0,0 +1,11 @@ +[ + { + "matrix": [ + { "783e6dbb-ea0e-411f-94e2-717eaad438bf": { + "mdev_type": "vfio_ap-passthrough", + "start": "manual" + } + } + ] + } +] diff --git a/tests/nodedevmdevctldata/mdevctl-list-single-noattr.out.xml b/= tests/nodedevmdevctldata/mdevctl-list-single-noattr.out.xml new file mode 100644 index 0000000000..85958695da --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-single-noattr.out.xml @@ -0,0 +1,8 @@ + + mdev_783e6dbb_ea0e_411f_94e2_717eaad438bf + matrix + + + + + diff --git a/tests/nodedevmdevctldata/mdevctl-list-single.json b/tests/node= devmdevctldata/mdevctl-list-single.json new file mode 100644 index 0000000000..a1843c2c8e --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-single.json @@ -0,0 +1,31 @@ +[ + { + "matrix": [ + { "783e6dbb-ea0e-411f-94e2-717eaad438bf": { + "mdev_type": "vfio_ap-passthrough", + "start": "manual", + "attrs": [ + { + "assign_adapter": "5" + }, + { + "assign_adapter": "6" + }, + { + "assign_domain": "0xab" + }, + { + "assign_control_domain": "0xab" + }, + { + "assign_domain": "4" + }, + { + "assign_control_domain": "4" + } + ] + } + } + ] + } +] diff --git a/tests/nodedevmdevctldata/mdevctl-list-single.out.xml b/tests/n= odedevmdevctldata/mdevctl-list-single.out.xml new file mode 100644 index 0000000000..cb443346ef --- /dev/null +++ b/tests/nodedevmdevctldata/mdevctl-list-single.out.xml @@ -0,0 +1,14 @@ + + mdev_783e6dbb_ea0e_411f_94e2_717eaad438bf + matrix + + + + + + + + + + + diff --git a/tests/nodedevmdevctltest.c b/tests/nodedevmdevctltest.c index d75dfb1d3e..585d23d72e 100644 --- a/tests/nodedevmdevctltest.c +++ b/tests/nodedevmdevctltest.c @@ -143,6 +143,87 @@ testMdevctlStop(const void *data) return ret; } =20 +static int +testMdevctlListDefined(const void *data G_GNUC_UNUSED) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + const char *actualCmdline =3D NULL; + int ret =3D -1; + g_autoptr(virCommand) cmd =3D NULL; + g_autofree char *output =3D NULL; + g_autofree char *cmdlinefile =3D + g_strdup_printf("%s/nodedevmdevctldata/mdevctl-list-defined.argv", + abs_srcdir); + + cmd =3D nodeDeviceGetMdevctlListCommand(true, &output); + + if (!cmd) + goto cleanup; + + virCommandSetDryRun(&buf, NULL, NULL); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + if (!(actualCmdline =3D virBufferCurrentContent(&buf))) + goto cleanup; + + if (nodedevCompareToFile(actualCmdline, cmdlinefile) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + virBufferFreeAndReset(&buf); + virCommandSetDryRun(NULL, NULL, NULL); + return ret; +} + +static int +testMdevctlParse(const void *data) +{ + g_autofree char *buf =3D NULL; + const char *filename =3D data; + g_autofree char *jsonfile =3D g_strdup_printf("%s/nodedevmdevctldata/%= s.json", + abs_srcdir, filename); + g_autofree char *xmloutfile =3D g_strdup_printf("%s/nodedevmdevctldata= /%s.out.xml", + abs_srcdir, filename); + g_autofree char *actualxml =3D NULL; + int ret =3D -1; + int nmdevs =3D 0; + virNodeDeviceDefPtr *mdevs =3D NULL; + virBuffer xmloutbuf =3D VIR_BUFFER_INITIALIZER; + + if (virFileReadAll(jsonfile, 1024*1024, &buf) < 0) { + VIR_TEST_DEBUG("Unable to read file %s", jsonfile); + return -1; + } + + if ((nmdevs =3D nodeDeviceParseMdevctlJSON(buf, &mdevs)) < 0) { + VIR_TEST_DEBUG("Unable to parse json for %s", filename); + return -1; + } + + for (int i =3D 0; i < nmdevs; i++) { + g_autofree char *devxml =3D virNodeDeviceDefFormat(mdevs[i]); + if (!devxml) + goto cleanup; + virBufferAddStr(&xmloutbuf, devxml); + } + + if (nodedevCompareToFile(virBufferCurrentContent(&xmloutbuf), xmloutfi= le) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + virBufferFreeAndReset(&xmloutbuf); + for (int i =3D 0; i < nmdevs; i++) + virNodeDeviceDefFree(mdevs[i]); + g_free(mdevs); + + return ret; +} + static void nodedevTestDriverFree(virNodeDeviceDriverStatePtr drv) { @@ -284,6 +365,15 @@ mymain(void) #define DO_TEST_STOP(uuid) \ DO_TEST_FULL("mdevctl stop " uuid, testMdevctlStop, uuid) =20 +#define DO_TEST_LIST_DEFINED() \ + do { \ + if (virTestRun("mdevctl list --defined", testMdevctlListDefined, N= ULL) < 0) \ + ret =3D -1; \ + } while (0) + +#define DO_TEST_PARSE_JSON(filename) \ + DO_TEST_FULL("parse mdevctl json " filename, testMdevctlParse, filenam= e) + /* Test mdevctl start commands */ DO_TEST_START("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366"); DO_TEST_START("mdev_fedc4916_1ca8_49ac_b176_871d16c13076"); @@ -292,6 +382,13 @@ mymain(void) /* Test mdevctl stop command, pass an arbitrary uuid */ DO_TEST_STOP("e2451f73-c95b-4124-b900-e008af37c576"); =20 + DO_TEST_LIST_DEFINED(); + + DO_TEST_PARSE_JSON("mdevctl-list-single"); + DO_TEST_PARSE_JSON("mdevctl-list-single-noattr"); + DO_TEST_PARSE_JSON("mdevctl-list-multiple"); + DO_TEST_PARSE_JSON("mdevctl-list-multiple-parents"); + done: nodedevTestDriverFree(driver); =20 --=20 2.21.3