}
+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,
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;
}
+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)
{
}
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);
" </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)
}
+/* 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)
{
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);