xref: /spdk/scripts/spdkcli.py (revision 307b8c112ffd90a26d53dd15fad67bd9038ef526)
1#!/usr/bin/env python3
2import os
3import sys
4import argparse
5from configshell_fb import ConfigShell, shell, ExecutionError
6from pyparsing import (alphanums, Optional, Suppress, Word, Regex,
7                       removeQuotes, dblQuotedString, OneOrMore)
8
9sys.path.append(os.path.dirname(__file__) + '/../python')
10
11from spdk.rpc.client import JSONRPCException, JSONRPCClient  # noqa
12from spdk.spdkcli import UIRoot  # noqa
13
14
15def add_quotes_to_shell(spdk_shell):
16    command = shell.locatedExpr(Word(alphanums + '_'))('command')
17    value = dblQuotedString.addParseAction(removeQuotes)
18    value_word = Word(alphanums + r';,=_\+/.<>()~@:-%[]')
19    keyword = Word(alphanums + r'_\-')
20    kparam = shell.locatedExpr(keyword + Suppress('=') +
21                               Optional(value | value_word, default=''))('kparams*')
22    pparam = shell.locatedExpr(value | value_word)('pparams*')
23    parameters = OneOrMore(kparam | pparam)
24    bookmark = Regex(r'@([A-Za-z0-9:_.]|-)+')
25    pathstd = Regex(r'([A-Za-z0-9:_.\[\]]|-)*' + '/' + r'([A-Za-z0-9:_.\[\]/]|-)*') \
26        | '..' | '.'
27    path = shell.locatedExpr(bookmark | pathstd | '*')('path')
28    spdk_shell._parser = Optional(path) + Optional(command) + Optional(parameters)
29
30
31def main():
32    """
33    Start SPDK CLI
34    :return:
35    """
36    spdk_shell = ConfigShell("~/.scripts")
37    spdk_shell.interactive = True
38    add_quotes_to_shell(spdk_shell)
39
40    parser = argparse.ArgumentParser(description="SPDK command line interface")
41    parser.add_argument('-s', dest='server_addr',
42                        help='RPC domain socket path or IP address', default='/var/tmp/spdk.sock')
43    parser.add_argument('-p', dest='port',
44                        help='RPC port number (if server_addr is IP address)',
45                        default=None, type=int)
46    parser.add_argument("-v", dest="verbose", help="Print request/response JSON for configuration calls",
47                        default=False, action="store_true")
48    parser.add_argument("commands", metavar="command", type=str, nargs="*", default="",
49                        help="commands to execute by SPDKCli as one-line command")
50    args = parser.parse_args()
51
52    try:
53        client = JSONRPCClient(args.server_addr, port=args.port)
54    except JSONRPCException as e:
55        spdk_shell.log.error("%s. SPDK not running?" % e)
56        sys.exit(1)
57
58    with client:
59        root_node = UIRoot(client, spdk_shell)
60        root_node.verbose = args.verbose
61        try:
62            root_node.refresh()
63        except BaseException:
64            pass
65
66        if args.commands:
67            try:
68                spdk_shell.interactive = False
69                spdk_shell.run_cmdline(" ".join(args.commands))
70            except Exception as e:
71                sys.stderr.write("%s\n" % e)
72                sys.exit(1)
73            sys.exit(0)
74
75        spdk_shell.con.display("SPDK CLI v0.1")
76        spdk_shell.con.display("")
77
78        while not spdk_shell._exit:
79            try:
80                spdk_shell.run_interactive()
81            except (JSONRPCException, ExecutionError) as e:
82                spdk_shell.log.error("%s" % e)
83            except BrokenPipeError as e:
84                spdk_shell.log.error("Lost connection with SPDK: %s" % e)
85
86
87if __name__ == "__main__":
88    main()
89