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 <jferlan(a)redhat.com>
---
src/test/test_driver.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++--
tests/fchosttest.c | 64 ++++++++++++++++++++++++++++++++++
2 files changed, 156 insertions(+), 2 deletions(-)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 61c82b9..a9bb5a6 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -4366,6 +4366,34 @@ testConnectFindStoragePoolSources(virConnectPtr conn
ATTRIBUTE_UNUSED,
}
+static virNodeDeviceObjPtr
+testNodeDeviceMockCreateVport(testDriverPtr driver,
+ const char *wwnn,
+ const char *wwpn);
+static int
+testCreateVport(testDriverPtr driver,
+ const char *wwnn,
+ const char *wwpn)
+{
+ virNodeDeviceObjPtr obj = NULL;
+ /* The storage_backend_scsi createVport() will use the input adapter
+ * fields parent name, parent_wwnn/parent_wwpn, or parent_fabric_wwn
+ * in order to determine whether the provided parent can be used to
+ * create a vHBA or will find "an available vport capable" to create
+ * a vHBA. In order to do this, it uses the virVHBA* API's which traverse
+ * the sysfs looking at various fields (rather than going via nodedev).
+ *
+ * Since the test environ doesn't have the sysfs for the storage pool
+ * test, at least for now use the node device test infrastructure to
+ * create the vHBA. In the long run the result is the same. */
+ if (!(obj = testNodeDeviceMockCreateVport(driver, wwnn, wwpn)))
+ return -1;
+ virNodeDeviceObjUnlock(obj);
+
+ return 0;
+}
+
+
static virStoragePoolPtr
testStoragePoolCreateXML(virConnectPtr conn,
const char *xml,
@@ -4396,6 +4424,21 @@ testStoragePoolCreateXML(virConnectPtr conn,
goto cleanup;
def = NULL;
+ if (pool->def->source.adapter.type ==
+ VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
+ /* In the real code, we'd call virVHBAManageVport followed by
+ * find_new_device, but we cannot do that here since we're not
+ * mocking udev. The mock routine will copy an existing vHBA and
+ * rename a few fields to mock that. */
+ if (testCreateVport(privconn,
+ pool->def->source.adapter.data.fchost.wwnn,
+ pool->def->source.adapter.data.fchost.wwpn) < 0) {
+ virStoragePoolObjRemove(&privconn->pools, pool);
+ pool = NULL;
+ goto cleanup;
+ }
+ }
+
if (testStoragePoolObjSetDefaults(pool) == -1) {
virStoragePoolObjRemove(&privconn->pools, pool);
pool = NULL;
@@ -4406,7 +4449,6 @@ testStoragePoolCreateXML(virConnectPtr conn,
event = virStoragePoolEventLifecycleNew(pool->def->name,
pool->def->uuid,
VIR_STORAGE_POOL_EVENT_STARTED,
0);
-
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
NULL, NULL);
@@ -4540,6 +4582,44 @@ testStoragePoolBuild(virStoragePoolPtr pool,
static int
+testDestroyVport(testDriverPtr privconn,
+ const char *wwnn ATTRIBUTE_UNUSED,
+ const char *wwpn ATTRIBUTE_UNUSED)
+{
+ int ret = -1;
+ virNodeDeviceObjPtr obj = NULL;
+ virObjectEventPtr event = NULL;
+
+ /* NB: Cannot use virVHBAGetHostByWWN (yet) like the storage_backend_scsi
+ * deleteVport() helper since that traverses the file system looking for
+ * 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 = virNodeDeviceObjFindByName(&privconn->devs,
"scsi_host12"))) {
+ virReportError(VIR_ERR_NO_NODE_DEVICE, "%s",
+ _("no node device with matching name
'scsi_host12'"));
+ goto cleanup;
+ }
+
+ event = virNodeDeviceEventLifecycleNew("scsi_host12",
+ VIR_NODE_DEVICE_EVENT_DELETED,
+ 0);
+
+ virNodeDeviceObjRemove(&privconn->devs, &obj);
+
+ ret = 0;
+
+ cleanup:
+ if (obj)
+ virNodeDeviceObjUnlock(obj);
+ testObjectEventQueue(privconn, event);
+ return ret;
+}
+
+
+static int
testStoragePoolDestroy(virStoragePoolPtr pool)
{
testDriverPtr privconn = pool->conn->privateData;
@@ -4563,7 +4643,17 @@ testStoragePoolDestroy(virStoragePoolPtr pool)
}
privpool->active = 0;
- event = virStoragePoolEventLifecycleNew(privpool->def->name,
privpool->def->uuid,
+
+ if (privpool->def->source.adapter.type ==
+ VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
+ if (testDestroyVport(privconn,
+ privpool->def->source.adapter.data.fchost.wwnn,
+ privpool->def->source.adapter.data.fchost.wwpn) <
0)
+ goto cleanup;
+ }
+
+ event = virStoragePoolEventLifecycleNew(privpool->def->name,
+ privpool->def->uuid,
VIR_STORAGE_POOL_EVENT_STOPPED,
0);
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[] =
" </capability>"
"</device>";
+/* virStoragePoolCreateXML using parent='%s' to find the vport capable HBA */
+static const char test11_xml[] =
+"<pool type='scsi'>"
+" <name>vhba_pool</name>"
+" <source>"
+" <adapter type='fc_host' parent='scsi_host1'
wwnn='20000000c9831b4b' wwpn='10000000c9831b4b'/>"
+" </source>"
+" <target>"
+" <path>/dev/disk/by-path</path>"
+" </target>"
+"</pool>";
+
+
/* Test virIsVHBACapable */
static int
test1(const void *data ATTRIBUTE_UNUSED)
@@ -275,6 +288,54 @@ manageVHBAByNodeDevice(const void *data)
}
+/* 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 = "scsi_host12";
+ virConnectPtr conn = NULL;
+ virStoragePoolPtr pool = NULL;
+ virNodeDevicePtr dev = NULL;
+ int ret = -1;
+ const char *vhba = data;
+
+ if (!(conn = virConnectOpen("test:///default")))
+ return -1;
+
+ if (!(pool = virStoragePoolCreateXML(conn, vhba, 0)))
+ goto cleanup;
+
+ if (!(dev = 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 = virNodeDeviceLookupByName(conn, expect_hostname))) {
+ VIR_DEBUG("Found expected_hostname '%s' after destroy",
+ expect_hostname);
+ goto cleanup;
+ }
+
+ ret = 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 = -1;
+ if (virTestRun("manageVHBAByStoragePool-by-parent",
manageVHBAByStoragePool,
+ test11_xml) < 0)
+ ret = -1;
cleanup:
VIR_FREE(fchost_prefix);
--
2.9.3