summaryrefslogtreecommitdiffstats
path: root/src/spdk/scripts/spdkcli/ui_node_nvmf.py
blob: 1b25298d12f34475dd6bd8f12fcfd546c4f25c83 (plain)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
from rpc.client import JSONRPCException
from .ui_node import UINode


class UINVMf(UINode):
    def __init__(self, parent):
        UINode.__init__(self, "nvmf", parent)
        self.refresh()

    def refresh(self):
        self._children = set([])
        UINVMfSubsystems(self)
        UINVMfTransports(self)


class UINVMfTransports(UINode):
    def __init__(self, parent):
        UINode.__init__(self, "transport", parent)
        self.refresh()

    def refresh(self):
        self._children = set([])
        for transport in self.get_root().nvmf_get_transports():
            UINVMfTransport(transport, self)

    def ui_command_create(self, trtype, max_queue_depth=None, max_io_qpairs_per_ctrlr=None,
                          in_capsule_data_size=None, max_io_size=None, io_unit_size=None, max_aq_depth=None):
        """Create a transport with given parameters

        Arguments:
            trtype - Example: 'RDMA'.
            max_queue_depth - Optional parameter. Integer, max value 65535.
            max_io_qpairs_per_ctrlr - Optional parameter. 16 bit Integer, max value 65535.
            in_capsule_data_size - Optional parameter. 32 bit Integer, max value 4294967295
            max_io_size - Optional parameter. 32 bit integer, max value 4294967295
            io_unit_size - Optional parameter. 32 bit integer, max value 4294967295
            max_aq_depth - Optional parameter. 32 bit integer, max value 4294967295
        """
        max_queue_depth = self.ui_eval_param(max_queue_depth, "number", None)
        max_io_qpairs_per_ctrlr = self.ui_eval_param(max_io_qpairs_per_ctrlr, "number", None)
        in_capsule_data_size = self.ui_eval_param(in_capsule_data_size, "number", None)
        max_io_size = self.ui_eval_param(max_io_size, "number", None)
        io_unit_size = self.ui_eval_param(io_unit_size, "number", None)
        max_aq_depth = self.ui_eval_param(max_aq_depth, "number", None)

        self.get_root().create_nvmf_transport(trtype=trtype,
                                              max_queue_depth=max_queue_depth,
                                              max_io_qpairs_per_ctrlr=max_io_qpairs_per_ctrlr,
                                              in_capsule_data_size=in_capsule_data_size,
                                              max_io_size=max_io_size,
                                              io_unit_size=io_unit_size,
                                              max_aq_depth=max_aq_depth)

    def summary(self):
        return "Transports: %s" % len(self.children), None


class UINVMfTransport(UINode):
    def __init__(self, transport, parent):
        UINode.__init__(self, transport.trtype, parent)
        self.transport = transport


class UINVMfSubsystems(UINode):
    def __init__(self, parent):
        UINode.__init__(self, "subsystem", parent)
        self.refresh()

    def refresh(self):
        self._children = set([])
        for subsystem in self.get_root().nvmf_get_subsystems():
            UINVMfSubsystem(subsystem, self)

    def delete(self, subsystem_nqn):
        self.get_root().nvmf_delete_subsystem(nqn=subsystem_nqn)

    def ui_command_create(self, nqn, serial_number=None,
                          max_namespaces=None, allow_any_host="false"):
        """Create subsystem with given parameteres.

        Arguments:
            nqn - Target nqn(ASCII).
            serial_number - Example: 'SPDK00000000000001'.
            max_namespaces - Optional parameter. Maximum number of namespaces allowed to added during
                             active connection
            allow_any_host - Optional parameter. Allow any host to connect (don't enforce host NQN
                             whitelist)
        """
        allow_any_host = self.ui_eval_param(allow_any_host, "bool", False)
        max_namespaces = self.ui_eval_param(max_namespaces, "number", 0)
        self.get_root().create_nvmf_subsystem(nqn=nqn, serial_number=serial_number,
                                              allow_any_host=allow_any_host,
                                              max_namespaces=max_namespaces)

    def ui_command_delete(self, subsystem_nqn):
        """Delete subsystem with given nqn.

        Arguments:
            nqn_subsystem - Name of susbsytem to delete
        """
        self.delete(subsystem_nqn)

    def ui_command_delete_all(self):
        """Delete all subsystems"""
        rpc_messages = ""
        for child in self._children:
            try:
                self.delete(child.subsystem.nqn)
            except JSONRPCException as e:
                rpc_messages += e.message
        if rpc_messages:
            raise JSONRPCException(rpc_messages)

    def summary(self):
        return "Subsystems: %s" % len(self.children), None


class UINVMfSubsystem(UINode):
    def __init__(self, subsystem, parent):
        UINode.__init__(self, subsystem.nqn, parent)
        self.subsystem = subsystem
        self.refresh()

    def refresh(self):
        self._children = set([])
        UINVMfSubsystemListeners(self.subsystem.listen_addresses, self)
        UINVMfSubsystemHosts(self.subsystem.hosts, self)
        if hasattr(self.subsystem, 'namespaces'):
            UINVMfSubsystemNamespaces(self.subsystem.namespaces, self)

    def refresh_node(self):
        for subsystem in self.get_root().nvmf_get_subsystems():
            if subsystem.nqn == self.subsystem.nqn:
                self.subsystem = subsystem
        self.refresh()

    def ui_command_show_details(self):
        self.shell.log.info(json.dumps(vars(self.lvs), indent=2))

    def ui_command_allow_any_host(self, disable="false"):
        """Disable or or enable allow_any_host flag.

        Arguments:
            disable - Optional parameter. If false then enable, if true disable
        """
        disable = self.ui_eval_param(disable, "bool", None)
        self.get_root().nvmf_subsystem_allow_any_host(
            nqn=self.subsystem.nqn, disable=disable)

    def summary(self):
        sn = None
        if hasattr(self.subsystem, 'serial_number'):
            sn = "sn=%s" % self.subsystem.serial_number
        st = None
        if hasattr(self.subsystem, 'subtype'):
            st = "st=%s" % self.subsystem.subtype
        allow_any_host = None
        if self.subsystem.allow_any_host:
            allow_any_host = "Allow any host"
        info = ", ".join(filter(None, [sn, st, allow_any_host]))
        return info, None


class UINVMfSubsystemListeners(UINode):
    def __init__(self, listen_addresses, parent):
        UINode.__init__(self, "listen_addresses", parent)
        self.listen_addresses = listen_addresses
        self.refresh()

    def refresh(self):
        self._children = set([])
        for address in self.listen_addresses:
            UINVMfSubsystemListener(address, self)

    def refresh_node(self):
        for subsystem in self.get_root().nvmf_get_subsystems():
            if subsystem.nqn == self.parent.subsystem.nqn:
                self.listen_addresses = subsystem.listen_addresses
        self.refresh()

    def delete(self, trtype, traddr, trsvcid, adrfam=None):
        self.get_root().nvmf_subsystem_remove_listener(
            nqn=self.parent.subsystem.nqn, trtype=trtype,
            traddr=traddr, trsvcid=trsvcid, adrfam=adrfam)

    def ui_command_create(self, trtype, traddr, trsvcid, adrfam):
        """Create address listener for subsystem.

        Arguments:
            trtype - NVMe-oF transport type: e.g., rdma.
            traddr - NVMe-oF transport address: e.g., an ip address.
            trsvcid - NVMe-oF transport service id: e.g., a port number.
            adrfam - NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc.
        """
        self.get_root().nvmf_subsystem_add_listener(
            nqn=self.parent.subsystem.nqn, trtype=trtype, traddr=traddr,
            trsvcid=trsvcid, adrfam=adrfam)

    def ui_command_delete(self, trtype, traddr, trsvcid, adrfam=None):
        """Remove address listener for subsystem.

        Arguments:
            trtype - Transport type (RDMA)
            traddr - NVMe-oF transport address: e.g., an ip address.
            trsvcid - NVMe-oF transport service id: e.g., a port number.
            adrfam - Optional argument. Address family ("IPv4", "IPv6", "IB" or "FC").
        """
        self.delete(trtype, traddr, trsvcid, adrfam)

    def ui_command_delete_all(self):
        """Remove all address listeners from subsystem."""
        rpc_messages = ""
        for la in self.listen_addresses:
            try:
                self.delete(la['trtype'], la['traddr'], la['trsvcid'], la['adrfam'])
            except JSONRPCException as e:
                rpc_messages += e.message
        if rpc_messages:
            raise JSONRPCException(rpc_messages)

    def summary(self):
        return "Addresses: %s" % len(self.listen_addresses), None


class UINVMfSubsystemListener(UINode):
    def __init__(self, address, parent):
        UINode.__init__(self, "%s:%s" % (address['traddr'], address['trsvcid']),
                        parent)
        self.address = address

    def summary(self):
        return "%s" % self.address['trtype'], True


class UINVMfSubsystemHosts(UINode):
    def __init__(self, hosts, parent):
        UINode.__init__(self, "hosts", parent)
        self.hosts = hosts
        self.refresh()

    def refresh(self):
        self._children = set([])
        for host in self.hosts:
            UINVMfSubsystemHost(host, self)

    def refresh_node(self):
        for subsystem in self.get_root().nvmf_get_subsystems():
            if subsystem.nqn == self.parent.subsystem.nqn:
                self.hosts = subsystem.hosts
        self.refresh()

    def delete(self, host):
        self.get_root().nvmf_subsystem_remove_host(
            nqn=self.parent.subsystem.nqn, host=host)

    def ui_command_create(self, host):
        """Add a host NQN to the whitelist of allowed hosts.

        Args:
            host: Host NQN to add to the list of allowed host NQNs
        """
        self.get_root().nvmf_subsystem_add_host(
            nqn=self.parent.subsystem.nqn, host=host)

    def ui_command_delete(self, host):
        """Delete host from subsystem.

        Arguments:
           host - NQN of host to remove.
        """
        self.delete(host)

    def ui_command_delete_all(self):
        """Delete host from subsystem"""
        rpc_messages = ""
        for host in self.hosts:
            try:
                self.delete(host['nqn'])
            except JSONRPCException as e:
                rpc_messages += e.message
        if rpc_messages:
            raise JSONRPCException(rpc_messages)

    def summary(self):
        return "Hosts: %s" % len(self.hosts), None


class UINVMfSubsystemHost(UINode):
    def __init__(self, host, parent):
        UINode.__init__(self, "%s" % host['nqn'], parent)
        self.host = host


class UINVMfSubsystemNamespaces(UINode):
    def __init__(self, namespaces, parent):
        UINode.__init__(self, "namespaces", parent)
        self.namespaces = namespaces
        self.refresh()

    def refresh(self):
        self._children = set([])
        for namespace in self.namespaces:
            UINVMfSubsystemNamespace(namespace, self)

    def refresh_node(self):
        for subsystem in self.get_root().nvmf_get_subsystems():
            if subsystem.nqn == self.parent.subsystem.nqn:
                self.namespaces = subsystem.namespaces
        self.refresh()

    def delete(self, nsid):
        self.get_root().nvmf_subsystem_remove_ns(
            nqn=self.parent.subsystem.nqn, nsid=nsid)

    def ui_command_create(self, bdev_name, nsid=None,
                          nguid=None, eui64=None, uuid=None):
        """Add a namespace to a subsystem.

        Args:
            bdev_name: Name of bdev to expose as a namespace.
        Optional args:
            nsid: Namespace ID.
            nguid: 16-byte namespace globally unique identifier in hexadecimal.
            eui64: 8-byte namespace EUI-64 in hexadecimal (e.g. "ABCDEF0123456789").
            uuid: Namespace UUID.
        """
        nsid = self.ui_eval_param(nsid, "number", None)
        self.get_root().nvmf_subsystem_add_ns(
            nqn=self.parent.subsystem.nqn, bdev_name=bdev_name,
            nsid=nsid, nguid=nguid, eui64=eui64, uuid=uuid)

    def ui_command_delete(self, nsid):
        """Delete namespace from subsystem.

        Arguments:
            nsid - Id of namespace to remove.
        """
        nsid = self.ui_eval_param(nsid, "number", None)
        self.delete(nsid)

    def ui_command_delete_all(self):
        """Delete all namespaces from subsystem."""
        rpc_messages = ""
        for namespace in self.namespaces:
            try:
                self.delete(namespace['nsid'])
            except JSONRPCException as e:
                rpc_messages += e.message
        if rpc_messages:
            raise JSONRPCException(rpc_messages)

    def summary(self):
        return "Namespaces: %s" % len(self.namespaces), None


class UINVMfSubsystemNamespace(UINode):
    def __init__(self, namespace, parent):
        UINode.__init__(self, namespace['bdev_name'], parent)
        self.namespace = namespace

    def summary(self):
        info = ", ".join([self.namespace['name'], str(self.namespace['nsid'])])
        return info, None