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