Package starcluster :: Module cli
[hide private]
[frames] | no frames]

Source Code for Module starcluster.cli

  1  #!/usr/bin/env python 
  2  """ 
  3  StarCluster Command Line Interface: 
  4   
  5  starcluster [global-opts] action [action-opts] [<action-args> ...] 
  6  """ 
  7  import os 
  8  import sys 
  9  import socket 
 10  import optparse 
 11  import traceback 
 12   
 13  from boto.exception import BotoServerError, EC2ResponseError, S3ResponseError 
 14   
 15  from starcluster import config 
 16  from starcluster import static 
 17  from starcluster import logger 
 18  from starcluster import commands 
 19  from starcluster import exception 
 20  from starcluster import optcomplete 
 21  from starcluster.logger import log, console 
 22  from starcluster import __version__ 
 23   
 24  __description__ = """ 
 25  StarCluster - (http://web.mit.edu/starcluster) (v. %s) 
 26  Software Tools for Academics and Researchers (STAR) 
 27  Please submit bug reports to starcluster@mit.edu 
 28  """ % __version__ 
 29   
 30   
31 -class StarClusterCLI(object):
32 """ 33 StarCluster Command Line Interface 34 """ 35 36 gparser = None 37 subcmds_map = {} 38
39 - def get_description(self):
40 return __description__.replace('\n', '', 1)
41
42 - def parse_subcommands(self, gparser, subcmds):
43 """ 44 Parse given global arguments, find subcommand from given list of 45 subcommand objects, parse local arguments and return a tuple of 46 global options, selected command object, command options, and 47 command arguments. 48 49 Call execute() on the command object to run. The command object has 50 members 'gopts' and 'opts' set for global and command options 51 respectively, you don't need to call execute with those but you could 52 if you wanted to. 53 """ 54 print self.get_description() 55 56 # Build map of name -> command and docstring. 57 cmds_header = 'Available Commands:' 58 gparser.usage += '\n\n%s\n' % cmds_header 59 gparser.usage += '%s\n' % ('-' * len(cmds_header)) 60 gparser.usage += "NOTE: Pass --help to any command for a list of its " 61 gparser.usage += 'options and detailed usage information\n\n' 62 for sc in subcmds: 63 helptxt = sc.__doc__.splitlines()[3].strip() 64 gparser.usage += '- %s: %s\n' % (', '.join(sc.names), 65 helptxt) 66 for n in sc.names: 67 assert n not in self.subcmds_map 68 self.subcmds_map[n] = sc 69 70 # Declare and parse global options. 71 gparser.disable_interspersed_args() 72 73 gopts, args = gparser.parse_args() 74 if not args: 75 gparser.print_help() 76 raise SystemExit("\nError: you must specify an action.") 77 subcmdname, subargs = args[0], args[1:] 78 79 # set debug level if specified 80 if gopts.DEBUG: 81 console.setLevel(logger.DEBUG) 82 # load StarClusterConfig into global options 83 try: 84 cfg = config.StarClusterConfig(gopts.CONFIG) 85 cfg.load() 86 except exception.ConfigNotFound, e: 87 log.error(e.msg) 88 e.display_options() 89 sys.exit(1) 90 except exception.ConfigError, e: 91 log.error(e.msg) 92 sys.exit(1) 93 gopts.CONFIG = cfg 94 95 # Parse command arguments and invoke command. 96 try: 97 sc = self.subcmds_map[subcmdname] 98 lparser = optparse.OptionParser(sc.__doc__.strip()) 99 sc.addopts(lparser) 100 sc.parser = lparser 101 sc.gparser = self.gparser 102 sc.subcmds_map = self.subcmds_map 103 sc.gopts = gopts 104 sc.opts, subsubargs = lparser.parse_args(subargs) 105 except KeyError: 106 raise SystemExit("Error: invalid command '%s'" % subcmdname) 107 return gopts, sc, sc.opts, subsubargs
108
109 - def create_global_parser(self):
110 gparser = optparse.OptionParser(__doc__.strip(), version=__version__) 111 gparser.add_option("-d", "--debug", dest="DEBUG", 112 action="store_true", default=False, 113 help="print debug messages " + \ 114 "(useful for diagnosing problems)") 115 gparser.add_option("-c", "--config", dest="CONFIG", action="store", 116 metavar="FILE", 117 help="use alternate config file (default: %s)" % \ 118 static.STARCLUSTER_CFG_FILE) 119 gparser.add_option("-r", "--region", dest="REGION", action="store", 120 help="specify a region to use (default: us-east-1)") 121 return gparser
122
123 - def bug_found(self):
124 log.error("Oops! Looks like you've found a bug in StarCluster") 125 log.error("Debug file written to: %s" % static.DEBUG_FILE) 126 log.error("Look for lines starting with PID: %s" % static.PID) 127 log.error("Please submit this file, minus any private information,") 128 log.error("to starcluster@mit.edu") 129 sys.exit(1)
130
131 - def main(self):
132 # Create global options parser. 133 self.gparser = gparser = self.create_global_parser() 134 # Declare subcommands. 135 subcmds = commands.all_cmds 136 # subcommand completions 137 scmap = {} 138 for sc in subcmds: 139 for n in sc.names: 140 scmap[n] = sc 141 142 if optcomplete: 143 listcter = optcomplete.ListCompleter(scmap.keys()) 144 subcter = optcomplete.NoneCompleter() 145 optcomplete.autocomplete( 146 gparser, listcter, None, subcter, subcommands=scmap) 147 elif 'COMP_LINE' in os.environ: 148 return -1 149 150 gopts, sc, opts, args = self.parse_subcommands(gparser, subcmds) 151 if args and args[0] == 'help': 152 sc.parser.print_help() 153 sys.exit(0) 154 try: 155 sc.execute(args) 156 except (EC2ResponseError, S3ResponseError, BotoServerError), e: 157 log.error("%s: %s" % (e.error_code, e.error_message)) 158 sys.exit(1) 159 except socket.gaierror, e: 160 log.error("Unable to connect: %s" % e) 161 log.error("Check your internet connection?") 162 sys.exit(1) 163 except exception.ThreadPoolException, e: 164 if not gopts.DEBUG: 165 e.print_excs() 166 log.debug(e.format_excs()) 167 print 168 self.bug_found() 169 except exception.BaseException, e: 170 log.error(e.msg, extra={'__textwrap__': True}) 171 sys.exit(1) 172 except SystemExit, e: 173 raise e 174 except Exception, e: 175 if not gopts.DEBUG: 176 traceback.print_exc() 177 log.debug(traceback.format_exc()) 178 print 179 self.bug_found()
180 181
182 -def main():
183 logger.configure_sc_logging() 184 StarClusterCLI().main()
185 186 if __name__ == '__main__': 187 try: 188 main() 189 except KeyboardInterrupt: 190 print "Interrupted, exiting." 191