]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | #!/usr/bin/python3 |
2 | # -*- mode:python -*- | |
3 | # vim: ts=4 sw=4 smarttab expandtab | |
4 | ||
5 | __all__ = ['ConsoleOptions', 'MgrModuleInterpreter'] | |
6 | ||
7 | import readline | |
8 | import sys | |
9 | from code import InteractiveConsole | |
10 | from collections import namedtuple | |
11 | from pathlib import Path | |
12 | ||
13 | from ceph_argparse import json_command | |
14 | ||
15 | ||
16 | ConsoleOptions = namedtuple('ConsoleOptions', | |
17 | ['name', 'conffile', 'prefix', 'timeout']) | |
18 | ||
19 | ||
20 | class MgrModuleInteractiveConsole(InteractiveConsole): | |
21 | def __init__(self, rados, opt, filename="<console>"): | |
22 | super().__init__(filename) | |
23 | self.cmd_prefix = opt.prefix | |
24 | self.timeout = opt.timeout | |
25 | self.cluster = rados.Rados(name=opt.name, | |
26 | conffile=opt.conffile) | |
27 | self.cluster.connect(timeout=opt.timeout) | |
28 | ||
29 | def _do_runsource(self, source): | |
30 | ret, buf, s = json_command(self.cluster, | |
31 | prefix=self.cmd_prefix, | |
32 | target=('mon-mgr',), | |
33 | inbuf=source.encode(), | |
34 | timeout=self.timeout) | |
35 | if ret == 0: | |
36 | # TODO: better way to encode the outputs | |
37 | sys.stdout.write(buf.decode()) | |
38 | sys.stderr.write(s) | |
39 | else: | |
40 | # needs more | |
41 | self.write("the input is not complete") | |
42 | ||
43 | def runsource(self, source, filename='<input>', symbol='single'): | |
44 | try: | |
45 | # just validate the syntax | |
46 | code = self.compile(source, filename, symbol) | |
47 | except (OverflowError, SyntaxError, ValueError): | |
48 | # Case 1 | |
49 | self.showsyntaxerror(filename) | |
50 | return False | |
51 | ||
52 | if code is None: | |
53 | # Case 2 | |
54 | return True | |
55 | ||
56 | # Case 3 | |
57 | self._do_runsource(source) | |
58 | return False | |
59 | ||
60 | def runcode(self, code): | |
61 | # code object cannot be pickled | |
62 | raise NotImplementedError() | |
63 | ||
64 | ||
65 | def show_env(): | |
66 | prog = Path(__file__).resolve() | |
67 | ceph_dir = prog.parents[2] | |
68 | python_path = ':'.join([f'{ceph_dir}/src/pybind', | |
69 | f'{ceph_dir}/build/lib/cython_modules/lib.3', | |
70 | f'{ceph_dir}/src/python-common', | |
71 | '$PYTHONPATH']) | |
72 | ld_library_path = ':'.join([f'{ceph_dir}/build/lib', | |
73 | '$LD_LIBRARY_PATH']) | |
74 | return f''' | |
75 | $ export PYTHONPATH={python_path} | |
76 | $ export LD_LIBRARY_PATH={ld_library_path}'''.strip('\n') | |
77 | ||
78 | ||
79 | def main(): | |
80 | import argparse | |
81 | try: | |
82 | import rados | |
83 | except ImportError: | |
84 | print(f'''Unable to import rados python binding. | |
85 | Please set the environment variables first: | |
86 | {show_env()}''', | |
87 | file=sys.stderr) | |
88 | exit(1) | |
89 | ||
90 | prog = Path(__file__).name | |
91 | epilog = f'''Usage: | |
92 | {prog} -c "print(mgr.release_name)"''' | |
93 | parser = argparse.ArgumentParser(epilog=epilog) | |
94 | parser.add_argument('--name', action='store', | |
95 | default='client.admin', | |
96 | help='user name for connecting to cluster') | |
97 | parser.add_argument('--conffile', action='store', | |
98 | default=rados.Rados.DEFAULT_CONF_FILES, | |
99 | help='path to ceph.conf') | |
100 | parser.add_argument('--prefix', action='store', | |
101 | default='mgr self-test eval', | |
102 | help='command prefix for eval the source') | |
103 | parser.add_argument('--timeout', action='store', | |
104 | type=int, | |
105 | default=10, | |
106 | help='timeout in seconds') | |
107 | parser.add_argument('--show-env', action='store_true', | |
108 | help='show instructions to set environment variables') | |
109 | group = parser.add_mutually_exclusive_group() | |
110 | group.add_argument('-c', action='store', | |
111 | help='optional statement', | |
112 | dest='command') | |
113 | group.add_argument('script', nargs='?', type=argparse.FileType('r')) | |
114 | args = parser.parse_args() | |
115 | options = ConsoleOptions(name=args.name, | |
116 | conffile=args.conffile, | |
117 | prefix=args.prefix, | |
118 | timeout=args.timeout) | |
119 | console = MgrModuleInteractiveConsole(rados, options) | |
120 | if args.show_env: | |
121 | print(show_env()) | |
122 | elif args.command: | |
123 | console.runsource(args.command) | |
124 | elif args.script: | |
125 | console.runsource(args.script.read()) | |
126 | else: | |
127 | sys.ps1 = f'[{args.prefix}] >>> ' | |
128 | console.interact() | |
129 | ||
130 | ||
131 | if __name__ == '__main__': | |
132 | main() |