xref: /spdk/python/spdk/spdkcli/ui_node_nvmf.py (revision 470e851852bb948334a272c9f8de495020fa082f)
1#  SPDX-License-Identifier: BSD-3-Clause
2#  Copyright (C) 2018 Intel Corporation.
3#  All rights reserved.
4
5from ..rpc.client import JSONRPCException
6from .ui_node import UINode
7
8
9class UINVMf(UINode):
10    def __init__(self, parent):
11        UINode.__init__(self, "nvmf", parent)
12        self.refresh()
13
14    def refresh(self):
15        self._children = set([])
16        UINVMfSubsystems(self)
17        UINVMfTransports(self)
18        UINVMfReferrals(self)
19
20
21class UINVMfTransports(UINode):
22    def __init__(self, parent):
23        UINode.__init__(self, "transport", parent)
24        self.refresh()
25
26    def refresh(self):
27        self._children = set([])
28        for transport in self.get_root().nvmf_get_transports():
29            UINVMfTransport(transport, self)
30
31    def ui_command_create(self, trtype, max_queue_depth=None, max_io_qpairs_per_ctrlr=None,
32                          in_capsule_data_size=None, max_io_size=None, io_unit_size=None, max_aq_depth=None):
33        """Create a transport with given parameters
34
35        Arguments:
36            trtype - Example: 'RDMA'.
37            max_queue_depth - Optional parameter. Integer, max value 65535.
38            max_io_qpairs_per_ctrlr - Optional parameter. 16 bit Integer, max value 65535.
39            in_capsule_data_size - Optional parameter. 32 bit Integer, max value 4294967295
40            max_io_size - Optional parameter. 32 bit integer, max value 4294967295
41            io_unit_size - Optional parameter. 32 bit integer, max value 4294967295
42            max_aq_depth - Optional parameter. 32 bit integer, max value 4294967295
43        """
44        max_queue_depth = self.ui_eval_param(max_queue_depth, "number", None)
45        max_io_qpairs_per_ctrlr = self.ui_eval_param(max_io_qpairs_per_ctrlr, "number", None)
46        in_capsule_data_size = self.ui_eval_param(in_capsule_data_size, "number", None)
47        max_io_size = self.ui_eval_param(max_io_size, "number", None)
48        io_unit_size = self.ui_eval_param(io_unit_size, "number", None)
49        max_aq_depth = self.ui_eval_param(max_aq_depth, "number", None)
50
51        self.get_root().create_nvmf_transport(trtype=trtype,
52                                              max_queue_depth=max_queue_depth,
53                                              max_io_qpairs_per_ctrlr=max_io_qpairs_per_ctrlr,
54                                              in_capsule_data_size=in_capsule_data_size,
55                                              max_io_size=max_io_size,
56                                              io_unit_size=io_unit_size,
57                                              max_aq_depth=max_aq_depth)
58
59    def summary(self):
60        return "Transports: %s" % len(self.children), None
61
62
63class UINVMfTransport(UINode):
64    def __init__(self, transport, parent):
65        UINode.__init__(self, transport.trtype, parent)
66        self.transport = transport
67
68
69class UINVMfSubsystems(UINode):
70    def __init__(self, parent):
71        UINode.__init__(self, "subsystem", parent)
72        self.refresh()
73
74    def refresh(self):
75        self._children = set([])
76        for subsystem in self.get_root().nvmf_get_subsystems():
77            UINVMfSubsystem(subsystem, self)
78
79    def delete(self, subsystem_nqn):
80        self.get_root().nvmf_delete_subsystem(nqn=subsystem_nqn)
81
82    def ui_command_create(self, nqn, serial_number=None,
83                          max_namespaces=None, allow_any_host="false"):
84        """Create subsystem with given parameters.
85
86        Arguments:
87            nqn - Target nqn(ASCII).
88            serial_number - Example: 'SPDK00000000000001'.
89            max_namespaces - Optional parameter. Maximum number of namespaces allowed to added during
90                             active connection
91            allow_any_host - Optional parameter. Allow any host to connect (don't enforce allowed host NQN
92                             list)
93        """
94        allow_any_host = self.ui_eval_param(allow_any_host, "bool", False)
95        max_namespaces = self.ui_eval_param(max_namespaces, "number", 0)
96        self.get_root().create_nvmf_subsystem(nqn=nqn, serial_number=serial_number,
97                                              allow_any_host=allow_any_host,
98                                              max_namespaces=max_namespaces)
99
100    def ui_command_delete(self, subsystem_nqn):
101        """Delete subsystem with given nqn.
102
103        Arguments:
104            nqn_subsystem - Name of subsystem to delete
105        """
106        self.delete(subsystem_nqn)
107
108    def ui_command_delete_all(self):
109        """Delete all subsystems"""
110        rpc_messages = ""
111        for child in self._children:
112            try:
113                self.delete(child.subsystem.nqn)
114            except JSONRPCException as e:
115                rpc_messages += e.message
116        if rpc_messages:
117            raise JSONRPCException(rpc_messages)
118
119    def summary(self):
120        return "Subsystems: %s" % len(self.children), None
121
122
123class UINVMfSubsystem(UINode):
124    def __init__(self, subsystem, parent):
125        UINode.__init__(self, subsystem.nqn, parent)
126        self.subsystem = subsystem
127        self.refresh()
128
129    def refresh(self):
130        self._children = set([])
131        UINVMfSubsystemListeners(self.subsystem.listen_addresses, self)
132        UINVMfSubsystemHosts(self.subsystem.hosts, self)
133        if hasattr(self.subsystem, 'namespaces'):
134            UINVMfSubsystemNamespaces(self.subsystem.namespaces, self)
135
136    def refresh_node(self):
137        for subsystem in self.get_root().nvmf_get_subsystems():
138            if subsystem.nqn == self.subsystem.nqn:
139                self.subsystem = subsystem
140        self.refresh()
141
142    def ui_command_show_details(self):
143        self.shell.log.info(json.dumps(vars(self.lvs), indent=2))
144
145    def ui_command_allow_any_host(self, disable="false"):
146        """Disable or or enable allow_any_host flag.
147
148        Arguments:
149            disable - Optional parameter. If false then enable, if true disable
150        """
151        disable = self.ui_eval_param(disable, "bool", None)
152        self.get_root().nvmf_subsystem_allow_any_host(
153            nqn=self.subsystem.nqn, disable=disable)
154
155    def summary(self):
156        sn = None
157        if hasattr(self.subsystem, 'serial_number'):
158            sn = "sn=%s" % self.subsystem.serial_number
159        st = None
160        if hasattr(self.subsystem, 'subtype'):
161            st = "st=%s" % self.subsystem.subtype
162        allow_any_host = None
163        if self.subsystem.allow_any_host:
164            allow_any_host = "Allow any host"
165        info = ", ".join(filter(None, [sn, st, allow_any_host]))
166        return info, None
167
168
169class UINVMfSubsystemListeners(UINode):
170    def __init__(self, listen_addresses, parent):
171        UINode.__init__(self, "listen_addresses", parent)
172        self.listen_addresses = listen_addresses
173        self.refresh()
174
175    def refresh(self):
176        self._children = set([])
177        for address in self.listen_addresses:
178            UINVMfSubsystemListener(address, self)
179
180    def refresh_node(self):
181        for subsystem in self.get_root().nvmf_get_subsystems():
182            if subsystem.nqn == self.parent.subsystem.nqn:
183                self.listen_addresses = subsystem.listen_addresses
184        self.refresh()
185
186    def delete(self, trtype, traddr, trsvcid, adrfam=None):
187        self.get_root().nvmf_subsystem_remove_listener(
188            nqn=self.parent.subsystem.nqn, trtype=trtype,
189            traddr=traddr, trsvcid=trsvcid, adrfam=adrfam)
190
191    def ui_command_create(self, trtype, traddr, trsvcid, adrfam):
192        """Create address listener for subsystem.
193
194        Arguments:
195            trtype - NVMe-oF transport type: e.g., rdma.
196            traddr - NVMe-oF transport address: e.g., an ip address.
197            trsvcid - NVMe-oF transport service id: e.g., a port number.
198            adrfam - NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc.
199        """
200        self.get_root().nvmf_subsystem_add_listener(
201            nqn=self.parent.subsystem.nqn, trtype=trtype, traddr=traddr,
202            trsvcid=trsvcid, adrfam=adrfam)
203
204    def ui_command_delete(self, trtype, traddr, trsvcid, adrfam=None):
205        """Remove address listener for subsystem.
206
207        Arguments:
208            trtype - Transport type (RDMA)
209            traddr - NVMe-oF transport address: e.g., an ip address.
210            trsvcid - NVMe-oF transport service id: e.g., a port number.
211            adrfam - Optional argument. Address family ("IPv4", "IPv6", "IB" or "FC").
212        """
213        self.delete(trtype, traddr, trsvcid, adrfam)
214
215    def ui_command_delete_all(self):
216        """Remove all address listeners from subsystem."""
217        rpc_messages = ""
218        for la in self.listen_addresses:
219            try:
220                self.delete(la['trtype'], la['traddr'], la['trsvcid'], la['adrfam'])
221            except JSONRPCException as e:
222                rpc_messages += e.message
223        if rpc_messages:
224            raise JSONRPCException(rpc_messages)
225
226    def summary(self):
227        return "Addresses: %s" % len(self.listen_addresses), None
228
229
230class UINVMfSubsystemListener(UINode):
231    def __init__(self, address, parent):
232        UINode.__init__(self, "%s:%s" % (address['traddr'], address['trsvcid']),
233                        parent)
234        self.address = address
235
236    def summary(self):
237        return "%s" % self.address['trtype'], True
238
239
240class UINVMfSubsystemHosts(UINode):
241    def __init__(self, hosts, parent):
242        UINode.__init__(self, "hosts", parent)
243        self.hosts = hosts
244        self.refresh()
245
246    def refresh(self):
247        self._children = set([])
248        for host in self.hosts:
249            UINVMfSubsystemHost(host, self)
250
251    def refresh_node(self):
252        for subsystem in self.get_root().nvmf_get_subsystems():
253            if subsystem.nqn == self.parent.subsystem.nqn:
254                self.hosts = subsystem.hosts
255        self.refresh()
256
257    def delete(self, host):
258        self.get_root().nvmf_subsystem_remove_host(
259            nqn=self.parent.subsystem.nqn, host=host)
260
261    def ui_command_create(self, host):
262        """Add a host NQN to the list of allowed hosts.
263
264        Args:
265            host: Host NQN to add to the list of allowed host NQNs
266        """
267        self.get_root().nvmf_subsystem_add_host(
268            nqn=self.parent.subsystem.nqn, host=host)
269
270    def ui_command_delete(self, host):
271        """Delete host from subsystem.
272
273        Arguments:
274           host - NQN of host to remove.
275        """
276        self.delete(host)
277
278    def ui_command_delete_all(self):
279        """Delete host from subsystem"""
280        rpc_messages = ""
281        for host in self.hosts:
282            try:
283                self.delete(host['nqn'])
284            except JSONRPCException as e:
285                rpc_messages += e.message
286        if rpc_messages:
287            raise JSONRPCException(rpc_messages)
288
289    def summary(self):
290        return "Hosts: %s" % len(self.hosts), None
291
292
293class UINVMfSubsystemHost(UINode):
294    def __init__(self, host, parent):
295        UINode.__init__(self, "%s" % host['nqn'], parent)
296        self.host = host
297
298
299class UINVMfSubsystemNamespaces(UINode):
300    def __init__(self, namespaces, parent):
301        UINode.__init__(self, "namespaces", parent)
302        self.namespaces = namespaces
303        self.refresh()
304
305    def refresh(self):
306        self._children = set([])
307        for namespace in self.namespaces:
308            UINVMfSubsystemNamespace(namespace, self)
309
310    def refresh_node(self):
311        for subsystem in self.get_root().nvmf_get_subsystems():
312            if subsystem.nqn == self.parent.subsystem.nqn:
313                self.namespaces = subsystem.namespaces
314        self.refresh()
315
316    def delete(self, nsid):
317        self.get_root().nvmf_subsystem_remove_ns(
318            nqn=self.parent.subsystem.nqn, nsid=nsid)
319
320    def ui_command_create(self, bdev_name, nsid=None,
321                          nguid=None, eui64=None, uuid=None):
322        """Add a namespace to a subsystem.
323
324        Args:
325            bdev_name: Name of bdev to expose as a namespace.
326        Optional args:
327            nsid: Namespace ID.
328            nguid: 16-byte namespace globally unique identifier in hexadecimal.
329            eui64: 8-byte namespace EUI-64 in hexadecimal (e.g. "ABCDEF0123456789").
330            uuid: Namespace UUID.
331        """
332        nsid = self.ui_eval_param(nsid, "number", None)
333        self.get_root().nvmf_subsystem_add_ns(
334            nqn=self.parent.subsystem.nqn, bdev_name=bdev_name,
335            nsid=nsid, nguid=nguid, eui64=eui64, uuid=uuid)
336
337    def ui_command_delete(self, nsid):
338        """Delete namespace from subsystem.
339
340        Arguments:
341            nsid - Id of namespace to remove.
342        """
343        nsid = self.ui_eval_param(nsid, "number", None)
344        self.delete(nsid)
345
346    def ui_command_delete_all(self):
347        """Delete all namespaces from subsystem."""
348        rpc_messages = ""
349        for namespace in self.namespaces:
350            try:
351                self.delete(namespace['nsid'])
352            except JSONRPCException as e:
353                rpc_messages += e.message
354        if rpc_messages:
355            raise JSONRPCException(rpc_messages)
356
357    def summary(self):
358        return "Namespaces: %s" % len(self.namespaces), None
359
360
361class UINVMfSubsystemNamespace(UINode):
362    def __init__(self, namespace, parent):
363        UINode.__init__(self, namespace['bdev_name'], parent)
364        self.namespace = namespace
365
366    def summary(self):
367        info = ", ".join([self.namespace['name'], str(self.namespace['nsid'])])
368        return info, None
369
370
371class UINVMfReferral(UINode):
372    def __init__(self, address, secure_channel, parent):
373        UINode.__init__(self, "%s:%s" % (address['traddr'], address['trsvcid']),
374                        parent)
375        self.address = address
376        self.secure_channel = secure_channel
377        self.refresh()
378
379    def refresh(self):
380        self._children = set([])
381
382    def refresh_node(self):
383        self.refresh()
384
385    def summary(self):
386        info = ", ".join([self.address['trtype'], "Secure channel"]) if self.secure_channel \
387            else self.address['trtype']
388        return info, None
389
390
391class UINVMfReferrals(UINode):
392    def __init__(self, parent):
393        UINode.__init__(self, "referral", parent)
394        self.refresh()
395
396    def refresh(self):
397        self._children = set([])
398        for referral in self.get_root().nvmf_discovery_get_referrals():
399            UINVMfReferral(referral.address, referral.secure_channel, self)
400
401    def delete(self, trtype, traddr, trsvcid, adrfam=None):
402        self.get_root().nvmf_discovery_remove_referral(
403            trtype=trtype, traddr=traddr, trsvcid=trsvcid, adrfam=adrfam)
404
405    def ui_command_create(self, trtype, traddr, trsvcid, adrfam, secure_channel=False):
406        """Create a referral to a discovery subsystem.
407
408        Arguments:
409            trtype - NVMe-oF transport type: e.g., rdma.
410            traddr - NVMe-oF transport address: e.g., an ip address.
411            trsvcid - NVMe-oF transport service id: e.g., a port number.
412            adrfam - NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc.
413            secure_channel - The connection to that discovery subsystem requires a secure channel
414            Default: False
415        """
416        self.get_root().nvmf_discovery_add_referral(
417            trtype=trtype, traddr=traddr,
418            trsvcid=trsvcid, adrfam=adrfam, secure_channel=bool(secure_channel))
419
420    def ui_command_delete(self, trtype, traddr, trsvcid, adrfam=None):
421        """Remove a referral to a discovery subsystem.
422
423        Arguments:
424            trtype - NVMe-oF transport type: e.g., rdma.
425            traddr - NVMe-oF transport address: e.g., an ip address.
426            trsvcid - NVMe-oF transport service id: e.g., a port number.
427            adrfam - Optional argument. NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc.
428        """
429        self.delete(trtype, traddr, trsvcid, adrfam)
430
431    def summary(self):
432        return "Referrals: %s" % len(self.children), None
433