]>
git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/scripts/spdkcli/ui_root.py
1 from .ui_node
import UINode
, UIBdevs
, UILvolStores
, UIVhosts
2 from .ui_node_nvmf
import UINVMf
3 from .ui_node_iscsi
import UIISCSI
6 from functools
import wraps
11 Root node for CLI menu tree structure. Refreshes running config on startup.
13 def __init__(self
, client
, shell
):
14 UINode
.__init
__(self
, "/", shell
=shell
)
15 self
.current_bdevs
= []
16 self
.current_lvol_stores
= []
17 self
.current_vhost_ctrls
= []
18 self
.current_nvmf_transports
= []
19 self
.current_nvmf_subsystems
= []
20 self
.set_rpc_target(client
)
22 self
.is_init
= self
.check_init()
26 self
.methods
= self
.rpc_get_methods(current
=True)
27 if self
.is_init
is False:
28 methods
= "\n".join(self
.methods
)
29 self
.shell
.log
.warning("SPDK Application is not yet initialized.\n"
30 "Please initialize subsystems with framework_start_init command.\n"
31 "List of available commands in current state:\n"
34 # Pass because we'd like to build main tree structure for "ls"
35 # even if state is uninitialized
38 self
._children
= set([])
41 if self
.has_subsystem("vhost"):
43 if self
.has_subsystem("nvmf"):
45 if self
.has_subsystem("iscsi"):
48 def set_rpc_target(self
, client
):
51 def print_array(self
, a
):
55 # For any configuration calls (create, delete, construct, etc.)
56 # Check if verbose option is to be used and set appropriately.
57 # Do not use for "get_*" methods so that output is not
59 def w(self
, **kwargs
):
60 self
.client
.log_set_level("INFO" if self
.verbose
else "ERROR")
62 self
.client
.log_set_level("ERROR")
66 def is_method_available(f
):
67 # Check if method f is available for given spdk target
68 def w(self
, **kwargs
):
69 if f
.__name
__ in self
.methods
:
72 # If given method is not avaialble return empty list
73 # similar to real get_* like rpc
77 def ui_command_framework_start_init(self
):
78 if rpc
.framework_start_init(self
.client
):
82 def ui_command_load_config(self
, filename
):
83 with
open(filename
, "r") as fd
:
84 rpc
.load_config(self
.client
, fd
)
86 def ui_command_load_subsystem_config(self
, filename
):
87 with
open(filename
, "r") as fd
:
88 rpc
.load_subsystem_config(self
.client
, fd
)
90 def ui_command_save_config(self
, filename
, indent
=2):
91 with
open(filename
, "w") as fd
:
92 rpc
.save_config(self
.client
, fd
, indent
)
94 def ui_command_save_subsystem_config(self
, filename
, subsystem
, indent
=2):
95 with
open(filename
, "w") as fd
:
96 rpc
.save_subsystem_config(self
.client
, fd
, indent
, subsystem
)
98 def rpc_get_methods(self
, current
=False):
99 return rpc
.rpc_get_methods(self
.client
, current
=current
)
101 def check_init(self
):
102 return "framework_start_init" not in self
.rpc_get_methods(current
=True)
104 def bdev_get_bdevs(self
, bdev_type
):
106 self
.current_bdevs
= rpc
.bdev
.bdev_get_bdevs(self
.client
)
107 # Following replace needs to be done in order for some of the bdev
108 # listings to work: logical volumes, split disk.
109 # For example logical volumes: listing in menu is "Logical_Volume"
110 # (cannot have space), but the product name in SPDK is "Logical Volume"
111 bdev_type
= bdev_type
.replace("_", " ")
112 for bdev
in [x
for x
in self
.current_bdevs
if bdev_type
in x
["product_name"].lower()]:
116 def bdev_get_iostat(self
, **kwargs
):
117 return rpc
.bdev
.bdev_get_iostat(self
.client
, **kwargs
)
120 def bdev_split_create(self
, **kwargs
):
121 response
= rpc
.bdev
.bdev_split_create(self
.client
, **kwargs
)
122 return self
.print_array(response
)
125 def bdev_split_delete(self
, **kwargs
):
126 rpc
.bdev
.bdev_split_delete(self
.client
, **kwargs
)
129 def create_malloc_bdev(self
, **kwargs
):
130 response
= rpc
.bdev
.bdev_malloc_create(self
.client
, **kwargs
)
134 def bdev_malloc_delete(self
, **kwargs
):
135 rpc
.bdev
.bdev_malloc_delete(self
.client
, **kwargs
)
138 def create_iscsi_bdev(self
, **kwargs
):
139 response
= rpc
.bdev
.bdev_iscsi_create(self
.client
, **kwargs
)
143 def bdev_iscsi_delete(self
, **kwargs
):
144 rpc
.bdev
.bdev_iscsi_delete(self
.client
, **kwargs
)
147 def bdev_aio_create(self
, **kwargs
):
148 response
= rpc
.bdev
.bdev_aio_create(self
.client
, **kwargs
)
152 def bdev_aio_delete(self
, **kwargs
):
153 rpc
.bdev
.bdev_aio_delete(self
.client
, **kwargs
)
156 def create_lvol_bdev(self
, **kwargs
):
157 response
= rpc
.lvol
.bdev_lvol_create(self
.client
, **kwargs
)
161 def bdev_lvol_delete(self
, **kwargs
):
162 response
= rpc
.lvol
.bdev_lvol_delete(self
.client
, **kwargs
)
166 def create_nvme_bdev(self
, **kwargs
):
167 response
= rpc
.bdev
.bdev_nvme_attach_controller(self
.client
, **kwargs
)
171 def bdev_nvme_detach_controller(self
, **kwargs
):
172 rpc
.bdev
.bdev_nvme_detach_controller(self
.client
, **kwargs
)
175 def bdev_null_create(self
, **kwargs
):
176 response
= rpc
.bdev
.bdev_null_create(self
.client
, **kwargs
)
180 def bdev_null_delete(self
, **kwargs
):
181 rpc
.bdev
.bdev_null_delete(self
.client
, **kwargs
)
184 def create_error_bdev(self
, **kwargs
):
185 response
= rpc
.bdev
.bdev_error_create(self
.client
, **kwargs
)
188 def bdev_error_delete(self
, **kwargs
):
189 rpc
.bdev
.bdev_error_delete(self
.client
, **kwargs
)
193 def bdev_lvol_get_lvstores(self
):
195 self
.current_lvol_stores
= rpc
.lvol
.bdev_lvol_get_lvstores(self
.client
)
196 for lvs
in self
.current_lvol_stores
:
200 def bdev_lvol_create_lvstore(self
, **kwargs
):
201 response
= rpc
.lvol
.bdev_lvol_create_lvstore(self
.client
, **kwargs
)
205 def bdev_lvol_delete_lvstore(self
, **kwargs
):
206 rpc
.lvol
.bdev_lvol_delete_lvstore(self
.client
, **kwargs
)
209 def bdev_pmem_create_pool(self
, **kwargs
):
210 response
= rpc
.pmem
.bdev_pmem_create_pool(self
.client
, **kwargs
)
214 def bdev_pmem_delete_pool(self
, **kwargs
):
215 rpc
.pmem
.bdev_pmem_delete_pool(self
.client
, **kwargs
)
218 def bdev_pmem_get_pool_info(self
, **kwargs
):
219 response
= rpc
.pmem
.bdev_pmem_get_pool_info(self
.client
, **kwargs
)
223 def bdev_pmem_create(self
, **kwargs
):
224 response
= rpc
.bdev
.bdev_pmem_create(self
.client
, **kwargs
)
228 def bdev_pmem_delete(self
, **kwargs
):
229 response
= rpc
.bdev
.bdev_pmem_delete(self
.client
, **kwargs
)
233 def create_rbd_bdev(self
, **kwargs
):
234 response
= rpc
.bdev
.bdev_rbd_create(self
.client
, **kwargs
)
238 def bdev_rbd_delete(self
, **kwargs
):
239 response
= rpc
.bdev
.bdev_rbd_delete(self
.client
, **kwargs
)
243 def create_virtio_dev(self
, **kwargs
):
244 response
= rpc
.vhost
.bdev_virtio_attach_controller(self
.client
, **kwargs
)
245 return self
.print_array(response
)
248 def bdev_virtio_detach_controller(self
, **kwargs
):
249 response
= rpc
.vhost
.bdev_virtio_detach_controller(self
.client
, **kwargs
)
253 def bdev_raid_create(self
, **kwargs
):
254 rpc
.bdev
.bdev_raid_create(self
.client
, **kwargs
)
257 def bdev_raid_delete(self
, **kwargs
):
258 rpc
.bdev
.bdev_raid_delete(self
.client
, **kwargs
)
262 def bdev_virtio_scsi_get_devices(self
):
264 for bdev
in rpc
.vhost
.bdev_virtio_scsi_get_devices(self
.client
):
268 def list_vhost_ctrls(self
):
270 self
.current_vhost_ctrls
= rpc
.vhost
.vhost_get_controllers(self
.client
)
274 def vhost_get_controllers(self
, ctrlr_type
):
276 self
.list_vhost_ctrls()
277 for ctrlr
in [x
for x
in self
.current_vhost_ctrls
if ctrlr_type
in list(x
["backend_specific"].keys())]:
278 yield VhostCtrlr(ctrlr
)
281 def vhost_delete_controller(self
, **kwargs
):
282 rpc
.vhost
.vhost_delete_controller(self
.client
, **kwargs
)
285 def vhost_create_scsi_controller(self
, **kwargs
):
286 rpc
.vhost
.vhost_create_scsi_controller(self
.client
, **kwargs
)
289 def vhost_create_blk_controller(self
, **kwargs
):
290 rpc
.vhost
.vhost_create_blk_controller(self
.client
, **kwargs
)
293 def vhost_scsi_controller_remove_target(self
, **kwargs
):
294 rpc
.vhost
.vhost_scsi_controller_remove_target(self
.client
, **kwargs
)
297 def vhost_scsi_controller_add_target(self
, **kwargs
):
298 rpc
.vhost
.vhost_scsi_controller_add_target(self
.client
, **kwargs
)
300 def vhost_controller_set_coalescing(self
, **kwargs
):
301 rpc
.vhost
.vhost_controller_set_coalescing(self
.client
, **kwargs
)
304 def create_nvmf_transport(self
, **kwargs
):
305 rpc
.nvmf
.nvmf_create_transport(self
.client
, **kwargs
)
307 def list_nvmf_transports(self
):
309 self
.current_nvmf_transports
= rpc
.nvmf
.nvmf_get_transports(self
.client
)
313 def nvmf_get_transports(self
):
315 self
.list_nvmf_transports()
316 for transport
in self
.current_nvmf_transports
:
317 yield NvmfTransport(transport
)
319 def list_nvmf_subsystems(self
):
321 self
.current_nvmf_subsystems
= rpc
.nvmf
.nvmf_get_subsystems(self
.client
)
325 def nvmf_get_subsystems(self
):
327 self
.list_nvmf_subsystems()
328 for subsystem
in self
.current_nvmf_subsystems
:
329 yield NvmfSubsystem(subsystem
)
332 def create_nvmf_subsystem(self
, **kwargs
):
333 rpc
.nvmf
.nvmf_create_subsystem(self
.client
, **kwargs
)
336 def nvmf_delete_subsystem(self
, **kwargs
):
337 rpc
.nvmf
.nvmf_delete_subsystem(self
.client
, **kwargs
)
340 def nvmf_subsystem_add_listener(self
, **kwargs
):
341 rpc
.nvmf
.nvmf_subsystem_add_listener(self
.client
, **kwargs
)
344 def nvmf_subsystem_remove_listener(self
, **kwargs
):
345 rpc
.nvmf
.nvmf_subsystem_remove_listener(self
.client
, **kwargs
)
348 def nvmf_subsystem_add_host(self
, **kwargs
):
349 rpc
.nvmf
.nvmf_subsystem_add_host(self
.client
, **kwargs
)
352 def nvmf_subsystem_remove_host(self
, **kwargs
):
353 rpc
.nvmf
.nvmf_subsystem_remove_host(self
.client
, **kwargs
)
356 def nvmf_subsystem_allow_any_host(self
, **kwargs
):
357 rpc
.nvmf
.nvmf_subsystem_allow_any_host(self
.client
, **kwargs
)
360 def nvmf_subsystem_add_ns(self
, **kwargs
):
361 rpc
.nvmf
.nvmf_subsystem_add_ns(self
.client
, **kwargs
)
364 def nvmf_subsystem_remove_ns(self
, **kwargs
):
365 rpc
.nvmf
.nvmf_subsystem_remove_ns(self
.client
, **kwargs
)
368 def nvmf_subsystem_allow_any_host(self
, **kwargs
):
369 rpc
.nvmf
.nvmf_subsystem_allow_any_host(self
.client
, **kwargs
)
373 def scsi_get_devices(self
):
375 for device
in rpc
.iscsi
.scsi_get_devices(self
.client
):
376 yield ScsiObj(device
)
380 def iscsi_get_target_nodes(self
):
382 for tg
in rpc
.iscsi
.iscsi_get_target_nodes(self
.client
):
386 def iscsi_create_target_node(self
, **kwargs
):
387 rpc
.iscsi
.iscsi_create_target_node(self
.client
, **kwargs
)
390 def iscsi_delete_target_node(self
, **kwargs
):
391 rpc
.iscsi
.iscsi_delete_target_node(self
.client
, **kwargs
)
395 def iscsi_get_portal_groups(self
):
397 for pg
in rpc
.iscsi
.iscsi_get_portal_groups(self
.client
):
402 def iscsi_get_initiator_groups(self
):
404 for ig
in rpc
.iscsi
.iscsi_get_initiator_groups(self
.client
):
408 def construct_portal_group(self
, **kwargs
):
409 rpc
.iscsi
.iscsi_create_portal_group(self
.client
, **kwargs
)
412 def iscsi_delete_portal_group(self
, **kwargs
):
413 rpc
.iscsi
.iscsi_delete_portal_group(self
.client
, **kwargs
)
416 def construct_initiator_group(self
, **kwargs
):
417 rpc
.iscsi
.iscsi_create_initiator_group(self
.client
, **kwargs
)
420 def iscsi_delete_initiator_group(self
, **kwargs
):
421 rpc
.iscsi
.iscsi_delete_initiator_group(self
.client
, **kwargs
)
425 def iscsi_get_connections(self
, **kwargs
):
427 for ic
in rpc
.iscsi
.iscsi_get_connections(self
.client
, **kwargs
):
431 def iscsi_initiator_group_add_initiators(self
, **kwargs
):
432 rpc
.iscsi
.iscsi_initiator_group_add_initiators(self
.client
, **kwargs
)
435 def iscsi_initiator_group_remove_initiators(self
, **kwargs
):
436 rpc
.iscsi
.iscsi_initiator_group_remove_initiators(self
.client
, **kwargs
)
439 def iscsi_target_node_add_pg_ig_maps(self
, **kwargs
):
440 rpc
.iscsi
.iscsi_target_node_add_pg_ig_maps(self
.client
, **kwargs
)
443 def iscsi_target_node_remove_pg_ig_maps(self
, **kwargs
):
444 rpc
.iscsi
.iscsi_target_node_remove_pg_ig_maps(self
.client
, **kwargs
)
447 def iscsi_auth_group_add_secret(self
, **kwargs
):
448 rpc
.iscsi
.iscsi_auth_group_add_secret(self
.client
, **kwargs
)
451 def iscsi_auth_group_remove_secret(self
, **kwargs
):
452 rpc
.iscsi
.iscsi_auth_group_remove_secret(self
.client
, **kwargs
)
456 def iscsi_get_auth_groups(self
, **kwargs
):
457 return rpc
.iscsi
.iscsi_get_auth_groups(self
.client
, **kwargs
)
460 def iscsi_create_auth_group(self
, **kwargs
):
461 rpc
.iscsi
.iscsi_create_auth_group(self
.client
, **kwargs
)
464 def iscsi_delete_auth_group(self
, **kwargs
):
465 rpc
.iscsi
.iscsi_delete_auth_group(self
.client
, **kwargs
)
468 def iscsi_target_node_set_auth(self
, **kwargs
):
469 rpc
.iscsi
.iscsi_target_node_set_auth(self
.client
, **kwargs
)
472 def iscsi_target_node_add_lun(self
, **kwargs
):
473 rpc
.iscsi
.iscsi_target_node_add_lun(self
.client
, **kwargs
)
476 def iscsi_set_discovery_auth(self
, **kwargs
):
477 rpc
.iscsi
.iscsi_set_discovery_auth(self
.client
, **kwargs
)
481 def iscsi_get_options(self
, **kwargs
):
482 return rpc
.iscsi
.iscsi_get_options(self
.client
, **kwargs
)
484 def has_subsystem(self
, subsystem
):
485 for system
in rpc
.subsystem
.framework_get_subsystems(self
.client
):
486 if subsystem
.lower() == system
["subsystem"].lower():
492 def __init__(self
, bdev_info
):
494 All class attributes are set based on what information is received
495 from bdev_get_bdevs RPC call.
496 # TODO: Document in docstring parameters which describe bdevs.
497 # TODO: Possible improvement: JSON schema might be used here in future
499 for i
in list(bdev_info
.keys()):
500 setattr(self
, i
, bdev_info
[i
])
503 class LvolStore(object):
504 def __init__(self
, lvs_info
):
506 All class attributes are set based on what information is received
507 from bdev_get_bdevs RPC call.
508 # TODO: Document in docstring parameters which describe bdevs.
509 # TODO: Possible improvement: JSON schema might be used here in future
511 for i
in list(lvs_info
.keys()):
512 setattr(self
, i
, lvs_info
[i
])
515 class VhostCtrlr(object):
516 def __init__(self
, ctrlr_info
):
518 All class attributes are set based on what information is received
519 from vhost_get_controllers RPC call.
520 # TODO: Document in docstring parameters which describe bdevs.
521 # TODO: Possible improvement: JSON schema might be used here in future
523 for i
in list(ctrlr_info
.keys()):
524 setattr(self
, i
, ctrlr_info
[i
])
527 class NvmfTransport(object):
528 def __init__(self
, transport_info
):
530 All class attributes are set based on what information is received
531 from get_nvmf_transport RPC call.
532 # TODO: Document in docstring parameters which describe bdevs.
533 # TODO: Possible improvement: JSON schema might be used here in future
535 for i
in transport_info
.keys():
536 setattr(self
, i
, transport_info
[i
])
539 class NvmfSubsystem(object):
540 def __init__(self
, subsystem_info
):
542 All class attributes are set based on what information is received
543 from get_nvmf_subsystem RPC call.
544 # TODO: Document in docstring parameters which describe bdevs.
545 # TODO: Possible improvement: JSON schema might be used here in future
547 for i
in subsystem_info
.keys():
548 setattr(self
, i
, subsystem_info
[i
])
551 class ScsiObj(object):
552 def __init__(self
, device_info
):
554 All class attributes are set based on what information is received
555 from iscsi related RPC calls.
556 # TODO: Document in docstring parameters which describe bdevs.
557 # TODO: Possible improvement: JSON schema might be used here in future
559 for i
in device_info
.keys():
560 setattr(self
, i
, device_info
[i
])