diff options
Diffstat (limited to 'src/spdk/scripts/rpc/__init__.py')
-rw-r--r-- | src/spdk/scripts/rpc/__init__.py | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/spdk/scripts/rpc/__init__.py b/src/spdk/scripts/rpc/__init__.py new file mode 100644 index 000000000..f764d7ae5 --- /dev/null +++ b/src/spdk/scripts/rpc/__init__.py @@ -0,0 +1,201 @@ +import json +import os +import sys + +from io import IOBase as io + +from . import app +from . import bdev +from . import blobfs +from . import env_dpdk +from . import idxd +from . import ioat +from . import iscsi +from . import log +from . import lvol +from . import nbd +from . import net +from . import notify +from . import nvme +from . import nvmf +from . import pmem +from . import subsystem +from . import trace +from . import vhost +from . import vmd +from . import sock +from . import client as rpc_client +from .helpers import deprecated_alias + + +@deprecated_alias('start_subsystem_init') +def framework_start_init(client): + """Start initialization of subsystems""" + return client.call('framework_start_init') + + +@deprecated_alias('wait_subsystem_init') +def framework_wait_init(client): + """Block until subsystems have been initialized""" + return client.call('framework_wait_init') + + +@deprecated_alias("get_rpc_methods") +def rpc_get_methods(client, current=None, include_aliases=None): + """Get list of supported RPC methods. + Args: + current: Get list of RPC methods only callable in the current state. + include_aliases: Include aliases in the list with RPC methods. + """ + params = {} + + if current: + params['current'] = current + if include_aliases: + params['include_aliases'] = include_aliases + + return client.call('rpc_get_methods', params) + + +@deprecated_alias("get_spdk_version") +def spdk_get_version(client): + """Get SPDK version""" + return client.call('spdk_get_version') + + +def _json_dump(config, fd, indent): + if indent is None: + indent = 2 + elif indent < 0: + indent = None + json.dump(config, fd, indent=indent) + fd.write('\n') + + +def _json_load(j): + if j == sys.stdin or isinstance(j, io): + json_conf = json.load(j) + elif os.path.exists(j): + with open(j, "r") as j: + json_conf = json.load(j) + else: + json_conf = json.loads(j) + return json_conf + + +def save_config(client, fd, indent=2): + """Write current (live) configuration of SPDK subsystems and targets to stdout. + Args: + fd: opened file descriptor where data will be saved + indent: Indent level. Value less than 0 mean compact mode. + Default indent level is 2. + """ + config = { + 'subsystems': [] + } + + for elem in client.call('framework_get_subsystems'): + cfg = { + 'subsystem': elem['subsystem'], + 'config': client.call('framework_get_config', {"name": elem['subsystem']}) + } + config['subsystems'].append(cfg) + + _json_dump(config, fd, indent) + + +def load_config(client, fd, include_aliases=False): + """Configure SPDK subsystems and targets using JSON RPC read from stdin. + Args: + fd: opened file descriptor where data will be taken from + """ + json_config = _json_load(fd) + + # remove subsystems with no config + subsystems = json_config['subsystems'] + for subsystem in list(subsystems): + if not subsystem['config']: + subsystems.remove(subsystem) + + # check if methods in the config file are known + allowed_methods = client.call('rpc_get_methods', {'include_aliases': include_aliases}) + if not subsystems and 'framework_start_init' in allowed_methods: + framework_start_init(client) + return + + for subsystem in list(subsystems): + config = subsystem['config'] + for elem in list(config): + if 'method' not in elem or elem['method'] not in allowed_methods: + raise rpc_client.JSONRPCException("Unknown method was included in the config file") + + while subsystems: + allowed_methods = client.call('rpc_get_methods', {'current': True, + 'include_aliases': include_aliases}) + allowed_found = False + + for subsystem in list(subsystems): + config = subsystem['config'] + for elem in list(config): + if 'method' not in elem or elem['method'] not in allowed_methods: + continue + + client.call(elem['method'], elem['params']) + config.remove(elem) + allowed_found = True + + if not config: + subsystems.remove(subsystem) + + if 'framework_start_init' in allowed_methods: + framework_start_init(client) + allowed_found = True + + if not allowed_found: + break + + if subsystems: + print("Some configs were skipped because the RPC state that can call them passed over.") + + +def save_subsystem_config(client, fd, indent=2, name=None): + """Write current (live) configuration of SPDK subsystem to stdout. + Args: + fd: opened file descriptor where data will be saved + indent: Indent level. Value less than 0 mean compact mode. + Default is indent level 2. + """ + cfg = { + 'subsystem': name, + 'config': client.call('framework_get_config', {"name": name}) + } + + _json_dump(cfg, fd, indent) + + +def load_subsystem_config(client, fd): + """Configure SPDK subsystem using JSON RPC read from stdin. + Args: + fd: opened file descriptor where data will be taken from + """ + subsystem = _json_load(fd) + + if not subsystem['config']: + return + + allowed_methods = client.call('rpc_get_methods') + config = subsystem['config'] + for elem in list(config): + if 'method' not in elem or elem['method'] not in allowed_methods: + raise rpc_client.JSONRPCException("Unknown method was included in the config file") + + allowed_methods = client.call('rpc_get_methods', {'current': True}) + for elem in list(config): + if 'method' not in elem or elem['method'] not in allowed_methods: + continue + + client.call(elem['method'], elem['params']) + config.remove(elem) + + if config: + print("Some configs were skipped because they cannot be called in the current RPC state.") |