util: Create a new virvhba module and move/rename API's

Rather than have them mixed in with the virutil apis, create a separate
virvhba.c module and move the vHBA related calls into there. Soon there
will be more added.

Also modify the names of the functions and some arguments to be more
indicative of what is really happening. Adjust the callers respectively.

While I was changing fchosttest, rather than the non-descriptive names
test1...test6, rename them to match what the test is doing.
This commit is contained in:
John Ferlan 2017-01-23 12:54:42 -05:00
parent 9588a21b32
commit 16416816c1
13 changed files with 693 additions and 578 deletions

View File

@ -258,6 +258,7 @@ src/util/virtypedparam.c
src/util/viruri.c
src/util/virusb.c
src/util/virutil.c
src/util/virvhba.c
src/util/virxml.c
src/vbox/vbox_MSCOMGlue.c
src/vbox/vbox_XPCOMCGlue.c

View File

@ -184,6 +184,7 @@ UTIL_SOURCES = \
util/viruri.h util/viruri.c \
util/virutil.c util/virutil.h \
util/viruuid.c util/viruuid.h \
util/virvhba.c util/virvhba.h \
util/virxdrdefs.h \
util/virxml.c util/virxml.h \
$(NULL)

View File

@ -45,6 +45,7 @@
#include "virfile.h"
#include "virstring.h"
#include "virlog.h"
#include "virvhba.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@ -2396,8 +2397,8 @@ matchFCHostToSCSIHost(virConnectPtr conn,
/* 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 = virGetFCHostNameByWWN(NULL, fc_adapter.data.fchost.wwnn,
fc_adapter.data.fchost.wwpn))) {
if ((name = virVHBAGetHostByWWN(NULL, fc_adapter.data.fchost.wwnn,
fc_adapter.data.fchost.wwpn))) {
/* Get the scsi_hostN for the vHBA in order to see if it
* matches our scsi_hostnum

View File

@ -2679,15 +2679,12 @@ virUSBDeviceSetUsedBy;
virDoubleToStr;
virEnumFromString;
virEnumToString;
virFindFCHostCapableVport;
virFindSCSIHostByPCI;
virFormatIntDecimal;
virGetDeviceID;
virGetDeviceUnprivSGIO;
virGetEnvAllowSUID;
virGetEnvBlockSUID;
virGetFCHostNameByFabricWWN;
virGetFCHostNameByWWN;
virGetGroupID;
virGetGroupList;
virGetGroupName;
@ -2710,11 +2707,8 @@ virGetUserRuntimeDirectory;
virGetUserShell;
virHexToBin;
virIndexToDiskName;
virIsCapableFCHost;
virIsCapableVport;
virIsDevMapperDevice;
virIsSUID;
virManageVport;
virMemoryLimitIsSet;
virMemoryLimitTruncate;
virMemoryMaxValue;
@ -2722,7 +2716,6 @@ virParseNumber;
virParseOwnershipIds;
virParseVersionString;
virPipeReadUntilEOF;
virReadFCHost;
virReadSCSIUniqueId;
virScaleInteger;
virSetBlocking;
@ -2750,6 +2743,16 @@ virUUIDIsValid;
virUUIDParse;
# util/virvhba.h
virVHBAFindVportHost;
virVHBAGetConfig;
virVHBAGetHostByFabricWWN;
virVHBAGetHostByWWN;
virVHBAIsVportCapable;
virVHBAManageVport;
virVHBAPathExists;
# util/virxml.h
virXMLCheckIllegalChars;
virXMLChildElementCount;

View File

@ -39,7 +39,7 @@
#include "node_device_driver.h"
#include "node_device_hal.h"
#include "node_device_linux_sysfs.h"
#include "virutil.h"
#include "virvhba.h"
#include "viraccessapicheck.h"
#include "virnetdev.h"
@ -616,12 +616,8 @@ nodeDeviceCreateXML(virConnectPtr conn,
goto cleanup;
}
if (virManageVport(parent_host,
wwpn,
wwnn,
VPORT_CREATE) == -1) {
if (virVHBAManageVport(parent_host, wwpn, wwnn, VPORT_CREATE) < 0)
goto cleanup;
}
dev = find_new_device(conn, wwnn, wwpn);
/* We don't check the return value, because one way or another,
@ -679,19 +675,12 @@ nodeDeviceDestroy(virNodeDevicePtr dev)
virNodeDeviceObjUnlock(obj);
obj = NULL;
if (virNodeDeviceGetParentHost(&driver->devs,
dev->name,
parent_name,
&parent_host) == -1) {
if (virNodeDeviceGetParentHost(&driver->devs, dev->name, parent_name,
&parent_host) < 0)
goto out;
}
if (virManageVport(parent_host,
wwpn,
wwnn,
VPORT_DELETE) == -1) {
if (virVHBAManageVport(parent_host, wwpn, wwnn, VPORT_DELETE) < 0)
goto out;
}
ret = 0;
out:

View File

@ -34,6 +34,7 @@
#include "virlog.h"
#include "virfile.h"
#include "virstring.h"
#include "virvhba.h"
#define VIR_FROM_THIS VIR_FROM_NODEDEV
@ -55,34 +56,34 @@ nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapDataPtr d)
VIR_DEBUG("Checking if host%d is an FC HBA", d->scsi_host.host);
if (virIsCapableFCHost(NULL, d->scsi_host.host)) {
if (virVHBAPathExists(NULL, d->scsi_host.host)) {
d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST;
if (!(tmp = virReadFCHost(NULL, d->scsi_host.host, "port_name"))) {
if (!(tmp = virVHBAGetConfig(NULL, d->scsi_host.host, "port_name"))) {
VIR_WARN("Failed to read WWPN for host%d", d->scsi_host.host);
goto cleanup;
}
VIR_FREE(d->scsi_host.wwpn);
VIR_STEAL_PTR(d->scsi_host.wwpn, tmp);
if (!(tmp = virReadFCHost(NULL, d->scsi_host.host, "node_name"))) {
if (!(tmp = virVHBAGetConfig(NULL, d->scsi_host.host, "node_name"))) {
VIR_WARN("Failed to read WWNN for host%d", d->scsi_host.host);
goto cleanup;
}
VIR_FREE(d->scsi_host.wwnn);
VIR_STEAL_PTR(d->scsi_host.wwnn, tmp);
if ((tmp = virReadFCHost(NULL, d->scsi_host.host, "fabric_name"))) {
if ((tmp = virVHBAGetConfig(NULL, d->scsi_host.host, "fabric_name"))) {
VIR_FREE(d->scsi_host.fabric_wwn);
VIR_STEAL_PTR(d->scsi_host.fabric_wwn, tmp);
}
}
if (virIsCapableVport(NULL, d->scsi_host.host)) {
if (virVHBAIsVportCapable(NULL, d->scsi_host.host)) {
d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS;
if (!(tmp = virReadFCHost(NULL, d->scsi_host.host,
"max_npiv_vports"))) {
if (!(tmp = virVHBAGetConfig(NULL, d->scsi_host.host,
"max_npiv_vports"))) {
VIR_WARN("Failed to read max_npiv_vports for host%d",
d->scsi_host.host);
goto cleanup;
@ -93,8 +94,8 @@ nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapDataPtr d)
goto cleanup;
}
if (!(tmp = virReadFCHost(NULL, d->scsi_host.host,
"npiv_vports_inuse"))) {
if (!(tmp = virVHBAGetConfig(NULL, d->scsi_host.host,
"npiv_vports_inuse"))) {
VIR_WARN("Failed to read npiv_vports_inuse for host%d",
d->scsi_host.host);
goto cleanup;

View File

@ -34,6 +34,7 @@
#include "virfile.h"
#include "vircommand.h"
#include "virstring.h"
#include "virvhba.h"
#include "storage_util.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@ -193,9 +194,9 @@ getAdapterName(virStoragePoolSourceAdapter adapter)
ignore_value(VIR_STRDUP(name, adapter.data.scsi_host.name));
}
} else if (adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
if (!(name = virGetFCHostNameByWWN(NULL,
adapter.data.fchost.wwnn,
adapter.data.fchost.wwpn))) {
if (!(name = virVHBAGetHostByWWN(NULL,
adapter.data.fchost.wwnn,
adapter.data.fchost.wwpn))) {
virReportError(VIR_ERR_XML_ERROR,
_("Failed to find SCSI host with wwnn='%s', "
"wwpn='%s'"), adapter.data.fchost.wwnn,
@ -269,8 +270,8 @@ createVport(virConnectPtr conn,
* using the wwnn/wwpn, then a nodedev is already created for
* this pool and we don't have to create the vHBA
*/
if ((name = virGetFCHostNameByWWN(NULL, adapter->data.fchost.wwnn,
adapter->data.fchost.wwpn))) {
if ((name = virVHBAGetHostByWWN(NULL, adapter->data.fchost.wwnn,
adapter->data.fchost.wwpn))) {
/* If a parent was provided, let's make sure the 'name' we've
* retrieved has the same parent
*/
@ -287,22 +288,22 @@ createVport(virConnectPtr conn,
} else if (adapter->data.fchost.parent_wwnn &&
adapter->data.fchost.parent_wwpn) {
if (!(parent_hoststr =
virGetFCHostNameByWWN(NULL, adapter->data.fchost.parent_wwnn,
adapter->data.fchost.parent_wwpn))) {
virVHBAGetHostByWWN(NULL, adapter->data.fchost.parent_wwnn,
adapter->data.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) {
if (!(parent_hoststr =
virGetFCHostNameByFabricWWN(NULL,
adapter->data.fchost.parent_fabric_wwn))) {
virVHBAGetHostByFabricWWN(NULL,
adapter->data.fchost.parent_fabric_wwn))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("cannot find parent using provided fabric_wwn"));
goto cleanup;
}
} else {
if (!(parent_hoststr = virFindFCHostCapableVport(NULL))) {
if (!(parent_hoststr = virVHBAFindVportHost(NULL))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("'parent' for vHBA not specified, and "
"cannot find one on this host"));
@ -322,9 +323,9 @@ createVport(virConnectPtr conn,
* parent. Besides we have a way to determine the parent based on
* the 'name' field.
*/
if (!skip_capable_check && !virIsCapableFCHost(NULL, parent_host)) {
if (!skip_capable_check && !virVHBAPathExists(NULL, parent_host)) {
virReportError(VIR_ERR_XML_ERROR,
_("parent '%s' specified for vHBA is not vport capable"),
_("parent '%s' specified for vHBA does not exist"),
parent_hoststr);
goto cleanup;
}
@ -342,8 +343,8 @@ createVport(virConnectPtr conn,
}
}
if (virManageVport(parent_host, adapter->data.fchost.wwpn,
adapter->data.fchost.wwnn, VPORT_CREATE) < 0)
if (virVHBAManageVport(parent_host, adapter->data.fchost.wwpn,
adapter->data.fchost.wwnn, VPORT_CREATE) < 0)
goto cleanup;
virFileWaitForDevices();
@ -353,8 +354,8 @@ 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 = virGetFCHostNameByWWN(NULL, adapter->data.fchost.wwnn,
adapter->data.fchost.wwpn))) {
if ((name = virVHBAGetHostByWWN(NULL, adapter->data.fchost.wwnn,
adapter->data.fchost.wwpn))) {
if (VIR_ALLOC(cbdata) == 0) {
memcpy(cbdata->pool_uuid, pool->def->uuid, VIR_UUID_BUFLEN);
VIR_STEAL_PTR(cbdata->fchost_name, name);
@ -399,8 +400,8 @@ deleteVport(virConnectPtr conn,
return 0;
/* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn */
if (!(name = virGetFCHostNameByWWN(NULL, adapter.data.fchost.wwnn,
adapter.data.fchost.wwpn))) {
if (!(name = virVHBAGetHostByWWN(NULL, adapter.data.fchost.wwnn,
adapter.data.fchost.wwpn))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to find fc_host for wwnn='%s' and wwpn='%s'"),
adapter.data.fchost.wwnn, adapter.data.fchost.wwpn);
@ -422,8 +423,8 @@ deleteVport(virConnectPtr conn,
goto cleanup;
}
if (virManageVport(parent_host, adapter.data.fchost.wwpn,
adapter.data.fchost.wwnn, VPORT_DELETE) < 0)
if (virVHBAManageVport(parent_host, adapter.data.fchost.wwpn,
adapter.data.fchost.wwnn, VPORT_DELETE) < 0)
goto cleanup;
ret = 0;

View File

@ -35,6 +35,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include "virlog.h"
#include "virscsi.h"
#include "viralloc.h"
#include "virfile.h"
@ -46,6 +47,9 @@
/* For virReportOOMError() and virReportSystemError() */
#define VIR_FROM_THIS VIR_FROM_NONE
VIR_LOG_INIT("util.scsi");
struct _virUsedByInfo {
char *drvname; /* which driver */
char *domname; /* which domain */

View File

@ -1777,7 +1777,7 @@ virGetDeviceUnprivSGIO(const char *path,
}
#ifdef __linux__
# define SYSFS_FC_HOST_PATH "/sys/class/fc_host"
# define SYSFS_SCSI_HOST_PATH "/sys/class/scsi_host"
/* virReadSCSIUniqueId:
@ -2004,404 +2004,8 @@ virGetSCSIHostNameByParentaddr(unsigned int domain,
return name;
}
/* virReadFCHost:
* @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
* @host: Host number, E.g. 5 of "fc_host/host5"
* @entry: Name of the sysfs entry to read
*
* Read the value of sysfs "fc_host" entry.
*
* Returns result as a string on success, caller must free @result after
* Otherwise returns NULL.
*/
char *
virReadFCHost(const char *sysfs_prefix,
int host,
const char *entry)
{
char *sysfs_path = NULL;
char *p = NULL;
char *buf = NULL;
char *result = NULL;
if (virAsprintf(&sysfs_path, "%s/host%d/%s",
sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH,
host, entry) < 0)
goto cleanup;
if (!virFileExists(sysfs_path))
goto cleanup;
if (virFileReadAll(sysfs_path, 1024, &buf) < 0)
goto cleanup;
if ((p = strchr(buf, '\n')))
*p = '\0';
if ((p = strstr(buf, "0x")))
p += strlen("0x");
else
p = buf;
ignore_value(VIR_STRDUP(result, p));
cleanup:
VIR_FREE(sysfs_path);
VIR_FREE(buf);
return result;
}
bool
virIsCapableFCHost(const char *sysfs_prefix,
int host)
{
char *sysfs_path = NULL;
bool ret = false;
if (virAsprintf(&sysfs_path, "%s/host%d",
sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH,
host) < 0)
return false;
if (virFileExists(sysfs_path))
ret = true;
VIR_FREE(sysfs_path);
return ret;
}
bool
virIsCapableVport(const char *sysfs_prefix,
int host)
{
char *scsi_host_path = NULL;
char *fc_host_path = NULL;
bool ret = false;
if (virAsprintf(&fc_host_path,
"%s/host%d/%s",
sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH,
host,
"vport_create") < 0)
return false;
if (virAsprintf(&scsi_host_path,
"%s/host%d/%s",
sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH,
host,
"vport_create") < 0)
goto cleanup;
if (virFileExists(fc_host_path) ||
virFileExists(scsi_host_path))
ret = true;
cleanup:
VIR_FREE(fc_host_path);
VIR_FREE(scsi_host_path);
return ret;
}
int
virManageVport(const int parent_host,
const char *wwpn,
const char *wwnn,
int operation)
{
int ret = -1;
char *operation_path = NULL, *vport_name = NULL;
const char *operation_file = NULL;
switch (operation) {
case VPORT_CREATE:
operation_file = "vport_create";
break;
case VPORT_DELETE:
operation_file = "vport_delete";
break;
default:
virReportError(VIR_ERR_OPERATION_INVALID,
_("Invalid vport operation (%d)"), operation);
goto cleanup;
}
if (virAsprintf(&operation_path,
"%s/host%d/%s",
SYSFS_FC_HOST_PATH,
parent_host,
operation_file) < 0)
goto cleanup;
if (!virFileExists(operation_path)) {
VIR_FREE(operation_path);
if (virAsprintf(&operation_path,
"%s/host%d/%s",
SYSFS_SCSI_HOST_PATH,
parent_host,
operation_file) < 0)
goto cleanup;
if (!virFileExists(operation_path)) {
virReportError(VIR_ERR_OPERATION_INVALID,
_("vport operation '%s' is not supported for host%d"),
operation_file, parent_host);
goto cleanup;
}
}
if (virAsprintf(&vport_name,
"%s:%s",
wwpn,
wwnn) < 0)
goto cleanup;
if (virFileWriteStr(operation_path, vport_name, 0) == 0)
ret = 0;
else
virReportSystemError(errno,
_("Write of '%s' to '%s' during "
"vport create/delete failed"),
vport_name, operation_path);
cleanup:
VIR_FREE(vport_name);
VIR_FREE(operation_path);
return ret;
}
/* virReadCompareWWN
* @prefix: path to the wwn file
* @d_name: name of the current directory
* @f_name: file name to read
*
* Read/compare the on-disk file with the passed wwn value.
*
* Returns:
* -1 : Error
* 0 : No match
* 1 : Match
*/
static int
virReadCompareWWN(const char *prefix,
const char *d_name,
const char *f_name,
const char *wwn)
{
char *path;
char *buf = NULL;
char *p;
int ret = -1;
if (virAsprintf(&path, "%s/%s/%s", prefix, d_name, f_name) < 0)
return -1;
if (!virFileExists(path)) {
ret = 0;
goto cleanup;
}
if (virFileReadAll(path, 1024, &buf) < 0)
goto cleanup;
if ((p = strchr(buf, '\n')))
*p = '\0';
if (STRPREFIX(buf, "0x"))
p = buf + strlen("0x");
else
p = buf;
if (STRNEQ(wwn, p))
ret = 0;
else
ret = 1;
cleanup:
VIR_FREE(path);
VIR_FREE(buf);
return ret;
}
/* virGetFCHostNameByWWN:
*
* Iterate over the sysfs tree to get FC host name (e.g. host5)
* by the provided "wwnn,wwpn" pair.
*
* Returns the FC host name which must be freed by the caller,
* or NULL on failure.
*/
char *
virGetFCHostNameByWWN(const char *sysfs_prefix,
const char *wwnn,
const char *wwpn)
{
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH;
struct dirent *entry = NULL;
DIR *dir = NULL;
char *ret = NULL;
if (virDirOpen(&dir, prefix) < 0)
return NULL;
while (virDirRead(dir, &entry, prefix) > 0) {
int rc;
if ((rc = virReadCompareWWN(prefix, entry->d_name,
"node_name", wwnn)) < 0)
goto cleanup;
if (rc == 0)
continue;
if ((rc = virReadCompareWWN(prefix, entry->d_name,
"port_name", wwpn)) < 0)
goto cleanup;
if (rc == 0)
continue;
ignore_value(VIR_STRDUP(ret, entry->d_name));
break;
}
cleanup:
VIR_DIR_CLOSE(dir);
return ret;
}
/* virGetFCHostNameByFabricWWN:
*
* Iterate over the sysfs tree to get FC host name (e.g. host5)
* by the provided "fabric_wwn". This would find a host on a SAN.
*
* Returns the FC host name which must be freed by the caller,
* or NULL on failure.
*/
char *
virGetFCHostNameByFabricWWN(const char *sysfs_prefix,
const char *fabric_wwn)
{
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH;
struct dirent *entry = NULL;
DIR *dir = NULL;
char *vport_create_path = NULL;
char *ret = NULL;
if (virDirOpen(&dir, prefix) < 0)
return NULL;
while (virDirRead(dir, &entry, prefix) > 0) {
int rc;
VIR_FREE(vport_create_path);
/* Existing vHBA's will have the same fabric_name, but won't
* have the vport_create file - so we check for both */
if (virAsprintf(&vport_create_path, "%s/%s/vport_create", prefix,
entry->d_name) < 0)
goto cleanup;
if (!virFileExists(vport_create_path))
continue;
if ((rc = virReadCompareWWN(prefix, entry->d_name,
"fabric_name", fabric_wwn)) < 0)
goto cleanup;
if (rc == 0)
continue;
ignore_value(VIR_STRDUP(ret, entry->d_name));
break;
}
cleanup:
VIR_DIR_CLOSE(dir);
VIR_FREE(vport_create_path);
return ret;
}
# define PORT_STATE_ONLINE "Online"
/* virFindFCHostCapableVport:
*
* Iterate over the sysfs and find out the first online HBA which
* supports vport, and not saturated. Returns the host name (e.g.
* host5) on success, or NULL on failure.
*/
char *
virFindFCHostCapableVport(const char *sysfs_prefix)
{
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH;
DIR *dir = NULL;
struct dirent *entry = NULL;
char *max_vports = NULL;
char *vports = NULL;
char *state = NULL;
char *ret = NULL;
if (virDirOpen(&dir, prefix) < 0)
return NULL;
while (virDirRead(dir, &entry, prefix) > 0) {
unsigned int host;
char *p = NULL;
p = entry->d_name + strlen("host");
if (virStrToLong_ui(p, NULL, 10, &host) == -1) {
VIR_DEBUG("Failed to parse host number from '%s'",
entry->d_name);
continue;
}
if (!virIsCapableVport(prefix, host))
continue;
if (!(state = virReadFCHost(prefix, host, "port_state"))) {
VIR_DEBUG("Failed to read port_state for host%d", host);
continue;
}
/* Skip the not online FC host */
if (STRNEQ(state, PORT_STATE_ONLINE)) {
VIR_FREE(state);
continue;
}
VIR_FREE(state);
if (!(max_vports = virReadFCHost(prefix, host, "max_npiv_vports"))) {
VIR_DEBUG("Failed to read max_npiv_vports for host%d", host);
continue;
}
if (!(vports = virReadFCHost(prefix, host, "npiv_vports_inuse"))) {
VIR_DEBUG("Failed to read npiv_vports_inuse for host%d", host);
VIR_FREE(max_vports);
continue;
}
/* Compare from the strings directly, instead of converting
* the strings to integers first
*/
if ((strlen(max_vports) >= strlen(vports)) ||
((strlen(max_vports) == strlen(vports)) &&
strcmp(max_vports, vports) > 0)) {
ignore_value(VIR_STRDUP(ret, entry->d_name));
goto cleanup;
}
VIR_FREE(max_vports);
VIR_FREE(vports);
}
cleanup:
VIR_DIR_CLOSE(dir);
VIR_FREE(max_vports);
VIR_FREE(vports);
return ret;
}
#else
int
virReadSCSIUniqueId(const char *sysfs_prefix ATTRIBUTE_UNUSED,
int host ATTRIBUTE_UNUSED,
@ -2439,65 +2043,6 @@ virGetSCSIHostNameByParentaddr(unsigned int domain ATTRIBUTE_UNUSED,
return NULL;
}
char *
virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED,
int host ATTRIBUTE_UNUSED,
const char *entry ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
bool
virIsCapableFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED,
int host ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return false;
}
bool
virIsCapableVport(const char *sysfs_prefix ATTRIBUTE_UNUSED,
int host ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return false;
}
int
virManageVport(const int parent_host ATTRIBUTE_UNUSED,
const char *wwpn ATTRIBUTE_UNUSED,
const char *wwnn ATTRIBUTE_UNUSED,
int operation ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return -1;
}
char *
virGetFCHostNameByWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
const char *wwnn ATTRIBUTE_UNUSED,
const char *wwpn ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
char *
virGetFCHostNameByFabricWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
const char *fabric_wwn ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
char *
virFindFCHostCapableVport(const char *sysfs_prefix ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
#endif /* __linux__ */
/**

View File

@ -182,35 +182,8 @@ virGetSCSIHostNameByParentaddr(unsigned int domain,
unsigned int slot,
unsigned int function,
unsigned int unique_id);
char *virReadFCHost(const char *sysfs_prefix,
int host,
const char *entry)
ATTRIBUTE_NONNULL(3);
bool virIsCapableFCHost(const char *sysfs_prefix, int host);
bool virIsCapableVport(const char *sysfs_prefix, int host);
enum {
VPORT_CREATE,
VPORT_DELETE,
};
int virManageVport(const int parent_host,
const char *wwpn,
const char *wwnn,
int operation)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
char *virGetFCHostNameByWWN(const char *sysfs_prefix,
const char *wwnn,
const char *wwpn)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
char *virGetFCHostNameByFabricWWN(const char *sysfs_prefix,
const char *fabric_wwn)
ATTRIBUTE_NONNULL(2);
char *virFindFCHostCapableVport(const char *sysfs_prefix);
int virParseOwnershipIds(const char *label, uid_t *uidPtr, gid_t *gidPtr);

534
src/util/virvhba.c Normal file
View File

@ -0,0 +1,534 @@
/*
* virvhba.c: Generic vHBA management utility functions
*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "viralloc.h"
#include "virerror.h"
#include "virfile.h"
#include "virlog.h"
#include "virstring.h"
#include "virvhba.h"
#define VIR_FROM_THIS VIR_FROM_NONE
VIR_LOG_INIT("util.vhba");
#ifdef __linux__
# define SYSFS_SCSI_HOST_PATH "/sys/class/scsi_host"
# define SYSFS_FC_HOST_PATH "/sys/class/fc_host"
# define PORT_STATE_ONLINE "Online"
/* virVHBAPathExists:
* @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
* @host: Host number, E.g. 5 of "fc_host/host5"
*
* Check if the "fc_host" to provided host# exists. This path may be either
* a vHBA capable path or a vHBA itself.
*
* Returns true if it does, false if not
*/
bool
virVHBAPathExists(const char *sysfs_prefix,
int host)
{
char *sysfs_path = NULL;
bool ret = false;
if (virAsprintf(&sysfs_path, "%s/host%d",
sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH,
host) < 0)
return false;
if (virFileExists(sysfs_path))
ret = true;
VIR_FREE(sysfs_path);
return ret;
}
/* virVHBAIsVportCapable:
* @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
* @host: Host number, E.g. 5 of "fc_host/host5"
*
* Not all vHBA paths can create/delete a vport - only the parent NPIV
* capable HBA has the "vport_create" and "vport_delete" functions.
* A vHBA created path does not have the function files.
*
* NB: Checks both the "fc_host" and "scsi_host" paths.
*
* Returns true if capable, false if not
*/
bool
virVHBAIsVportCapable(const char *sysfs_prefix,
int host)
{
char *scsi_host_path = NULL;
char *fc_host_path = NULL;
bool ret = false;
if (virAsprintf(&fc_host_path,
"%s/host%d/%s",
sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH,
host,
"vport_create") < 0)
return false;
if (virAsprintf(&scsi_host_path,
"%s/host%d/%s",
sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH,
host,
"vport_create") < 0)
goto cleanup;
if (virFileExists(fc_host_path) || virFileExists(scsi_host_path))
ret = true;
cleanup:
VIR_FREE(fc_host_path);
VIR_FREE(scsi_host_path);
return ret;
}
/* virVHBAGetConfig:
* @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
* @host: Host number, E.g. 5 of "fc_host/host5"
* @entry: Name of the FC sysfs entry to read
*
* Read the value of a vHBA sysfs "fc_host" entry (if it exists).
*
* Returns result as a string on success, caller is responsible for
* freeing the @result; otherwise returns NULL on failure.
*/
char *
virVHBAGetConfig(const char *sysfs_prefix,
int host,
const char *entry)
{
char *sysfs_path = NULL;
char *p = NULL;
char *buf = NULL;
char *result = NULL;
if (virAsprintf(&sysfs_path, "%s/host%d/%s",
sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH,
host, entry) < 0)
goto cleanup;
if (!virFileExists(sysfs_path))
goto cleanup;
if (virFileReadAll(sysfs_path, 1024, &buf) < 0)
goto cleanup;
if ((p = strchr(buf, '\n')))
*p = '\0';
if ((p = strstr(buf, "0x")))
p += strlen("0x");
else
p = buf;
ignore_value(VIR_STRDUP(result, p));
cleanup:
VIR_FREE(sysfs_path);
VIR_FREE(buf);
return result;
}
/* virVHBAFindVportHost:
*
* Iterate over the sysfs and find out the first online HBA which
* supports vport, and is not saturated. Returns the host name (e.g.
* host5) on success, or NULL on failure.
*
* It's up to the caller to free the returned string.
*/
char *
virVHBAFindVportHost(const char *sysfs_prefix)
{
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH;
DIR *dir = NULL;
struct dirent *entry = NULL;
char *max_vports = NULL;
char *vports = NULL;
char *state = NULL;
char *ret = NULL;
if (virDirOpen(&dir, prefix) < 0)
return NULL;
while (virDirRead(dir, &entry, prefix) > 0) {
unsigned int host;
char *p = NULL;
p = entry->d_name + strlen("host");
if (virStrToLong_ui(p, NULL, 10, &host) == -1) {
VIR_DEBUG("Failed to parse host number from '%s'",
entry->d_name);
continue;
}
if (!virVHBAPathExists(prefix, host))
continue;
if (!(state = virVHBAGetConfig(prefix, host, "port_state"))) {
VIR_DEBUG("Failed to read port_state for host%d", host);
continue;
}
/* Skip the not online FC host */
if (STRNEQ(state, PORT_STATE_ONLINE)) {
VIR_FREE(state);
continue;
}
VIR_FREE(state);
if (!(max_vports = virVHBAGetConfig(prefix, host, "max_npiv_vports"))) {
VIR_DEBUG("Failed to read max_npiv_vports for host%d", host);
continue;
}
if (!(vports = virVHBAGetConfig(prefix, host, "npiv_vports_inuse"))) {
VIR_DEBUG("Failed to read npiv_vports_inuse for host%d", host);
VIR_FREE(max_vports);
continue;
}
/* Compare from the strings directly, instead of converting
* the strings to integers first
*/
if ((strlen(max_vports) >= strlen(vports)) ||
((strlen(max_vports) == strlen(vports)) &&
strcmp(max_vports, vports) > 0)) {
ignore_value(VIR_STRDUP(ret, entry->d_name));
goto cleanup;
}
VIR_FREE(max_vports);
VIR_FREE(vports);
}
cleanup:
VIR_DIR_CLOSE(dir);
VIR_FREE(max_vports);
VIR_FREE(vports);
return ret;
}
/* virVHBAManageVport:
* @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
* @wwnn: world wide node name used to create/delete the vport
* @wwpn: world wide port name used to create/delete the vport
* @operation: create or delete
*
* NB: Checks both the "fc_host" and "scsi_host" paths.
* Returns true if capable, false if not
*/
int
virVHBAManageVport(const int parent_host,
const char *wwpn,
const char *wwnn,
int operation)
{
int ret = -1;
char *operation_path = NULL, *vport_name = NULL;
const char *operation_file = NULL;
switch (operation) {
case VPORT_CREATE:
operation_file = "vport_create";
break;
case VPORT_DELETE:
operation_file = "vport_delete";
break;
default:
virReportError(VIR_ERR_OPERATION_INVALID,
_("Invalid vport operation (%d)"), operation);
goto cleanup;
}
if (virAsprintf(&operation_path, "%s/host%d/%s",
SYSFS_FC_HOST_PATH, parent_host, operation_file) < 0)
goto cleanup;
if (!virFileExists(operation_path)) {
VIR_FREE(operation_path);
if (virAsprintf(&operation_path, "%s/host%d/%s",
SYSFS_SCSI_HOST_PATH, parent_host, operation_file) < 0)
goto cleanup;
if (!virFileExists(operation_path)) {
virReportError(VIR_ERR_OPERATION_INVALID,
_("vport operation '%s' is not supported "
"for host%d"),
operation_file, parent_host);
goto cleanup;
}
}
/* Create/Delete is handled through the file passing the wwpn:wwnn as
* a parameter. This results in the kernel managing the port. For udev,
* an event is posted and handled in udevEventHandleCallback resulting
* in calling either the Add or Remove device functions. This translates
* into either adding or removing a node device object and a node device
* lifecycle event for applications to consume. */
if (virAsprintf(&vport_name, "%s:%s", wwpn, wwnn) < 0)
goto cleanup;
if (virFileWriteStr(operation_path, vport_name, 0) == 0)
ret = 0;
else
virReportSystemError(errno,
_("Write of '%s' to '%s' during "
"vport create/delete failed"),
vport_name, operation_path);
cleanup:
VIR_FREE(vport_name);
VIR_FREE(operation_path);
return ret;
}
/* vhbaReadCompareWWN
* @prefix: path to the wwn file
* @d_name: name of the current directory
* @f_name: file name to read
*
* Read/compare the on-disk file with the passed wwn value.
*
* Returns:
* -1 : Error
* 0 : No match
* 1 : Match
*/
static int
vhbaReadCompareWWN(const char *prefix,
const char *d_name,
const char *f_name,
const char *wwn)
{
char *path;
char *buf = NULL;
char *p;
int ret = -1;
if (virAsprintf(&path, "%s/%s/%s", prefix, d_name, f_name) < 0)
return -1;
if (!virFileExists(path)) {
ret = 0;
goto cleanup;
}
if (virFileReadAll(path, 1024, &buf) < 0)
goto cleanup;
if ((p = strchr(buf, '\n')))
*p = '\0';
if (STRPREFIX(buf, "0x"))
p = buf + strlen("0x");
else
p = buf;
if (STRNEQ(wwn, p))
ret = 0;
else
ret = 1;
cleanup:
VIR_FREE(path);
VIR_FREE(buf);
return ret;
}
/* virVHBAGetHostByWWN:
*
* Iterate over the sysfs tree to get FC host name (e.g. host5)
* by the provided "wwnn,wwpn" pair.
*
* Returns the FC host name which must be freed by the caller,
* or NULL on failure.
*/
char *
virVHBAGetHostByWWN(const char *sysfs_prefix,
const char *wwnn,
const char *wwpn)
{
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH;
struct dirent *entry = NULL;
DIR *dir = NULL;
char *ret = NULL;
if (virDirOpen(&dir, prefix) < 0)
return NULL;
while (virDirRead(dir, &entry, prefix) > 0) {
int rc;
if ((rc = vhbaReadCompareWWN(prefix, entry->d_name,
"node_name", wwnn)) < 0)
goto cleanup;
if (rc == 0)
continue;
if ((rc = vhbaReadCompareWWN(prefix, entry->d_name,
"port_name", wwpn)) < 0)
goto cleanup;
if (rc == 0)
continue;
ignore_value(VIR_STRDUP(ret, entry->d_name));
break;
}
cleanup:
VIR_DIR_CLOSE(dir);
return ret;
}
/* virVHBAGetHostByFabricWWN:
*
* Iterate over the sysfs tree to get FC host name (e.g. host5)
* by the provided "fabric_wwn". This would find a host on a SAN.
*
* Returns the FC host name which must be freed by the caller,
* or NULL on failure.
*/
char *
virVHBAGetHostByFabricWWN(const char *sysfs_prefix,
const char *fabric_wwn)
{
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH;
struct dirent *entry = NULL;
DIR *dir = NULL;
char *vport_create_path = NULL;
char *ret = NULL;
if (virDirOpen(&dir, prefix) < 0)
return NULL;
while (virDirRead(dir, &entry, prefix) > 0) {
int rc;
VIR_FREE(vport_create_path);
/* Existing vHBA's will have the same fabric_name, but won't
* have the vport_create file - so we check for both */
if (virAsprintf(&vport_create_path, "%s/%s/vport_create", prefix,
entry->d_name) < 0)
goto cleanup;
if (!virFileExists(vport_create_path))
continue;
if ((rc = vhbaReadCompareWWN(prefix, entry->d_name,
"fabric_name", fabric_wwn)) < 0)
goto cleanup;
if (rc == 0)
continue;
ignore_value(VIR_STRDUP(ret, entry->d_name));
break;
}
cleanup:
VIR_DIR_CLOSE(dir);
VIR_FREE(vport_create_path);
return ret;
}
#else
bool
virVHBAPathExists(const char *sysfs_prefix ATTRIBUTE_UNUSED,
int host ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return false;
}
bool
virVHBAVportIsCapable(const char *sysfs_prefix ATTRIBUTE_UNUSED,
int host ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return false;
}
char *
virVHBAGetConfig(const char *sysfs_prefix ATTRIBUTE_UNUSED,
int host ATTRIBUTE_UNUSED,
const char *entry ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
char *
virVHBAFindVportHost(const char *sysfs_prefix ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
int
virVHBAManageVport(const int parent_host ATTRIBUTE_UNUSED,
const char *wwpn ATTRIBUTE_UNUSED,
const char *wwnn ATTRIBUTE_UNUSED,
int operation ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return -1;
}
char *
virVHBAGetHostByWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
const char *wwnn ATTRIBUTE_UNUSED,
const char *wwpn ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
char *
virVHBAGetHostByFabricWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
const char *fabric_wwn ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
return NULL;
}
#endif /* __linux__ */

62
src/util/virvhba.h Normal file
View File

@ -0,0 +1,62 @@
/*
* virvhba.h: Generic vHBA management utility functions
*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef __VIR_VHBA_H__
# define __VIR_VHBA_H__
# include "internal.h"
enum {
VPORT_CREATE,
VPORT_DELETE,
};
bool
virVHBAPathExists(const char *sysfs_prefix, int host);
bool
virVHBAIsVportCapable(const char *sysfs_prefix, int host);
char *
virVHBAGetConfig(const char *sysfs_prefix,
int host,
const char *entry)
ATTRIBUTE_NONNULL(3);
char *
virVHBAFindVportHost(const char *sysfs_prefix);
int
virVHBAManageVport(const int parent_host,
const char *wwpn,
const char *wwnn,
int operation)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
char *
virVHBAGetHostByWWN(const char *sysfs_prefix,
const char *wwnn,
const char *wwpn)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
char *
virVHBAGetHostByFabricWWN(const char *sysfs_prefix,
const char *fabric_wwn)
ATTRIBUTE_NONNULL(2);
#endif /* __VIR_VBHA_H__ */

View File

@ -20,7 +20,7 @@
#include <config.h>
#include "virstring.h"
#include "virutil.h"
#include "virvhba.h"
#include "testutils.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@ -31,31 +31,28 @@ static char *fchost_prefix;
#define TEST_FC_HOST_NUM 5
#define TEST_FC_HOST_NUM_NO_FAB 6
/* Test virIsCapableFCHost */
/* Test virIsVHBACapable */
static int
test1(const void *data ATTRIBUTE_UNUSED)
{
if (virIsCapableFCHost(TEST_FC_HOST_PREFIX,
TEST_FC_HOST_NUM) &&
virIsCapableFCHost(TEST_FC_HOST_PREFIX,
TEST_FC_HOST_NUM_NO_FAB))
if (virVHBAPathExists(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM) &&
virVHBAPathExists(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB))
return 0;
return -1;
}
/* Test virIsCapableVport */
/* Test virVHBAIsVportCapable */
static int
test2(const void *data ATTRIBUTE_UNUSED)
{
if (virIsCapableVport(TEST_FC_HOST_PREFIX,
TEST_FC_HOST_NUM))
if (virVHBAIsVportCapable(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM))
return 0;
return -1;
}
/* Test virReadFCHost */
/* Test virVHBAGetConfig */
static int
test3(const void *data ATTRIBUTE_UNUSED)
{
@ -71,25 +68,25 @@ test3(const void *data ATTRIBUTE_UNUSED)
char *vports = NULL;
int ret = -1;
if (!(wwnn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"node_name")))
if (!(wwnn = virVHBAGetConfig(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"node_name")))
return -1;
if (!(wwpn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"port_name")))
if (!(wwpn = virVHBAGetConfig(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"port_name")))
goto cleanup;
if (!(fabric_wwn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"fabric_name")))
if (!(fabric_wwn = virVHBAGetConfig(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"fabric_name")))
goto cleanup;
if (!(max_vports = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"max_npiv_vports")))
if (!(max_vports = virVHBAGetConfig(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"max_npiv_vports")))
goto cleanup;
if (!(vports = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"npiv_vports_inuse")))
if (!(vports = virVHBAGetConfig(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM,
"npiv_vports_inuse")))
goto cleanup;
if (STRNEQ(expect_wwnn, wwnn) ||
@ -109,7 +106,7 @@ test3(const void *data ATTRIBUTE_UNUSED)
return ret;
}
/* Test virGetFCHostNameByWWN */
/* Test virVHBAGetHostByWWN */
static int
test4(const void *data ATTRIBUTE_UNUSED)
{
@ -117,9 +114,9 @@ test4(const void *data ATTRIBUTE_UNUSED)
char *hostname = NULL;
int ret = -1;
if (!(hostname = virGetFCHostNameByWWN(TEST_FC_HOST_PREFIX,
"2001001b32a9da4e",
"2101001b32a9da4e")))
if (!(hostname = virVHBAGetHostByWWN(TEST_FC_HOST_PREFIX,
"2001001b32a9da4e",
"2101001b32a9da4e")))
return -1;
if (STRNEQ(hostname, expect_hostname))
@ -131,7 +128,10 @@ test4(const void *data ATTRIBUTE_UNUSED)
return ret;
}
/* Test virFindFCHostCapableVport (host4 is not Online) */
/* Test virVHBAFindVportHost
*
* NB: host4 is not Online, so it should not be found
*/
static int
test5(const void *data ATTRIBUTE_UNUSED)
{
@ -139,7 +139,7 @@ test5(const void *data ATTRIBUTE_UNUSED)
char *hostname = NULL;
int ret = -1;
if (!(hostname = virFindFCHostCapableVport(TEST_FC_HOST_PREFIX)))
if (!(hostname = virVHBAFindVportHost(TEST_FC_HOST_PREFIX)))
return -1;
if (STRNEQ(hostname, expect_hostname))
@ -151,7 +151,7 @@ test5(const void *data ATTRIBUTE_UNUSED)
return ret;
}
/* Test virReadFCHost fabric name optional */
/* Test virVHBAGetConfig fabric name optional */
static int
test6(const void *data ATTRIBUTE_UNUSED)
{
@ -162,17 +162,17 @@ test6(const void *data ATTRIBUTE_UNUSED)
char *fabric_wwn = NULL;
int ret = -1;
if (!(wwnn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB,
"node_name")))
if (!(wwnn = virVHBAGetConfig(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB,
"node_name")))
return -1;
if (!(wwpn = virReadFCHost(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB,
"port_name")))
if (!(wwpn = virVHBAGetConfig(TEST_FC_HOST_PREFIX, TEST_FC_HOST_NUM_NO_FAB,
"port_name")))
goto cleanup;
if ((fabric_wwn = virReadFCHost(TEST_FC_HOST_PREFIX,
TEST_FC_HOST_NUM_NO_FAB,
"fabric_name")))
if ((fabric_wwn = virVHBAGetConfig(TEST_FC_HOST_PREFIX,
TEST_FC_HOST_NUM_NO_FAB,
"fabric_name")))
goto cleanup;
if (STRNEQ(expect_wwnn, wwnn) ||
@ -198,17 +198,17 @@ mymain(void)
goto cleanup;
}
if (virTestRun("test1", test1, NULL) < 0)
if (virTestRun("virVHBAPathExists", test1, NULL) < 0)
ret = -1;
if (virTestRun("test2", test2, NULL) < 0)
if (virTestRun("virVHBAIsVportCapable", test2, NULL) < 0)
ret = -1;
if (virTestRun("test3", test3, NULL) < 0)
if (virTestRun("virVHBAGetConfig", test3, NULL) < 0)
ret = -1;
if (virTestRun("test4", test4, NULL) < 0)
if (virTestRun("virVHBAGetHostByWWN", test4, NULL) < 0)
ret = -1;
if (virTestRun("test5", test5, NULL) < 0)
if (virTestRun("virVHBAFindVportHost", test5, NULL) < 0)
ret = -1;
if (virTestRun("test6", test6, NULL) < 0)
if (virTestRun("virVHBAGetConfig-empty-fabric_wwn", test6, NULL) < 0)
ret = -1;
cleanup: