]>
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 start_subsystem_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
.set_log_level("INFO" if self
.verbose
else "ERROR")
62 self
.client
.set_log_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_start_subsystem_init(self
):
78 if rpc
.start_subsystem_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 "start_subsystem_init" not in self
.rpc_get_methods(current
=True)
104 def get_bdevs(self
, bdev_type
):
106 self
.current_bdevs
= rpc
.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 get_bdevs_iostat(self
, **kwargs
):
117 return rpc
.bdev
.get_bdevs_iostat(self
.client
, **kwargs
)
120 def split_bdev(self
, **kwargs
):
121 response
= rpc
.bdev
.construct_split_vbdev(self
.client
, **kwargs
)
122 return self
.print_array(response
)
125 def destruct_split_bdev(self
, **kwargs
):
126 rpc
.bdev
.destruct_split_vbdev(self
.client
, **kwargs
)
129 def create_malloc_bdev(self
, **kwargs
):
130 response
= rpc
.bdev
.construct_malloc_bdev(self
.client
, **kwargs
)
134 def delete_malloc_bdev(self
, **kwargs
):
135 rpc
.bdev
.delete_malloc_bdev(self
.client
, **kwargs
)
138 def create_iscsi_bdev(self
, **kwargs
):
139 response
= rpc
.bdev
.construct_iscsi_bdev(self
.client
, **kwargs
)
143 def delete_iscsi_bdev(self
, **kwargs
):
144 rpc
.bdev
.delete_iscsi_bdev(self
.client
, **kwargs
)
147 def create_aio_bdev(self
, **kwargs
):
148 response
= rpc
.bdev
.construct_aio_bdev(self
.client
, **kwargs
)
152 def delete_aio_bdev(self
, **kwargs
):
153 rpc
.bdev
.delete_aio_bdev(self
.client
, **kwargs
)
156 def create_lvol_bdev(self
, **kwargs
):
157 response
= rpc
.lvol
.construct_lvol_bdev(self
.client
, **kwargs
)
161 def destroy_lvol_bdev(self
, **kwargs
):
162 response
= rpc
.lvol
.destroy_lvol_bdev(self
.client
, **kwargs
)
166 def create_nvme_bdev(self
, **kwargs
):
167 response
= rpc
.bdev
.construct_nvme_bdev(self
.client
, **kwargs
)
171 def delete_nvme_controller(self
, **kwargs
):
172 rpc
.bdev
.delete_nvme_controller(self
.client
, **kwargs
)
175 def create_null_bdev(self
, **kwargs
):
176 response
= rpc
.bdev
.construct_null_bdev(self
.client
, **kwargs
)
180 def delete_null_bdev(self
, **kwargs
):
181 rpc
.bdev
.delete_null_bdev(self
.client
, **kwargs
)
184 def create_error_bdev(self
, **kwargs
):
185 response
= rpc
.bdev
.construct_error_bdev(self
.client
, **kwargs
)
188 def delete_error_bdev(self
, **kwargs
):
189 rpc
.bdev
.delete_error_bdev(self
.client
, **kwargs
)
193 def get_lvol_stores(self
):
195 self
.current_lvol_stores
= rpc
.lvol
.get_lvol_stores(self
.client
)
196 for lvs
in self
.current_lvol_stores
:
200 def create_lvol_store(self
, **kwargs
):
201 response
= rpc
.lvol
.construct_lvol_store(self
.client
, **kwargs
)
205 def delete_lvol_store(self
, **kwargs
):
206 rpc
.lvol
.destroy_lvol_store(self
.client
, **kwargs
)
209 def create_pmem_pool(self
, **kwargs
):
210 response
= rpc
.pmem
.create_pmem_pool(self
.client
, **kwargs
)
214 def delete_pmem_pool(self
, **kwargs
):
215 rpc
.pmem
.delete_pmem_pool(self
.client
, **kwargs
)
218 def create_pmem_bdev(self
, **kwargs
):
219 response
= rpc
.bdev
.construct_pmem_bdev(self
.client
, **kwargs
)
223 def delete_pmem_bdev(self
, **kwargs
):
224 response
= rpc
.bdev
.delete_pmem_bdev(self
.client
, **kwargs
)
228 def create_rbd_bdev(self
, **kwargs
):
229 response
= rpc
.bdev
.construct_rbd_bdev(self
.client
, **kwargs
)
233 def delete_rbd_bdev(self
, **kwargs
):
234 response
= rpc
.bdev
.delete_rbd_bdev(self
.client
, **kwargs
)
238 def create_virtio_dev(self
, **kwargs
):
239 response
= rpc
.vhost
.construct_virtio_dev(self
.client
, **kwargs
)
240 return self
.print_array(response
)
243 def remove_virtio_bdev(self
, **kwargs
):
244 response
= rpc
.vhost
.remove_virtio_bdev(self
.client
, **kwargs
)
248 def construct_raid_bdev(self
, **kwargs
):
249 rpc
.bdev
.construct_raid_bdev(self
.client
, **kwargs
)
252 def destroy_raid_bdev(self
, **kwargs
):
253 rpc
.bdev
.destroy_raid_bdev(self
.client
, **kwargs
)
257 def get_virtio_scsi_devs(self
):
259 for bdev
in rpc
.vhost
.get_virtio_scsi_devs(self
.client
):
263 def list_vhost_ctrls(self
):
265 self
.current_vhost_ctrls
= rpc
.vhost
.get_vhost_controllers(self
.client
)
269 def get_vhost_controllers(self
, ctrlr_type
):
271 self
.list_vhost_ctrls()
272 for ctrlr
in [x
for x
in self
.current_vhost_ctrls
if ctrlr_type
in list(x
["backend_specific"].keys())]:
273 yield VhostCtrlr(ctrlr
)
276 def remove_vhost_controller(self
, **kwargs
):
277 rpc
.vhost
.remove_vhost_controller(self
.client
, **kwargs
)
280 def create_vhost_scsi_controller(self
, **kwargs
):
281 rpc
.vhost
.construct_vhost_scsi_controller(self
.client
, **kwargs
)
284 def create_vhost_blk_controller(self
, **kwargs
):
285 rpc
.vhost
.construct_vhost_blk_controller(self
.client
, **kwargs
)
288 def remove_vhost_scsi_target(self
, **kwargs
):
289 rpc
.vhost
.remove_vhost_scsi_target(self
.client
, **kwargs
)
292 def add_vhost_scsi_lun(self
, **kwargs
):
293 rpc
.vhost
.add_vhost_scsi_lun(self
.client
, **kwargs
)
295 def set_vhost_controller_coalescing(self
, **kwargs
):
296 rpc
.vhost
.set_vhost_controller_coalescing(self
.client
, **kwargs
)
299 def create_nvmf_transport(self
, **kwargs
):
300 rpc
.nvmf
.nvmf_create_transport(self
.client
, **kwargs
)
302 def list_nvmf_transports(self
):
304 self
.current_nvmf_transports
= rpc
.nvmf
.get_nvmf_transports(self
.client
)
308 def get_nvmf_transports(self
):
310 self
.list_nvmf_transports()
311 for transport
in self
.current_nvmf_transports
:
312 yield NvmfTransport(transport
)
314 def list_nvmf_subsystems(self
):
316 self
.current_nvmf_subsystems
= rpc
.nvmf
.get_nvmf_subsystems(self
.client
)
320 def get_nvmf_subsystems(self
):
322 self
.list_nvmf_subsystems()
323 for subsystem
in self
.current_nvmf_subsystems
:
324 yield NvmfSubsystem(subsystem
)
327 def create_nvmf_subsystem(self
, **kwargs
):
328 rpc
.nvmf
.nvmf_subsystem_create(self
.client
, **kwargs
)
331 def delete_nvmf_subsystem(self
, **kwargs
):
332 rpc
.nvmf
.delete_nvmf_subsystem(self
.client
, **kwargs
)
335 def nvmf_subsystem_add_listener(self
, **kwargs
):
336 rpc
.nvmf
.nvmf_subsystem_add_listener(self
.client
, **kwargs
)
339 def nvmf_subsystem_remove_listener(self
, **kwargs
):
340 rpc
.nvmf
.nvmf_subsystem_remove_listener(self
.client
, **kwargs
)
343 def nvmf_subsystem_add_host(self
, **kwargs
):
344 rpc
.nvmf
.nvmf_subsystem_add_host(self
.client
, **kwargs
)
347 def nvmf_subsystem_remove_host(self
, **kwargs
):
348 rpc
.nvmf
.nvmf_subsystem_remove_host(self
.client
, **kwargs
)
351 def nvmf_subsystem_allow_any_host(self
, **kwargs
):
352 rpc
.nvmf
.nvmf_subsystem_allow_any_host(self
.client
, **kwargs
)
355 def nvmf_subsystem_add_ns(self
, **kwargs
):
356 rpc
.nvmf
.nvmf_subsystem_add_ns(self
.client
, **kwargs
)
359 def nvmf_subsystem_remove_ns(self
, **kwargs
):
360 rpc
.nvmf
.nvmf_subsystem_remove_ns(self
.client
, **kwargs
)
363 def nvmf_subsystem_allow_any_host(self
, **kwargs
):
364 rpc
.nvmf
.nvmf_subsystem_allow_any_host(self
.client
, **kwargs
)
368 def get_scsi_devices(self
):
370 for device
in rpc
.iscsi
.get_scsi_devices(self
.client
):
371 yield ScsiObj(device
)
375 def get_target_nodes(self
):
377 for tg
in rpc
.iscsi
.get_target_nodes(self
.client
):
381 def construct_target_node(self
, **kwargs
):
382 rpc
.iscsi
.construct_target_node(self
.client
, **kwargs
)
385 def delete_target_node(self
, **kwargs
):
386 rpc
.iscsi
.delete_target_node(self
.client
, **kwargs
)
390 def get_portal_groups(self
):
392 for pg
in rpc
.iscsi
.get_portal_groups(self
.client
):
397 def get_initiator_groups(self
):
399 for ig
in rpc
.iscsi
.get_initiator_groups(self
.client
):
403 def construct_portal_group(self
, **kwargs
):
404 rpc
.iscsi
.add_portal_group(self
.client
, **kwargs
)
407 def delete_portal_group(self
, **kwargs
):
408 rpc
.iscsi
.delete_portal_group(self
.client
, **kwargs
)
411 def construct_initiator_group(self
, **kwargs
):
412 rpc
.iscsi
.add_initiator_group(self
.client
, **kwargs
)
415 def delete_initiator_group(self
, **kwargs
):
416 rpc
.iscsi
.delete_initiator_group(self
.client
, **kwargs
)
420 def get_iscsi_connections(self
, **kwargs
):
422 for ic
in rpc
.iscsi
.get_iscsi_connections(self
.client
, **kwargs
):
426 def add_initiators_to_initiator_group(self
, **kwargs
):
427 rpc
.iscsi
.add_initiators_to_initiator_group(self
.client
, **kwargs
)
430 def delete_initiators_from_initiator_group(self
, **kwargs
):
431 rpc
.iscsi
.delete_initiators_from_initiator_group(self
.client
, **kwargs
)
434 def add_pg_ig_maps(self
, **kwargs
):
435 rpc
.iscsi
.add_pg_ig_maps(self
.client
, **kwargs
)
438 def delete_pg_ig_maps(self
, **kwargs
):
439 rpc
.iscsi
.delete_pg_ig_maps(self
.client
, **kwargs
)
442 def add_secret_to_iscsi_auth_group(self
, **kwargs
):
443 rpc
.iscsi
.add_secret_to_iscsi_auth_group(self
.client
, **kwargs
)
446 def delete_secret_from_iscsi_auth_group(self
, **kwargs
):
447 rpc
.iscsi
.delete_secret_from_iscsi_auth_group(self
.client
, **kwargs
)
451 def get_iscsi_auth_groups(self
, **kwargs
):
452 return rpc
.iscsi
.get_iscsi_auth_groups(self
.client
, **kwargs
)
455 def add_iscsi_auth_group(self
, **kwargs
):
456 rpc
.iscsi
.add_iscsi_auth_group(self
.client
, **kwargs
)
459 def delete_iscsi_auth_group(self
, **kwargs
):
460 rpc
.iscsi
.delete_iscsi_auth_group(self
.client
, **kwargs
)
463 def set_iscsi_target_node_auth(self
, **kwargs
):
464 rpc
.iscsi
.set_iscsi_target_node_auth(self
.client
, **kwargs
)
467 def target_node_add_lun(self
, **kwargs
):
468 rpc
.iscsi
.target_node_add_lun(self
.client
, **kwargs
)
471 def set_iscsi_discovery_auth(self
, **kwargs
):
472 rpc
.iscsi
.set_iscsi_discovery_auth(self
.client
, **kwargs
)
476 def get_iscsi_global_params(self
, **kwargs
):
477 return rpc
.iscsi
.get_iscsi_global_params(self
.client
, **kwargs
)
479 def has_subsystem(self
, subsystem
):
480 for system
in rpc
.subsystem
.get_subsystems(self
.client
):
481 if subsystem
.lower() == system
["subsystem"].lower():
487 def __init__(self
, bdev_info
):
489 All class attributes are set based on what information is received
490 from get_bdevs RPC call.
491 # TODO: Document in docstring parameters which describe bdevs.
492 # TODO: Possible improvement: JSON schema might be used here in future
494 for i
in list(bdev_info
.keys()):
495 setattr(self
, i
, bdev_info
[i
])
498 class LvolStore(object):
499 def __init__(self
, lvs_info
):
501 All class attributes are set based on what information is received
502 from get_bdevs RPC call.
503 # TODO: Document in docstring parameters which describe bdevs.
504 # TODO: Possible improvement: JSON schema might be used here in future
506 for i
in list(lvs_info
.keys()):
507 setattr(self
, i
, lvs_info
[i
])
510 class VhostCtrlr(object):
511 def __init__(self
, ctrlr_info
):
513 All class attributes are set based on what information is received
514 from get_vhost_controllers RPC call.
515 # TODO: Document in docstring parameters which describe bdevs.
516 # TODO: Possible improvement: JSON schema might be used here in future
518 for i
in list(ctrlr_info
.keys()):
519 setattr(self
, i
, ctrlr_info
[i
])
522 class NvmfTransport(object):
523 def __init__(self
, transport_info
):
525 All class attributes are set based on what information is received
526 from get_nvmf_transport RPC call.
527 # TODO: Document in docstring parameters which describe bdevs.
528 # TODO: Possible improvement: JSON schema might be used here in future
530 for i
in transport_info
.keys():
531 setattr(self
, i
, transport_info
[i
])
534 class NvmfSubsystem(object):
535 def __init__(self
, subsystem_info
):
537 All class attributes are set based on what information is received
538 from get_nvmf_subsystem RPC call.
539 # TODO: Document in docstring parameters which describe bdevs.
540 # TODO: Possible improvement: JSON schema might be used here in future
542 for i
in subsystem_info
.keys():
543 setattr(self
, i
, subsystem_info
[i
])
546 class ScsiObj(object):
547 def __init__(self
, device_info
):
549 All class attributes are set based on what information is received
550 from iscsi related RPC calls.
551 # TODO: Document in docstring parameters which describe bdevs.
552 # TODO: Possible improvement: JSON schema might be used here in future
554 for i
in device_info
.keys():
555 setattr(self
, i
, device_info
[i
])