summaryrefslogtreecommitdiffstats
path: root/src/spdk/scripts/spdkcli/ui_root.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdk/scripts/spdkcli/ui_root.py')
-rw-r--r--src/spdk/scripts/spdkcli/ui_root.py560
1 files changed, 560 insertions, 0 deletions
diff --git a/src/spdk/scripts/spdkcli/ui_root.py b/src/spdk/scripts/spdkcli/ui_root.py
new file mode 100644
index 000000000..cec8eb5f9
--- /dev/null
+++ b/src/spdk/scripts/spdkcli/ui_root.py
@@ -0,0 +1,560 @@
+from .ui_node import UINode, UIBdevs, UILvolStores, UIVhosts
+from .ui_node_nvmf import UINVMf
+from .ui_node_iscsi import UIISCSI
+import rpc.client
+import rpc
+from functools import wraps
+
+
+class UIRoot(UINode):
+ """
+ Root node for CLI menu tree structure. Refreshes running config on startup.
+ """
+ def __init__(self, client, shell):
+ UINode.__init__(self, "/", shell=shell)
+ self.current_bdevs = []
+ self.current_lvol_stores = []
+ self.current_vhost_ctrls = []
+ self.current_nvmf_transports = []
+ self.current_nvmf_subsystems = []
+ self.set_rpc_target(client)
+ self.verbose = False
+ self.is_init = self.check_init()
+ self.methods = []
+
+ def refresh(self):
+ self.methods = self.rpc_get_methods(current=True)
+ if self.is_init is False:
+ methods = "\n".join(self.methods)
+ self.shell.log.warning("SPDK Application is not yet initialized.\n"
+ "Please initialize subsystems with framework_start_init command.\n"
+ "List of available commands in current state:\n"
+ "%s" % methods)
+ else:
+ # Pass because we'd like to build main tree structure for "ls"
+ # even if state is uninitialized
+ pass
+
+ self._children = set([])
+ UIBdevs(self)
+ UILvolStores(self)
+ if self.has_subsystem("vhost"):
+ UIVhosts(self)
+ if self.has_subsystem("nvmf"):
+ UINVMf(self)
+ if self.has_subsystem("iscsi"):
+ UIISCSI(self)
+
+ def set_rpc_target(self, client):
+ self.client = client
+
+ def print_array(self, a):
+ return " ".join(a)
+
+ def verbose(f):
+ # For any configuration calls (create, delete, construct, etc.)
+ # Check if verbose option is to be used and set appropriately.
+ # Do not use for "get_*" methods so that output is not
+ # flooded.
+ def w(self, **kwargs):
+ self.client.log_set_level("INFO" if self.verbose else "ERROR")
+ r = f(self, **kwargs)
+ self.client.log_set_level("ERROR")
+ return r
+ return w
+
+ def is_method_available(f):
+ # Check if method f is available for given spdk target
+ def w(self, **kwargs):
+ if f.__name__ in self.methods:
+ r = f(self, **kwargs)
+ return r
+ # If given method is not avaialble return empty list
+ # similar to real get_* like rpc
+ return []
+ return w
+
+ def ui_command_framework_start_init(self):
+ if rpc.framework_start_init(self.client):
+ self.is_init = True
+ self.refresh()
+
+ def ui_command_load_config(self, filename):
+ with open(filename, "r") as fd:
+ rpc.load_config(self.client, fd)
+
+ def ui_command_load_subsystem_config(self, filename):
+ with open(filename, "r") as fd:
+ rpc.load_subsystem_config(self.client, fd)
+
+ def ui_command_save_config(self, filename, indent=2):
+ with open(filename, "w") as fd:
+ rpc.save_config(self.client, fd, indent)
+
+ def ui_command_save_subsystem_config(self, filename, subsystem, indent=2):
+ with open(filename, "w") as fd:
+ rpc.save_subsystem_config(self.client, fd, indent, subsystem)
+
+ def rpc_get_methods(self, current=False):
+ return rpc.rpc_get_methods(self.client, current=current)
+
+ def check_init(self):
+ return "framework_start_init" not in self.rpc_get_methods(current=True)
+
+ def bdev_get_bdevs(self, bdev_type):
+ if self.is_init:
+ self.current_bdevs = rpc.bdev.bdev_get_bdevs(self.client)
+ # Following replace needs to be done in order for some of the bdev
+ # listings to work: logical volumes, split disk.
+ # For example logical volumes: listing in menu is "Logical_Volume"
+ # (cannot have space), but the product name in SPDK is "Logical Volume"
+ bdev_type = bdev_type.replace("_", " ")
+ for bdev in [x for x in self.current_bdevs if bdev_type in x["product_name"].lower()]:
+ test = Bdev(bdev)
+ yield test
+
+ def bdev_get_iostat(self, **kwargs):
+ return rpc.bdev.bdev_get_iostat(self.client, **kwargs)
+
+ @verbose
+ def bdev_split_create(self, **kwargs):
+ response = rpc.bdev.bdev_split_create(self.client, **kwargs)
+ return self.print_array(response)
+
+ @verbose
+ def bdev_split_delete(self, **kwargs):
+ rpc.bdev.bdev_split_delete(self.client, **kwargs)
+
+ @verbose
+ def create_malloc_bdev(self, **kwargs):
+ response = rpc.bdev.bdev_malloc_create(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_malloc_delete(self, **kwargs):
+ rpc.bdev.bdev_malloc_delete(self.client, **kwargs)
+
+ @verbose
+ def create_iscsi_bdev(self, **kwargs):
+ response = rpc.bdev.bdev_iscsi_create(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_iscsi_delete(self, **kwargs):
+ rpc.bdev.bdev_iscsi_delete(self.client, **kwargs)
+
+ @verbose
+ def bdev_aio_create(self, **kwargs):
+ response = rpc.bdev.bdev_aio_create(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_aio_delete(self, **kwargs):
+ rpc.bdev.bdev_aio_delete(self.client, **kwargs)
+
+ @verbose
+ def create_lvol_bdev(self, **kwargs):
+ response = rpc.lvol.bdev_lvol_create(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_lvol_delete(self, **kwargs):
+ response = rpc.lvol.bdev_lvol_delete(self.client, **kwargs)
+ return response
+
+ @verbose
+ def create_nvme_bdev(self, **kwargs):
+ response = rpc.bdev.bdev_nvme_attach_controller(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_nvme_detach_controller(self, **kwargs):
+ rpc.bdev.bdev_nvme_detach_controller(self.client, **kwargs)
+
+ @verbose
+ def bdev_null_create(self, **kwargs):
+ response = rpc.bdev.bdev_null_create(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_null_delete(self, **kwargs):
+ rpc.bdev.bdev_null_delete(self.client, **kwargs)
+
+ @verbose
+ def create_error_bdev(self, **kwargs):
+ response = rpc.bdev.bdev_error_create(self.client, **kwargs)
+
+ @verbose
+ def bdev_error_delete(self, **kwargs):
+ rpc.bdev.bdev_error_delete(self.client, **kwargs)
+
+ @verbose
+ @is_method_available
+ def bdev_lvol_get_lvstores(self):
+ if self.is_init:
+ self.current_lvol_stores = rpc.lvol.bdev_lvol_get_lvstores(self.client)
+ for lvs in self.current_lvol_stores:
+ yield LvolStore(lvs)
+
+ @verbose
+ def bdev_lvol_create_lvstore(self, **kwargs):
+ response = rpc.lvol.bdev_lvol_create_lvstore(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_lvol_delete_lvstore(self, **kwargs):
+ rpc.lvol.bdev_lvol_delete_lvstore(self.client, **kwargs)
+
+ @verbose
+ def bdev_pmem_create_pool(self, **kwargs):
+ response = rpc.pmem.bdev_pmem_create_pool(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_pmem_delete_pool(self, **kwargs):
+ rpc.pmem.bdev_pmem_delete_pool(self.client, **kwargs)
+
+ @verbose
+ def bdev_pmem_get_pool_info(self, **kwargs):
+ response = rpc.pmem.bdev_pmem_get_pool_info(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_pmem_create(self, **kwargs):
+ response = rpc.bdev.bdev_pmem_create(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_pmem_delete(self, **kwargs):
+ response = rpc.bdev.bdev_pmem_delete(self.client, **kwargs)
+ return response
+
+ @verbose
+ def create_rbd_bdev(self, **kwargs):
+ response = rpc.bdev.bdev_rbd_create(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_rbd_delete(self, **kwargs):
+ response = rpc.bdev.bdev_rbd_delete(self.client, **kwargs)
+ return response
+
+ @verbose
+ def create_virtio_dev(self, **kwargs):
+ response = rpc.vhost.bdev_virtio_attach_controller(self.client, **kwargs)
+ return self.print_array(response)
+
+ @verbose
+ def bdev_virtio_detach_controller(self, **kwargs):
+ response = rpc.vhost.bdev_virtio_detach_controller(self.client, **kwargs)
+ return response
+
+ @verbose
+ def bdev_raid_create(self, **kwargs):
+ rpc.bdev.bdev_raid_create(self.client, **kwargs)
+
+ @verbose
+ def bdev_raid_delete(self, **kwargs):
+ rpc.bdev.bdev_raid_delete(self.client, **kwargs)
+
+ @verbose
+ @is_method_available
+ def bdev_virtio_scsi_get_devices(self):
+ if self.is_init:
+ for bdev in rpc.vhost.bdev_virtio_scsi_get_devices(self.client):
+ test = Bdev(bdev)
+ yield test
+
+ def list_vhost_ctrls(self):
+ if self.is_init:
+ self.current_vhost_ctrls = rpc.vhost.vhost_get_controllers(self.client)
+
+ @verbose
+ @is_method_available
+ def vhost_get_controllers(self, ctrlr_type):
+ if self.is_init:
+ self.list_vhost_ctrls()
+ for ctrlr in [x for x in self.current_vhost_ctrls if ctrlr_type in list(x["backend_specific"].keys())]:
+ yield VhostCtrlr(ctrlr)
+
+ @verbose
+ def vhost_delete_controller(self, **kwargs):
+ rpc.vhost.vhost_delete_controller(self.client, **kwargs)
+
+ @verbose
+ def vhost_create_scsi_controller(self, **kwargs):
+ rpc.vhost.vhost_create_scsi_controller(self.client, **kwargs)
+
+ @verbose
+ def vhost_create_blk_controller(self, **kwargs):
+ rpc.vhost.vhost_create_blk_controller(self.client, **kwargs)
+
+ @verbose
+ def vhost_scsi_controller_remove_target(self, **kwargs):
+ rpc.vhost.vhost_scsi_controller_remove_target(self.client, **kwargs)
+
+ @verbose
+ def vhost_scsi_controller_add_target(self, **kwargs):
+ rpc.vhost.vhost_scsi_controller_add_target(self.client, **kwargs)
+
+ def vhost_controller_set_coalescing(self, **kwargs):
+ rpc.vhost.vhost_controller_set_coalescing(self.client, **kwargs)
+
+ @verbose
+ def create_nvmf_transport(self, **kwargs):
+ rpc.nvmf.nvmf_create_transport(self.client, **kwargs)
+
+ def list_nvmf_transports(self):
+ if self.is_init:
+ self.current_nvmf_transports = rpc.nvmf.nvmf_get_transports(self.client)
+
+ @verbose
+ @is_method_available
+ def nvmf_get_transports(self):
+ if self.is_init:
+ self.list_nvmf_transports()
+ for transport in self.current_nvmf_transports:
+ yield NvmfTransport(transport)
+
+ def list_nvmf_subsystems(self):
+ if self.is_init:
+ self.current_nvmf_subsystems = rpc.nvmf.nvmf_get_subsystems(self.client)
+
+ @verbose
+ @is_method_available
+ def nvmf_get_subsystems(self):
+ if self.is_init:
+ self.list_nvmf_subsystems()
+ for subsystem in self.current_nvmf_subsystems:
+ yield NvmfSubsystem(subsystem)
+
+ @verbose
+ def create_nvmf_subsystem(self, **kwargs):
+ rpc.nvmf.nvmf_create_subsystem(self.client, **kwargs)
+
+ @verbose
+ def nvmf_delete_subsystem(self, **kwargs):
+ rpc.nvmf.nvmf_delete_subsystem(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_add_listener(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_add_listener(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_remove_listener(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_remove_listener(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_add_host(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_add_host(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_remove_host(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_remove_host(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_allow_any_host(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_allow_any_host(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_add_ns(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_add_ns(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_remove_ns(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_remove_ns(self.client, **kwargs)
+
+ @verbose
+ def nvmf_subsystem_allow_any_host(self, **kwargs):
+ rpc.nvmf.nvmf_subsystem_allow_any_host(self.client, **kwargs)
+
+ @verbose
+ @is_method_available
+ def scsi_get_devices(self):
+ if self.is_init:
+ for device in rpc.iscsi.scsi_get_devices(self.client):
+ yield ScsiObj(device)
+
+ @verbose
+ @is_method_available
+ def iscsi_get_target_nodes(self):
+ if self.is_init:
+ for tg in rpc.iscsi.iscsi_get_target_nodes(self.client):
+ yield tg
+
+ @verbose
+ def iscsi_create_target_node(self, **kwargs):
+ rpc.iscsi.iscsi_create_target_node(self.client, **kwargs)
+
+ @verbose
+ def iscsi_delete_target_node(self, **kwargs):
+ rpc.iscsi.iscsi_delete_target_node(self.client, **kwargs)
+
+ @verbose
+ @is_method_available
+ def iscsi_get_portal_groups(self):
+ if self.is_init:
+ for pg in rpc.iscsi.iscsi_get_portal_groups(self.client):
+ yield ScsiObj(pg)
+
+ @verbose
+ @is_method_available
+ def iscsi_get_initiator_groups(self):
+ if self.is_init:
+ for ig in rpc.iscsi.iscsi_get_initiator_groups(self.client):
+ yield ScsiObj(ig)
+
+ @verbose
+ def construct_portal_group(self, **kwargs):
+ rpc.iscsi.iscsi_create_portal_group(self.client, **kwargs)
+
+ @verbose
+ def iscsi_delete_portal_group(self, **kwargs):
+ rpc.iscsi.iscsi_delete_portal_group(self.client, **kwargs)
+
+ @verbose
+ def construct_initiator_group(self, **kwargs):
+ rpc.iscsi.iscsi_create_initiator_group(self.client, **kwargs)
+
+ @verbose
+ def iscsi_delete_initiator_group(self, **kwargs):
+ rpc.iscsi.iscsi_delete_initiator_group(self.client, **kwargs)
+
+ @verbose
+ @is_method_available
+ def iscsi_get_connections(self, **kwargs):
+ if self.is_init:
+ for ic in rpc.iscsi.iscsi_get_connections(self.client, **kwargs):
+ yield ic
+
+ @verbose
+ def iscsi_initiator_group_add_initiators(self, **kwargs):
+ rpc.iscsi.iscsi_initiator_group_add_initiators(self.client, **kwargs)
+
+ @verbose
+ def iscsi_initiator_group_remove_initiators(self, **kwargs):
+ rpc.iscsi.iscsi_initiator_group_remove_initiators(self.client, **kwargs)
+
+ @verbose
+ def iscsi_target_node_add_pg_ig_maps(self, **kwargs):
+ rpc.iscsi.iscsi_target_node_add_pg_ig_maps(self.client, **kwargs)
+
+ @verbose
+ def iscsi_target_node_remove_pg_ig_maps(self, **kwargs):
+ rpc.iscsi.iscsi_target_node_remove_pg_ig_maps(self.client, **kwargs)
+
+ @verbose
+ def iscsi_auth_group_add_secret(self, **kwargs):
+ rpc.iscsi.iscsi_auth_group_add_secret(self.client, **kwargs)
+
+ @verbose
+ def iscsi_auth_group_remove_secret(self, **kwargs):
+ rpc.iscsi.iscsi_auth_group_remove_secret(self.client, **kwargs)
+
+ @verbose
+ @is_method_available
+ def iscsi_get_auth_groups(self, **kwargs):
+ return rpc.iscsi.iscsi_get_auth_groups(self.client, **kwargs)
+
+ @verbose
+ def iscsi_create_auth_group(self, **kwargs):
+ rpc.iscsi.iscsi_create_auth_group(self.client, **kwargs)
+
+ @verbose
+ def iscsi_delete_auth_group(self, **kwargs):
+ rpc.iscsi.iscsi_delete_auth_group(self.client, **kwargs)
+
+ @verbose
+ def iscsi_target_node_set_auth(self, **kwargs):
+ rpc.iscsi.iscsi_target_node_set_auth(self.client, **kwargs)
+
+ @verbose
+ def iscsi_target_node_add_lun(self, **kwargs):
+ rpc.iscsi.iscsi_target_node_add_lun(self.client, **kwargs)
+
+ @verbose
+ def iscsi_set_discovery_auth(self, **kwargs):
+ rpc.iscsi.iscsi_set_discovery_auth(self.client, **kwargs)
+
+ @verbose
+ @is_method_available
+ def iscsi_get_options(self, **kwargs):
+ return rpc.iscsi.iscsi_get_options(self.client, **kwargs)
+
+ def has_subsystem(self, subsystem):
+ for system in rpc.subsystem.framework_get_subsystems(self.client):
+ if subsystem.lower() == system["subsystem"].lower():
+ return True
+ return False
+
+
+class Bdev(object):
+ def __init__(self, bdev_info):
+ """
+ All class attributes are set based on what information is received
+ from bdev_get_bdevs RPC call.
+ # TODO: Document in docstring parameters which describe bdevs.
+ # TODO: Possible improvement: JSON schema might be used here in future
+ """
+ for i in list(bdev_info.keys()):
+ setattr(self, i, bdev_info[i])
+
+
+class LvolStore(object):
+ def __init__(self, lvs_info):
+ """
+ All class attributes are set based on what information is received
+ from bdev_get_bdevs RPC call.
+ # TODO: Document in docstring parameters which describe bdevs.
+ # TODO: Possible improvement: JSON schema might be used here in future
+ """
+ for i in list(lvs_info.keys()):
+ setattr(self, i, lvs_info[i])
+
+
+class VhostCtrlr(object):
+ def __init__(self, ctrlr_info):
+ """
+ All class attributes are set based on what information is received
+ from vhost_get_controllers RPC call.
+ # TODO: Document in docstring parameters which describe bdevs.
+ # TODO: Possible improvement: JSON schema might be used here in future
+ """
+ for i in list(ctrlr_info.keys()):
+ setattr(self, i, ctrlr_info[i])
+
+
+class NvmfTransport(object):
+ def __init__(self, transport_info):
+ """
+ All class attributes are set based on what information is received
+ from get_nvmf_transport RPC call.
+ # TODO: Document in docstring parameters which describe bdevs.
+ # TODO: Possible improvement: JSON schema might be used here in future
+ """
+ for i in transport_info.keys():
+ setattr(self, i, transport_info[i])
+
+
+class NvmfSubsystem(object):
+ def __init__(self, subsystem_info):
+ """
+ All class attributes are set based on what information is received
+ from get_nvmf_subsystem RPC call.
+ # TODO: Document in docstring parameters which describe bdevs.
+ # TODO: Possible improvement: JSON schema might be used here in future
+ """
+ for i in subsystem_info.keys():
+ setattr(self, i, subsystem_info[i])
+
+
+class ScsiObj(object):
+ def __init__(self, device_info):
+ """
+ All class attributes are set based on what information is received
+ from iscsi related RPC calls.
+ # TODO: Document in docstring parameters which describe bdevs.
+ # TODO: Possible improvement: JSON schema might be used here in future
+ """
+ for i in device_info.keys():
+ setattr(self, i, device_info[i])