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
|
# 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._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):
return isinstance(other, self.__class__) and self._key == other._key
def __ne__(self, other):
return not isinstance(other, self.__class__) or self._key != other._key
def __hash__(self):
return self._hash
|