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