1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
# Copyright (c) 2022, Dell Inc. or its subsidiaries. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# See the LICENSE file for details.
#
# This file is part of NVMe STorage Appliance Services (nvme-stas).
#
# Authors: Martin Belanger <Martin.Belanger@dell.com>
#
'''This module defines the Transport Identifier Object, which is used
throughout nvme-stas to uniquely identify a Controller'''
import hashlib
from staslib import conf
class TID: # pylint: disable=too-many-instance-attributes
'''Transport Identifier'''
RDMA_IP_PORT = '4420'
DISC_IP_PORT = '8009'
def __init__(self, cid: dict):
'''@param cid: Controller Identifier. A dictionary with the following
contents.
{
# Transport parameters
'transport': str, # [mandatory]
'traddr': str, # [mandatory]
'subsysnqn': str, # [mandatory]
'trsvcid': str, # [optional]
'host-traddr': str, # [optional]
'host-iface': str, # [optional]
# Connection parameters
'dhchap-ctrl-secret': str, # [optional]
'hdr-digest': str, # [optional]
'data-digest': str, # [optional]
'nr-io-queues': str, # [optional]
'nr-write-queues': str, # [optional]
'nr-poll-queues': str, # [optional]
'queue-size': str, # [optional]
'kato': str, # [optional]
'reconnect-delay': str, # [optional]
'ctrl-loss-tmo': str, # [optional]
'disable-sqflow': str, # [optional]
}
'''
self._cfg = {
k: v
for k, v in cid.items()
if k not in ('transport', 'traddr', 'subsysnqn', 'trsvcid', 'host-traddr', 'host-iface')
}
self._transport = cid.get('transport', '')
self._traddr = cid.get('traddr', '')
self._trsvcid = ''
if self._transport in ('tcp', 'rdma'):
trsvcid = cid.get('trsvcid', None)
self._trsvcid = (
trsvcid if trsvcid else (TID.RDMA_IP_PORT if self._transport == 'rdma' else TID.DISC_IP_PORT)
)
self._host_traddr = cid.get('host-traddr', '')
self._host_iface = '' if conf.SvcConf().ignore_iface else cid.get('host-iface', '')
self._subsysnqn = cid.get('subsysnqn', '')
self._shortkey = (self._transport, self._traddr, self._trsvcid, self._subsysnqn, self._host_traddr)
self._key = (self._transport, self._traddr, self._trsvcid, self._subsysnqn, self._host_traddr, self._host_iface)
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
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,
'host-iface': self.host_iface,
}
# When migrating an old last known config, the "_cfg" member may
# not exist. Therefor retrive it with getattr() to avoid a crash.
cfg = getattr(self, '_cfg', None)
if cfg:
data.update(cfg)
return data
def __str__(self):
return self._id
def __repr__(self):
return self._id
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
if self._host_iface and other._host_iface:
return self._key == other._key
return self._shortkey == other._shortkey
def __ne__(self, other):
if not isinstance(other, self.__class__):
return True
if self._host_iface and other._host_iface:
return self._key != other._key
return self._shortkey != other._shortkey
def __hash__(self):
return self._hash
|