summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-08-06 07:52:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-08-06 07:52:00 +0000
commit9a81a6cf9f75a764ad8b32bd1fc4ee64e200f172 (patch)
treebffae7d405fb77e945d668d2269b2359686ceb3e
parentReleasing debian version 2.3~rc2-1. (diff)
downloadnvme-stas-9a81a6cf9f75a764ad8b32bd1fc4ee64e200f172.tar.xz
nvme-stas-9a81a6cf9f75a764ad8b32bd1fc4ee64e200f172.zip
Merging upstream version 2.3~rc3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--NEWS.md2
-rw-r--r--meson.build2
-rwxr-xr-xstacctl.py7
-rwxr-xr-xstacd.py4
-rwxr-xr-xstafctl.py31
-rwxr-xr-xstafd.py11
-rw-r--r--staslib/avahi.py8
-rw-r--r--staslib/conf.py17
-rw-r--r--staslib/service.py20
-rw-r--r--staslib/stacd.idl3
-rw-r--r--staslib/stafd.idl9
-rw-r--r--staslib/stas.py16
-rw-r--r--staslib/trid.py62
-rw-r--r--staslib/udev.py10
-rwxr-xr-xtest/test-controller.py4
-rwxr-xr-xtest/test-nbft.py2
-rwxr-xr-xtest/test-nbft_conf.py3
-rwxr-xr-xtest/test-service.py3
-rwxr-xr-xtest/test-transport_id.py3
-rwxr-xr-xtest/test-udev.py47
20 files changed, 189 insertions, 75 deletions
diff --git a/NEWS.md b/NEWS.md
index 4583cea..5edf33c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -13,13 +13,13 @@ Bug fixes:
* For TCP transport: use `sysfs` controller `src_addr` attribute when matching to a configured "candidate" controller. This is to determine when an existing controller (located under the `sysfs`) can be reused instead of creating a new one. This avoids creating unnecessary duplicate connections.
* Udev event handling: use `systemctl restart` instead of `systemctl start`. There is a small chance that a `start` operation has not completed when a new `start` is required. Issuing a `start` while a `start` is being performed has no effect. However, a `restart` will be handled properly.
* `stafd`: Do not delete and recreate DC objects on kernel events indicating that an nvme device associated to a discovery controller was removed by the kernel. This was done to kick start the reconnect process, but was also causing the DLPE (Discovery Log Page Entries) cache to be lost. This could potentially result in `stacd` disconnecting from I/O controllers. Instead, keep the existing DC object which contains a valid DLPE cache and simply restart the "retry to connect" timer. This way the DLPE cache is maintained throughout the reconnect to DC process.
+* While testing Boot from SAN (BFS) and using a Host NQN during boot that is different from the Host NQN used after boot (i.e. the Host NQN defined in `/etc/nvme/hostnqn`), we found that nvme-stas and libnvme are reusing existing connections even if the Host NQN doesn't match. nvme-stas will now take a connection's Host NQN into consideration before deciding if a connection can be reused. A similar fix will be provided in libnvme as well.
## Changes with release 2.2.3
Bug fixes:
* When processing kernel nvme events, only react to `rediscover` and not to `connected` events. The `connected` event happens too early (before the nvme device has been fully identified).
-*
## Changes with release 2.2.2
diff --git a/meson.build b/meson.build
index 1e6f864..2c19b62 100644
--- a/meson.build
+++ b/meson.build
@@ -9,7 +9,7 @@
project(
'nvme-stas',
meson_version: '>= 0.53.0',
- version: '2.3-rc2',
+ version: '2.3-rc3',
license: 'Apache-2.0',
default_options: [
'buildtype=release',
diff --git a/stacctl.py b/stacctl.py
index 29e3e9a..9375af4 100755
--- a/stacctl.py
+++ b/stacctl.py
@@ -39,9 +39,10 @@ def _extract_cid(ctrl):
ctrl['transport'],
ctrl['traddr'],
ctrl['trsvcid'],
+ ctrl['subsysnqn'],
ctrl['host-traddr'],
ctrl['host-iface'],
- ctrl['subsysnqn'],
+ ctrl['host-nqn'],
)
@@ -52,9 +53,9 @@ def status(args): # pylint: disable=unused-argument
info = json.loads(iface.process_info())
info['controllers'] = iface.list_controllers(True)
for controller in info['controllers']:
- transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn = _extract_cid(controller)
+ transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn = _extract_cid(controller)
controller.update(
- json.loads(iface.controller_info(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn))
+ json.loads(iface.controller_info(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn))
)
print(pprint.pformat(info, width=120))
diff --git a/stacd.py b/stacd.py
index 731b414..b13904a 100755
--- a/stacd.py
+++ b/stacd.py
@@ -90,10 +90,10 @@ if __name__ == '__main__':
return json.dumps(info)
def controller_info( # pylint: disable=too-many-arguments,no-self-use
- self, transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn
+ self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
) -> str:
'''@brief D-Bus method used to return information about a controller'''
- controller = STAC.get_controller(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn)
+ controller = STAC.get_controller(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn)
return json.dumps(controller.info()) if controller else '{}'
def list_controllers(self, detailed) -> list: # pylint: disable=no-self-use
diff --git a/stafctl.py b/stafctl.py
index a05de3a..a9f94ec 100755
--- a/stafctl.py
+++ b/stafctl.py
@@ -15,7 +15,7 @@ import pprint
from argparse import ArgumentParser
import dasbus.error
from dasbus.connection import SystemMessageBus
-from staslib import defs
+from staslib import conf, defs
def tron(args): # pylint: disable=unused-argument
@@ -39,9 +39,10 @@ def _extract_cid(ctrl):
ctrl['transport'],
ctrl['traddr'],
ctrl['trsvcid'],
+ ctrl['subsysnqn'],
ctrl['host-traddr'],
ctrl['host-iface'],
- ctrl['subsysnqn'],
+ ctrl['host-nqn'],
)
@@ -52,10 +53,12 @@ def status(args): # pylint: disable=unused-argument
info = json.loads(iface.process_info())
info['controllers'] = iface.list_controllers(True)
for controller in info['controllers']:
- transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn = _extract_cid(controller)
- controller['log_pages'] = iface.get_log_pages(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn)
+ transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn = _extract_cid(controller)
+ controller['log_pages'] = iface.get_log_pages(
+ transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
+ )
controller.update(
- json.loads(iface.controller_info(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn))
+ json.loads(iface.controller_info(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn))
)
print(pprint.pformat(info, width=120))
@@ -75,7 +78,15 @@ def dlp(args):
'''@brief retrieve a controller's discovery log pages from stafd'''
bus = SystemMessageBus()
iface = bus.get_proxy(defs.STAFD_DBUS_NAME, defs.STAFD_DBUS_PATH)
- info = iface.get_log_pages(args.transport, args.traddr, args.trsvcid, args.host_traddr, args.host_iface, args.nqn)
+ info = iface.get_log_pages(
+ args.transport,
+ args.traddr,
+ args.trsvcid,
+ args.nqn,
+ args.host_traddr,
+ args.host_iface,
+ args.host_nqn,
+ )
print(pprint.pformat(info, width=120))
@@ -154,6 +165,14 @@ PRSR.add_argument(
default='',
)
PRSR.add_argument(
+ '-q',
+ '--host-nqn',
+ metavar='<nqn>',
+ action='store',
+ help='This field specifies the host NQN (default: "%(default)s")',
+ default=conf.SysConf().hostnqn,
+)
+PRSR.add_argument(
'-n',
'--nqn',
metavar='<nqn>',
diff --git a/stafd.py b/stafd.py
index afa21f7..0777405 100755
--- a/stafd.py
+++ b/stafd.py
@@ -70,9 +70,10 @@ if __name__ == '__main__':
transport: str,
traddr: str,
trsvcid: str,
+ subsysnqn: str,
host_traddr: str,
host_iface: str,
- subsysnqn: str,
+ host_nqn: str,
device: str,
):
'''@brief Signal sent when log pages have changed.'''
@@ -108,17 +109,17 @@ if __name__ == '__main__':
return json.dumps(info)
def controller_info( # pylint: disable=no-self-use,too-many-arguments
- self, transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn
+ self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
) -> str:
'''@brief D-Bus method used to return information about a controller'''
- controller = STAF.get_controller(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn)
+ controller = STAF.get_controller(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn)
return json.dumps(controller.info()) if controller else '{}'
def get_log_pages( # pylint: disable=no-self-use,too-many-arguments
- self, transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn
+ self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
) -> list:
'''@brief D-Bus method used to retrieve the discovery log pages from one controller'''
- controller = STAF.get_controller(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn)
+ controller = STAF.get_controller(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn)
return controller.log_pages() if controller else list()
def get_all_log_pages(self, detailed) -> str: # pylint: disable=no-self-use
diff --git a/staslib/avahi.py b/staslib/avahi.py
index f29f89d..84a0b2a 100644
--- a/staslib/avahi.py
+++ b/staslib/avahi.py
@@ -333,15 +333,19 @@ class Avahi: # pylint: disable=too-many-instance-attributes
'transport': tcp,
'traddr': str(),
'trsvcid': str(),
- 'host-iface': str(),
'subsysnqn': 'nqn.2014-08.org.nvmexpress.discovery',
+ 'host-traddr': str(),
+ 'host-iface': str(),
+ 'host-nqn': str(),
},
{
'transport': tcp,
'traddr': str(),
'trsvcid': str(),
- 'host-iface': str(),
'subsysnqn': 'nqn.2014-08.org.nvmexpress.discovery',
+ 'host-traddr': str(),
+ 'host-iface': str(),
+ 'host-nqn': str(),
},
[...]
]
diff --git a/staslib/conf.py b/staslib/conf.py
index e5c038b..4497698 100644
--- a/staslib/conf.py
+++ b/staslib/conf.py
@@ -334,9 +334,10 @@ class SvcConf(metaclass=singleton.Singleton): # pylint: disable=too-many-public
'transport': [TRANSPORT],
'traddr': [TRADDR],
'trsvcid': [TRSVCID],
+ 'subsysnqn': [NQN],
'host-traddr': [TRADDR],
'host-iface': [IFACE],
- 'subsysnqn': [NQN],
+ 'host-nqn': [NQN],
'dhchap-ctrl-secret': [KEY],
'hdr-digest': [BOOL]
'data-digest': [BOOL]
@@ -721,9 +722,11 @@ class NbftConf(metaclass=singleton.Singleton):
hfis = data.get('hfi', [])
discovery = data.get('discovery', [])
subsystem = data.get('subsystem', [])
+ host = data.get('host', {})
+ hostnqn = host.get('nqn', None) if host.get('host_nqn_configured', False) else None
- self._disc_ctrls.extend(NbftConf.__nbft_disc_to_cids(discovery, hfis))
- self._subs_ctrls.extend(NbftConf.__nbft_subs_to_cids(subsystem, hfis))
+ self._disc_ctrls.extend(NbftConf.__nbft_disc_to_cids(hostnqn, discovery, hfis))
+ self._subs_ctrls.extend(NbftConf.__nbft_subs_to_cids(hostnqn, subsystem, hfis))
dcs = property(lambda self: self._disc_ctrls)
iocs = property(lambda self: self._subs_ctrls)
@@ -738,12 +741,14 @@ class NbftConf(metaclass=singleton.Singleton):
return self.dcs if defs.PROG_NAME == 'stafd' else []
@staticmethod
- def __nbft_disc_to_cids(discovery, hfis):
+ def __nbft_disc_to_cids(hostnqn, discovery, hfis):
cids = []
for ctrl in discovery:
cid = NbftConf.__uri2cid(ctrl['uri'])
cid['subsysnqn'] = ctrl['nqn']
+ if hostnqn:
+ cid['host-nqn'] = hostnqn
host_iface = NbftConf.__get_host_iface(ctrl.get('hfi_index'), hfis)
if host_iface:
@@ -754,7 +759,7 @@ class NbftConf(metaclass=singleton.Singleton):
return cids
@staticmethod
- def __nbft_subs_to_cids(subsystem, hfis):
+ def __nbft_subs_to_cids(hostnqn, subsystem, hfis):
cids = []
for ctrl in subsystem:
@@ -766,6 +771,8 @@ class NbftConf(metaclass=singleton.Singleton):
'hdr-digest': ctrl['pdu_header_digest_required'],
'data-digest': ctrl['data_digest_required'],
}
+ if hostnqn:
+ cid['host-nqn'] = hostnqn
indexes = ctrl.get('hfi_indexes')
if isinstance(indexes, list) and len(indexes) > 0:
diff --git a/staslib/service.py b/staslib/service.py
index e681f3a..08a775a 100644
--- a/staslib/service.py
+++ b/staslib/service.py
@@ -393,9 +393,10 @@ class Stac(Service):
for staf_data in self._get_log_pages_from_stafd():
host_traddr = staf_data['discovery-controller']['host-traddr']
host_iface = staf_data['discovery-controller']['host-iface']
+ host_nqn = staf_data['discovery-controller']['host-nqn']
for dlpe in staf_data['log-pages']:
if dlpe.get('subtype') == 'nvme': # eliminate discovery controllers
- tid = stas.tid_from_dlpe(dlpe, host_traddr, host_iface)
+ tid = stas.tid_from_dlpe(dlpe, host_traddr, host_iface, host_nqn)
discovered_ctrls[tid] = dlpe
discovered_ctrl_list = list(discovered_ctrls.keys())
@@ -476,19 +477,20 @@ class Stac(Service):
logging.debug('Stac._disconnect_from_staf() - Disconnected from staf')
def _log_pages_changed( # pylint: disable=too-many-arguments
- self, transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn, device
+ self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn, device
):
if not self._alive():
return
logging.debug(
- 'Stac._log_pages_changed() - transport=%s, traddr=%s, trsvcid=%s, host_traddr=%s, host_iface=%s, subsysnqn=%s, device=%s',
+ 'Stac._log_pages_changed() - transport=%s, traddr=%s, trsvcid=%s, subsysnqn=%s, host_traddr=%s, host_iface=%s, host_nqn=%s, device=%s',
transport,
traddr,
trsvcid,
+ subsysnqn,
host_traddr,
host_iface,
- subsysnqn,
+ host_nqn,
device,
)
if self._cfg_soak_tmr:
@@ -693,9 +695,10 @@ class Staf(Service):
controller.tid.transport,
controller.tid.traddr,
controller.tid.trsvcid,
+ controller.tid.subsysnqn,
controller.tid.host_traddr,
controller.tid.host_iface,
- controller.tid.subsysnqn,
+ controller.tid.host_nqn,
device,
)
@@ -708,7 +711,12 @@ class Staf(Service):
def _referrals(self) -> list:
return [
- stas.tid_from_dlpe(dlpe, controller.tid.host_traddr, controller.tid.host_iface)
+ stas.tid_from_dlpe(
+ dlpe,
+ controller.tid.host_traddr,
+ controller.tid.host_iface,
+ controller.tid.host_nqn,
+ )
for controller in self.get_controllers()
for dlpe in controller.referrals()
]
diff --git a/staslib/stacd.idl b/staslib/stacd.idl
index efefbbe..d609742 100644
--- a/staslib/stacd.idl
+++ b/staslib/stacd.idl
@@ -9,9 +9,10 @@
<arg direction="in" type="s" name="transport"/>
<arg direction="in" type="s" name="traddr"/>
<arg direction="in" type="s" name="trsvcid"/>
+ <arg direction="in" type="s" name="subsysnqn"/>
<arg direction="in" type="s" name="host_traddr"/>
<arg direction="in" type="s" name="host_iface"/>
- <arg direction="in" type="s" name="subsysnqn"/>
+ <arg direction="in" type="s" name="host_nqn"/>
<arg direction="out" type="s" name="info_json"/>
</method>
</interface>
diff --git a/staslib/stafd.idl b/staslib/stafd.idl
index 8c98ffe..a494751 100644
--- a/staslib/stafd.idl
+++ b/staslib/stafd.idl
@@ -9,9 +9,10 @@
<arg direction="in" type="s" name="transport"/>
<arg direction="in" type="s" name="traddr"/>
<arg direction="in" type="s" name="trsvcid"/>
+ <arg direction="in" type="s" name="subsysnqn"/>
<arg direction="in" type="s" name="host_traddr"/>
<arg direction="in" type="s" name="host_iface"/>
- <arg direction="in" type="s" name="subsysnqn"/>
+ <arg direction="in" type="s" name="host_nqn"/>
<arg direction="out" type="s" name="info_json"/>
</method>
</interface>
@@ -25,9 +26,10 @@
<arg direction="in" type="s" name="transport"/>
<arg direction="in" type="s" name="traddr"/>
<arg direction="in" type="s" name="trsvcid"/>
+ <arg direction="in" type="s" name="subsysnqn"/>
<arg direction="in" type="s" name="host_traddr"/>
<arg direction="in" type="s" name="host_iface"/>
- <arg direction="in" type="s" name="subsysnqn"/>
+ <arg direction="in" type="s" name="host_nqn"/>
<arg direction="out" type="aa{ss}" name="log_pages"/>
</method>
<method name="get_all_log_pages">
@@ -38,9 +40,10 @@
<arg direction="out" type="s" name="transport"/>
<arg direction="out" type="s" name="traddr"/>
<arg direction="out" type="s" name="trsvcid"/>
+ <arg direction="out" type="s" name="subsysnqn"/>
<arg direction="out" type="s" name="host_traddr"/>
<arg direction="out" type="s" name="host_iface"/>
- <arg direction="out" type="s" name="subsysnqn"/>
+ <arg direction="out" type="s" name="host_nqn"/>
<arg direction="out" type="s" name="device"/>
</signal>
<signal name="dc_removed"></signal>
diff --git a/staslib/stas.py b/staslib/stas.py
index e333b90..47ce5de 100644
--- a/staslib/stas.py
+++ b/staslib/stas.py
@@ -125,7 +125,7 @@ def remove_invalid_addresses(controllers: list):
# ******************************************************************************
-def tid_from_dlpe(dlpe, host_traddr, host_iface):
+def tid_from_dlpe(dlpe, host_traddr, host_iface, host_nqn):
'''@brief Take a Discovery Log Page Entry and return a Controller ID as a dict.'''
cid = {
'transport': dlpe['trtype'],
@@ -135,6 +135,8 @@ def tid_from_dlpe(dlpe, host_traddr, host_iface):
'host-iface': host_iface,
'subsysnqn': dlpe['subnqn'],
}
+ if host_nqn:
+ cid['host-nqn'] = host_nqn
return trid.TID(cid)
@@ -416,16 +418,24 @@ class ServiceABC(abc.ABC): # pylint: disable=too-many-instance-attributes
return self._controllers.values()
def get_controller(
- self, transport: str, traddr: str, trsvcid: str, host_traddr: str, host_iface: str, subsysnqn: str
+ self,
+ transport: str,
+ traddr: str,
+ trsvcid: str,
+ subsysnqn: str,
+ host_traddr: str,
+ host_iface: str,
+ host_nqn: str,
): # pylint: disable=too-many-arguments
'''@brief get the specified controller object from the list of controllers'''
cid = {
'transport': transport,
'traddr': traddr,
'trsvcid': trsvcid,
+ 'subsysnqn': subsysnqn,
'host-traddr': host_traddr,
'host-iface': host_iface,
- 'subsysnqn': subsysnqn,
+ 'host-nqn': host_nqn,
}
return self._controllers.get(trid.TID(cid))
diff --git a/staslib/trid.py b/staslib/trid.py
index 11065ea..e814f4e 100644
--- a/staslib/trid.py
+++ b/staslib/trid.py
@@ -30,6 +30,7 @@ class TID: # pylint: disable=too-many-instance-attributes
'trsvcid': str, # [optional]
'host-traddr': str, # [optional]
'host-iface': str, # [optional]
+ 'host-nqn': str, # [optional]
# Connection parameters
'dhchap-ctrl-secret': str, # [optional]
@@ -58,59 +59,54 @@ class TID: # pylint: disable=too-many-instance-attributes
self._trsvcid = (
trsvcid if trsvcid else (TID.RDMA_IP_PORT if self._transport == 'rdma' else TID.DISC_IP_PORT)
)
+ sysconf = conf.SysConf()
self._host_traddr = cid.get('host-traddr', '')
self._host_iface = '' if conf.SvcConf().ignore_iface else cid.get('host-iface', '')
+ self._host_nqn = cid.get('host-nqn', sysconf.hostnqn)
self._subsysnqn = cid.get('subsysnqn', '')
- self._key = (self._transport, self._traddr, self._trsvcid, self._subsysnqn, self._host_traddr, self._host_iface)
+ self._key = (
+ self._transport,
+ self._traddr,
+ self._trsvcid,
+ self._subsysnqn,
+ self._host_traddr,
+ self._host_iface,
+ self._host_nqn,
+ )
self._hash = int.from_bytes(
hashlib.md5(''.join(self._key).encode('utf-8')).digest(), 'big'
) # We need a consistent hash between restarts
self._id = f'({self._transport}, {self._traddr}, {self._trsvcid}{", " + self._subsysnqn if self._subsysnqn else ""}{", " + self._host_iface if self._host_iface else ""}{", " + self._host_traddr if self._host_traddr else ""})' # pylint: disable=line-too-long
- @property
- def transport(self): # pylint: disable=missing-function-docstring
- return self._transport
-
- @property
- def traddr(self): # pylint: disable=missing-function-docstring
- return self._traddr
-
- @property
- def trsvcid(self): # pylint: disable=missing-function-docstring
- return self._trsvcid
-
- @property
- def host_traddr(self): # pylint: disable=missing-function-docstring
- return self._host_traddr
-
- @property
- def host_iface(self): # pylint: disable=missing-function-docstring
- return self._host_iface
-
- @property
- def subsysnqn(self): # pylint: disable=missing-function-docstring
- return self._subsysnqn
-
- @property
- def cfg(self): # pylint: disable=missing-function-docstring
- return self._cfg
+ host_traddr = property(lambda self: self._host_traddr)
+ host_iface = property(lambda self: self._host_iface)
+ subsysnqn = property(lambda self: self._subsysnqn)
+ transport = property(lambda self: self._transport)
+ host_nqn = property(lambda self: self._host_nqn)
+ trsvcid = property(lambda self: self._trsvcid)
+ traddr = property(lambda self: self._traddr)
+ cfg = property(lambda self: self._cfg)
def as_dict(self):
'''Return object members as a dictionary'''
data = {
- 'transport': self.transport,
'traddr': self.traddr,
- 'subsysnqn': self.subsysnqn,
'trsvcid': self.trsvcid,
- 'host-traddr': self.host_traddr,
+ 'transport': self.transport,
+ 'subsysnqn': self.subsysnqn,
'host-iface': self.host_iface,
+ 'host-traddr': self.host_traddr,
}
- # When migrating an old last known config, the "_cfg" member may
- # not exist. Therefor retrive it with getattr() to avoid a crash.
+ # When migrating an old last known config, some members may not
+ # exist. Therefore retrieve them with getattr() to avoid a crash.
cfg = getattr(self, '_cfg', None)
if cfg:
data.update(cfg)
+
+ sysconf = conf.SysConf()
+ data['host-nqn'] = getattr(self, '_host_nqn', sysconf.hostnqn)
+
return data
def __str__(self):
diff --git a/staslib/udev.py b/staslib/udev.py
index 80555dd..b9bd258 100644
--- a/staslib/udev.py
+++ b/staslib/udev.py
@@ -259,8 +259,13 @@ class Udev:
cid.src_addr can only be read from the sysfs starting with kernel
6.1.
'''
- # 'transport', 'traddr', 'trsvcid', and 'subsysnqn' must exactly match.
- if cid['transport'] != tid.transport or cid['trsvcid'] != tid.trsvcid or cid['subsysnqn'] != tid.subsysnqn:
+ # 'transport', 'traddr', 'trsvcid', 'subsysnqn', and 'host-nqn' must exactly match.
+ if (
+ cid['transport'] != tid.transport
+ or cid['trsvcid'] != tid.trsvcid
+ or cid['subsysnqn'] != tid.subsysnqn
+ or cid['host-nqn'] != tid.host_nqn
+ ):
return False
if tid.transport in ('tcp', 'rdma'):
@@ -489,6 +494,7 @@ class Udev:
'host-iface': Udev._get_property(device, 'NVME_HOST_IFACE'),
'subsysnqn': Udev._get_attribute(device, 'subsysnqn'),
'src-addr': Udev.get_key_from_attr(device, 'address', 'src_addr='),
+ 'host-nqn': Udev._get_attribute(device, 'hostnqn'),
}
return cid
diff --git a/test/test-controller.py b/test/test-controller.py
index d33a6a2..54e4349 100755
--- a/test/test-controller.py
+++ b/test/test-controller.py
@@ -118,6 +118,7 @@ class Test(TestCase):
'trsvcid': '8009',
'host-traddr': '1.2.3.4',
'host-iface': 'wlp0s20f3',
+ 'host-nqn': 'nqn.1988-11.com.dell:poweredge:1234',
}
)
@@ -186,6 +187,7 @@ class Test(TestCase):
'host-iface': 'wlp0s20f3',
'subsysnqn': 'nqn.1988-11.com.dell:SFSS:2:20220208134025e8',
'device': 'nvme?',
+ 'host-nqn': 'nqn.1988-11.com.dell:poweredge:1234',
},
)
@@ -198,6 +200,7 @@ class Test(TestCase):
'trsvcid': '8009',
'host-traddr': '1.2.3.4',
'host-iface': 'wlp0s20f3',
+ 'host-nqn': 'nqn.1988-11.com.dell:poweredge:1234',
'device': 'nvme?',
'connect attempts': '1',
'retry connect timer': '60.0s [off]',
@@ -215,6 +218,7 @@ class Test(TestCase):
'trsvcid': '8009',
'host-traddr': '1.2.3.4',
'host-iface': 'wlp0s20f3',
+ 'host-nqn': 'nqn.1988-11.com.dell:poweredge:1234',
'subsysnqn': 'nqn.1988-11.com.dell:SFSS:2:20220208134025e8',
'device': 'nvme?',
'connect attempts': '1',
diff --git a/test/test-nbft.py b/test/test-nbft.py
index cf62214..3f0fa97 100755
--- a/test/test-nbft.py
+++ b/test/test-nbft.py
@@ -39,7 +39,7 @@ NBFT_DATA = {
"host_nqn_configured": True,
"id": "44454c4c-3400-1036-8038-b2c04f313233",
"nqn": "nqn.1988-11.com.dell:PowerEdge.R760.1234567",
- "primary_admin_host_flag": "not " "indicated",
+ "primary_admin_host_flag": "not indicated",
},
"subsystem": [
{
diff --git a/test/test-nbft_conf.py b/test/test-nbft_conf.py
index 85cb35d..072c3db 100755
--- a/test/test-nbft_conf.py
+++ b/test/test-nbft_conf.py
@@ -11,6 +11,7 @@ EXPECTED_DCS = [
'traddr': '100.71.103.50',
'transport': 'tcp',
'trsvcid': '8009',
+ 'host-nqn': 'nqn.1988-11.com.dell:PowerEdge.R760.1234567',
}
]
EXPECTED_IOCS = [
@@ -21,6 +22,7 @@ EXPECTED_IOCS = [
'traddr': '100.71.103.48',
'transport': 'tcp',
'trsvcid': '4420',
+ 'host-nqn': 'nqn.1988-11.com.dell:PowerEdge.R760.1234567',
},
{
'data-digest': False,
@@ -29,6 +31,7 @@ EXPECTED_IOCS = [
'traddr': '100.71.103.49',
'transport': 'tcp',
'trsvcid': '4420',
+ 'host-nqn': 'nqn.1988-11.com.dell:PowerEdge.R760.1234567',
},
]
diff --git a/test/test-service.py b/test/test-service.py
index ef1cb6e..567d592 100755
--- a/test/test-service.py
+++ b/test/test-service.py
@@ -58,9 +58,10 @@ class Test(TestCase):
transport='tcp',
traddr='10.10.10.10',
trsvcid='8009',
+ subsysnqn='nqn.1988-11.com.dell:SFSS:2:20220208134025e8',
host_traddr='1.2.3.4',
host_iface='wlp0s20f3',
- subsysnqn='nqn.1988-11.com.dell:SFSS:2:20220208134025e8',
+ host_nqn='nqn.2014-08.org.nvmexpress:uuid:01234567-0123-0123-0123-0123456789ab',
),
None,
)
diff --git a/test/test-transport_id.py b/test/test-transport_id.py
index 36953dd..d0386ec 100755
--- a/test/test-transport_id.py
+++ b/test/test-transport_id.py
@@ -13,6 +13,7 @@ class Test(unittest.TestCase):
TRSVCID = '8009'
HOST_TRADDR = '1.2.3.4'
HOST_IFACE = 'wlp0s20f3'
+ HOST_NQN = 'nqn.1988-11.com.dell:12345'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -23,6 +24,7 @@ class Test(unittest.TestCase):
'trsvcid': Test.TRSVCID,
'host-traddr': Test.HOST_TRADDR,
'host-iface': Test.HOST_IFACE,
+ 'host-nqn': Test.HOST_NQN,
}
self.other_cid = {
'transport': Test.TRANSPORT,
@@ -31,6 +33,7 @@ class Test(unittest.TestCase):
'trsvcid': Test.TRSVCID,
'host-traddr': Test.HOST_TRADDR,
'host-iface': Test.HOST_IFACE,
+ 'host-nqn': Test.HOST_NQN,
}
self.tid = trid.TID(self.cid)
diff --git a/test/test-udev.py b/test/test-udev.py
index 71e5f8a..9508de4 100755
--- a/test/test-udev.py
+++ b/test/test-udev.py
@@ -33,6 +33,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'hello',
'host-traddr': src_ip,
'host-iface': ifname,
+ 'host-nqn': '',
}
),
True,
@@ -47,6 +48,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'hello',
'host-traddr': src_ip,
'host-iface': ifname,
+ 'host-nqn': '',
}
),
False,
@@ -61,6 +63,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'hello',
'host-traddr': src_ip,
'host-iface': ifname,
+ 'host-nqn': '',
}
),
False,
@@ -75,6 +78,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'hello',
'host-traddr': src_ip,
'host-iface': ifname,
+ 'host-nqn': '',
}
),
False,
@@ -89,6 +93,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'hello',
'host-traddr': '255.255.255.255',
'host-iface': ifname,
+ 'host-nqn': '',
}
),
False,
@@ -103,6 +108,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'hello',
'host-traddr': src_ip,
'host-iface': 'blah',
+ 'host-nqn': '',
}
),
False,
@@ -117,6 +123,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'bob',
'host-traddr': src_ip,
'host-iface': ifname,
+ 'host-nqn': '',
}
),
False,
@@ -130,6 +137,7 @@ def get_tids_to_test(family, src_ip, ifname):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-iface': ifname,
+ 'host-nqn': '',
}
),
True,
@@ -143,6 +151,7 @@ def get_tids_to_test(family, src_ip, ifname):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': src_ip,
+ 'host-nqn': '',
}
),
True,
@@ -155,6 +164,7 @@ def get_tids_to_test(family, src_ip, ifname):
'traddr': traddr(family),
'trsvcid': '8009',
'subsysnqn': 'hello',
+ 'host-nqn': '',
}
),
True,
@@ -169,6 +179,7 @@ def get_tids_to_test(family, src_ip, ifname):
'subsysnqn': 'hello',
'host-traddr': src_ip,
'host-iface': ifname,
+ 'host-nqn': '',
}
),
True,
@@ -182,6 +193,7 @@ def get_tids_to_test(family, src_ip, ifname):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-iface': ifname,
+ 'host-nqn': '',
}
),
True,
@@ -296,6 +308,7 @@ class Test(unittest.TestCase):
'host-traddr': src_ipv4,
'host-iface': ifname,
'src-addr': src_ipv4,
+ 'host-nqn': '',
}
cid_legacy = {
'transport': 'tcp',
@@ -305,6 +318,7 @@ class Test(unittest.TestCase):
'host-traddr': src_ipv4,
'host-iface': ifname,
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
for case_id, tid, match in get_tids_to_test(4, src_ipv4, ifname):
self.assertEqual(match, udev.UDEV._cid_matches_tid(tid, cid), msg=f'Test Case {case_id} failed')
@@ -321,6 +335,7 @@ class Test(unittest.TestCase):
'host-traddr': '',
'host-iface': '',
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -329,6 +344,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': '1.1.1.1',
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case A4.1 failed')
@@ -341,6 +357,7 @@ class Test(unittest.TestCase):
'host-traddr': '',
'host-iface': ifname,
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -348,6 +365,7 @@ class Test(unittest.TestCase):
'traddr': traddr(4),
'trsvcid': '8009',
'subsysnqn': 'hello',
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case A4.2 failed')
@@ -363,6 +381,7 @@ class Test(unittest.TestCase):
'host-traddr': src_ipv4,
'host-iface': '',
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -371,6 +390,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': '1.1.1.1',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case B4 failed')
@@ -382,6 +402,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-iface': 'blah',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case C4 failed')
@@ -393,6 +414,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-iface': ifname,
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case D4 failed')
@@ -405,6 +427,7 @@ class Test(unittest.TestCase):
'host-traddr': '',
'host-iface': ifname,
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -414,6 +437,7 @@ class Test(unittest.TestCase):
'subsysnqn': 'hello',
'host-traddr': '1.1.1.1',
'host-iface': 'blah',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case E4 failed')
@@ -425,6 +449,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': '1.1.1.1',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case F4 failed')
@@ -436,6 +461,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': ipv4_addrs[0],
+ 'host-nqn': '',
}
)
match = len(ipv4_addrs) == 1 and iputil.get_ipaddress_obj(
@@ -456,6 +482,7 @@ class Test(unittest.TestCase):
'host-traddr': src_ipv6,
'host-iface': ifname,
'src-addr': src_ipv6,
+ 'host-nqn': '',
}
cid_legacy = {
'transport': 'tcp',
@@ -465,6 +492,7 @@ class Test(unittest.TestCase):
'host-traddr': src_ipv6,
'host-iface': ifname,
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
for case_id, tid, match in get_tids_to_test(6, src_ipv6, ifname):
self.assertEqual(match, udev.UDEV._cid_matches_tid(tid, cid), msg=f'Test Case {case_id} failed')
@@ -480,6 +508,7 @@ class Test(unittest.TestCase):
'host-traddr': '',
'host-iface': '',
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -488,6 +517,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': 'AAAA::FFFF',
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case A6.1 failed')
@@ -500,6 +530,7 @@ class Test(unittest.TestCase):
'host-traddr': '',
'host-iface': ifname,
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -507,6 +538,7 @@ class Test(unittest.TestCase):
'traddr': traddr(6),
'trsvcid': '8009',
'subsysnqn': 'hello',
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case A6.2 failed')
@@ -522,6 +554,7 @@ class Test(unittest.TestCase):
'host-traddr': src_ipv6,
'host-iface': '',
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -530,6 +563,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': 'AAAA::FFFF',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case B6 failed')
@@ -541,6 +575,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-iface': 'blah',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case C6 failed')
@@ -552,6 +587,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-iface': ifname,
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case D6 failed')
@@ -564,6 +600,7 @@ class Test(unittest.TestCase):
'host-traddr': '',
'host-iface': ifname,
'src-addr': '', # Legacy
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -573,6 +610,7 @@ class Test(unittest.TestCase):
'subsysnqn': 'hello',
'host-traddr': 'AAA::BBBB',
'host-iface': 'blah',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case E6 failed')
@@ -584,6 +622,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': 'AAA::BBB',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid_legacy), msg=f'Legacy Test Case F6 failed')
@@ -595,6 +634,7 @@ class Test(unittest.TestCase):
'trsvcid': '8009',
'subsysnqn': 'hello',
'host-traddr': ipv6_addrs[0],
+ 'host-nqn': '',
}
)
match = len(ipv6_addrs) == 1 and iputil.get_ipaddress_obj(
@@ -612,6 +652,7 @@ class Test(unittest.TestCase):
'host-traddr': 'AAA::BBBB',
'host-iface': '',
'src-addr': '',
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -620,6 +661,7 @@ class Test(unittest.TestCase):
'trsvcid': '',
'subsysnqn': 'hello',
'host-traddr': 'AAA::BBBB',
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid), msg=f'Test Case FC-1 failed')
@@ -631,6 +673,7 @@ class Test(unittest.TestCase):
'trsvcid': '',
'subsysnqn': 'hello',
'host-traddr': 'BBBB::AAA',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid), msg=f'Test Case FC-2 failed')
@@ -645,6 +688,7 @@ class Test(unittest.TestCase):
'host-traddr': '5.4.3.2',
'host-iface': '',
'src-addr': '',
+ 'host-nqn': '',
}
tid = trid.TID(
{
@@ -653,6 +697,7 @@ class Test(unittest.TestCase):
'trsvcid': '4444',
'subsysnqn': 'hello',
'host-traddr': '5.4.3.2',
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid), msg=f'Test Case RDMA-1 failed')
@@ -664,6 +709,7 @@ class Test(unittest.TestCase):
'trsvcid': '4444',
'subsysnqn': 'hello',
'host-traddr': '5.5.6.6',
+ 'host-nqn': '',
}
)
self.assertEqual(False, udev.UDEV._cid_matches_tid(tid, cid), msg=f'Test Case RDMA-2 failed')
@@ -674,6 +720,7 @@ class Test(unittest.TestCase):
'traddr': '2.3.4.5',
'trsvcid': '4444',
'subsysnqn': 'hello',
+ 'host-nqn': '',
}
)
self.assertEqual(True, udev.UDEV._cid_matches_tid(tid, cid), msg=f'Test Case RDMA-3 failed')