blob: 9951b6934c475e3b3a138924734d57026f71749b [file] [log] [blame]
Scott Baker96b995a2017-02-15 16:21:12 -08001#!/usr/bin/python
2#
3# XOSAPI interactive shell
4
5
Scott Baker82915412017-02-17 11:04:41 -08006import argparse
Scott Baker96b995a2017-02-15 16:21:12 -08007import functools
Zack Williams045b63d2019-01-22 16:30:57 -07008import os
9import sys
Scott Baker96b995a2017-02-15 16:21:12 -080010import atexit
11import readline
Scott Bakerd0f1dc12018-04-23 12:05:32 -070012import traceback
Scott Baker96b995a2017-02-15 16:21:12 -080013
14from twisted.internet import reactor
Scott Bakere02aa692018-03-23 09:54:14 -070015from xosapi.version import __version__
Scott Baker96b995a2017-02-15 16:21:12 -080016
Scott Baker82915412017-02-17 11:04:41 -080017current_client = None
18
Zack Williams045b63d2019-01-22 16:30:57 -070019
Scott Baker82915412017-02-17 11:04:41 -080020def parse_args():
21 parser = argparse.ArgumentParser()
22
Matteo Scandolo10a2f3c2018-04-20 16:59:38 +020023 defs = {"grpc_insecure_endpoint": "xos-core:50055",
24 "grpc_secure_endpoint": "xos-core:50051",
25 "config": '/opt/xos/config.yml'}
Scott Baker82915412017-02-17 11:04:41 -080026
Matteo Scandolo10a2f3c2018-04-20 16:59:38 +020027 _help = 'Path to the config file (default: %s)' % defs['config']
Scott Baker82915412017-02-17 11:04:41 -080028 parser.add_argument(
Matteo Scandolo10a2f3c2018-04-20 16:59:38 +020029 '-C', '--config', dest='config', action='store',
30 default=defs['config'],
Scott Baker82915412017-02-17 11:04:41 -080031 help=_help)
32
Matteo Scandolo10a2f3c2018-04-20 16:59:38 +020033 _help = ('gRPC insecure end-point to connect to. It is a direct',
34 '. (default: %s'
Scott Baker82915412017-02-17 11:04:41 -080035 % defs['grpc_insecure_endpoint'])
36 parser.add_argument('-G', '--grpc-insecure-endpoint',
37 dest='grpc_insecure_endpoint',
38 action='store',
39 default=defs["grpc_insecure_endpoint"],
40 help=_help)
41
Matteo Scandolo10a2f3c2018-04-20 16:59:38 +020042 _help = ('gRPC secure end-point to connect to. It is a direct',
43 '. (default: %s'
Scott Baker82915412017-02-17 11:04:41 -080044 % defs["grpc_secure_endpoint"])
45 parser.add_argument('-S', '--grpc-secure-endpoint',
46 dest='grpc_secure_endpoint',
47 action='store',
48 default=defs["grpc_secure_endpoint"],
49 help=_help)
50
51 parser.add_argument('-u', '--username',
52 dest='username',
53 action='store',
54 default=None,
55 help=_help)
56
57 parser.add_argument('-p', '--password',
58 dest='password',
59 action='store',
60 default=None,
61 help=_help)
62
63 _help = 'omit startup banner log lines'
64 parser.add_argument('-n', '--no-banner',
65 dest='no_banner',
66 action='store_true',
67 default=False,
68 help=_help)
69
70 _help = "suppress debug and info logs"
71 parser.add_argument('-q', '--quiet',
72 dest='quiet',
73 action='count',
74 help=_help)
75
Zack Williams045b63d2019-01-22 16:30:57 -070076 _help = 'increase verbosity level (can be used multiple times)'
Scott Baker82915412017-02-17 11:04:41 -080077 parser.add_argument('-v', '--verbose',
78 dest='verbose',
79 action='count',
80 help=_help)
81
Zack Williams045b63d2019-01-22 16:30:57 -070082 _help = 'print version'
Scott Bakere02aa692018-03-23 09:54:14 -070083 parser.add_argument('-V', '--version',
84 dest='version',
85 action='store_true',
86 default=False,
87 help=_help)
88
Scott Baker82915412017-02-17 11:04:41 -080089 args = parser.parse_args()
90
91 return args
92
Zack Williams045b63d2019-01-22 16:30:57 -070093
Scott Baker82915412017-02-17 11:04:41 -080094def login(username=None, password=None):
Matteo Scandoloe3d2f262018-06-05 17:45:39 -070095 from xosapi.xos_grpc_client import InsecureClient, SecureClient
Scott Baker82915412017-02-17 11:04:41 -080096 if current_client:
97 current_client.stop()
98 current_client.session_change = True
99
100 # now switch
101
102 if username:
103 client = SecureClient(endpoint=args.grpc_secure_endpoint, username=username, password=password)
104 client.set_reconnect_callback(functools.partial(start_xossh, client))
105 client.start()
106 else:
107 client = InsecureClient(endpoint=args.grpc_insecure_endpoint)
108 client.set_reconnect_callback(functools.partial(start_xossh, client))
109 client.start()
110
Zack Williams045b63d2019-01-22 16:30:57 -0700111
Scott Bakerf6145a22017-03-29 14:50:25 -0700112def setDirtyModels(*args, **kwargs):
113 return current_client.utility.SetDirtyModels(current_client.utility_pb2.ModelFilter(*args, **kwargs))
114
Zack Williams045b63d2019-01-22 16:30:57 -0700115
Scott Bakerf6145a22017-03-29 14:50:25 -0700116def listDirtyModels(*args, **kwargs):
117 return current_client.utility.ListDirtyModels(current_client.utility_pb2.ModelFilter(*args, **kwargs))
118
Zack Williams045b63d2019-01-22 16:30:57 -0700119
Scott Bakerf6145a22017-03-29 14:50:25 -0700120def listModelDefs():
121 return current_client.modeldefs.ListModelDefs(Empty())
122
Zack Williams045b63d2019-01-22 16:30:57 -0700123
Scott Baker0f9dfcd2018-01-12 12:23:13 -0800124def loadModels(name, version, xproto_filenames=[], decl_filenames=[], attic_filenames=[]):
125 request = current_client.dynamicload_pb2.LoadModelsRequest(name=name, version=version)
126 for fn in xproto_filenames:
127 item = request.xprotos.add()
128 item.filename = fn
129 item.contents = open(fn).read()
130 for fn in decl_filenames:
131 item = request.decls.add()
132 item.filename = fn
133 item.contents = open(fn).read()
134 for fn in attic_filenames:
135 item = request.attics.add()
136 item.filename = fn
137 item.contents = open(fn).read()
138 return current_client.dynamicload.LoadModels(request)
139
Zack Williams045b63d2019-01-22 16:30:57 -0700140
Scott Baker0f9dfcd2018-01-12 12:23:13 -0800141def unloadModels(name, version):
142 request = current_client.dynamicload_pb2.UnloadModelsRequest(name=name, version=version)
143 return current_client.dynamicload.UnloadModels(request)
144
Zack Williams045b63d2019-01-22 16:30:57 -0700145
Scott Bakerc8bbe9e2018-01-16 17:48:59 -0800146def getLoadStatus():
147 request = Empty()
148 return current_client.dynamicload.GetLoadStatus(request)
149
Zack Williams045b63d2019-01-22 16:30:57 -0700150
Scott Bakerf6145a22017-03-29 14:50:25 -0700151def listUtility():
152 print 'setDirtyModels(class_name=None)'
153 print 'listDirtyModels(class_name=None)'
154 print 'listModelDefs()'
Scott Baker0f9dfcd2018-01-12 12:23:13 -0800155 print 'loadModels(name, version, xproto_filenames, decl_filenames, attic_filenames)'
156 print 'unloadModels(name, version)'
Scott Bakerc8bbe9e2018-01-16 17:48:59 -0800157 print 'getLoadStatus()'
Scott Bakerf6145a22017-03-29 14:50:25 -0700158
Zack Williams045b63d2019-01-22 16:30:57 -0700159
Scott Baker82915412017-02-17 11:04:41 -0800160def examples():
Scott Bakerd1940972017-05-01 15:45:32 -0700161 print 'Slice.objects.all() # list all slices'
162 print 'Slice.objects.first().dump() # dump the first slice'
Scott Baker95f7d952017-03-09 10:04:26 -0800163 print 's = Slice.objects.new() # create a new slice'
Scott Baker82915412017-02-17 11:04:41 -0800164 print 's.name = "mysite_foo" # set a slice name'
165 print 's.site_id = coreapi.Site.objects.all()[0].id # grab the first site'
166 print 's.save() # save the slice'
167 print
Scott Baker96b995a2017-02-15 16:21:12 -0800168
Zack Williams045b63d2019-01-22 16:30:57 -0700169
Scott Baker96b995a2017-02-15 16:21:12 -0800170def start_xossh(client):
Scott Baker82915412017-02-17 11:04:41 -0800171 global coreapi, current_client
Scott Baker96b995a2017-02-15 16:21:12 -0800172 coreapi = client.xos_orm
Scott Baker82915412017-02-17 11:04:41 -0800173 current_client = client
Scott Baker96b995a2017-02-15 16:21:12 -0800174
Scott Baker82915412017-02-17 11:04:41 -0800175 current_client.session_change = False
Scott Baker96b995a2017-02-15 16:21:12 -0800176
Scott Baker82915412017-02-17 11:04:41 -0800177 if not args.no_banner:
178 print
Zack Williams045b63d2019-01-22 16:30:57 -0700179 print r"__ __ ____ _____ _____ _ _"
180 print r"\ \ / / / __ \ / ____| / ____| | | | |"
181 print r" \ V / | | | | | (___ | (___ | |__| |"
182 print r" > < | | | | \___ \ \___ \ | __ |"
183 print r" / . \ | |__| | ____) | ____) | | | | |"
184 print r"/_/ \_\ \____/ |_____/ |_____/ |_| |_|"
Scott Baker82915412017-02-17 11:04:41 -0800185 print
186
187 print "XOS Core server at %s" % client.endpoint
188
Scott Baker95f7d952017-03-09 10:04:26 -0800189 print 'Type "listObjects()" for a list of all objects'
Scott Bakerf6145a22017-03-29 14:50:25 -0700190 print 'Type "listUtility()" for a list of utility functions'
Scott Baker82915412017-02-17 11:04:41 -0800191 print 'Type "login("username", "password")" to switch to a secure shell'
192 print 'Type "examples()" for some examples'
Scott Baker96b995a2017-02-15 16:21:12 -0800193
194 # Load command history
195 history_path = os.path.join(os.environ["HOME"], ".xossh_history")
196 try:
197 file(history_path, 'a').close()
198 readline.read_history_file(history_path)
199 atexit.register(readline.write_history_file, history_path)
200 except IOError:
201 pass
202
203 # Enable tab completion
204 readline.parse_and_bind("tab: complete")
205
Scott Baker82915412017-02-17 11:04:41 -0800206 reactor.callLater(0, functools.partial(do_xossh_prompt, client))
Scott Baker96b995a2017-02-15 16:21:12 -0800207
Zack Williams045b63d2019-01-22 16:30:57 -0700208
Scott Baker82915412017-02-17 11:04:41 -0800209def do_xossh_prompt(client):
Scott Baker95f7d952017-03-09 10:04:26 -0800210 for k in client.xos_orm.all_model_names:
211 locals()[k] = getattr(client.xos_orm, k)
212
213 locals()["listObjects"] = client.xos_orm.listObjects
214
Scott Baker82915412017-02-17 11:04:41 -0800215 prompt = "xossh "
Scott Baker96b995a2017-02-15 16:21:12 -0800216 try:
217 while True:
218 command = ""
219 while True:
220 # Get line
221 try:
222 if command == "":
223 sep = ">>> "
224 else:
225 sep = "... "
226 line = raw_input(prompt + sep)
227 # Ctrl-C
228 except KeyboardInterrupt:
229 command = ""
230 print
231 break
232
233 # Build up multi-line command
234 command += line
235
236 # Blank line or first line does not end in :
237 if line == "" or (command == line and line[-1] != ':'):
238 break
239
240 command += os.linesep
241
Scott Baker96b995a2017-02-15 16:21:12 -0800242 # Quit
Scott Baker82915412017-02-17 11:04:41 -0800243 if command in ["q", "quit", "exit"]:
244 reactor.stop()
245 return
Scott Baker96b995a2017-02-15 16:21:12 -0800246
Scott Bakera6ca40b2018-06-07 12:31:23 -0700247 if (command == "") or (command.strip().startswith("#")):
Scott Baker82915412017-02-17 11:04:41 -0800248 # blank line
249 pass
250 else:
251 try:
252 # Do it
253 code = compile(command, "<stdin>", "single")
254 exec code
Scott Bakerd0f1dc12018-04-23 12:05:32 -0700255 except Exception:
256 traceback.print_exc()
Scott Baker82915412017-02-17 11:04:41 -0800257
258 # check to see if login() was used
259 if client.session_change:
260 return
261
262 #reactor.callLater(0, functools.partial(do_xossh_prompt, client))
Scott Baker96b995a2017-02-15 16:21:12 -0800263
264 except EOFError:
265 print
Scott Baker82915412017-02-17 11:04:41 -0800266 reactor.stop()
Scott Baker96b995a2017-02-15 16:21:12 -0800267
Zack Williams045b63d2019-01-22 16:30:57 -0700268
Scott Baker96b995a2017-02-15 16:21:12 -0800269def main():
Scott Baker82915412017-02-17 11:04:41 -0800270 global args
271 args = parse_args()
Scott Baker95f7d952017-03-09 10:04:26 -0800272
Matteo Scandoloe3d2f262018-06-05 17:45:39 -0700273 from xosconfig import Config
274
275 config_file = args.config
276 Config.init(config_file, 'synchronizer-config-schema.yaml')
277
Scott Bakere02aa692018-03-23 09:54:14 -0700278 if args.version:
279 print __version__
280 sys.exit(0)
281
Scott Baker82915412017-02-17 11:04:41 -0800282 login(username=args.username, password=args.password)
Scott Baker96b995a2017-02-15 16:21:12 -0800283 reactor.run()
284
Zack Williams045b63d2019-01-22 16:30:57 -0700285
Scott Baker96b995a2017-02-15 16:21:12 -0800286if __name__ == "__main__":
287 main()