summaryrefslogtreecommitdiffstats
path: root/staslib/conf.py
diff options
context:
space:
mode:
Diffstat (limited to 'staslib/conf.py')
-rw-r--r--staslib/conf.py106
1 files changed, 101 insertions, 5 deletions
diff --git a/staslib/conf.py b/staslib/conf.py
index a54da98..e5c038b 100644
--- a/staslib/conf.py
+++ b/staslib/conf.py
@@ -14,7 +14,8 @@ import sys
import logging
import functools
import configparser
-from staslib import defs, singleton, timeparse
+from urllib.parse import urlparse
+from staslib import defs, iputil, nbft, singleton, timeparse
__TOKEN_RE = re.compile(r'\s*;\s*')
__OPTION_RE = re.compile(r'\s*=\s*')
@@ -83,7 +84,8 @@ def _to_ip_family(text):
class OrderedMultisetDict(dict):
'''This class is used to change the behavior of configparser.ConfigParser
and allow multiple configuration parameters with the same key. The
- result is a list of values.
+ result is a list of values, where values are sorted by the order they
+ appear in the file.
'''
def __setitem__(self, key, value):
@@ -317,7 +319,7 @@ class SvcConf(metaclass=singleton.Singleton): # pylint: disable=too-many-public
option = 'persistent-connections'
value = self.get_option(section, option, ignore_default=True)
- legacy = self.get_option('Global', 'persistent-connections', ignore_default=True)
+ legacy = self.get_option('Global', option, ignore_default=True)
if value is None and legacy is None:
return self._defaults.get((section, option), True)
@@ -381,7 +383,7 @@ class SvcConf(metaclass=singleton.Singleton): # pylint: disable=too-many-public
controller_list = self.get_option('Controllers', 'exclude')
# 2022-09-20: Look for "blacklist". This is for backwards compatibility
- # with releases 1.0 to 1.1.6. This is to be phased out (i.e. remove by 2024)
+ # with releases 1.0 to 1.1.x. This is to be phased out (i.e. remove by 2024)
controller_list += self.get_option('Controllers', 'blacklist')
excluded = [_parse_controller(controller) for controller in controller_list]
@@ -572,7 +574,7 @@ class SysConf(metaclass=singleton.Singleton):
try:
value = self.__get_value('Host', 'key', defs.NVME_HOSTKEY)
except FileNotFoundError as ex:
- logging.info('Host key undefined: %s', ex)
+ logging.debug('Host key undefined: %s', ex)
value = None
return value
@@ -701,3 +703,97 @@ class NvmeOptions(metaclass=singleton.Singleton):
def dhchap_ctrlkey_supp(self):
'''This option allows specifying the controller DHCHAP key used for authentication.'''
return self._supported_options['dhchap_ctrl_secret']
+
+
+# ******************************************************************************
+class NbftConf(metaclass=singleton.Singleton):
+ '''Read and cache configuration file.'''
+
+ def __init__(self, root_dir=defs.NBFT_SYSFS_PATH):
+ self._disc_ctrls = []
+ self._subs_ctrls = []
+
+ nbft_files = nbft.get_nbft_files(root_dir)
+ if len(nbft_files):
+ logging.info('NBFT location(s): %s', list(nbft_files.keys()))
+
+ for data in nbft_files.values():
+ hfis = data.get('hfi', [])
+ discovery = data.get('discovery', [])
+ subsystem = data.get('subsystem', [])
+
+ self._disc_ctrls.extend(NbftConf.__nbft_disc_to_cids(discovery, hfis))
+ self._subs_ctrls.extend(NbftConf.__nbft_subs_to_cids(subsystem, hfis))
+
+ dcs = property(lambda self: self._disc_ctrls)
+ iocs = property(lambda self: self._subs_ctrls)
+
+ def get_controllers(self):
+ '''Retrieve the list of controllers. Stafd only cares about
+ discovery controllers. Stacd only cares about I/O controllers.'''
+
+ # For now, only return DCs. There are still unanswered questions
+ # regarding I/O controllers, e.g. what if multipathing has been
+ # configured.
+ return self.dcs if defs.PROG_NAME == 'stafd' else []
+
+ @staticmethod
+ def __nbft_disc_to_cids(discovery, hfis):
+ cids = []
+
+ for ctrl in discovery:
+ cid = NbftConf.__uri2cid(ctrl['uri'])
+ cid['subsysnqn'] = ctrl['nqn']
+
+ host_iface = NbftConf.__get_host_iface(ctrl.get('hfi_index'), hfis)
+ if host_iface:
+ cid['host-iface'] = host_iface
+
+ cids.append(cid)
+
+ return cids
+
+ @staticmethod
+ def __nbft_subs_to_cids(subsystem, hfis):
+ cids = []
+
+ for ctrl in subsystem:
+ cid = {
+ 'transport': ctrl['trtype'],
+ 'traddr': ctrl['traddr'],
+ 'trsvcid': ctrl['trsvcid'],
+ 'subsysnqn': ctrl['subsys_nqn'],
+ 'hdr-digest': ctrl['pdu_header_digest_required'],
+ 'data-digest': ctrl['data_digest_required'],
+ }
+
+ indexes = ctrl.get('hfi_indexes')
+ if isinstance(indexes, list) and len(indexes) > 0:
+ host_iface = NbftConf.__get_host_iface(indexes[0], hfis)
+ if host_iface:
+ cid['host-iface'] = host_iface
+
+ cids.append(cid)
+
+ return cids
+
+ @staticmethod
+ def __get_host_iface(indx, hfis):
+ if indx is None or indx >= len(hfis):
+ return None
+
+ mac = hfis[indx].get('mac_addr')
+ if mac is None:
+ return None
+
+ return iputil.mac2iface(mac)
+
+ @staticmethod
+ def __uri2cid(uri: str):
+ '''Convert a URI of the form "nvme+tcp://100.71.103.50:8009/" to a Controller ID'''
+ obj = urlparse(uri)
+ return {
+ 'transport': obj.scheme.split('+')[1],
+ 'traddr': obj.hostname,
+ 'trsvcid': str(obj.port),
+ }