Setting tag plcapi-5.4-2
[plcapi.git] / plcsh
1 #!/usr/bin/python
2 #
3 # Interactive shell for testing PLCAPI
4 #
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2005 The Trustees of Princeton University
7 #
8
9 import os
10 import sys
11 from socket import gethostname
12 from optparse import OptionParser
13 from getpass import getpass
14 from traceback import print_exc
15
16 sys.path.append(os.path.dirname(os.path.realpath(sys.argv[0])))
17 from PLC.Shell import Shell
18
19 usage="""Usage: %prog [options]
20    runs an interactive shell
21 Usage: %prog [options] script script-arguments
22 Usage: %prog script [plcsh-options --] script arguments
23    run a script"""
24
25 parser = OptionParser(usage=usage,add_help_option = False)
26 parser.add_option("-f", "--config", help = "PLC configuration file")
27 parser.add_option("-h", "--url", help = "API URL")
28 parser.add_option("-c", "--cacert", help = "API SSL certificate")
29 parser.add_option("-k", "--insecure", help = "Do not check SSL certificate")
30 parser.add_option("-m", "--method", help = "API authentication method")
31 parser.add_option("-s", "--session", help = "API session key")
32 parser.add_option("-u", "--user", help = "API user name")
33 parser.add_option("-p", "--password", help = "API password")
34 parser.add_option("-r", "--role", help = "API role")
35 parser.add_option("-x", "--xmlrpc", action = "store_true", default = False, help = "Use XML-RPC interface")
36 # pass this to the invoked shell if any
37 parser.add_option("--help", action = "store_true", dest="help", default=False,
38                   help = "show this help message and exit")
39 (options, args) = parser.parse_args()
40
41 if not args and options.help:
42     parser.print_help()
43     sys.exit(1)    
44
45 # If user is specified but password is not
46 if options.user is not None and options.password is None:
47     try:
48         options.password = getpass()
49     except (EOFError, KeyboardInterrupt):
50         print
51         sys.exit(0)
52
53 # Initialize a single global instance (scripts may re-initialize
54 # this instance and/or create additional instances).
55 try:
56     shell = Shell(globals = globals(),
57                   config = options.config,
58                   url = options.url, xmlrpc = options.xmlrpc, cacert = options.cacert,
59                   method = options.method, role = options.role,
60                   user = options.user, password = options.password,
61                   session = options.session)
62     # Register a few more globals for backward compatibility
63     auth = shell.auth
64     api = shell.api
65     config = shell.config
66 except Exception, err:
67     print "Error:", err
68     print
69     parser.print_help()
70     sys.exit(1)
71
72 # If called by a script 
73 if args:
74     if not os.path.exists(args[0]):
75         print 'File %s not found'%args[0]
76         parser.print_help()
77         sys.exit(1)
78     else:
79         # re-append --help if provided
80         if options.help:
81             args.append('--help')
82         # use args as sys.argv for the next shell, so our own options get removed for the next script
83         sys.argv = args
84         script = sys.argv[0]
85         # Add of script to sys.path 
86         path = os.path.dirname(os.path.abspath(script))
87         sys.path.append(path)
88         execfile(script)
89
90 # Otherwise, run an interactive shell environment
91 else:
92     if shell.server is None:
93         print "PlanetLab Central Direct API Access"
94         prompt = ""
95     elif shell.auth['AuthMethod'] == "anonymous":
96         prompt = "[anonymous]"
97         print "Connected anonymously"
98     elif shell.auth['AuthMethod'] == "session":
99         # XXX No way to tell node and user sessions apart from the
100         # client point of view.
101         prompt = "[%s]" % gethostname()
102         print "%s connected using session authentication" % gethostname()
103     else:
104         prompt = "[%s]" % shell.auth['Username']
105         print "%s connected using %s authentication" % \
106               (shell.auth['Username'], shell.auth['AuthMethod'])
107
108     # Readline and tab completion support
109     import atexit
110     import readline
111     import rlcompleter
112
113     print 'Type "system.listMethods()" or "help(method)" for more information.'
114     # Load command history
115     history_path = os.path.join(os.environ["HOME"], ".plcapi_history")
116     try:
117         file(history_path, 'a').close()
118         readline.read_history_file(history_path)
119         atexit.register(readline.write_history_file, history_path)
120     except IOError:
121         pass
122
123     # Enable tab completion
124     readline.parse_and_bind("tab: complete")
125
126     try:
127         while True:
128             command = ""
129             while True:
130                 # Get line
131                 try:
132                     if command == "":
133                         sep = ">>> "
134                     else:
135                         sep = "... "
136                     line = raw_input(prompt + sep)
137                 # Ctrl-C
138                 except KeyboardInterrupt:
139                     command = ""
140                     print
141                     break
142
143                 # Build up multi-line command
144                 command += line
145
146                 # Blank line or first line does not end in :
147                 if line == "" or (command == line and line[-1] != ':'):
148                     break
149
150                 command += os.linesep
151
152             # Blank line
153             if command == "":
154                 continue
155             # Quit
156             elif command in ["q", "quit", "exit"]:
157                 break
158
159             try:
160                 try:
161                     # Try evaluating as an expression and printing the result
162                     result = eval(command)
163                     if result is not None:
164                         print result
165                 except SyntaxError:
166                     # Fall back to executing as a statement
167                     exec command
168             except Exception, err:
169                 print_exc()
170
171     except EOFError:
172         print
173         pass