mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 03:21:19 +00:00
storage: Guess the parent if it's not specified for vHBA
This finds the parent for vHBA by iterating over all the HBA which supports vport_ops capability on the host, and return the first one which is online, not saturated (vports in use is less than max_vports).
This commit is contained in:
parent
34f9651005
commit
f5a610872a
@ -1852,6 +1852,7 @@ virFileStripSuffix;
|
||||
virFileUnlock;
|
||||
virFileWaitForDevices;
|
||||
virFileWriteStr;
|
||||
virFindFCHostCapableVport;
|
||||
virFindFileInPath;
|
||||
virFormatIntDecimal;
|
||||
virGetDeviceID;
|
||||
|
@ -660,10 +660,12 @@ createVport(virStoragePoolSourceAdapter adapter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!adapter.data.fchost.parent) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("'parent' for vHBA must be specified"));
|
||||
return -1;
|
||||
if (!adapter.data.fchost.parent &&
|
||||
!(adapter.data.fchost.parent = virFindFCHostCapableVport(NULL))) {
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("'parent' for vHBA not specified, and "
|
||||
"cannot find one on this host"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (getHostNumber(adapter.data.fchost.parent, &parent_host) < 0)
|
||||
|
@ -3670,6 +3670,92 @@ cleanup:
|
||||
VIR_FREE(wwpn_buf);
|
||||
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,.
|
||||
*/
|
||||
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 (!(dir = opendir(prefix))) {
|
||||
virReportSystemError(errno,
|
||||
_("Failed to opendir path '%s'"),
|
||||
prefix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((entry = readdir(dir))) {
|
||||
unsigned int host;
|
||||
char *p = NULL;
|
||||
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
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(NULL, host))
|
||||
continue;
|
||||
|
||||
if (virReadFCHost(NULL, host, "port_state", &state) < 0) {
|
||||
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 (virReadFCHost(NULL, host, "max_npiv_vports", &max_vports) < 0) {
|
||||
VIR_DEBUG("Failed to read max_npiv_vports for host%d", host);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (virReadFCHost(NULL, host, "npiv_vports_inuse", &vports) < 0) {
|
||||
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)) {
|
||||
ret = strdup(entry->d_name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_FREE(max_vports);
|
||||
VIR_FREE(vports);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
closedir(dir);
|
||||
VIR_FREE(max_vports);
|
||||
VIR_FREE(vports);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int
|
||||
virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED,
|
||||
@ -3716,4 +3802,11 @@ virGetFCHostNameByWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
virFindFCHostCapableVport(const char *sysfs_prefix ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
@ -322,4 +322,6 @@ char *virGetFCHostNameByWWN(const char *sysfs_prefix,
|
||||
const char *wwpn)
|
||||
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
|
||||
char *virFindFCHostCapableVport(const char *sysfs_prefix);
|
||||
|
||||
#endif /* __VIR_UTIL_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user