From nobody Sun Feb 8 19:39:59 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.25 as permitted sender) client-ip=209.132.183.25; envelope-from=libvir-list-bounces@redhat.com; helo=mx4-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.25 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx4-phx2.redhat.com (mx4-phx2.redhat.com [209.132.183.25]) by mx.zohomail.com with SMTPS id 1489180488118909.2499673532136; Fri, 10 Mar 2017 13:14:48 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx4-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v2ALBQN2009171; Fri, 10 Mar 2017 16:11:26 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v2ALAt4X023899 for ; Fri, 10 Mar 2017 16:10:55 -0500 Received: from localhost.localdomain.com (ovpn-117-9.phx2.redhat.com [10.3.117.9]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v2ALArRj011410 for ; Fri, 10 Mar 2017 16:10:55 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Fri, 10 Mar 2017 16:10:35 -0500 Message-Id: <20170310211050.27784-4-jferlan@redhat.com> In-Reply-To: <20170310211050.27784-1-jferlan@redhat.com> References: <20170310211050.27784-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v3 03/18] conf: Split out storage pool source adapter helpers 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: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Split out the code that munges through the storage pool adapter into helpers - it's about to be moved into it's own source file. This is purely code motion at this point. Signed-off-by: John Ferlan --- src/conf/storage_conf.c | 455 ++++++++++++++++++++++++++------------------= ---- 1 file changed, 243 insertions(+), 212 deletions(-) diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 8e3b175..1993d3a 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -463,6 +463,128 @@ virStoragePoolObjRemove(virStoragePoolObjListPtr pool= s, } =20 static int +virStoragePoolDefParseSourceAdapter(virStoragePoolSourcePtr source, + xmlXPathContextPtr ctxt) +{ + int ret =3D -1; + char *adapter_type =3D NULL; + char *managed =3D NULL; + + if ((adapter_type =3D virXPathString("string(./adapter/@type)", ctxt))= ) { + if ((source->adapter.type =3D + virStoragePoolSourceAdapterTypeFromString(adapter_type)) <=3D= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown pool adapter type '%s'"), + adapter_type); + goto cleanup; + } + + if (source->adapter.type =3D=3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + source->adapter.data.fchost.parent =3D + virXPathString("string(./adapter/@parent)", ctxt); + managed =3D virXPathString("string(./adapter/@managed)", ctxt); + if (managed) { + source->adapter.data.fchost.managed =3D + virTristateBoolTypeFromString(managed); + if (source->adapter.data.fchost.managed < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown fc_host managed setting '%s'= "), + managed); + goto cleanup; + } + } + + source->adapter.data.fchost.parent_wwnn =3D + virXPathString("string(./adapter/@parent_wwnn)", ctxt); + source->adapter.data.fchost.parent_wwpn =3D + virXPathString("string(./adapter/@parent_wwpn)", ctxt); + source->adapter.data.fchost.parent_fabric_wwn =3D + virXPathString("string(./adapter/@parent_fabric_wwn)", ctx= t); + + source->adapter.data.fchost.wwpn =3D + virXPathString("string(./adapter/@wwpn)", ctxt); + source->adapter.data.fchost.wwnn =3D + virXPathString("string(./adapter/@wwnn)", ctxt); + } else if (source->adapter.type =3D=3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + + source->adapter.data.scsi_host.name =3D + virXPathString("string(./adapter/@name)", ctxt); + if (virXPathNode("./adapter/parentaddr", ctxt)) { + xmlNodePtr addrnode =3D virXPathNode("./adapter/parentaddr= /address", + ctxt); + virPCIDeviceAddressPtr addr =3D + &source->adapter.data.scsi_host.parentaddr; + + if (!addrnode) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing scsi_host PCI address elemen= t")); + goto cleanup; + } + source->adapter.data.scsi_host.has_parent =3D true; + if (virPCIDeviceAddressParseXML(addrnode, addr) < 0) + goto cleanup; + if ((virXPathInt("string(./adapter/parentaddr/@unique_id)", + ctxt, + &source->adapter.data.scsi_host.unique_id= ) < 0) || + (source->adapter.data.scsi_host.unique_id < 0)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing or invalid scsi adapter " + "'unique_id' value")); + goto cleanup; + } + } + } + } else { + char *wwnn =3D NULL; + char *wwpn =3D NULL; + char *parent =3D NULL; + + /* "type" was not specified in the XML, so we must verify that + * "wwnn", "wwpn", "parent", or "parentaddr" are also not in the + * XML. If any are found, then we cannot just use "name" alone". + */ + wwnn =3D virXPathString("string(./adapter/@wwnn)", ctxt); + wwpn =3D virXPathString("string(./adapter/@wwpn)", ctxt); + parent =3D virXPathString("string(./adapter/@parent)", ctxt); + + if (wwnn || wwpn || parent) { + VIR_FREE(wwnn); + VIR_FREE(wwpn); + VIR_FREE(parent); + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Use of 'wwnn', 'wwpn', and 'parent' attribut= es " + "requires use of the adapter 'type'")); + goto cleanup; + } + + if (virXPathNode("./adapter/parentaddr", ctxt)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Use of 'parent' element requires use " + "of the adapter 'type'")); + goto cleanup; + } + + /* To keep back-compat, 'type' is not required to specify + * for scsi_host adapter. + */ + if ((source->adapter.data.scsi_host.name =3D + virXPathString("string(./adapter/@name)", ctxt))) + source->adapter.type =3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST; + } + + ret =3D 0; + + cleanup: + VIR_FREE(adapter_type); + VIR_FREE(managed); + return ret; +} + + +static int virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, virStoragePoolSourcePtr source, int pool_type, @@ -476,8 +598,6 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, virStorageAuthDefPtr authdef =3D NULL; char *name =3D NULL; char *port =3D NULL; - char *adapter_type =3D NULL; - char *managed =3D NULL; int n; =20 relnode =3D ctxt->node; @@ -583,110 +703,8 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, VIR_STRDUP(source->dir, "/") < 0) goto cleanup; =20 - if ((adapter_type =3D virXPathString("string(./adapter/@type)", ctxt))= ) { - if ((source->adapter.type =3D - virStoragePoolSourceAdapterTypeFromString(adapter_type)) <=3D= 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unknown pool adapter type '%s'"), - adapter_type); - goto cleanup; - } - - if (source->adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { - source->adapter.data.fchost.parent =3D - virXPathString("string(./adapter/@parent)", ctxt); - managed =3D virXPathString("string(./adapter/@managed)", ctxt); - if (managed) { - source->adapter.data.fchost.managed =3D - virTristateBoolTypeFromString(managed); - if (source->adapter.data.fchost.managed < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unknown fc_host managed setting '%s'= "), - managed); - goto cleanup; - } - } - - source->adapter.data.fchost.parent_wwnn =3D - virXPathString("string(./adapter/@parent_wwnn)", ctxt); - source->adapter.data.fchost.parent_wwpn =3D - virXPathString("string(./adapter/@parent_wwpn)", ctxt); - source->adapter.data.fchost.parent_fabric_wwn =3D - virXPathString("string(./adapter/@parent_fabric_wwn)", ctx= t); - - source->adapter.data.fchost.wwpn =3D - virXPathString("string(./adapter/@wwpn)", ctxt); - source->adapter.data.fchost.wwnn =3D - virXPathString("string(./adapter/@wwnn)", ctxt); - } else if (source->adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { - - source->adapter.data.scsi_host.name =3D - virXPathString("string(./adapter/@name)", ctxt); - if (virXPathNode("./adapter/parentaddr", ctxt)) { - xmlNodePtr addrnode =3D virXPathNode("./adapter/parentaddr= /address", - ctxt); - virPCIDeviceAddressPtr addr =3D - &source->adapter.data.scsi_host.parentaddr; - - if (!addrnode) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Missing scsi_host PCI address elemen= t")); - goto cleanup; - } - source->adapter.data.scsi_host.has_parent =3D true; - if (virPCIDeviceAddressParseXML(addrnode, addr) < 0) - goto cleanup; - if ((virXPathInt("string(./adapter/parentaddr/@unique_id)", - ctxt, - &source->adapter.data.scsi_host.unique_id= ) < 0) || - (source->adapter.data.scsi_host.unique_id < 0)) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Missing or invalid scsi adapter " - "'unique_id' value")); - goto cleanup; - } - } - } - } else { - char *wwnn =3D NULL; - char *wwpn =3D NULL; - char *parent =3D NULL; - - /* "type" was not specified in the XML, so we must verify that - * "wwnn", "wwpn", "parent", or "parentaddr" are also not in the - * XML. If any are found, then we cannot just use "name" alone". - */ - wwnn =3D virXPathString("string(./adapter/@wwnn)", ctxt); - wwpn =3D virXPathString("string(./adapter/@wwpn)", ctxt); - parent =3D virXPathString("string(./adapter/@parent)", ctxt); - - if (wwnn || wwpn || parent) { - VIR_FREE(wwnn); - VIR_FREE(wwpn); - VIR_FREE(parent); - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Use of 'wwnn', 'wwpn', and 'parent' attribut= es " - "requires use of the adapter 'type'")); - goto cleanup; - } - - if (virXPathNode("./adapter/parentaddr", ctxt)) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Use of 'parent' element requires use " - "of the adapter 'type'")); - goto cleanup; - } - - /* To keep back-compat, 'type' is not required to specify - * for scsi_host adapter. - */ - if ((source->adapter.data.scsi_host.name =3D - virXPathString("string(./adapter/@name)", ctxt))) - source->adapter.type =3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST; - } + if (virStoragePoolDefParseSourceAdapter(source, ctxt) < 0) + goto cleanup; =20 if ((authnode =3D virXPathNode("./auth", ctxt))) { if (!(authdef =3D virStorageAuthDefParse(node->doc, authnode))) @@ -711,8 +729,6 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, =20 VIR_FREE(port); VIR_FREE(nodeset); - VIR_FREE(adapter_type); - VIR_FREE(managed); virStorageAuthDefFree(authdef); return ret; } @@ -831,6 +847,74 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt, return ret; } =20 +static int +virStoragePoolSourceAdapterParseValidate(virStoragePoolDefPtr ret) +{ + if (!ret->source.adapter.type) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing storage pool source adapter")); + return -1; + } + + if (ret->source.adapter.type =3D=3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + if (!ret->source.adapter.data.fchost.wwnn || + !ret->source.adapter.data.fchost.wwpn) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'wwnn' and 'wwpn' must be specified for adap= ter " + "type 'fchost'")); + return -1; + } + + if (!virValidateWWN(ret->source.adapter.data.fchost.wwnn) || + !virValidateWWN(ret->source.adapter.data.fchost.wwpn)) + return -1; + + if ((ret->source.adapter.data.fchost.parent_wwnn && + !ret->source.adapter.data.fchost.parent_wwpn) || + (!ret->source.adapter.data.fchost.parent_wwnn && + ret->source.adapter.data.fchost.parent_wwpn)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("must supply both parent_wwnn and " + "parent_wwpn not just one or the other")); + return -1; + } + + if (ret->source.adapter.data.fchost.parent_wwnn && + !virValidateWWN(ret->source.adapter.data.fchost.parent_wwnn)) + return -1; + + if (ret->source.adapter.data.fchost.parent_wwpn && + !virValidateWWN(ret->source.adapter.data.fchost.parent_wwpn)) + return -1; + + if (ret->source.adapter.data.fchost.parent_fabric_wwn && + !virValidateWWN(ret->source.adapter.data.fchost.parent_fabric_= wwn)) + return -1; + + } else if (ret->source.adapter.type =3D=3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + if (!ret->source.adapter.data.scsi_host.name && + !ret->source.adapter.data.scsi_host.has_parent) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Either 'name' or 'parent' must be specified " + "for the 'scsi_host' adapter")); + return -1; + } + + if (ret->source.adapter.data.scsi_host.name && + ret->source.adapter.data.scsi_host.has_parent) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Both 'name' and 'parent' cannot be specified= " + "for the 'scsi_host' adapter")); + return -1; + } + } + + return 0; +} + + static virStoragePoolDefPtr virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) { @@ -921,68 +1005,9 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) } } =20 - if (options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) { - if (!ret->source.adapter.type) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing storage pool source adapter")); + if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) && + (virStoragePoolSourceAdapterParseValidate(ret)) < 0) goto error; - } - - if (ret->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { - if (!ret->source.adapter.data.fchost.wwnn || - !ret->source.adapter.data.fchost.wwpn) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("'wwnn' and 'wwpn' must be specified for = adapter " - "type 'fchost'")); - goto error; - } - - if (!virValidateWWN(ret->source.adapter.data.fchost.wwnn) || - !virValidateWWN(ret->source.adapter.data.fchost.wwpn)) - goto error; - - if ((ret->source.adapter.data.fchost.parent_wwnn && - !ret->source.adapter.data.fchost.parent_wwpn) || - (!ret->source.adapter.data.fchost.parent_wwnn && - ret->source.adapter.data.fchost.parent_wwpn)) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("must supply both parent_wwnn and " - "parent_wwpn not just one or the other")); - goto error; - } - - if (ret->source.adapter.data.fchost.parent_wwnn && - !virValidateWWN(ret->source.adapter.data.fchost.parent_wwn= n)) - goto error; - - if (ret->source.adapter.data.fchost.parent_wwpn && - !virValidateWWN(ret->source.adapter.data.fchost.parent_wwp= n)) - goto error; - - if (ret->source.adapter.data.fchost.parent_fabric_wwn && - !virValidateWWN(ret->source.adapter.data.fchost.parent_fab= ric_wwn)) - goto error; - - } else if (ret->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { - if (!ret->source.adapter.data.scsi_host.name && - !ret->source.adapter.data.scsi_host.has_parent) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Either 'name' or 'parent' must be specif= ied " - "for the 'scsi_host' adapter")); - goto error; - } - - if (ret->source.adapter.data.scsi_host.name && - ret->source.adapter.data.scsi_host.has_parent) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Both 'name' and 'parent' cannot be speci= fied " - "for the 'scsi_host' adapter")); - goto error; - } - } - } =20 /* If DEVICE is the only source type, then its required */ if (options->flags =3D=3D VIR_STORAGE_POOL_SOURCE_DEVICE) { @@ -1086,6 +1111,51 @@ virStoragePoolDefParseFile(const char *filename) return virStoragePoolDefParse(NULL, filename); } =20 +static void +virStoragePoolSourceAdapterFormat(virBufferPtr buf, + virStoragePoolSourcePtr src) +{ + virBufferAsprintf(buf, "adapter= .type)); + + if (src->adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_H= OST) { + virBufferEscapeString(buf, " parent=3D'%s'", + src->adapter.data.fchost.parent); + if (src->adapter.data.fchost.managed) + virBufferAsprintf(buf, " managed=3D'%s'", + virTristateBoolTypeToString(src->adapter.dat= a.fchost.managed)); + virBufferEscapeString(buf, " parent_wwnn=3D'%s'", + src->adapter.data.fchost.parent_wwnn); + virBufferEscapeString(buf, " parent_wwpn=3D'%s'", + src->adapter.data.fchost.parent_wwpn); + virBufferEscapeString(buf, " parent_fabric_wwn=3D'%s'", + src->adapter.data.fchost.parent_fabric_wwn); + + virBufferAsprintf(buf, " wwnn=3D'%s' wwpn=3D'%s'/>\n", + src->adapter.data.fchost.wwnn, + src->adapter.data.fchost.wwpn); + } else if (src->adapter.type =3D=3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + if (src->adapter.data.scsi_host.name) { + virBufferAsprintf(buf, " name=3D'%s'/>\n", + src->adapter.data.scsi_host.name); + } else { + virPCIDeviceAddress addr; + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "\n", + src->adapter.data.scsi_host.unique_id); + virBufferAdjustIndent(buf, 2); + addr =3D src->adapter.data.scsi_host.parentaddr; + ignore_value(virPCIDeviceAddressFormat(buf, addr, false)); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } + } +} + static int virStoragePoolSourceFormat(virBufferPtr buf, virStoragePoolOptionsPtr options, @@ -1135,49 +1205,10 @@ virStoragePoolSourceFormat(virBufferPtr buf, if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) virBufferEscapeString(buf, "\n", src->dir); =20 - if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER)) { - if (src->adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_= FC_HOST || - src->adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_= SCSI_HOST) - virBufferAsprintf(buf, "adapter.type)); - - if (src->adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_= FC_HOST) { - virBufferEscapeString(buf, " parent=3D'%s'", - src->adapter.data.fchost.parent); - if (src->adapter.data.fchost.managed) - virBufferAsprintf(buf, " managed=3D'%s'", - virTristateBoolTypeToString(src->adapter= .data.fchost.managed)); - virBufferEscapeString(buf, " parent_wwnn=3D'%s'", - src->adapter.data.fchost.parent_wwnn); - virBufferEscapeString(buf, " parent_wwpn=3D'%s'", - src->adapter.data.fchost.parent_wwpn); - virBufferEscapeString(buf, " parent_fabric_wwn=3D'%s'", - src->adapter.data.fchost.parent_fabric_w= wn); - - virBufferAsprintf(buf, " wwnn=3D'%s' wwpn=3D'%s'/>\n", - src->adapter.data.fchost.wwnn, - src->adapter.data.fchost.wwpn); - } else if (src->adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { - if (src->adapter.data.scsi_host.name) { - virBufferAsprintf(buf, " name=3D'%s'/>\n", - src->adapter.data.scsi_host.name); - } else { - virPCIDeviceAddress addr; - virBufferAddLit(buf, ">\n"); - virBufferAdjustIndent(buf, 2); - virBufferAsprintf(buf, "\n", - src->adapter.data.scsi_host.unique_id); - virBufferAdjustIndent(buf, 2); - addr =3D src->adapter.data.scsi_host.parentaddr; - ignore_value(virPCIDeviceAddressFormat(buf, addr, false)); - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); - } - } - } + if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) && + (src->adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_= HOST || + src->adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCS= I_HOST)) + virStoragePoolSourceAdapterFormat(buf, src); =20 if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) virBufferEscapeString(buf, "%s\n", src->name); --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list