From nobody Wed Apr 24 14:17:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.39 as permitted sender) client-ip=209.132.183.39; envelope-from=libvir-list-bounces@redhat.com; helo=mx6-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.39 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx6-phx2.redhat.com (mx6-phx2.redhat.com [209.132.183.39]) by mx.zohomail.com with SMTPS id 1488387297062804.8836949183006; Wed, 1 Mar 2017 08:54:57 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx6-phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21Gpe6V005678; Wed, 1 Mar 2017 11:51:40 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GobH7002080 for ; Wed, 1 Mar 2017 11:50:37 -0500 Received: from localhost.localdomain.com (ovpn-116-78.phx2.redhat.com [10.3.116.78]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21GoaBv006153 for ; Wed, 1 Mar 2017 11:50:36 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Wed, 1 Mar 2017 11:50:28 -0500 Message-Id: <20170301165033.27944-2-jferlan@redhat.com> In-Reply-To: <20170301165033.27944-1-jferlan@redhat.com> References: <20170301165033.27944-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 1/6] tests: Add createVHBAByStoragePool-by-parent to fchosttest 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" Add a new test to fchosttest in order to test creation of our vHBA via the Storage Pool logic. Unlike the real code, we cannot yet use the virVHBA* API's because they (currently) traverse the file system in order to get the parent vport capable scsi_host. Besides there's no "real" NPIV device here - so we have to take some liberties, at least for now. Instead, we'll follow the node device tests partially in order to create and destroy the vHBA with the test node devices. Signed-off-by: John Ferlan --- src/test/test_driver.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++= ++-- tests/fchosttest.c | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 2 deletions(-) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 314f08c..2dd2238 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4365,6 +4365,34 @@ testConnectFindStoragePoolSources(virConnectPtr conn= ATTRIBUTE_UNUSED, } =20 =20 +static virNodeDeviceObjPtr +testNodeDeviceMockCreateVport(testDriverPtr driver, + const char *wwnn, + const char *wwpn); +static int +testCreateVport(testDriverPtr driver, + const char *wwnn, + const char *wwpn) +{ + virNodeDeviceObjPtr obj =3D NULL; + /* The storage_backend_scsi createVport() will use the input adapter + * fields parent name, parent_wwnn/parent_wwpn, or parent_fabric_wwn + * in order to determine whether the provided parent can be used to + * create a vHBA or will find "an available vport capable" to create + * a vHBA. In order to do this, it uses the virVHBA* API's which trave= rse + * the sysfs looking at various fields (rather than going via nodedev). + * + * Since the test environ doesn't have the sysfs for the storage pool + * test, at least for now use the node device test infrastructure to + * create the vHBA. In the long run the result is the same. */ + if (!(obj =3D testNodeDeviceMockCreateVport(driver, wwnn, wwpn))) + return -1; + virNodeDeviceObjUnlock(obj); + + return 0; +} + + static virStoragePoolPtr testStoragePoolCreateXML(virConnectPtr conn, const char *xml, @@ -4395,6 +4423,21 @@ testStoragePoolCreateXML(virConnectPtr conn, goto cleanup; def =3D NULL; =20 + if (pool->def->source.adapter.type =3D=3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + /* In the real code, we'd call virVHBAManageVport followed by + * find_new_device, but we cannot do that here since we're not + * mocking udev. The mock routine will copy an existing vHBA and + * rename a few fields to mock that. */ + if (testCreateVport(privconn, + pool->def->source.adapter.data.fchost.wwnn, + pool->def->source.adapter.data.fchost.wwpn) < = 0) { + virStoragePoolObjRemove(&privconn->pools, pool); + pool =3D NULL; + goto cleanup; + } + } + if (testStoragePoolObjSetDefaults(pool) =3D=3D -1) { virStoragePoolObjRemove(&privconn->pools, pool); pool =3D NULL; @@ -4405,7 +4448,6 @@ testStoragePoolCreateXML(virConnectPtr conn, event =3D virStoragePoolEventLifecycleNew(pool->def->name, pool->def->= uuid, VIR_STORAGE_POOL_EVENT_STARTED, 0); - ret =3D virGetStoragePool(conn, pool->def->name, pool->def->uuid, NULL, NULL); =20 @@ -4539,6 +4581,44 @@ testStoragePoolBuild(virStoragePoolPtr pool, =20 =20 static int +testDestroyVport(testDriverPtr privconn, + const char *wwnn ATTRIBUTE_UNUSED, + const char *wwpn ATTRIBUTE_UNUSED) +{ + int ret =3D -1; + virNodeDeviceObjPtr obj =3D NULL; + virObjectEventPtr event =3D NULL; + + /* NB: Cannot use virVHBAGetHostByWWN (yet) like the storage_backend_s= csi + * deleteVport() helper since that traverses the file system looking f= or + * the wwnn/wwpn. So our choice short term is to cheat and use the name + * (scsi_host12) we know was created. + * + * Reaching across the boundaries of space and time into the + * Node Device in order to remove */ + if (!(obj =3D virNodeDeviceFindByName(&privconn->devs, "scsi_host12"))= ) { + virReportError(VIR_ERR_NO_NODE_DEVICE, "%s", + _("no node device with matching name 'scsi_host12'"= )); + goto cleanup; + } + + event =3D virNodeDeviceEventLifecycleNew("scsi_host12", + VIR_NODE_DEVICE_EVENT_DELETED, + 0); + + virNodeDeviceObjRemove(&privconn->devs, &obj); + + ret =3D 0; + + cleanup: + if (obj) + virNodeDeviceObjUnlock(obj); + testObjectEventQueue(privconn, event); + return ret; +} + + +static int testStoragePoolDestroy(virStoragePoolPtr pool) { testDriverPtr privconn =3D pool->conn->privateData; @@ -4562,7 +4642,17 @@ testStoragePoolDestroy(virStoragePoolPtr pool) } =20 privpool->active =3D 0; - event =3D virStoragePoolEventLifecycleNew(privpool->def->name, privpoo= l->def->uuid, + + if (privpool->def->source.adapter.type =3D=3D + VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + if (testDestroyVport(privconn, + privpool->def->source.adapter.data.fchost.wwn= n, + privpool->def->source.adapter.data.fchost.wwp= n) < 0) + goto cleanup; + } + + event =3D virStoragePoolEventLifecycleNew(privpool->def->name, + privpool->def->uuid, VIR_STORAGE_POOL_EVENT_STOPPED, 0); =20 diff --git a/tests/fchosttest.c b/tests/fchosttest.c index 51fdcbd..dc6b9af 100644 --- a/tests/fchosttest.c +++ b/tests/fchosttest.c @@ -75,6 +75,19 @@ static const char test10_xml[] =3D " " ""; =20 +/* virStoragePoolCreateXML using parent=3D'%s' to find the vport capable H= BA */ +static const char test11_xml[] =3D +"" +" vhba_pool" +" " +" " +" " +" " +" /dev/disk/by-path" +" " +""; + + /* Test virIsVHBACapable */ static int test1(const void *data ATTRIBUTE_UNUSED) @@ -275,6 +288,54 @@ manageVHBAByNodeDevice(const void *data) } =20 =20 +/* Test manageVHBAByStoragePool + * - Test both virStoragePoolCreateXML and virStoragePoolDestroy + * - Create a storage pool vHBA allowing usage of various different + * methods based on the input data/xml argument. + * - Be sure that it's possible to destroy the storage pool as well. + */ +static int +manageVHBAByStoragePool(const void *data) +{ + const char *expect_hostname =3D "scsi_host12"; + virConnectPtr conn =3D NULL; + virStoragePoolPtr pool =3D NULL; + virNodeDevicePtr dev =3D NULL; + int ret =3D -1; + const char *vhba =3D data; + + if (!(conn =3D virConnectOpen("test:///default"))) + return -1; + + if (!(pool =3D virStoragePoolCreateXML(conn, vhba, 0))) + goto cleanup; + + if (!(dev =3D virNodeDeviceLookupByName(conn, expect_hostname))) { + VIR_DEBUG("Failed to find expected_hostname '%s'", expect_hostname= ); + ignore_value(virStoragePoolDestroy(pool)); + goto cleanup; + } + + if (virStoragePoolDestroy(pool) < 0) + goto cleanup; + + if ((dev =3D virNodeDeviceLookupByName(conn, expect_hostname))) { + VIR_DEBUG("Found expected_hostname '%s' after destroy", + expect_hostname); + goto cleanup; + } + + ret =3D 0; + + cleanup: + if (pool) + virStoragePoolFree(pool); + if (conn) + virConnectClose(conn); + return ret; +} + + static int mymain(void) { @@ -310,6 +371,9 @@ mymain(void) if (virTestRun("manageVHBAByNodeDevice-parent-fabric-wwn", manageVHBAByNodeDevice, test10_xml) < 0) ret =3D -1; + if (virTestRun("manageVHBAByStoragePool-by-parent", manageVHBAByStorag= ePool, + test11_xml) < 0) + ret =3D -1; =20 cleanup: VIR_FREE(fchost_prefix); --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 14:17:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.37 as permitted sender) client-ip=209.132.183.37; envelope-from=libvir-list-bounces@redhat.com; helo=mx5-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.37 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx5-phx2.redhat.com (mx5-phx2.redhat.com [209.132.183.37]) by mx.zohomail.com with SMTPS id 148838726947770.32649183922604; Wed, 1 Mar 2017 08:54:29 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx5-phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21GoeaX060506; Wed, 1 Mar 2017 11:50:40 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GobmW002085 for ; Wed, 1 Mar 2017 11:50:37 -0500 Received: from localhost.localdomain.com (ovpn-116-78.phx2.redhat.com [10.3.116.78]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21GoaBw006153 for ; Wed, 1 Mar 2017 11:50:37 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Wed, 1 Mar 2017 11:50:29 -0500 Message-Id: <20170301165033.27944-3-jferlan@redhat.com> In-Reply-To: <20170301165033.27944-1-jferlan@redhat.com> References: <20170301165033.27944-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 2/6] conf: Convert virStoragePoolSourceAdapter to virStorageAdapter 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" Introduce src/conf/storage_adapter_conf.{c,h}. Separate out the parsing/formatting and management into a separate conf module. Move the virStoragePoolSourceAdapter from storage_conf.h and rename to virStorageAdapter. This includes creating 'scsi_host' and 'fchost' specific structs as virStorageAdapterSCSIHost and virStorageAdapterFCHost which allows code using the structs to use the typedefs rather than needing to take the lengthy union paths. Modify code in the various places which formerly used the pool structure to use the new model. This includes some changes that will use the Ptr rather than just the struct (try to shorten the number of times one has to type adapter.data.fchost or adapter.data.scsi_host as well as [pool->]def->source.adapter. Signed-off-by: John Ferlan --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/conf/storage_adapter_conf.c | 291 ++++++++++++++++++++++++++++++++ src/conf/storage_adapter_conf.h | 89 ++++++++++ src/conf/storage_conf.c | 333 +++++++++------------------------= ---- src/conf/storage_conf.h | 35 +--- src/libvirt_private.syms | 16 +- src/phyp/phyp_driver.c | 3 +- src/storage/storage_backend_scsi.c | 129 +++++++------- src/test/test_driver.c | 5 +- 10 files changed, 538 insertions(+), 365 deletions(-) create mode 100644 src/conf/storage_adapter_conf.c create mode 100644 src/conf/storage_adapter_conf.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 9f66697..e927b90 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -40,6 +40,7 @@ src/conf/object_event.c src/conf/secret_conf.c src/conf/snapshot_conf.c src/conf/storage_conf.c +src/conf/storage_adapter_conf.c src/conf/virchrdev.c src/conf/virdomainobjlist.c src/conf/virsecretobj.c diff --git a/src/Makefile.am b/src/Makefile.am index a85cd0d..239826a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -377,6 +377,7 @@ NWFILTER_CONF_SOURCES =3D \ =20 # Storage driver generic impl APIs STORAGE_CONF_SOURCES =3D \ + conf/storage_adapter_conf.h conf/storage_adapter_conf.c \ conf/storage_conf.h conf/storage_conf.c =20 # Interface driver generic impl APIs diff --git a/src/conf/storage_adapter_conf.c b/src/conf/storage_adapter_con= f.c new file mode 100644 index 0000000..9ee18a2 --- /dev/null +++ b/src/conf/storage_adapter_conf.c @@ -0,0 +1,291 @@ +/* + * storage_adapter_conf.c: helpers to handle storage pool adapter manipula= tion + * (derived from storage_conf.c) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#include + +#include "storage_conf.h" + +#include "viralloc.h" +#include "virerror.h" +#include "virlog.h" +#include "virstring.h" +#include "virutil.h" +#include "virxml.h" + +#define VIR_FROM_THIS VIR_FROM_STORAGE + +VIR_LOG_INIT("conf.storage_adapter_conf"); + +VIR_ENUM_IMPL(virStorageAdapter, + VIR_STORAGE_ADAPTER_TYPE_LAST, + "default", "scsi_host", "fc_host") + + +int +virStorageAdapterVHBAParseXML(xmlNodePtr node, + virStorageAdapterFCHostPtr fchost) +{ + char *managed =3D NULL; + + fchost->parent =3D virXMLPropString(node, "parent"); + + if ((managed =3D virXMLPropString(node, "managed"))) { + if ((fchost->managed =3D + virTristateBoolTypeFromString(managed)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown fc_host managed setting '%s'"), + managed); + VIR_FREE(managed); + return -1; + } + } + + fchost->parent_wwnn =3D virXMLPropString(node, "parent_wwnn"); + fchost->parent_wwpn =3D virXMLPropString(node, "parent_wwpn"); + fchost->parent_fabric_wwn =3D virXMLPropString(node, "parent_fabric_ww= n"); + fchost->wwpn =3D virXMLPropString(node, "wwpn"); + fchost->wwnn =3D virXMLPropString(node, "wwnn"); + + VIR_FREE(managed); + return 0; +} + + +int +virStorageAdapterParseXML(virStorageAdapterPtr adapter, + xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + int ret =3D -1; + xmlNodePtr relnode =3D ctxt->node; + char *adapter_type =3D NULL; + virStorageAdapterSCSIHostPtr scsi_host; + + ctxt->node =3D node; + + if ((adapter_type =3D virXMLPropString(node, "type"))) { + if ((adapter->type =3D + virStorageAdapterTypeFromString(adapter_type)) <=3D 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unknown pool adapter type '%s'"), + adapter_type); + goto cleanup; + } + + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_HOST) { + if (virStorageAdapterVHBAParseXML(node, &adapter->data.fchost)= < 0) + goto cleanup; + } + + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) { + scsi_host =3D &adapter->data.scsi_host; + + scsi_host->name =3D virXMLPropString(node, "name"); + if (virXPathNode("./parentaddr", ctxt)) { + xmlNodePtr addrnode =3D virXPathNode("./parentaddr/address= ", + ctxt); + virPCIDeviceAddressPtr addr =3D &scsi_host->parentaddr; + if (!addrnode) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing scsi_host PCI address elemen= t")); + goto cleanup; + } + scsi_host->has_parent =3D true; + if (virPCIDeviceAddressParseXML(addrnode, addr) < 0) + goto cleanup; + if ((virXPathInt("string(./parentaddr/@unique_id)", + ctxt, + &scsi_host->unique_id) < 0) || + (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 virXMLPropString(node, "wwnn"); + char *wwpn =3D virXMLPropString(node, "wwpn"); + char *parent =3D virXMLPropString(node, "parent"); + + /* "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". + */ + 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("./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 ((adapter->data.scsi_host.name =3D virXMLPropString(node, "name= "))) + adapter->type =3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST; + } + + ret =3D 0; + + cleanup: + ctxt->node =3D relnode; + VIR_FREE(adapter_type); + return ret; +} + + +void +virStorageAdapterVHBAFormat(virBufferPtr buf, + virStorageAdapterFCHostPtr fchost) +{ + virBufferEscapeString(buf, " parent=3D'%s'", fchost->parent); + virBufferEscapeString(buf, " parent_wwnn=3D'%s'", fchost->parent_wwnn); + virBufferEscapeString(buf, " parent_wwpn=3D'%s'", fchost->parent_wwpn); + virBufferEscapeString(buf, " parent_fabric_wwn=3D'%s'", + fchost->parent_fabric_wwn); + if (fchost->managed !=3D VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(buf, " managed=3D'%s'", + virTristateBoolTypeToString(fchost->managed)); + + virBufferAsprintf(buf, " wwnn=3D'%s' wwpn=3D'%s'/>\n", + fchost->wwnn, fchost->wwpn); +} + + +void +virStorageAdapterFormat(virBufferPtr buf, + virStorageAdapterPtr adapter) +{ + virBufferAsprintf(buf, "type)); + + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_HOST) + virStorageAdapterVHBAFormat(buf, &adapter->data.fchost); + + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) { + virStorageAdapterSCSIHostPtr scsi_host =3D &adapter->data.scsi_hos= t; + + if (scsi_host->name) { + virBufferAsprintf(buf, " name=3D'%s'/>\n", scsi_host->name); + } else { + virPCIDeviceAddress addr; + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "\n", + scsi_host->unique_id); + virBufferAdjustIndent(buf, 2); + addr =3D scsi_host->parentaddr; + ignore_value(virPCIDeviceAddressFormat(buf, addr, false)); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } + } +} + + +void +virStorageAdapterVHBAClear(virStorageAdapterFCHostPtr fchost) +{ + VIR_FREE(fchost->parent); + VIR_FREE(fchost->parent_wwnn); + VIR_FREE(fchost->parent_wwpn); + VIR_FREE(fchost->parent_fabric_wwn); + VIR_FREE(fchost->wwnn); + VIR_FREE(fchost->wwpn); +} + + +void +virStorageAdapterClear(virStorageAdapterPtr adapter) +{ + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_HOST) + virStorageAdapterVHBAClear(&adapter->data.fchost); + + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) + VIR_FREE(adapter->data.scsi_host.name); +} + + +int +virStorageAdapterVHBAParseValidate(virStorageAdapterFCHostPtr fchost) +{ + if (!fchost->wwnn || !fchost->wwpn) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'wwnn' and 'wwpn' must be specified for " + "a VHBA adapter")); + return -1; + } + + if (!virValidateWWN(fchost->wwnn) || !virValidateWWN(fchost->wwpn)) + return -1; + + if (fchost->parent_wwnn && !virValidateWWN(fchost->parent_wwnn)) + return -1; + + if (fchost->parent_wwpn && !virValidateWWN(fchost->parent_wwpn)) + return -1; + + if (fchost->parent_fabric_wwn && + !virValidateWWN(fchost->parent_fabric_wwn)) + return -1; + + return 0; +} + + +int +virStorageAdapterParseValidate(virStorageAdapterPtr adapter) +{ + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_HOST) + return virStorageAdapterVHBAParseValidate(&adapter->data.fchost); + + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) { + virStorageAdapterSCSIHostPtr scsi_host =3D &adapter->data.scsi_hos= t; + + if (!scsi_host->name && !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 (scsi_host->name && 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; +} diff --git a/src/conf/storage_adapter_conf.h b/src/conf/storage_adapter_con= f.h new file mode 100644 index 0000000..d566fc4 --- /dev/null +++ b/src/conf/storage_adapter_conf.h @@ -0,0 +1,89 @@ +/* + * storage_adapter_conf.h: helpers to handle storage pool adapter manipula= tion + * (derived from storage_conf.h) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#ifndef __VIR_STORAGE_ADAPTER_CONF_H__ +# define __VIR_STORAGE_ADAPTER_CONF_H__ + +# include "virpci.h" +# include "virxml.h" + + +typedef enum { + VIR_STORAGE_ADAPTER_TYPE_DEFAULT =3D 0, + VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST, + VIR_STORAGE_ADAPTER_TYPE_FC_HOST, + + VIR_STORAGE_ADAPTER_TYPE_LAST, +} virStorageAdapterType; +VIR_ENUM_DECL(virStorageAdapter) + +typedef struct _virStorageAdapterSCSIHost virStorageAdapterSCSIHost; +typedef virStorageAdapterSCSIHost *virStorageAdapterSCSIHostPtr; +struct _virStorageAdapterSCSIHost { + char *name; + virPCIDeviceAddress parentaddr; /* host address */ + int unique_id; + bool has_parent; +}; + +typedef struct _virStorageAdapterFCHost virStorageAdapterFCHost; +typedef virStorageAdapterFCHost *virStorageAdapterFCHostPtr; +struct _virStorageAdapterFCHost { + char *parent; + char *parent_wwnn; + char *parent_wwpn; + char *parent_fabric_wwn; + char *wwnn; + char *wwpn; + int managed; /* enum virTristateSwitch */ +}; + +typedef struct _virStorageAdapter virStorageAdapter; +typedef virStorageAdapter *virStorageAdapterPtr; +struct _virStorageAdapter { + int type; /* virStorageAdapterType */ + + union { + virStorageAdapterSCSIHost scsi_host; + virStorageAdapterFCHost fchost; + } data; +}; + + +int virStorageAdapterVHBAParseXML(xmlNodePtr node, + virStorageAdapterFCHostPtr fchost); + +int virStorageAdapterParseXML(virStorageAdapterPtr adapter, + xmlNodePtr node, + xmlXPathContextPtr ctxt); + +void virStorageAdapterVHBAFormat(virBufferPtr buf, + virStorageAdapterFCHostPtr fchost); + +void virStorageAdapterFormat(virBufferPtr buf, virStorageAdapterPtr adapte= r); + +void virStorageAdapterVHBAClear(virStorageAdapterFCHostPtr fchost); + +void virStorageAdapterClear(virStorageAdapterPtr adapter); + +int virStorageAdapterVHBAParseValidate(virStorageAdapterFCHostPtr fchost); + +int virStorageAdapterParseValidate(virStorageAdapterPtr adapter); + +#endif /* __VIR_STORAGE_ADAPTER_CONF_H__ */ diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index a52eeba..ffc5b5e 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -100,10 +100,6 @@ VIR_ENUM_IMPL(virStoragePartedFs, "ext2", "ext2", "extended") =20 -VIR_ENUM_IMPL(virStoragePoolSourceAdapter, - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_LAST, - "default", "scsi_host", "fc_host") - typedef const char *(*virStorageVolFormatToString)(int format); typedef int (*virStorageVolFormatFromString)(const char *format); =20 @@ -342,21 +338,6 @@ virStorageVolDefFree(virStorageVolDefPtr def) VIR_FREE(def); } =20 -static void -virStoragePoolSourceAdapterClear(virStoragePoolSourceAdapterPtr adapter) -{ - if (adapter->type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST)= { - VIR_FREE(adapter->data.fchost.wwnn); - VIR_FREE(adapter->data.fchost.wwpn); - VIR_FREE(adapter->data.fchost.parent); - VIR_FREE(adapter->data.fchost.parent_wwnn); - VIR_FREE(adapter->data.fchost.parent_wwpn); - VIR_FREE(adapter->data.fchost.parent_fabric_wwn); - } else if (adapter->type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { - VIR_FREE(adapter->data.scsi_host.name); - } -} =20 void virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev) @@ -382,7 +363,7 @@ virStoragePoolSourceClear(virStoragePoolSourcePtr sourc= e) VIR_FREE(source->devices); VIR_FREE(source->dir); VIR_FREE(source->name); - virStoragePoolSourceAdapterClear(&source->adapter); + virStorageAdapterClear(&source->adapter); VIR_FREE(source->initiator.iqn); virStorageAuthDefFree(source->auth); VIR_FREE(source->vendor); @@ -462,6 +443,7 @@ virStoragePoolObjRemove(virStoragePoolObjListPtr pools, } } =20 + static int virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, virStoragePoolSourcePtr source, @@ -470,14 +452,13 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, { int ret =3D -1; xmlNodePtr relnode, authnode, *nodeset =3D NULL; + xmlNodePtr adapternode; int nsource; size_t i; virStoragePoolOptionsPtr options; 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,109 +564,9 @@ 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); + if ((adapternode =3D virXPathNode("./adapter", ctxt))) { + if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt)= < 0) 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; } =20 if ((authnode =3D virXPathNode("./auth", ctxt))) { @@ -711,8 +592,6 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, =20 VIR_FREE(port); VIR_FREE(nodeset); - VIR_FREE(adapter_type); - VIR_FREE(managed); virStorageAuthDefFree(authdef); return ret; } @@ -928,37 +807,8 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) goto error; } =20 - 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; - } 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; - } - } + if (virStorageAdapterParseValidate(&ret->source.adapter) < 0) + goto error; } =20 /* If DEVICE is the only source type, then its required */ @@ -1112,49 +962,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_ADAPTER_TYPE_FC_HOST || + src->adapter.type =3D=3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST)) + virStorageAdapterFormat(buf, &src->adapter); =20 if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) virBufferEscapeString(buf, "%s\n", src->name); @@ -2279,16 +2090,16 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListP= tr pools, =20 =20 static int -getSCSIHostNumber(virStoragePoolSourceAdapter adapter, +getSCSIHostNumber(virStorageAdapterSCSIHostPtr scsi_host, unsigned int *hostnum) { int ret =3D -1; unsigned int num; char *name =3D NULL; =20 - if (adapter.data.scsi_host.has_parent) { - virPCIDeviceAddress addr =3D adapter.data.scsi_host.parentaddr; - unsigned int unique_id =3D adapter.data.scsi_host.unique_id; + if (scsi_host->has_parent) { + virPCIDeviceAddress addr =3D scsi_host->parentaddr; + unsigned int unique_id =3D scsi_host->unique_id; =20 if (!(name =3D virSCSIHostGetNameByParentaddr(addr.domain, addr.bus, @@ -2299,7 +2110,7 @@ getSCSIHostNumber(virStoragePoolSourceAdapter adapter, if (virSCSIHostGetNumber(name, &num) < 0) goto cleanup; } else { - if (virSCSIHostGetNumber(adapter.data.scsi_host.name, &num) < 0) + if (virSCSIHostGetNumber(scsi_host->name, &num) < 0) goto cleanup; } =20 @@ -2330,7 +2141,7 @@ virStorageIsSameHostnum(const char *name, * matchFCHostToSCSIHost: * * @conn: Connection pointer - * @fc_adapter: fc_host adapter (either def or pool->def) + * @fchost: fc_host adapter ptr (either def or pool->def) * @scsi_hostnum: Already determined "scsi_pool" hostnum * * Returns true/false whether there is a match between the incoming @@ -2338,7 +2149,7 @@ virStorageIsSameHostnum(const char *name, */ static bool matchFCHostToSCSIHost(virConnectPtr conn, - virStoragePoolSourceAdapter fc_adapter, + virStorageAdapterFCHostPtr fchost, unsigned int scsi_hostnum) { bool ret =3D false; @@ -2349,16 +2160,14 @@ matchFCHostToSCSIHost(virConnectPtr conn, /* If we have a parent defined, get its hostnum, and compare to the * scsi_hostnum. If they are the same, then we have a match */ - if (fc_adapter.data.fchost.parent && - virStorageIsSameHostnum(fc_adapter.data.fchost.parent, scsi_hostnu= m)) + if (fchost->parent && + virStorageIsSameHostnum(fchost->parent, scsi_hostnum)) return true; =20 - /* If we find an fc_adapter name, then either libvirt created a vHBA + /* If we find an fc adapter name, then either libvirt created a vHBA * for this fc_host or a 'virsh nodedev-create' generated a vHBA. */ - if ((name =3D virVHBAGetHostByWWN(NULL, fc_adapter.data.fchost.wwnn, - fc_adapter.data.fchost.wwpn))) { - + if ((name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) { /* Get the scsi_hostN for the vHBA in order to see if it * matches our scsi_hostnum */ @@ -2372,7 +2181,7 @@ matchFCHostToSCSIHost(virConnectPtr conn, * If the parent fc_hostnum is the same as the scsi_hostnum, we * have a match. */ - if (conn && !fc_adapter.data.fchost.parent) { + if (conn && !fchost->parent) { if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) goto cleanup; if ((parent_name =3D virNodeDeviceGetParentName(conn, @@ -2404,25 +2213,21 @@ matchFCHostToSCSIHost(virConnectPtr conn, return ret; } =20 + static bool -matchSCSIAdapterParent(virStoragePoolObjPtr pool, - virStoragePoolDefPtr def) +matchSCSIAdapterParent(virStorageAdapterSCSIHostPtr pool_scsi_host, + virStorageAdapterSCSIHostPtr def_scsi_host) { - virPCIDeviceAddressPtr pooladdr =3D - &pool->def->source.adapter.data.scsi_host.parentaddr; - virPCIDeviceAddressPtr defaddr =3D - &def->source.adapter.data.scsi_host.parentaddr; - int pool_unique_id =3D - pool->def->source.adapter.data.scsi_host.unique_id; - int def_unique_id =3D - def->source.adapter.data.scsi_host.unique_id; + virPCIDeviceAddressPtr pooladdr =3D &pool_scsi_host->parentaddr; + virPCIDeviceAddressPtr defaddr =3D &def_scsi_host->parentaddr; + if (pooladdr->domain =3D=3D defaddr->domain && pooladdr->bus =3D=3D defaddr->bus && pooladdr->slot =3D=3D defaddr->slot && pooladdr->function =3D=3D defaddr->function && - pool_unique_id =3D=3D def_unique_id) { + pool_scsi_host->unique_id =3D=3D def_scsi_host->unique_id) return true; - } + return false; } =20 @@ -2465,6 +2270,8 @@ virStoragePoolSourceFindDuplicate(virConnectPtr conn, int ret =3D 1; virStoragePoolObjPtr pool =3D NULL; virStoragePoolObjPtr matchpool =3D NULL; + virStorageAdapterPtr pool_adapter; + virStorageAdapterPtr def_adapter; =20 /* Check the pool list for duplicate underlying storage */ for (i =3D 0; i < pools->count; i++) { @@ -2500,62 +2307,70 @@ virStoragePoolSourceFindDuplicate(virConnectPtr con= n, break; =20 case VIR_STORAGE_POOL_SCSI: - if (pool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST && - def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { - if (STREQ(pool->def->source.adapter.data.fchost.wwnn, - def->source.adapter.data.fchost.wwnn) && - STREQ(pool->def->source.adapter.data.fchost.wwpn, - def->source.adapter.data.fchost.wwpn)) + pool_adapter =3D &pool->def->source.adapter; + def_adapter =3D &def->source.adapter; + if (pool_adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_HOST= && + def_adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_HOST)= { + virStorageAdapterFCHostPtr pool_fchost =3D + &pool_adapter->data.fchost; + virStorageAdapterFCHostPtr def_fchost =3D + &def_adapter->data.fchost; + if (STREQ(pool_fchost->wwnn, def_fchost->wwnn) && + STREQ(pool_fchost->wwpn, def_fchost->wwpn)) matchpool =3D pool; - } else if (pool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST && - def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + } else if (pool_adapter->type =3D=3D + VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST && + def_adapter->type =3D=3D + VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) { + virStorageAdapterSCSIHostPtr pool_scsi_host =3D + &pool_adapter->data.scsi_host; + virStorageAdapterSCSIHostPtr def_scsi_host =3D + &def_adapter->data.scsi_host; unsigned int pool_hostnum, def_hostnum; =20 - if (pool->def->source.adapter.data.scsi_host.has_parent && - def->source.adapter.data.scsi_host.has_parent && - matchSCSIAdapterParent(pool, def)) { + if (pool_scsi_host->has_parent && + def_scsi_host->has_parent && + matchSCSIAdapterParent(pool_scsi_host, def_scsi_host))= { matchpool =3D pool; break; } =20 - if (getSCSIHostNumber(pool->def->source.adapter, - &pool_hostnum) < 0 || - getSCSIHostNumber(def->source.adapter, &def_hostnum) <= 0) + if (getSCSIHostNumber(pool_scsi_host, &pool_hostnum) < 0 || + getSCSIHostNumber(def_scsi_host, &def_hostnum) < 0) break; if (pool_hostnum =3D=3D def_hostnum) matchpool =3D pool; - } else if (pool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST && - def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + } else if (pool_adapter->type =3D=3D + VIR_STORAGE_ADAPTER_TYPE_FC_HOST && + def_adapter->type =3D=3D + VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) { + virStorageAdapterFCHostPtr pool_fchost =3D + &pool_adapter->data.fchost; + virStorageAdapterSCSIHostPtr def_scsi_host =3D + &def_adapter->data.scsi_host; unsigned int scsi_hostnum; =20 /* Get the scsi_hostN for the scsi_host source adapter def= */ - if (getSCSIHostNumber(def->source.adapter, - &scsi_hostnum) < 0) + if (getSCSIHostNumber(def_scsi_host, &scsi_hostnum) < 0) break; =20 - if (matchFCHostToSCSIHost(conn, pool->def->source.adapter, - scsi_hostnum)) { + if (matchFCHostToSCSIHost(conn, pool_fchost, scsi_hostnum)= ) { matchpool =3D pool; break; } =20 - } else if (pool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST && - def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + } else if (pool_adapter->type =3D=3D + VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST && + def_adapter->type =3D=3D + VIR_STORAGE_ADAPTER_TYPE_FC_HOST) { + virStorageAdapterSCSIHostPtr pool_scsi_host =3D + &pool_adapter->data.scsi_host; unsigned int scsi_hostnum; =20 - if (getSCSIHostNumber(pool->def->source.adapter, - &scsi_hostnum) < 0) + if (getSCSIHostNumber(pool_scsi_host, &scsi_hostnum) < 0) break; =20 - if (matchFCHostToSCSIHost(conn, def->source.adapter, + if (matchFCHostToSCSIHost(conn, &def_adapter->data.fchost, scsi_hostnum)) { matchpool =3D pool; break; diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 1723afc..7c4c684 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -31,6 +31,7 @@ # include "virthread.h" # include "device_conf.h" # include "object_event.h" +# include "storage_adapter_conf.h" =20 # include =20 @@ -170,38 +171,6 @@ struct _virStoragePoolSourceDevice { } geometry; }; =20 -typedef enum { - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_DEFAULT =3D 0, - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST, - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST, - - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_LAST, -} virStoragePoolSourceAdapterType; -VIR_ENUM_DECL(virStoragePoolSourceAdapter) - -typedef struct _virStoragePoolSourceAdapter virStoragePoolSourceAdapter; -typedef virStoragePoolSourceAdapter *virStoragePoolSourceAdapterPtr; -struct _virStoragePoolSourceAdapter { - int type; /* virStoragePoolSourceAdapterType */ - - union { - struct { - char *name; - virPCIDeviceAddress parentaddr; /* host address */ - int unique_id; - bool has_parent; - } scsi_host; - struct { - char *parent; - char *parent_wwnn; - char *parent_wwpn; - char *parent_fabric_wwn; - char *wwnn; - char *wwpn; - int managed; /* enum virTristateSwitch */ - } fchost; - } data; -}; =20 typedef struct _virStoragePoolSource virStoragePoolSource; typedef virStoragePoolSource *virStoragePoolSourcePtr; @@ -218,7 +187,7 @@ struct _virStoragePoolSource { char *dir; =20 /* Or an adapter */ - virStoragePoolSourceAdapter adapter; + virStorageAdapter adapter; =20 /* Or a name */ char *name; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bce0487..7ccf56b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -873,6 +873,19 @@ virDomainSnapshotStateTypeToString; virDomainSnapshotUpdateRelations; =20 =20 +# conf/storage_adapter_conf.h +virStorageAdapterClear; +virStorageAdapterFormat; +virStorageAdapterParseValidate; +virStorageAdapterParseXML; +virStorageAdapterTypeFromString; +virStorageAdapterTypeToString; +virStorageAdapterVHBAClear; +virStorageAdapterVHBAFormat; +virStorageAdapterVHBAParseValidate; +virStorageAdapterVHBAParseXML; + + # conf/storage_conf.h virStoragePartedFsTypeToString; virStoragePoolDefFormat; @@ -902,8 +915,6 @@ virStoragePoolObjSaveDef; virStoragePoolObjUnlock; virStoragePoolSaveConfig; virStoragePoolSaveState; -virStoragePoolSourceAdapterTypeFromString; -virStoragePoolSourceAdapterTypeToString; virStoragePoolSourceClear; virStoragePoolSourceDeviceClear; virStoragePoolSourceFindDuplicate; @@ -2439,6 +2450,7 @@ virSocketAddrSetIPv6Addr; virSocketAddrSetIPv6AddrNetOrder; virSocketAddrSetPort; =20 + # util/virstorageencryption.h virStorageEncryptionFormat; virStorageEncryptionFree; diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 7a5df3f..39fa026 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -2467,8 +2467,7 @@ phypBuildStoragePool(virConnectPtr conn, virStoragePo= olDefPtr def) int exit_status =3D 0; virBuffer buf =3D VIR_BUFFER_INITIALIZER; =20 - if (source.adapter.type !=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) { + if (source.adapter.type !=3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Only 'scsi_host' adapter is supported")); goto cleanup; diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backe= nd_scsi.c index 642e795..ff17409 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -176,15 +176,17 @@ virStoragePoolFCRefreshThread(void *opaque) } =20 static char * -getAdapterName(virStoragePoolSourceAdapter adapter) +getAdapterName(virStorageAdapterPtr adapter) { char *name =3D NULL; char *parentaddr =3D NULL; =20 - if (adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST= ) { - if (adapter.data.scsi_host.has_parent) { - virPCIDeviceAddress addr =3D adapter.data.scsi_host.parentaddr; - unsigned int unique_id =3D adapter.data.scsi_host.unique_id; + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) { + virStorageAdapterSCSIHostPtr scsi_host =3D &adapter->data.scsi_hos= t; + + if (scsi_host->has_parent) { + virPCIDeviceAddress addr =3D scsi_host->parentaddr; + unsigned int unique_id =3D scsi_host->unique_id; =20 if (!(name =3D virSCSIHostGetNameByParentaddr(addr.domain, addr.bus, @@ -193,16 +195,17 @@ getAdapterName(virStoragePoolSourceAdapter adapter) unique_id))) goto cleanup; } else { - ignore_value(VIR_STRDUP(name, adapter.data.scsi_host.name)); + ignore_value(VIR_STRDUP(name, scsi_host->name)); } - } else if (adapter.type =3D=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC= _HOST) { - if (!(name =3D virVHBAGetHostByWWN(NULL, - adapter.data.fchost.wwnn, - adapter.data.fchost.wwpn))) { + } + + if (adapter->type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_HOST) { + virStorageAdapterFCHostPtr fchost =3D &adapter->data.fchost; + + if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwp= n))) { virReportError(VIR_ERR_XML_ERROR, _("Failed to find SCSI host with wwnn=3D'%s', " - "wwpn=3D'%s'"), adapter.data.fchost.wwnn, - adapter.data.fchost.wwpn); + "wwpn=3D'%s'"), fchost->wwnn, fchost->wwpn); } } =20 @@ -254,10 +257,10 @@ checkParent(virConnectPtr conn, =20 static int createVport(virConnectPtr conn, - virStoragePoolObjPtr pool) + virStoragePoolDefPtr def, + const char *configFile, + virStorageAdapterFCHostPtr fchost) { - const char *configFile =3D pool->configFile; - virStoragePoolSourceAdapterPtr adapter =3D &pool->def->source.adapter; unsigned int parent_host; char *name =3D NULL; char *parent_hoststr =3D NULL; @@ -266,45 +269,37 @@ createVport(virConnectPtr conn, virThread thread; int ret =3D -1; =20 - if (adapter->type !=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) - return 0; - VIR_DEBUG("conn=3D%p, configFile=3D'%s' parent=3D'%s', wwnn=3D'%s' wwp= n=3D'%s'", - conn, NULLSTR(configFile), NULLSTR(adapter->data.fchost.pare= nt), - adapter->data.fchost.wwnn, adapter->data.fchost.wwpn); + conn, NULLSTR(configFile), NULLSTR(fchost->parent), + fchost->wwnn, fchost->wwpn); =20 /* If we find an existing HBA/vHBA within the fc_host sysfs * using the wwnn/wwpn, then a nodedev is already created for * this pool and we don't have to create the vHBA */ - if ((name =3D virVHBAGetHostByWWN(NULL, adapter->data.fchost.wwnn, - adapter->data.fchost.wwpn))) { + if ((name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) { /* If a parent was provided, let's make sure the 'name' we've * retrieved has the same parent */ - if (adapter->data.fchost.parent && - checkParent(conn, name, adapter->data.fchost.parent)) + if (fchost->parent && checkParent(conn, name, fchost->parent)) ret =3D 0; =20 goto cleanup; } =20 - if (adapter->data.fchost.parent) { - if (VIR_STRDUP(parent_hoststr, adapter->data.fchost.parent) < 0) + if (fchost->parent) { + if (VIR_STRDUP(parent_hoststr, fchost->parent) < 0) goto cleanup; - } else if (adapter->data.fchost.parent_wwnn && - adapter->data.fchost.parent_wwpn) { - if (!(parent_hoststr =3D - virVHBAGetHostByWWN(NULL, adapter->data.fchost.parent_wwnn, - adapter->data.fchost.parent_wwpn))) { + } else if (fchost->parent_wwnn && fchost->parent_wwpn) { + if (!(parent_hoststr =3D virVHBAGetHostByWWN(NULL, fchost->parent_= wwnn, + fchost->parent_wwpn))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cannot find parent using provided wwnn/wwpn"= )); goto cleanup; } - } else if (adapter->data.fchost.parent_fabric_wwn) { + } else if (fchost->parent_fabric_wwn) { if (!(parent_hoststr =3D - virVHBAGetHostByFabricWWN(NULL, - adapter->data.fchost.parent_fabric= _wwn))) { + virVHBAGetHostByFabricWWN(NULL, fchost->parent_fabric_wwn)))= { virReportError(VIR_ERR_XML_ERROR, "%s", _("cannot find parent using provided fabric_wwn= ")); goto cleanup; @@ -323,8 +318,8 @@ createVport(virConnectPtr conn, goto cleanup; =20 /* NOTE: - * We do not save the parent_hoststr in adapter->data.fchost.parent - * since we could be writing out the 'def' to the saved XML config. + * We do not save the parent_hoststr in fchost->parent since + * we could be writing out the 'def' to the saved XML config. * If we wrote out the name in the XML, then future starts would * always use the same parent rather than finding the "best available" * parent. Besides we have a way to determine the parent based on @@ -342,16 +337,16 @@ createVport(virConnectPtr conn, * restart, we need to save the persistent configuration. So if not * already defined as YES, then force the issue. */ - if (adapter->data.fchost.managed !=3D VIR_TRISTATE_BOOL_YES) { - adapter->data.fchost.managed =3D VIR_TRISTATE_BOOL_YES; + if (fchost->managed !=3D VIR_TRISTATE_BOOL_YES) { + fchost->managed =3D VIR_TRISTATE_BOOL_YES; if (configFile) { - if (virStoragePoolSaveConfig(configFile, pool->def) < 0) + if (virStoragePoolSaveConfig(configFile, def) < 0) goto cleanup; } } =20 - if (virVHBAManageVport(parent_host, adapter->data.fchost.wwpn, - adapter->data.fchost.wwnn, VPORT_CREATE) < 0) + if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, + VPORT_CREATE) < 0) goto cleanup; =20 virFileWaitForDevices(); @@ -361,10 +356,9 @@ createVport(virConnectPtr conn, * retry logic set to true. If the thread isn't created, then no big * deal since it's still possible to refresh the pool later. */ - if ((name =3D virVHBAGetHostByWWN(NULL, adapter->data.fchost.wwnn, - adapter->data.fchost.wwpn))) { + if ((name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) { if (VIR_ALLOC(cbdata) =3D=3D 0) { - memcpy(cbdata->pool_uuid, pool->def->uuid, VIR_UUID_BUFLEN); + memcpy(cbdata->pool_uuid, def->uuid, VIR_UUID_BUFLEN); VIR_STEAL_PTR(cbdata->fchost_name, name); =20 if (virThreadCreate(&thread, false, virStoragePoolFCRefreshThr= ead, @@ -384,9 +378,10 @@ createVport(virConnectPtr conn, return ret; } =20 + static int deleteVport(virConnectPtr conn, - virStoragePoolSourceAdapter adapter) + virStorageAdapterFCHostPtr fchost) { unsigned int parent_host; char *name =3D NULL; @@ -394,25 +389,19 @@ deleteVport(virConnectPtr conn, char *vhba_parent =3D NULL; int ret =3D -1; =20 - if (adapter.type !=3D VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) - return 0; - VIR_DEBUG("conn=3D%p parent=3D'%s', managed=3D'%d' wwnn=3D'%s' wwpn=3D= '%s'", - conn, NULLSTR(adapter.data.fchost.parent), - adapter.data.fchost.managed, - adapter.data.fchost.wwnn, - adapter.data.fchost.wwpn); + conn, NULLSTR(fchost->parent), fchost->managed, + fchost->wwnn, fchost->wwpn); =20 /* If we're not managing the deletion of the vHBA, then just return */ - if (adapter.data.fchost.managed !=3D VIR_TRISTATE_BOOL_YES) + if (fchost->managed !=3D VIR_TRISTATE_BOOL_YES) return 0; =20 /* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn= */ - if (!(name =3D virVHBAGetHostByWWN(NULL, adapter.data.fchost.wwnn, - adapter.data.fchost.wwpn))) { + if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to find fc_host for wwnn=3D'%s' and wwpn= =3D'%s'"), - adapter.data.fchost.wwnn, adapter.data.fchost.wwpn); + fchost->wwnn, fchost->wwpn); goto cleanup; } =20 @@ -420,8 +409,8 @@ deleteVport(virConnectPtr conn, * get the parent_host value; otherwise, we have to determine * the parent scsi_host which we did not save at startup time */ - if (adapter.data.fchost.parent) { - if (virSCSIHostGetNumber(adapter.data.fchost.parent, &parent_host)= < 0) + if (fchost->parent) { + if (virSCSIHostGetNumber(fchost->parent, &parent_host) < 0) goto cleanup; } else { if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) @@ -434,8 +423,8 @@ deleteVport(virConnectPtr conn, goto cleanup; } =20 - if (virVHBAManageVport(parent_host, adapter.data.fchost.wwpn, - adapter.data.fchost.wwnn, VPORT_DELETE) < 0) + if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, + VPORT_DELETE) < 0) goto cleanup; =20 ret =3D 0; @@ -458,13 +447,13 @@ virStorageBackendSCSICheckPool(virStoragePoolObjPtr p= ool, =20 *isActive =3D false; =20 - if (!(name =3D getAdapterName(pool->def->source.adapter))) { + if (!(name =3D getAdapterName(&pool->def->source.adapter))) { /* It's normal for the pool with "fc_host" type source * adapter fails to get the adapter name, since the vHBA * the adapter based on might be not created yet. */ if (pool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + VIR_STORAGE_ADAPTER_TYPE_FC_HOST) { virResetLastError(); return 0; } else { @@ -498,7 +487,7 @@ virStorageBackendSCSIRefreshPool(virConnectPtr conn ATT= RIBUTE_UNUSED, =20 pool->def->allocation =3D pool->def->capacity =3D pool->def->available= =3D 0; =20 - if (!(name =3D getAdapterName(pool->def->source.adapter))) + if (!(name =3D getAdapterName(&pool->def->source.adapter))) return -1; =20 if (virSCSIHostGetNumber(name, &host) < 0) @@ -518,19 +507,27 @@ virStorageBackendSCSIRefreshPool(virConnectPtr conn A= TTRIBUTE_UNUSED, return ret; } =20 + static int virStorageBackendSCSIStartPool(virConnectPtr conn, virStoragePoolObjPtr pool) { - return createVport(conn, pool); + if (pool->def->source.adapter.type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_= HOST) + return createVport(conn, pool->def, pool->configFile, + &pool->def->source.adapter.data.fchost); + + return 0; } =20 + static int virStorageBackendSCSIStopPool(virConnectPtr conn, virStoragePoolObjPtr pool) { - virStoragePoolSourceAdapter adapter =3D pool->def->source.adapter; - return deleteVport(conn, adapter); + if (pool->def->source.adapter.type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_= HOST) + return deleteVport(conn, &pool->def->source.adapter.data.fchost); + + return 0; } =20 virStorageBackend virStorageBackendSCSI =3D { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 2dd2238..f713c3e 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4423,8 +4423,7 @@ testStoragePoolCreateXML(virConnectPtr conn, goto cleanup; def =3D NULL; =20 - if (pool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + if (pool->def->source.adapter.type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_= HOST) { /* In the real code, we'd call virVHBAManageVport followed by * find_new_device, but we cannot do that here since we're not * mocking udev. The mock routine will copy an existing vHBA and @@ -4644,7 +4643,7 @@ testStoragePoolDestroy(virStoragePoolPtr pool) privpool->active =3D 0; =20 if (privpool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + VIR_STORAGE_ADAPTER_TYPE_FC_HOST) { if (testDestroyVport(privconn, privpool->def->source.adapter.data.fchost.wwn= n, privpool->def->source.adapter.data.fchost.wwp= n) < 0) --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 14:17:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.24 as permitted sender) client-ip=209.132.183.24; envelope-from=libvir-list-bounces@redhat.com; helo=mx3-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.24 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx3-phx2.redhat.com (mx3-phx2.redhat.com [209.132.183.24]) by mx.zohomail.com with SMTPS id 1488387286975685.4705125648435; Wed, 1 Mar 2017 08:54:46 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx3-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GpenG012710; Wed, 1 Mar 2017 11:51:40 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21Gocqp002091 for ; Wed, 1 Mar 2017 11:50:38 -0500 Received: from localhost.localdomain.com (ovpn-116-78.phx2.redhat.com [10.3.116.78]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21GoaBx006153 for ; Wed, 1 Mar 2017 11:50:37 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Wed, 1 Mar 2017 11:50:30 -0500 Message-Id: <20170301165033.27944-4-jferlan@redhat.com> In-Reply-To: <20170301165033.27944-1-jferlan@redhat.com> References: <20170301165033.27944-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 3/6] util: Rename virFileWaitForDevices 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" The function is actually in virutil.c, but prototyped in virfile.h. This patch fixes that by renaming the function to virWaitForDevices, adding the prototype in virutil.h and libvirt_private.syms, and then changing the callers to use the new name. Signed-off-by: John Ferlan --- src/libvirt_private.syms | 2 +- src/node_device/node_device_driver.c | 2 +- src/storage/storage_backend_disk.c | 6 +++--- src/storage/storage_backend_iscsi.c | 2 +- src/storage/storage_backend_logical.c | 4 ++-- src/storage/storage_backend_mpath.c | 2 +- src/storage/storage_backend_scsi.c | 2 +- src/storage/storage_util.c | 2 +- src/util/virfile.h | 2 -- src/util/virutil.c | 4 ++-- src/util/virutil.h | 2 ++ 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7ccf56b..83d01c4 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1644,7 +1644,6 @@ virFileStripSuffix; virFileTouch; virFileUnlock; virFileUpdatePerm; -virFileWaitForDevices; virFileWrapperFdClose; virFileWrapperFdFree; virFileWrapperFdNew; @@ -2747,6 +2746,7 @@ virTristateSwitchTypeFromString; virTristateSwitchTypeToString; virUpdateSelfLastChanged; virValidateWWN; +virWaitForDevices; =20 =20 # util/viruuid.h diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_de= vice_driver.c index 5d57006..fcb5644 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -548,7 +548,7 @@ find_new_device(virConnectPtr conn, const char *wwnn, c= onst char *wwpn) =20 while ((now - start) < LINUX_NEW_DEVICE_WAIT_TIME) { =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 dev =3D nodeDeviceLookupSCSIHostByWWN(conn, wwnn, wwpn, 0); =20 diff --git a/src/storage/storage_backend_disk.c b/src/storage/storage_backe= nd_disk.c index 50bdd36..39371f2 100644 --- a/src/storage/storage_backend_disk.c +++ b/src/storage/storage_backend_disk.c @@ -426,7 +426,7 @@ virStorageBackendDiskRefreshPool(virConnectPtr conn ATT= RIBUTE_UNUSED, VIR_FREE(pool->def->source.devices[0].freeExtents); pool->def->source.devices[0].nfreeExtent =3D 0; =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 if (!virFileExists(pool->def->source.devices[0].path)) { virReportError(VIR_ERR_INVALID_ARG, @@ -450,7 +450,7 @@ virStorageBackendDiskStartPool(virConnectPtr conn ATTRI= BUTE_UNUSED, virStoragePoolFormatDiskTypeToString(pool->def->source.format); const char *path =3D pool->def->source.devices[0].path; =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 if (!virFileExists(path)) { virReportError(VIR_ERR_INVALID_ARG, @@ -859,7 +859,7 @@ virStorageBackendDiskCreateVol(virConnectPtr conn, goto cleanup; =20 /* wait for device node to show up */ - virFileWaitForDevices(); + virWaitForDevices(); =20 /* Blow away free extent info, as we're about to re-populate it */ VIR_FREE(pool->def->source.devices[0].freeExtents); diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_back= end_iscsi.c index 866fa74..14f3e09 100644 --- a/src/storage/storage_backend_iscsi.c +++ b/src/storage/storage_backend_iscsi.c @@ -98,7 +98,7 @@ virStorageBackendISCSIGetHostNumber(const char *sysfs_pat= h, =20 VIR_DEBUG("Finding host number from '%s'", sysfs_path); =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 if (virDirOpen(&sysdir, sysfs_path) < 0) goto cleanup; diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_ba= ckend_logical.c index 756c62e..29d63b1 100644 --- a/src/storage/storage_backend_logical.c +++ b/src/storage/storage_backend_logical.c @@ -831,7 +831,7 @@ virStorageBackendLogicalRefreshPool(virConnectPtr conn = ATTRIBUTE_UNUSED, virCommandPtr cmd =3D NULL; int ret =3D -1; =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 /* Get list of all logical volumes */ if (virStorageBackendLogicalFindLVs(pool, NULL) < 0) @@ -925,7 +925,7 @@ virStorageBackendLogicalDeleteVol(virConnectPtr conn AT= TRIBUTE_UNUSED, =20 virCheckFlags(0, -1); =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 lvchange_cmd =3D virCommandNewArgList(LVCHANGE, "-aln", vol->target.pa= th, NULL); lvremove_cmd =3D virCommandNewArgList(LVREMOVE, "-f", vol->target.path= , NULL); diff --git a/src/storage/storage_backend_mpath.c b/src/storage/storage_back= end_mpath.c index 4bb38bb..606b399 100644 --- a/src/storage/storage_backend_mpath.c +++ b/src/storage/storage_backend_mpath.c @@ -262,7 +262,7 @@ virStorageBackendMpathRefreshPool(virConnectPtr conn AT= TRIBUTE_UNUSED, =20 pool->def->allocation =3D pool->def->capacity =3D pool->def->available= =3D 0; =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 virStorageBackendGetMaps(pool); =20 diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backe= nd_scsi.c index ff17409..abbd38d 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -349,7 +349,7 @@ createVport(virConnectPtr conn, VPORT_CREATE) < 0) goto cleanup; =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 /* Creating our own VPORT didn't leave enough time to find any LUN's, * so, let's create a thread whose job it is to call the FindLU's with diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index a665bac..64fc843 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -4012,7 +4012,7 @@ virStorageBackendSCSIFindLUs(virStoragePoolObjPtr poo= l, =20 VIR_DEBUG("Discovering LUs on host %u", scanhost); =20 - virFileWaitForDevices(); + virWaitForDevices(); =20 if (virDirOpen(&devicedir, device_path) < 0) return -1; diff --git a/src/util/virfile.h b/src/util/virfile.h index f2a3faa..b29feee 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -292,8 +292,6 @@ int virFileOpenTty(int *ttymaster, =20 char *virFileFindMountPoint(const char *type); =20 -void virFileWaitForDevices(void); - /* NB: this should be combined with virFileBuildPath */ # define virBuildPath(path, ...) \ virBuildPathInternal(path, __VA_ARGS__, NULL) diff --git a/src/util/virutil.c b/src/util/virutil.c index bb0f2d2..79db1d8 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -1582,7 +1582,7 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *gro= ups, int ngroups, =20 =20 #if defined(UDEVADM) || defined(UDEVSETTLE) -void virFileWaitForDevices(void) +void virWaitForDevices(void) { # ifdef UDEVADM const char *const settleprog[] =3D { UDEVADM, "settle", NULL }; @@ -1603,7 +1603,7 @@ void virFileWaitForDevices(void) ignore_value(virRun(settleprog, &exitstatus)); } #else -void virFileWaitForDevices(void) +void virWaitForDevices(void) {} #endif =20 diff --git a/src/util/virutil.h b/src/util/virutil.h index 877207c..e097b77 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -51,6 +51,8 @@ int virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *gro= ups, int ngroups, unsigned long long capBits, bool clearExistingCaps); =20 +void virWaitForDevices(void); + int virScaleInteger(unsigned long long *value, const char *suffix, unsigned long long scale, unsigned long long limit) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 14:17:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.24 as permitted sender) client-ip=209.132.183.24; envelope-from=libvir-list-bounces@redhat.com; helo=mx3-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.24 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx3-phx2.redhat.com (mx3-phx2.redhat.com [209.132.183.24]) by mx.zohomail.com with SMTPS id 1488387448752467.24923009505824; Wed, 1 Mar 2017 08:57:28 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx3-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GqHXE012752; Wed, 1 Mar 2017 11:52:17 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GocrS002108 for ; Wed, 1 Mar 2017 11:50:38 -0500 Received: from localhost.localdomain.com (ovpn-116-78.phx2.redhat.com [10.3.116.78]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21GoaC0006153 for ; Wed, 1 Mar 2017 11:50:38 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Wed, 1 Mar 2017 11:50:31 -0500 Message-Id: <20170301165033.27944-5-jferlan@redhat.com> In-Reply-To: <20170301165033.27944-1-jferlan@redhat.com> References: <20170301165033.27944-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 4/6] conf: Move/rename createVport and deleteVport 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" Move the bulk of the code to the node_device_conf and rename to virNodeDevice{Create|Delete}Vport. Alter the create algorithm slightly in order to return the name of the scsi_host vHBA that was created. The existing code would fetch the name and if it exists would start a thread looking for the LUNs; however, in no way did it validate the device was created for the storage pool even though it would be used thereafter. This slight change allows the code that checks if the node device by wwnn/wwpn already exists and return that name. This fixes a second yet seen issue that if the nodedev was present, but the parent by name wasn't provided (perhaps parent by wwnn/wwpn or by fabric_name), then a failure would be returned. For this path it shouldn't be an error - we should just be happy that something else is managing the device and we don't have to create/delete it. The end result is that the startVport code can now just start the thread once it gets a non NULL name back. Signed-off-by: John Ferlan --- src/conf/node_device_conf.c | 211 +++++++++++++++++++++++++++++++++= ++++ src/conf/node_device_conf.h | 9 ++ src/libvirt_private.syms | 2 + src/storage/storage_backend_scsi.c | 192 +++------------------------------ 4 files changed, 235 insertions(+), 179 deletions(-) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 43e23fc..e028027 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -2345,3 +2345,214 @@ virNodeDeviceGetParentName(virConnectPtr conn, =20 return parent; } + + +/* + * Using the host# name found via wwnn/wwpn lookup in the fc_host + * sysfs tree to get the parent 'scsi_host#' to ensure it matches. + */ +static bool +nodeDeviceCheckParent(virConnectPtr conn, + const char *name, + const char *parent_name) +{ + char *scsi_host_name =3D NULL; + char *vhba_parent =3D NULL; + bool retval =3D false; + + VIR_DEBUG("conn=3D%p, name=3D%s, parent_name=3D%s", conn, name, parent= _name); + + /* autostarted pool - assume we're OK */ + if (!conn) + return true; + + if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) + goto cleanup; + + if (!(vhba_parent =3D virNodeDeviceGetParentName(conn, scsi_host_name)= )) + goto cleanup; + + if (STRNEQ(parent_name, vhba_parent)) { + virReportError(VIR_ERR_XML_ERROR, + _("Parent attribute '%s' does not match parent '%s'= " + "determined for the '%s' wwnn/wwpn lookup."), + parent_name, vhba_parent, name); + goto cleanup; + } + + retval =3D true; + + cleanup: + VIR_FREE(vhba_parent); + VIR_FREE(scsi_host_name); + return retval; +} + + +/** + * @conn: Connection pointer + * @fchost: Pointer to vHBA adapter + * + * Create a vHBA for Storage. This code accomplishes this via searching + * through the sysfs for scsi_host/fc_host in order to first ensure some + * vHBA doesn't already exist for the requested wwnn/wwpn (e.g. an unmanag= ed + * vHBA) and to search for the parent vport capable scsi_host by name, + * wwnn/wwpn, or fabric_wwn (if provided). If no parent is provided, then + * a vport capable scsi_host will be selected. + * + * Returns vHBA name on success, NULL on failure with an error message set + */ +char * +virNodeDeviceCreateVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost) +{ + unsigned int parent_host; + char *name =3D NULL; + char *parent_hoststr =3D NULL; + bool skip_capable_check =3D false; + + VIR_DEBUG("conn=3D%p, parent=3D'%s', wwnn=3D'%s' wwpn=3D'%s'", + conn, NULLSTR(fchost->parent), fchost->wwnn, fchost->wwpn); + + /* If we find an existing HBA/vHBA within the fc_host sysfs + * using the wwnn/wwpn, then a nodedev is already created for + * this pool and we don't have to create the vHBA + */ + if ((name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) { + /* If a parent was provided, let's make sure the 'name' we've + * retrieved has the same parent. If not this will cause failure. = */ + if (fchost->parent && nodeDeviceCheckParent(conn, name, fchost->pa= rent)) + VIR_FREE(name); + + return name; + } + + if (fchost->parent) { + if (VIR_STRDUP(parent_hoststr, fchost->parent) < 0) + goto cleanup; + } else if (fchost->parent_wwnn && fchost->parent_wwpn) { + if (!(parent_hoststr =3D virVHBAGetHostByWWN(NULL, fchost->parent_= wwnn, + fchost->parent_wwpn))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("cannot find parent using provided wwnn/wwpn"= )); + goto cleanup; + } + } else if (fchost->parent_fabric_wwn) { + if (!(parent_hoststr =3D + virVHBAGetHostByFabricWWN(NULL, fchost->parent_fabric_wwn)))= { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("cannot find parent using provided fabric_wwn= ")); + goto cleanup; + } + } else { + if (!(parent_hoststr =3D virVHBAFindVportHost(NULL))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'parent' for vHBA not specified, and " + "cannot find one on this host")); + goto cleanup; + } + skip_capable_check =3D true; + } + + if (virSCSIHostGetNumber(parent_hoststr, &parent_host) < 0) + goto cleanup; + + /* NOTE: + * We do not save the parent_hoststr in fchost->parent since + * we could be writing out the 'def' to the saved XML config. + * If we wrote out the name in the XML, then future starts would + * always use the same parent rather than finding the "best available" + * parent. Besides we have a way to determine the parent based on + * the 'name' field. + */ + if (!skip_capable_check && !virVHBAPathExists(NULL, parent_host)) { + virReportError(VIR_ERR_XML_ERROR, + _("parent '%s' specified for vHBA does not exist"), + parent_hoststr); + goto cleanup; + } + + if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, + VPORT_CREATE) < 0) + goto cleanup; + + /* Let's ensure the device was created */ + virWaitForDevices(); + if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { + ignore_value(virVHBAManageVport(parent_host, fchost->wwpn, fchost-= >wwnn, + VPORT_DELETE)); + goto cleanup; + } + + cleanup: + VIR_FREE(parent_hoststr); + return name; +} + + +/** + * @conn: Connection pointer + * @fchost: Pointer to vHBA adapter + * + * As long as the vHBA is being managed, search for the scsi_host via the + * provided wwnn/wwpn and then find the corresponding parent scsi_host in + * order to send the delete request. + * + * Returns 0 on success, -1 on failure + */ +int +virNodeDeviceDeleteVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost) +{ + char *name =3D NULL; + char *scsi_host_name =3D NULL; + unsigned int parent_host; + char *vhba_parent =3D NULL; + int ret =3D -1; + + VIR_DEBUG("conn=3D%p parent=3D'%s', managed=3D'%d' wwnn=3D'%s' wwpn=3D= '%s'", + conn, NULLSTR(fchost->parent), fchost->managed, + fchost->wwnn, fchost->wwpn); + + /* If we're not managing the deletion of the vHBA, then just return */ + if (fchost->managed !=3D VIR_TRISTATE_BOOL_YES) + return 0; + + /* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn= */ + if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to find fc_host for wwnn=3D'%s' and wwpn= =3D'%s'"), + fchost->wwnn, fchost->wwpn); + goto cleanup; + } + + /* If at startup time we provided a parent, then use that to + * get the parent_host value; otherwise, we have to determine + * the parent scsi_host which we did not save at startup time + */ + if (fchost->parent) { + if (virSCSIHostGetNumber(fchost->parent, &parent_host) < 0) + goto cleanup; + } else { + if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) + goto cleanup; + + if (!(vhba_parent =3D virNodeDeviceGetParentName(conn, scsi_host_n= ame))) + goto cleanup; + + if (virSCSIHostGetNumber(vhba_parent, &parent_host) < 0) + goto cleanup; + } + + if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, + VPORT_DELETE) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + VIR_FREE(name); + VIR_FREE(vhba_parent); + VIR_FREE(scsi_host_name); + return ret; +} diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index 8213c27..59b57d9 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -28,10 +28,13 @@ # include "internal.h" # include "virbitmap.h" # include "virutil.h" +# include "virscsihost.h" # include "virthread.h" # include "virpci.h" +# include "virvhba.h" # include "device_conf.h" # include "object_event.h" +# include "storage_adapter_conf.h" =20 # include =20 @@ -340,4 +343,10 @@ int virNodeDeviceObjListExport(virConnectPtr conn, char *virNodeDeviceGetParentName(virConnectPtr conn, const char *nodedev_name); =20 +char *virNodeDeviceCreateVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost); + +int virNodeDeviceDeleteVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost); + #endif /* __VIR_NODE_DEVICE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 83d01c4..862761b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -695,11 +695,13 @@ virNodeDevCapsDefFree; virNodeDevCapTypeFromString; virNodeDevCapTypeToString; virNodeDeviceAssignDef; +virNodeDeviceCreateVport; virNodeDeviceDefFormat; virNodeDeviceDefFree; virNodeDeviceDefParseFile; virNodeDeviceDefParseNode; virNodeDeviceDefParseString; +virNodeDeviceDeleteVport; virNodeDeviceFindByName; virNodeDeviceFindBySysfsPath; virNodeDeviceGetParentHost; diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backe= nd_scsi.c index abbd38d..666e473 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -33,9 +33,7 @@ #include "virlog.h" #include "virfile.h" #include "vircommand.h" -#include "virscsihost.h" #include "virstring.h" -#include "virvhba.h" #include "storage_util.h" #include "node_device_conf.h" =20 @@ -214,57 +212,13 @@ getAdapterName(virStorageAdapterPtr adapter) return name; } =20 -/* - * Using the host# name found via wwnn/wwpn lookup in the fc_host - * sysfs tree to get the parent 'scsi_host#' to ensure it matches. - */ -static bool -checkParent(virConnectPtr conn, - const char *name, - const char *parent_name) -{ - char *scsi_host_name =3D NULL; - char *vhba_parent =3D NULL; - bool retval =3D false; - - VIR_DEBUG("conn=3D%p, name=3D%s, parent_name=3D%s", conn, name, parent= _name); - - /* autostarted pool - assume we're OK */ - if (!conn) - return true; - - if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) - goto cleanup; - - if (!(vhba_parent =3D virNodeDeviceGetParentName(conn, scsi_host_name)= )) - goto cleanup; - - if (STRNEQ(parent_name, vhba_parent)) { - virReportError(VIR_ERR_XML_ERROR, - _("Parent attribute '%s' does not match parent '%s'= " - "determined for the '%s' wwnn/wwpn lookup."), - parent_name, vhba_parent, name); - goto cleanup; - } - - retval =3D true; - - cleanup: - VIR_FREE(vhba_parent); - VIR_FREE(scsi_host_name); - return retval; -} - static int createVport(virConnectPtr conn, virStoragePoolDefPtr def, const char *configFile, virStorageAdapterFCHostPtr fchost) { - unsigned int parent_host; char *name =3D NULL; - char *parent_hoststr =3D NULL; - bool skip_capable_check =3D false; virStoragePoolFCRefreshInfoPtr cbdata =3D NULL; virThread thread; int ret =3D -1; @@ -273,66 +227,11 @@ createVport(virConnectPtr conn, conn, NULLSTR(configFile), NULLSTR(fchost->parent), fchost->wwnn, fchost->wwpn); =20 - /* If we find an existing HBA/vHBA within the fc_host sysfs - * using the wwnn/wwpn, then a nodedev is already created for - * this pool and we don't have to create the vHBA - */ - if ((name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) { - /* If a parent was provided, let's make sure the 'name' we've - * retrieved has the same parent - */ - if (fchost->parent && checkParent(conn, name, fchost->parent)) - ret =3D 0; =20 + if (!(name =3D virNodeDeviceCreateVport(conn, fchost))) goto cleanup; - } =20 - if (fchost->parent) { - if (VIR_STRDUP(parent_hoststr, fchost->parent) < 0) - goto cleanup; - } else if (fchost->parent_wwnn && fchost->parent_wwpn) { - if (!(parent_hoststr =3D virVHBAGetHostByWWN(NULL, fchost->parent_= wwnn, - fchost->parent_wwpn))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("cannot find parent using provided wwnn/wwpn"= )); - goto cleanup; - } - } else if (fchost->parent_fabric_wwn) { - if (!(parent_hoststr =3D - virVHBAGetHostByFabricWWN(NULL, fchost->parent_fabric_wwn)))= { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("cannot find parent using provided fabric_wwn= ")); - goto cleanup; - } - } else { - if (!(parent_hoststr =3D virVHBAFindVportHost(NULL))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("'parent' for vHBA not specified, and " - "cannot find one on this host")); - goto cleanup; - } - skip_capable_check =3D true; - } - - if (virSCSIHostGetNumber(parent_hoststr, &parent_host) < 0) - goto cleanup; - - /* NOTE: - * We do not save the parent_hoststr in fchost->parent since - * we could be writing out the 'def' to the saved XML config. - * If we wrote out the name in the XML, then future starts would - * always use the same parent rather than finding the "best available" - * parent. Besides we have a way to determine the parent based on - * the 'name' field. - */ - if (!skip_capable_check && !virVHBAPathExists(NULL, parent_host)) { - virReportError(VIR_ERR_XML_ERROR, - _("parent '%s' specified for vHBA does not exist"), - parent_hoststr); - goto cleanup; - } - - /* Since we're creating the vHBA, then we need to manage removing it + /* Since we've created the vHBA, then we need to manage removing it * as well. Since we need this setting to "live" through a libvirtd * restart, we need to save the persistent configuration. So if not * already defined as YES, then force the issue. @@ -345,28 +244,20 @@ createVport(virConnectPtr conn, } } =20 - if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, - VPORT_CREATE) < 0) - goto cleanup; - - virWaitForDevices(); - /* Creating our own VPORT didn't leave enough time to find any LUN's, * so, let's create a thread whose job it is to call the FindLU's with * retry logic set to true. If the thread isn't created, then no big * deal since it's still possible to refresh the pool later. */ - if ((name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) { - if (VIR_ALLOC(cbdata) =3D=3D 0) { - memcpy(cbdata->pool_uuid, def->uuid, VIR_UUID_BUFLEN); - VIR_STEAL_PTR(cbdata->fchost_name, name); - - if (virThreadCreate(&thread, false, virStoragePoolFCRefreshThr= ead, - cbdata) < 0) { - /* Oh well - at least someone can still refresh afterwards= */ - VIR_DEBUG("Failed to create FC Pool Refresh Thread"); - virStoragePoolFCRefreshDataFree(cbdata); - } + if (VIR_ALLOC(cbdata) =3D=3D 0) { + memcpy(cbdata->pool_uuid, def->uuid, VIR_UUID_BUFLEN); + VIR_STEAL_PTR(cbdata->fchost_name, name); + + if (virThreadCreate(&thread, false, virStoragePoolFCRefreshThread, + cbdata) < 0) { + /* Oh well - at least someone can still refresh afterwards */ + VIR_DEBUG("Failed to create FC Pool Refresh Thread"); + virStoragePoolFCRefreshDataFree(cbdata); } } =20 @@ -374,64 +265,6 @@ createVport(virConnectPtr conn, =20 cleanup: VIR_FREE(name); - VIR_FREE(parent_hoststr); - return ret; -} - - -static int -deleteVport(virConnectPtr conn, - virStorageAdapterFCHostPtr fchost) -{ - unsigned int parent_host; - char *name =3D NULL; - char *scsi_host_name =3D NULL; - char *vhba_parent =3D NULL; - int ret =3D -1; - - VIR_DEBUG("conn=3D%p parent=3D'%s', managed=3D'%d' wwnn=3D'%s' wwpn=3D= '%s'", - conn, NULLSTR(fchost->parent), fchost->managed, - fchost->wwnn, fchost->wwpn); - - /* If we're not managing the deletion of the vHBA, then just return */ - if (fchost->managed !=3D VIR_TRISTATE_BOOL_YES) - return 0; - - /* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn= */ - if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to find fc_host for wwnn=3D'%s' and wwpn= =3D'%s'"), - fchost->wwnn, fchost->wwpn); - goto cleanup; - } - - /* If at startup time we provided a parent, then use that to - * get the parent_host value; otherwise, we have to determine - * the parent scsi_host which we did not save at startup time - */ - if (fchost->parent) { - if (virSCSIHostGetNumber(fchost->parent, &parent_host) < 0) - goto cleanup; - } else { - if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) - goto cleanup; - - if (!(vhba_parent =3D virNodeDeviceGetParentName(conn, scsi_host_n= ame))) - goto cleanup; - - if (virSCSIHostGetNumber(vhba_parent, &parent_host) < 0) - goto cleanup; - } - - if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, - VPORT_DELETE) < 0) - goto cleanup; - - ret =3D 0; - cleanup: - VIR_FREE(name); - VIR_FREE(vhba_parent); - VIR_FREE(scsi_host_name); return ret; } =20 @@ -525,7 +358,8 @@ virStorageBackendSCSIStopPool(virConnectPtr conn, virStoragePoolObjPtr pool) { if (pool->def->source.adapter.type =3D=3D VIR_STORAGE_ADAPTER_TYPE_FC_= HOST) - return deleteVport(conn, &pool->def->source.adapter.data.fchost); + return virNodeDeviceDeleteVport(conn, + &pool->def->source.adapter.data.fc= host); =20 return 0; } --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 14:17:49 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.24 as permitted sender) client-ip=209.132.183.24; envelope-from=libvir-list-bounces@redhat.com; helo=mx3-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.24 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx3-phx2.redhat.com (mx3-phx2.redhat.com [209.132.183.24]) by mx.zohomail.com with SMTPS id 1488387381980229.20499314078393; Wed, 1 Mar 2017 08:56:21 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx3-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GqvEO012792; Wed, 1 Mar 2017 11:52:57 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GodGl002115 for ; Wed, 1 Mar 2017 11:50:39 -0500 Received: from localhost.localdomain.com (ovpn-116-78.phx2.redhat.com [10.3.116.78]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21GoaC1006153 for ; Wed, 1 Mar 2017 11:50:38 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Wed, 1 Mar 2017 11:50:32 -0500 Message-Id: <20170301165033.27944-6-jferlan@redhat.com> In-Reply-To: <20170301165033.27944-1-jferlan@redhat.com> References: <20170301165033.27944-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 5/6] util: Alter virNodeDevice{Create|Delete}Vport to use nodedev APIs 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" If we have a connection pointer there's no sense walking through the sysfs in order to create/destroy the vHBA. Instead, let's make use of the node device create/destroy API's. Since we don't have to rewrite all the various parent options for the test driver in order to test whether the storage pool creation works as the node device creation has been tested already, let's just use the altered API to test the storage pool paths. Fix a "bug" in the storage pool test driver code which "assumed" testStoragePoolObjSetDefaults should fill in the configFile for both the Define/Create (persistent) and CreateXML (transient) pools by just VIR_FREE() of the pool during CreateXML. Because the configFile was filled in, during Destroy, the pool wouldn't be free causing a test using the same name pool to fail. Signed-off-by: John Ferlan --- src/conf/node_device_conf.c | 121 ++++++++++++++++++++++++++++++++++++++++= ++++ src/test/test_driver.c | 6 +++ tests/fchosttest.c | 15 ++++++ 3 files changed, 142 insertions(+) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index e028027..f2f5e1c 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -2391,6 +2391,82 @@ nodeDeviceCheckParent(virConnectPtr conn, =20 /** * @conn: Connection pointer + * @fchost: Pointer to the vHBA adapter + * + * If we have a valid connection, then use the node device create + * XML API rather than traversing through the sysfs to create the vHBA. + * Generate the Node Device XML using the Storage vHBA Adapter providing + * either the parent name, parent wwnn/wwpn, or parent fabric_name if + * available to the Node Device code. Since the Storage XML processing + * requires the wwnn/wwpn to be used for the vHBA to be provided (and + * not generated), we can use that as the fc_host wwnn/wwpn. This will + * allow for easier search later when we need it. + * + * Returns vHBA name on success, NULL on failure with an error message set + */ +static char * +nodeDeviceCreateNodeDeviceVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + char *vhbaStr =3D NULL; + virNodeDevicePtr dev =3D NULL; + char *name; + bool created =3D false; + + /* If the nodedev already knows about this vHBA, then we're not + * managing it - we'll just use it. */ + if ((dev =3D virNodeDeviceLookupSCSIHostByWWN(conn, fchost->wwnn, + fchost->wwpn, 0))) + goto skip_create; + + virBufferAddLit(&buf, "\n"); + virBufferAdjustIndent(&buf, 2); + if (fchost->parent) + virBufferEscapeString(&buf, "%s\n", + fchost->parent); + else if (fchost->parent_wwnn && fchost->parent_wwpn) + virBufferAsprintf(&buf, "\n", + fchost->parent_wwnn, fchost->parent_wwpn); + else if (fchost->parent_fabric_wwn) + virBufferAsprintf(&buf, "\n", + fchost->parent_fabric_wwn); + virBufferAddLit(&buf, "\n"); + virBufferAdjustIndent(&buf, 2); + virBufferAsprintf(&buf, "\n", + fchost->wwnn, fchost->wwpn); + virBufferAddLit(&buf, "\n"); + virBufferAdjustIndent(&buf, -2); + virBufferAddLit(&buf, "\n"); + virBufferAdjustIndent(&buf, -2); + virBufferAddLit(&buf, "\n"); + + if (!(vhbaStr =3D virBufferContentAndReset(&buf))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("unable to create node device XML")); + goto cleanup; + } + + if (!(dev =3D virNodeDeviceCreateXML(conn, vhbaStr, 0))) + goto cleanup; + created =3D true; + + skip_create: + if (VIR_STRDUP(name, virNodeDeviceGetName(dev)) < 0) { + /* If we created, then destroy it */ + if (created) + ignore_value(virNodeDeviceDestroy(dev)); + } + + cleanup: + VIR_FREE(vhbaStr); + virObjectUnref(dev); + return name; +} + + +/** + * @conn: Connection pointer * @fchost: Pointer to vHBA adapter * * Create a vHBA for Storage. This code accomplishes this via searching @@ -2414,6 +2490,11 @@ virNodeDeviceCreateVport(virConnectPtr conn, VIR_DEBUG("conn=3D%p, parent=3D'%s', wwnn=3D'%s' wwpn=3D'%s'", conn, NULLSTR(fchost->parent), fchost->wwnn, fchost->wwpn); =20 + /* If we have a connection, bypass sysfs searching and use the + * NodeDevice API's in order to perform our delete */ + if (conn) + return nodeDeviceCreateNodeDeviceVport(conn, fchost); + /* If we find an existing HBA/vHBA within the fc_host sysfs * using the wwnn/wwpn, then a nodedev is already created for * this pool and we don't have to create the vHBA @@ -2494,6 +2575,41 @@ virNodeDeviceCreateVport(virConnectPtr conn, * @conn: Connection pointer * @fchost: Pointer to vHBA adapter * + * Search for the vHBA SCSI_HOST by the wwnn/wwpn provided at creation + * and use the node device driver to destroy. + * + * Returns 0 on success, -1 on failure w/ error message. + */ +static int +nodeDeviceDeleteNodeDeviceVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost) +{ + int ret =3D -1; + virNodeDevicePtr dev; + + if (!(dev =3D virNodeDeviceLookupSCSIHostByWWN(conn, fchost->wwnn, + fchost->wwpn, 0))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to find fc_host for wwnn=3D'%s' and wwpn= =3D'%s'"), + fchost->wwnn, fchost->wwpn); + return -1; + } + + if (virNodeDeviceDestroy(dev) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + virObjectUnref(dev); + return ret; +} + + +/** + * @conn: Connection pointer + * @fchost: Pointer to vHBA adapter + * * As long as the vHBA is being managed, search for the scsi_host via the * provided wwnn/wwpn and then find the corresponding parent scsi_host in * order to send the delete request. @@ -2518,6 +2634,11 @@ virNodeDeviceDeleteVport(virConnectPtr conn, if (fchost->managed !=3D VIR_TRISTATE_BOOL_YES) return 0; =20 + /* If we have a connection, bypass sysfs searching and use the + * NodeDevice API's in order to perform our delete */ + if (conn) + return nodeDeviceDeleteNodeDeviceVport(conn, fchost); + /* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn= */ if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { virReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/test/test_driver.c b/src/test/test_driver.c index f713c3e..d1ea493 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4442,6 +4442,12 @@ testStoragePoolCreateXML(virConnectPtr conn, pool =3D NULL; goto cleanup; } + + /* *SetDefaults fills this in for the persistent pools, but this + * would be a transient pool so remove it; otherwise, the Destroy + * code will not Remove the pool */ + VIR_FREE(pool->configFile); + pool->active =3D 1; =20 event =3D virStoragePoolEventLifecycleNew(pool->def->name, pool->def->= uuid, diff --git a/tests/fchosttest.c b/tests/fchosttest.c index dc6b9af..c024ae5 100644 --- a/tests/fchosttest.c +++ b/tests/fchosttest.c @@ -87,6 +87,18 @@ static const char test11_xml[] =3D " " ""; =20 +/* virStoragePoolCreateXML without any parent to find the vport capable HB= A */ +static const char test12_xml[] =3D +"" +" vhba_pool" +" " +" " +" " +" " +" /dev/disk/by-path" +" " +""; + =20 /* Test virIsVHBACapable */ static int @@ -374,6 +386,9 @@ mymain(void) if (virTestRun("manageVHBAByStoragePool-by-parent", manageVHBAByStorag= ePool, test11_xml) < 0) ret =3D -1; + if (virTestRun("manageVHBAByStoragePool-no-parent", manageVHBAByStorag= ePool, + test12_xml) < 0) + ret =3D -1; =20 cleanup: VIR_FREE(fchost_prefix); --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Wed Apr 24 14:17:49 2024 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 1488387390102225.13367860915537; Wed, 1 Mar 2017 08:56:30 -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 v21GqHXt018641; Wed, 1 Mar 2017 11:52:17 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v21GodST002121 for ; Wed, 1 Mar 2017 11:50:39 -0500 Received: from localhost.localdomain.com (ovpn-116-78.phx2.redhat.com [10.3.116.78]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v21GoaC2006153 for ; Wed, 1 Mar 2017 11:50:39 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Wed, 1 Mar 2017 11:50:33 -0500 Message-Id: <20170301165033.27944-7-jferlan@redhat.com> In-Reply-To: <20170301165033.27944-1-jferlan@redhat.com> References: <20170301165033.27944-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 6/6] tests: Add more storage pool vHBA tests 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" Add the parent wwnn/wwpn and fabric_wwn tests for the storage pool now that we have the capability to use the node device driver to handle the searches via a connection. Signed-off-by: John Ferlan --- tests/fchosttest.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/fchosttest.c b/tests/fchosttest.c index c024ae5..c080c9b 100644 --- a/tests/fchosttest.c +++ b/tests/fchosttest.c @@ -100,6 +100,30 @@ static const char test12_xml[] =3D ""; =20 =20 +/* virStoragePoolCreateXML parent wwnn/wwpn to find the vport capable HBA = */ +static const char test13_xml[] =3D +"" +" vhba_pool" +" " +" " +" " +" " +" /dev/disk/by-path" +" " +""; + +/* virStoragePoolCreateXML parent fabric_wwn to find the vport capable HBA= */ +static const char test14_xml[] =3D +"" +" vhba_pool" +" " +" " +" " +" " +" /dev/disk/by-path" +" " +""; + /* Test virIsVHBACapable */ static int test1(const void *data ATTRIBUTE_UNUSED) @@ -389,6 +413,14 @@ mymain(void) if (virTestRun("manageVHBAByStoragePool-no-parent", manageVHBAByStorag= ePool, test12_xml) < 0) ret =3D -1; + if (virTestRun("manageVHBAByStoragePool-parent-wwn", + manageVHBAByStoragePool, + test13_xml) < 0) + ret =3D -1; + if (virTestRun("manageVHBAByStoragePool-parent-fabric-wwn", + manageVHBAByStoragePool, + test14_xml) < 0) + ret =3D -1; =20 cleanup: VIR_FREE(fchost_prefix); --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list