From nobody Tue Apr 23 20:53:43 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 1487596934144297.9707830149696; Mon, 20 Feb 2017 05:22:14 -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 v1KDIaFQ001203; Mon, 20 Feb 2017 08:18:36 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDINnJ005719 for ; Mon, 20 Feb 2017 08:18:23 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMwl002607 for ; Mon, 20 Feb 2017 08:18:22 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:12 -0500 Message-Id: <20170220131819.2919-2-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 1/8] conf: Fix leak in virNodeDeviceDefParseXML 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 'nodes' is overwritten after the first usage and possibly leaked if any code in the first set of parsing goes to error. Found by Coverity. Signed-off-by: John Ferlan --- src/conf/node_device_conf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 1c81b48..07b0838 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -1766,7 +1766,7 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, { virNodeDeviceDefPtr def; virNodeDevCapsDefPtr *next_cap; - xmlNodePtr *nodes; + xmlNodePtr *nodes =3D NULL; int n, m; size_t i; =20 @@ -1789,7 +1789,6 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, def->sysfs_path =3D virXPathString("string(./path[1])", ctxt); =20 /* Parse devnodes */ - nodes =3D NULL; if ((n =3D virXPathNodeSet("./devnode", ctxt, &nodes)) < 0) goto error; =20 @@ -1842,7 +1841,7 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, ctxt); =20 /* Parse device capabilities */ - nodes =3D NULL; + VIR_FREE(nodes); if ((n =3D virXPathNodeSet("./capability", ctxt, &nodes)) < 0) goto error; =20 @@ -1859,10 +1858,8 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, nodes[i], create, virt_type); - if (!*next_cap) { - VIR_FREE(nodes); + if (!*next_cap) goto error; - } =20 next_cap =3D &(*next_cap)->next; } @@ -1872,6 +1869,7 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, =20 error: virNodeDeviceDefFree(def); + VIR_FREE(nodes); return NULL; } =20 --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Tue Apr 23 20:53:43 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 1487596936074249.25809167849275; Mon, 20 Feb 2017 05:22:16 -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 v1KDIcht001217; Mon, 20 Feb 2017 08:18:38 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDINso005724 for ; Mon, 20 Feb 2017 08:18:23 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMwm002607 for ; Mon, 20 Feb 2017 08:18:23 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:13 -0500 Message-Id: <20170220131819.2919-3-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 2/8] 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 | 95 ++++++++++++++++++++++++++++++++++++++++++++++= ++-- tests/fchosttest.c | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 2 deletions(-) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 5fef3f1..4dff0f1 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4365,6 +4365,32 @@ testConnectFindStoragePoolSources(virConnectPtr conn= ATTRIBUTE_UNUSED, } =20 =20 +static virNodeDeviceDefPtr +testNodeDeviceMockCreateVport(virConnectPtr conn, + const char *wwnn, + const char *wwpn); +static int +testCreateVport(virConnectPtr conn, + const char *wwnn, + const char *wwpn) +{ + /* 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 (!testNodeDeviceMockCreateVport(conn, wwnn, wwpn)) + return -1; + + return 0; +} + + static virStoragePoolPtr testStoragePoolCreateXML(virConnectPtr conn, const char *xml, @@ -4395,6 +4421,24 @@ 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. So in order to allow that to + * work properly, we need to drop our lock */ + testDriverUnlock(privconn); + if (testCreateVport(conn, pool->def->source.adapter.data.fchost.ww= nn, + pool->def->source.adapter.data.fchost.wwpn) < = 0) { + virStoragePoolObjRemove(&privconn->pools, pool); + pool =3D NULL; + testDriverLock(privconn); + goto cleanup; + } + testDriverLock(privconn); + } + if (testStoragePoolObjSetDefaults(pool) =3D=3D -1) { virStoragePoolObjRemove(&privconn->pools, pool); pool =3D NULL; @@ -4405,7 +4449,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 +4582,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 +4643,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 Tue Apr 23 20:53:43 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 14875969540931017.980199213411; Mon, 20 Feb 2017 05:22:34 -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 v1KDISHU032323; Mon, 20 Feb 2017 08:18:28 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDIOAX005729 for ; Mon, 20 Feb 2017 08:18:24 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMwn002607 for ; Mon, 20 Feb 2017 08:18:23 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:14 -0500 Message-Id: <20170220131819.2919-4-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 3/8] util: 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/util/virstoragedevice.{c,h}. Rather than have virstoragefile be a repository for more things - create a new module to share the adapter definitions between the storage pool and eventually the domain. The devices will need device address functions (no need to pollute more code for that). Move the virStoragePoolSourceAdapter from storage_conf into the new module and parcel out the the structure a bit more into 'fchost' and 'scsi_host' specific pieces creating virStoragePoolSourceAdapterSCSIHost and virStoragePoolSourceAdapterFCHost structures for easier access. 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_conf.c | 338 ++++++++-------------------------= ---- src/conf/storage_conf.h | 35 +--- src/libvirt_private.syms | 16 +- src/libxl/libxl_conf.c | 1 + src/phyp/phyp_driver.c | 3 +- src/storage/storage_backend_scsi.c | 131 +++++++------- src/test/test_driver.c | 4 +- src/util/virscsihost.c | 28 +-- src/util/virscsihost.h | 8 +- src/util/virstoragedevice.c | 292 ++++++++++++++++++++++++++++++++ src/util/virstoragedevice.h | 89 ++++++++++ 13 files changed, 548 insertions(+), 399 deletions(-) create mode 100644 src/util/virstoragedevice.c create mode 100644 src/util/virstoragedevice.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 9f66697..fe07d16 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -248,6 +248,7 @@ src/util/virsecret.c src/util/virsexpr.c src/util/virsocketaddr.c src/util/virstorageencryption.c +src/util/virstoragedevice.c src/util/virstoragefile.c src/util/virstring.c src/util/virsysinfo.c diff --git a/src/Makefile.am b/src/Makefile.am index 46ca272..d14b376 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -171,6 +171,7 @@ UTIL_SOURCES =3D \ util/virsexpr.c util/virsexpr.h \ util/virsocketaddr.h util/virsocketaddr.c \ util/virstorageencryption.c util/virstorageencryption.h \ + util/virstoragedevice.c util/virstoragedevice.h \ util/virstoragefile.c util/virstoragefile.h \ util/virstring.h util/virstring.c \ util/virsysinfo.c util/virsysinfo.h \ diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 0e9a51f..c68e827 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,27 +2090,20 @@ 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 (!(name =3D virSCSIHostGetNameByParentaddr(addr.domain, - addr.bus, - addr.slot, - addr.function, - unique_id))) + if (scsi_host->has_parent) { + if (!(name =3D virSCSIHostGetNameByParentaddr(scsi_host))) goto cleanup; 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 +2134,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 +2142,7 @@ virStorageIsSameHostnum(const char *name, */ static bool matchFCHostToSCSIHost(virConnectPtr conn, - virStoragePoolSourceAdapter fc_adapter, + virStorageAdapterFCHostPtr fchost, unsigned int scsi_hostnum) { char *name =3D NULL; @@ -2348,16 +2152,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 +2174,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) { VIR_FREE(name); return false; @@ -2404,25 +2206,21 @@ matchFCHostToSCSIHost(virConnectPtr conn, return false; } =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 +2263,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 +2300,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..67813b0 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -26,6 +26,7 @@ =20 # include "internal.h" # include "virstorageencryption.h" +# include "virstoragedevice.h" # include "virstoragefile.h" # include "virbitmap.h" # include "virthread.h" @@ -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 e6ccd69..b88e700 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -902,8 +902,6 @@ virStoragePoolObjSaveDef; virStoragePoolObjUnlock; virStoragePoolSaveConfig; virStoragePoolSaveState; -virStoragePoolSourceAdapterTypeFromString; -virStoragePoolSourceAdapterTypeToString; virStoragePoolSourceClear; virStoragePoolSourceDeviceClear; virStoragePoolSourceFindDuplicate; @@ -2435,6 +2433,20 @@ virSocketAddrSetIPv6Addr; virSocketAddrSetIPv6AddrNetOrder; virSocketAddrSetPort; =20 + +# util/virstoragedevice.h +virStorageAdapterClear; +virStorageAdapterFormat; +virStorageAdapterParseValidate; +virStorageAdapterParseXML; +virStorageAdapterTypeFromString; +virStorageAdapterTypeToString; +virStorageAdapterVHBAClear; +virStorageAdapterVHBAFormat; +virStorageAdapterVHBAParseValidate; +virStorageAdapterVHBAParseXML; + + # util/virstorageencryption.h virStorageEncryptionFormat; virStorageEncryptionFree; diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 4bab651..d32456c 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -46,6 +46,7 @@ #include "libxl_conf.h" #include "libxl_utils.h" #include "virstoragefile.h" +#include "virstoragedevice.h" #include "secret_util.h" =20 =20 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 cd05741..afc3c89 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -176,33 +176,30 @@ virStoragePoolFCRefreshThread(void *opaque) } =20 static char * -getAdapterName(virStoragePoolSourceAdapter adapter) +getAdapterName(virStorageAdapterPtr adapter) { char *name =3D NULL; char *parentaddr =3D NULL; + virStorageAdapterSCSIHostPtr scsi_host; + virStorageAdapterFCHostPtr fchost; =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) { + scsi_host =3D &adapter->data.scsi_host; =20 - if (!(name =3D virSCSIHostGetNameByParentaddr(addr.domain, - addr.bus, - addr.slot, - addr.function, - unique_id))) + if (scsi_host->has_parent) { + if (!(name =3D virSCSIHostGetNameByParentaddr(scsi_host))) 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) { + 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 +251,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 +263,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 +312,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 +331,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 +350,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 +372,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 +383,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 +403,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 +417,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 +441,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 +481,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) @@ -522,15 +505,21 @@ 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 4dff0f1..5733a20 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4422,7 +4422,7 @@ testStoragePoolCreateXML(virConnectPtr conn, def =3D NULL; =20 if (pool->def->source.adapter.type =3D=3D - VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) { + 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 @@ -4645,7 +4645,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) diff --git a/src/util/virscsihost.c b/src/util/virscsihost.c index eea0474..dffc958 100644 --- a/src/util/virscsihost.c +++ b/src/util/virscsihost.c @@ -218,36 +218,30 @@ virSCSIHostGetNumber(const char *adapter_name, } =20 /* virSCSIHostGetNameByParentaddr: - * @domain: The domain from the scsi_host parentaddr - * @bus: The bus from the scsi_host parentaddr - * @slot: The slot from the scsi_host parentaddr - * @function: The function from the scsi_host parentaddr - * @unique_id: The unique id value for parentaddr + * @scsi_host: The scsi_host adapter pointer. * * Generate a parentaddr and find the scsi_host host# for - * the provided parentaddr PCI address fields. + * the provided scsi_host. * * Returns the "host#" string which must be free'd by * the caller or NULL on error */ char * -virSCSIHostGetNameByParentaddr(unsigned int domain, - unsigned int bus, - unsigned int slot, - unsigned int function, - unsigned int unique_id) +virSCSIHostGetNameByParentaddr(virStorageAdapterSCSIHostPtr scsi_host) { + virPCIDeviceAddressPtr addr =3D &scsi_host->parentaddr; char *name =3D NULL; char *parentaddr =3D NULL; =20 if (virAsprintf(&parentaddr, "%04x:%02x:%02x.%01x", - domain, bus, slot, function) < 0) + addr->domain, addr->bus, addr->slot, addr->function) <= 0) goto cleanup; - if (!(name =3D virSCSIHostFindByPCI(NULL, parentaddr, unique_id))) { + if (!(name =3D virSCSIHostFindByPCI(NULL, parentaddr, + scsi_host->unique_id))) { virReportError(VIR_ERR_XML_ERROR, _("Failed to find scsi_host using PCI '%s' " "and unique_id=3D'%u'"), - parentaddr, unique_id); + parentaddr, scsi_host->unique_id); goto cleanup; } =20 @@ -284,11 +278,7 @@ virSCSIHostGetNumber(const char *adapter_name ATTRIBUT= E_UNUSED, } =20 char * -virSCSIHostGetNameByParentaddr(unsigned int domain ATTRIBUTE_UNUSED, - unsigned int bus ATTRIBUTE_UNUSED, - unsigned int slot ATTRIBUTE_UNUSED, - unsigned int function ATTRIBUTE_UNUSED, - unsigned int unique_id ATTRIBUTE_UNUSED) +virSCSIHostGetNameByParentaddr(virStorageAdapterSCSIHostPtr scsi_host) { virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")= ); return NULL; diff --git a/src/util/virscsihost.h b/src/util/virscsihost.h index c35ccb9..e0eddaf 100644 --- a/src/util/virscsihost.h +++ b/src/util/virscsihost.h @@ -21,6 +21,8 @@ =20 # include "internal.h" =20 +# include "virstoragedevice.h" + int virSCSIHostGetUniqueId(const char *sysfs_prefix, int host); =20 char *virSCSIHostFindByPCI(const char *sysfs_prefix, @@ -31,10 +33,6 @@ int virSCSIHostGetNumber(const char *adapter_name, unsigned int *result) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); =20 -char *virSCSIHostGetNameByParentaddr(unsigned int domain, - unsigned int bus, - unsigned int slot, - unsigned int function, - unsigned int unique_id); +char *virSCSIHostGetNameByParentaddr(virStorageAdapterSCSIHostPtr scsi_hos= t); =20 #endif /* __VIR_SCSI_HOST_H__ */ diff --git a/src/util/virstoragedevice.c b/src/util/virstoragedevice.c new file mode 100644 index 0000000..0d9db34 --- /dev/null +++ b/src/util/virstoragedevice.c @@ -0,0 +1,292 @@ +/* + * virstoragedevice.c: utility functions to share storage device mgmt + * between storage pools and domains + * + * 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 "device_conf.h" + +#include "viralloc.h" +#include "virerror.h" +#include "virlog.h" +#include "virstoragedevice.h" +#include "virstring.h" +#include "virutil.h" +#include "virxml.h" + +#define VIR_FROM_THIS VIR_FROM_STORAGE + +VIR_LOG_INIT("util.virstoragedevice"); + +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/util/virstoragedevice.h b/src/util/virstoragedevice.h new file mode 100644 index 0000000..c8459c7 --- /dev/null +++ b/src/util/virstoragedevice.h @@ -0,0 +1,89 @@ +/* + * virstoragedevice.h: utility functions to share storage device mgmt + * between storage pools and domains + * + * 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_DEVICE_H__ +# define __VIR_STORAGE_DEVICE_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_DEVICE_H__ */ --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Tue Apr 23 20:53:43 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 1487596939812718.04092838143; Mon, 20 Feb 2017 05:22:19 -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 v1KDIar7021561; Mon, 20 Feb 2017 08:18:36 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDIOAQ005738 for ; Mon, 20 Feb 2017 08:18:24 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMwo002607 for ; Mon, 20 Feb 2017 08:18:24 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:15 -0500 Message-Id: <20170220131819.2919-5-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 4/8] 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 b88e700..563d6f6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1628,7 +1628,6 @@ virFileStripSuffix; virFileTouch; virFileUnlock; virFileUpdatePerm; -virFileWaitForDevices; virFileWrapperFdClose; virFileWrapperFdFree; virFileWrapperFdNew; @@ -2743,6 +2742,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 819f1e5..75d8f63 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 2813341..4a5563a 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 b0191aa..2acd0ef 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 a5d692a..501e316 100644 --- a/src/storage/storage_backend_mpath.c +++ b/src/storage/storage_backend_mpath.c @@ -261,7 +261,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 afc3c89..33df1c9 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -343,7 +343,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 Tue Apr 23 20:53:43 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 1487596951581370.7828859738055; Mon, 20 Feb 2017 05:22:31 -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 v1KDIcbV026581; Mon, 20 Feb 2017 08:18:38 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDIPXw005743 for ; Mon, 20 Feb 2017 08:18:25 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMwp002607 for ; Mon, 20 Feb 2017 08:18:24 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:16 -0500 Message-Id: <20170220131819.2919-6-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 5/8] storage: 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 | 190 +++------------------------------ 4 files changed, 235 insertions(+), 177 deletions(-) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 07b0838..68ed5ad 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -2344,3 +2344,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..9495156 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -28,8 +28,11 @@ # include "internal.h" # include "virbitmap.h" # include "virutil.h" +# include "virscsihost.h" +# include "virstoragedevice.h" # include "virthread.h" # include "virpci.h" +# include "virvhba.h" # include "device_conf.h" # include "object_event.h" =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 563d6f6..210f637 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 33df1c9..e9747ca 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -208,57 +208,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; @@ -267,66 +223,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. @@ -339,28 +240,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 @@ -368,64 +261,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 @@ -517,7 +352,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 Tue Apr 23 20:53:43 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 1487596959583727.8998000601916; Mon, 20 Feb 2017 05:22:39 -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 v1KDIeki026592; Mon, 20 Feb 2017 08:18:40 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDIP0Y005753 for ; Mon, 20 Feb 2017 08:18:25 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMwq002607 for ; Mon, 20 Feb 2017 08:18:25 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:17 -0500 Message-Id: <20170220131819.2919-7-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 6/8] 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 68ed5ad..1d76096 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -2390,6 +2390,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 @@ -2413,6 +2489,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 @@ -2493,6 +2574,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. @@ -2517,6 +2633,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 5733a20..57bf09b 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4444,6 +4444,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 Tue Apr 23 20:53:43 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 1487596942517432.927952488089; Mon, 20 Feb 2017 05:22:22 -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 v1KDIfP3032391; Mon, 20 Feb 2017 08:18:41 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDIQDw005758 for ; Mon, 20 Feb 2017 08:18:26 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMwr002607 for ; Mon, 20 Feb 2017 08:18:25 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:18 -0500 Message-Id: <20170220131819.2919-8-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 7/8] 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 From nobody Tue Apr 23 20:53:43 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 1487596933957598.315364071927; Mon, 20 Feb 2017 05:22:13 -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 v1KDISTW021538; Mon, 20 Feb 2017 08:18:28 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1KDIQrM005769 for ; Mon, 20 Feb 2017 08:18:26 -0500 Received: from localhost.localdomain.com (ovpn-116-126.phx2.redhat.com [10.3.116.126]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1KDIMws002607 for ; Mon, 20 Feb 2017 08:18:26 -0500 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 20 Feb 2017 08:18:19 -0500 Message-Id: <20170220131819.2919-9-jferlan@redhat.com> In-Reply-To: <20170220131819.2919-1-jferlan@redhat.com> References: <20170220131819.2919-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 8/8] conf: Add vHBA controller definition to domain 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 parsing of a vHBA controller to a domain XML. The concept of a vHBA is somewhere between a scsi_host and , so rather than invent a new type, use the existing syntax and add an element to mimic the existing storage pool 'fc_host' element. The new element can be parsed, but is unusable. The syntax is: and is be a subelement of a element. A vHBA is only supported for the virtio-scsi. The controller will be used exclusively to pass through vHBA LUNs to the domain as they are discovered or remove them from the domain as that's discovered. Since this controller is a "virtual" device and no physical qemu -device is created for it, add checks into various places that would place a disk or hostdev LUN onto a controller to ensure the vHBA controller is not used. For now modify the qemu_command and qemu_hotplug code to error out if one of these is defined. Future patches will add support. Signed-off-by: John Ferlan --- docs/schemas/basictypes.rng | 66 ++++---- docs/schemas/domaincommon.rng | 12 +- src/conf/domain_audit.c | 32 ++++ src/conf/domain_conf.c | 180 +++++++++++++++++= ++-- src/conf/domain_conf.h | 2 + src/qemu/qemu_alias.c | 5 + src/qemu/qemu_command.c | 4 + src/qemu/qemu_hotplug.c | 16 ++ .../qemuxml2argv-vhba-no-parent.xml | 38 +++++ .../qemuxml2argv-vhba-parent-fabric.xml | 38 +++++ .../qemuxml2argv-vhba-parent-name.xml | 38 +++++ .../qemuxml2argv-vhba-parent-wwns.xml | 38 +++++ .../qemuxml2xmlout-vhba-no-parent.xml | 47 ++++++ .../qemuxml2xmlout-vhba-parent-fabric.xml | 47 ++++++ .../qemuxml2xmlout-vhba-parent-name.xml | 47 ++++++ .../qemuxml2xmlout-vhba-parent-wwns.xml | 47 ++++++ tests/qemuxml2xmltest.c | 9 ++ 17 files changed, 624 insertions(+), 42 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-vhba-no-parent.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-fabric.= xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-name.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-wwns.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-no-parent.= xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-fab= ric.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-nam= e.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-wwn= s.xml diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index cc560e6..6f050cd 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -417,43 +417,47 @@ fc_host - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + =20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index c5f1013..6738ee7 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1826,7 +1826,8 @@ - + scsi @@ -1845,6 +1846,9 @@ + + + @@ -4841,6 +4845,12 @@ =20 + + + + + + diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 2d9ff5e..fcd2c69 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -516,6 +516,32 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHos= tdevDefPtr hostdev, =20 =20 /** + * virDomainAuditVHBA: + * @vm: domain making a change in pass-through host device + * @vhba: device being attached or removed + * @reason: one of "start", "attach", or "detach" + * @success: true if the device passthrough operation succeeded + * + * Log an audit message about an attempted device passthrough change. + */ +static void +virDomainAuditVHBA(virDomainObjPtr vm, virStorageAdapterFCHostPtr fchost, + const char *reason, bool success) +{ + char *wwstr =3D NULL; + + if (virAsprintfQuiet(&wwstr, "%s:%s", fchost->wwpn, fchost->wwnn) < 0)= { + VIR_WARN("OOM while encoding audit message"); + return; + } + + virDomainAuditGenericDev(vm, "vhba", NULL, wwstr, reason, success); + + VIR_FREE(wwstr); +} + + +/** * virDomainAuditRedirdev: * @vm: domain making a change in pass-through host device * @redirdev: device being attached or removed @@ -864,6 +890,12 @@ virDomainAuditStart(virDomainObjPtr vm, const char *re= ason, bool success) virDomainAuditHostdev(vm, hostdev, "start", true); } =20 + for (i =3D 0; i < vm->def->ncontrollers; i++) { + if (!vm->def->controllers[i]->fchost) + continue; + virDomainAuditVHBA(vm, vm->def->controllers[i]->fchost, "start", t= rue); + } + for (i =3D 0; i < vm->def->nredirdevs; i++) { virDomainRedirdevDefPtr redirdev =3D vm->def->redirdevs[i]; virDomainAuditRedirdev(vm, redirdev, "start", true); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a56ea82..c993f57 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1789,16 +1789,22 @@ virDomainControllerDefNew(virDomainControllerType t= ype) } =20 =20 -void virDomainControllerDefFree(virDomainControllerDefPtr def) +void +virDomainControllerDefFree(virDomainControllerDefPtr def) { if (!def) return; =20 + if (def->fchost) { + virStorageAdapterVHBAClear(def->fchost); + VIR_FREE(def->fchost); + } virDomainDeviceInfoClear(&def->info); =20 VIR_FREE(def); } =20 + virDomainFSDefPtr virDomainFSDefNew(void) { @@ -2379,6 +2385,7 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr d= ef) VIR_FREE(def); } =20 + void virDomainHubDefFree(virDomainHubDefPtr def) { if (!def) @@ -3338,6 +3345,7 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device) case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: break; @@ -3653,7 +3661,6 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr de= f, case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_HUB: case VIR_DOMAIN_DEVICE_REDIRDEV: - case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_CHR: case VIR_DOMAIN_DEVICE_MEMBALLOON: @@ -3661,10 +3668,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr = def, case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: - case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_RNG: case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: + + case VIR_DOMAIN_DEVICE_NONE: + case VIR_DOMAIN_DEVICE_LAST: break; } #endif @@ -4169,6 +4178,10 @@ virDomainHostdevAssignAddress(virDomainXMLOptionPtr = xmlopt, if (def->controllers[i]->type !=3D VIR_DOMAIN_CONTROLLER_TYPE_SCSI) continue; =20 + /* Do not allow assignment to the VHBA controller */ + if (def->controllers[i]->fchost) + continue; + controller++; ret =3D virDomainControllerSCSINextUnit(def, max_unit, def->controllers[i]->idx); @@ -4197,6 +4210,24 @@ virDomainHostdevAssignAddress(virDomainXMLOptionPtr = xmlopt, } =20 =20 +/* Returns true if the passed in address info matches the controller addre= ss + * for a VHBA controller */ +static bool +virDomainDriveAddressIsUsedByVHBA(const virDomainDef *def, + const virDomainDeviceDriveAddress *addr) +{ + size_t i; + + for (i =3D 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->fchost && + def->controllers[i]->idx =3D=3D addr->controller) + return true; + } + + return false; +} + + static int virDomainDeviceDefPostParseInternal(virDomainDeviceDefPtr dev, const virDomainDef *def, @@ -4303,6 +4334,17 @@ virDomainDeviceDefPostParseInternal(virDomainDeviceD= efPtr dev, addr->target, addr->unit); return -1; } + + /* If the assignment was to a vHBA controller fail */ + if (virDomainDriveAddressIsUsedByVHBA(def, addr)) { + virReportError(VIR_ERR_XML_ERROR, + _("SCSI host address controller=3D'%u' " + "bus=3D'%u' target=3D'%u' unit=3D'%u'= cannot " + "use a vHBA controller"), + addr->controller, addr->bus, + addr->target, addr->unit); + return -1; + } } } } @@ -4318,6 +4360,16 @@ virDomainDeviceDefPostParseInternal(virDomainDeviceD= efPtr dev, virDomainControllerModelSCSITypeToString(VIR_DO= MAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI)); return -1; } + + if (cdev->fchost && cdev->type !=3D VIR_DOMAIN_CONTROLLER_TYPE_SCS= I && + cdev->model !=3D VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI)= { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid VHBA configuration, requires control= ler " + "model '%s'"), + virDomainControllerModelSCSITypeToString(VIR_DO= MAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI)); + return -1; + } + } =20 return 0; @@ -4736,7 +4788,8 @@ virDomainDiskAddressDiskBusCompatibility(virDomainDis= kBus bus, =20 =20 static int -virDomainDiskDefValidate(const virDomainDiskDef *disk) +virDomainDiskDefValidate(const virDomainDef *def, + const virDomainDiskDef *disk) { /* Validate LUN configuration */ if (disk->device =3D=3D VIR_DOMAIN_DISK_DEVICE_LUN) { @@ -4766,6 +4819,17 @@ virDomainDiskDefValidate(const virDomainDiskDef *dis= k) return -1; } =20 + /* If the disk is assigned to a controller being used for vHBA then + * reject it. + */ + if (disk->info.type =3D=3D VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE && + virDomainDriveAddressIsUsedByVHBA(def, &disk->info.addr.drive)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk '%s' improperly configured cannot use a " + "VHBA controller"), disk->dst); + return -1; + } + return 0; } =20 @@ -4822,7 +4886,7 @@ virDomainDeviceDefValidateInternal(const virDomainDev= iceDef *dev, { switch ((virDomainDeviceType) dev->type) { case VIR_DOMAIN_DEVICE_DISK: - return virDomainDiskDefValidate(dev->data.disk); + return virDomainDiskDefValidate(def, dev->data.disk); =20 case VIR_DOMAIN_DEVICE_REDIRDEV: return virDomainRedirdevDefValidate(def, dev->data.redirdev); @@ -4830,6 +4894,10 @@ virDomainDeviceDefValidateInternal(const virDomainDe= viceDef *dev, case VIR_DOMAIN_DEVICE_NET: return virDomainNetDefValidate(dev->data.net); =20 + case VIR_DOMAIN_DEVICE_CONTROLLER: + if (dev->data.controller->fchost) + return virStorageAdapterVHBAParseValidate(dev->data.controller= ->fchost); + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: @@ -4837,7 +4905,6 @@ virDomainDeviceDefValidateInternal(const virDomainDev= iceDef *dev, case VIR_DOMAIN_DEVICE_VIDEO: case VIR_DOMAIN_DEVICE_HOSTDEV: case VIR_DOMAIN_DEVICE_WATCHDOG: - case VIR_DOMAIN_DEVICE_CONTROLLER: case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_HUB: case VIR_DOMAIN_DEVICE_SMARTCARD: @@ -6757,7 +6824,16 @@ virDomainDiskDefAssignAddress(virDomainXMLOptionPtr = xmlopt, virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("using disk target name '%s' conflicts with " "SCSI host device address controller=3D'%u' " - "bus=3D'%u' target=3D'%u' unit=3D'%u"), + "bus=3D'%u' target=3D'%u' unit=3D'%u'"), + def->dst, controller, 0, 0, unit); + return -1; + } + + if (virDomainDriveAddressIsUsedByVHBA(vmdef, &addr)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("using disk target name '%s' conflicts with " + "VHBA controller=3D'%u' bus=3D'%u' target=3D'= %u' " + "unit=3D'%u'"), def->dst, controller, 0, 0, unit); return -1; } @@ -8572,6 +8648,20 @@ virDomainControllerModelTypeToString(virDomainContro= llerDefPtr def, } =20 =20 +static int +virDomainControllerVHBAParseXML(xmlNodePtr node, + virDomainControllerDefPtr def) +{ + if (VIR_ALLOC(def->fchost) < 0) + return -1; + + if (virStorageAdapterVHBAParseXML(node, def->fchost) < 0) + return -1; + + return 0; +} + + /* Parse the XML definition for a controller * @param node XML nodeset to parse for controller definition */ @@ -8669,6 +8759,9 @@ virDomainControllerDefParseXML(xmlNodePtr node, port =3D virXMLPropString(cur, "port"); busNr =3D virXMLPropString(cur, "busNr"); processedTarget =3D true; + } else if (xmlStrEqual(cur->name, BAD_CAST "adapter")) { + if (virDomainControllerVHBAParseXML(cur, def) < 0) + goto error; } } cur =3D cur->next; @@ -18609,6 +18702,67 @@ virDomainControllerDefCheckABIStability(virDomainC= ontrollerDefPtr src, return false; } =20 + if ((src->fchost && !dst->fchost) || (!src->fchost && dst->fchost)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Target controller VHBA presence does not match " + "source")); + return false; + } + + if (src->fchost) { + if (STRNEQ(src->fchost->wwnn, dst->fchost->wwnn)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target VHBA wwnn %s does not match source %s= "), + dst->fchost->wwnn, src->fchost->wwnn); + return false; + } + + if (STRNEQ(src->fchost->wwpn, dst->fchost->wwpn)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target VHBA wwpn %s does not match source %s= "), + dst->fchost->wwpn, src->fchost->wwpn); + return false; + } + + if (STRNEQ_NULLABLE(src->fchost->parent, dst->fchost->parent)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target VHBA parent %s does not match source = %s"), + NULLSTR(dst->fchost->parent), + NULLSTR(src->fchost->parent)); + return false; + } + + if (STRNEQ_NULLABLE(src->fchost->parent_wwnn, + dst->fchost->parent_wwnn)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target VHBA parent wwnn %s does not match " + "source %s"), + NULLSTR(dst->fchost->parent_wwnn), + NULLSTR(src->fchost->parent_wwnn)); + return false; + } + + if (STRNEQ_NULLABLE(src->fchost->parent_wwpn, + dst->fchost->parent_wwpn)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target VHBA parent wwpn %s does not match " + "source %s"), + NULLSTR(dst->fchost->parent_wwpn), + NULLSTR(src->fchost->parent_wwpn)); + return false; + } + + if (STRNEQ_NULLABLE(src->fchost->parent_fabric_wwn, + dst->fchost->parent_fabric_wwn)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target VHBA parent fabric wwn %s does not ma= tch " + "source %s"), + NULLSTR(dst->fchost->parent_fabric_wwn), + NULLSTR(src->fchost->parent_fabric_wwn)); + return false; + } + } + if (src->type =3D=3D VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) { if (src->opts.vioserial.ports !=3D dst->opts.vioserial.ports) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -19875,18 +20029,19 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPt= r src, case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_HUB: case VIR_DOMAIN_DEVICE_REDIRDEV: - case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_CHR: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: - case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_RNG: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: + + case VIR_DOMAIN_DEVICE_NONE: + case VIR_DOMAIN_DEVICE_LAST: break; } #endif @@ -20900,7 +21055,7 @@ virDomainControllerDefFormat(virBufferPtr buf, =20 if (pciModel || pciTarget || def->queues || def->cmd_per_lun || def->max_sectors || def->ioeven= tfd || - def->iothread || + def->iothread || def->fchost || virDomainDeviceInfoNeedsFormat(&def->info, flags) || pcihole64) { virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); @@ -20965,6 +21120,11 @@ virDomainControllerDefFormat(virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } =20 + if (def->fchost) { + virBufferAddLit(buf, "fchost); + } + if (virDomainDeviceInfoNeedsFormat(&def->info, flags) && virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) return -1; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7e1afa4..90ad556 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -48,6 +48,7 @@ # include "virobject.h" # include "device_conf.h" # include "virbitmap.h" +# include "virstoragedevice.h" # include "virstoragefile.h" # include "virseclabel.h" # include "virprocess.h" @@ -795,6 +796,7 @@ struct _virDomainControllerDef { virDomainPCIControllerOpts pciopts; virDomainUSBControllerOpts usbopts; } opts; + virStorageAdapterFCHostPtr fchost; virDomainDeviceInfo info; }; =20 diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 8521a44..6dc9985 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -165,6 +165,11 @@ qemuAssignDeviceControllerAlias(virDomainDefPtr domain= Def, /* first USB device is "usb", others are normal "usb%d" */ if (controller->idx =3D=3D 0) return VIR_STRDUP(controller->info.alias, "usb"); + } else if (controller->type =3D=3D VIR_DOMAIN_CONTROLLER_TYPE_SCSI && + controller->fchost) { + /* There is no need for an alias for a vHBA since we're not passing + * it through to QEMU */ + return 0; } /* all other controllers use the default ${type}${index} naming * scheme for alias/id. diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f4bcfd4..44c2c81 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3120,6 +3120,10 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, if (cont->type !=3D contOrder[j]) continue; =20 + /* skip vHBA controller */ + if (cont->fchost) + continue; + /* skip USB controllers with type none.*/ if (cont->type =3D=3D VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->model =3D=3D VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE) { diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 2f209f1..f7829da 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -481,6 +481,12 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr = driver, return -1; } =20 + if (controller->fchost) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("hotplug not support for vHBA controller.")); + return -1; + } + /* default idx would normally be set by virDomainDefPostParse(), * which isn't called in the case of live attach of a single * device. @@ -566,6 +572,10 @@ qemuDomainFindOrCreateSCSIDiskController(virQEMUDriver= Ptr driver, if (cont->type !=3D VIR_DOMAIN_CONTROLLER_TYPE_SCSI) continue; =20 + /* The VHBA controller has a singular purpose */ + if (cont->fchost) + continue; + if (cont->idx =3D=3D controller) return cont; } @@ -4597,6 +4607,12 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPt= r driver, goto cleanup; } =20 + if (detach->fchost) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("vHBA controller cannot be detached")); + goto cleanup; + } + if (!virDomainDeviceAddressIsValid(&detach->info, detach->info.type)) { virReportError(VIR_ERR_OPERATION_FAILED, _("device with invalid '%s' address cannot be detac= hed"), diff --git a/tests/qemuxml2argvdata/qemuxml2argv-vhba-no-parent.xml b/tests= /qemuxml2argvdata/qemuxml2argv-vhba-no-parent.xml new file mode 100644 index 0000000..20ef29c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-vhba-no-parent.xml @@ -0,0 +1,38 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + + + + + + + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-fabric.xml b/t= ests/qemuxml2argvdata/qemuxml2argv-vhba-parent-fabric.xml new file mode 100644 index 0000000..b58f924 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-fabric.xml @@ -0,0 +1,38 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + + + + + + + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-name.xml b/tes= ts/qemuxml2argvdata/qemuxml2argv-vhba-parent-name.xml new file mode 100644 index 0000000..539188c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-name.xml @@ -0,0 +1,38 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + + + + + + + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-wwns.xml b/tes= ts/qemuxml2argvdata/qemuxml2argv-vhba-parent-wwns.xml new file mode 100644 index 0000000..5ca1b80 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-vhba-parent-wwns.xml @@ -0,0 +1,38 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + + + + + + + + + + + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-no-parent.xml b/t= ests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-no-parent.xml new file mode 100644 index 0000000..9f5ad6b --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-no-parent.xml @@ -0,0 +1,47 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + +
+ + +
+ + + +
+ + +
+ + + + + +
+ + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-fabric.xml= b/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-fabric.xml new file mode 100644 index 0000000..753fe78 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-fabric.xml @@ -0,0 +1,47 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + +
+ + +
+ + + +
+ + +
+ + + + + +
+ + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-name.xml b= /tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-name.xml new file mode 100644 index 0000000..e7bce0a --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-name.xml @@ -0,0 +1,47 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + +
+ + +
+ + + +
+ + +
+ + + + + +
+ + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-wwns.xml b= /tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-wwns.xml new file mode 100644 index 0000000..2842f08 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-vhba-parent-wwns.xml @@ -0,0 +1,47 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + +
+ + +
+ + +
+ + + +
+ + +
+ + + + + +
+ + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 0702f58..e810afd 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -638,6 +638,15 @@ mymain(void) DO_TEST("disk-source-pool", NONE); DO_TEST("disk-source-pool-mode", NONE); =20 + DO_TEST("vhba-no-parent", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("vhba-parent-name", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("vhba-parent-wwns", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("vhba-parent-fabric", + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_SCSI); + DO_TEST("disk-drive-discard", NONE); DO_TEST("disk-drive-detect-zeroes", NONE); =20 --=20 2.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list