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, session 
 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 crashfile = open(static.CRASH_FILE, 'w') 125 crashfile.write(session.stream.getvalue()) 126 crashfile.close() 127 log.error("Oops! Looks like you've found a bug in StarCluster") 128 log.error("Crash report written to: %s" % static.CRASH_FILE) 129 log.error("Please remove any sensitive data from the crash report") 130 log.error("and submit it to starcluster@mit.edu") 131 sys.exit(1)
132
133 - def main(self):
134 # Create global options parser. 135 self.gparser = gparser = self.create_global_parser() 136 # Declare subcommands. 137 subcmds = commands.all_cmds 138 # subcommand completions 139 scmap = {} 140 for sc in subcmds: 141 for n in sc.names: 142 scmap[n] = sc 143 144 if optcomplete: 145 listcter = optcomplete.ListCompleter(scmap.keys()) 146 subcter = optcomplete.NoneCompleter() 147 optcomplete.autocomplete( 148 gparser, listcter, None, subcter, subcommands=scmap) 149 elif 'COMP_LINE' in os.environ: 150 return -1 151 152 gopts, sc, opts, args = self.parse_subcommands(gparser, subcmds) 153 if args and args[0] == 'help': 154 sc.parser.print_help() 155 sys.exit(0) 156 try: 157 sc.execute(args) 158 except (EC2ResponseError, S3ResponseError, BotoServerError), e: 159 log.error("%s: %s" % (e.error_code, e.error_message)) 160 sys.exit(1) 161 except socket.gaierror, e: 162 log.error("Unable to connect: %s" % e) 163 log.error("Check your internet connection?") 164 sys.exit(1) 165 except exception.ThreadPoolException, e: 166 if not gopts.DEBUG: 167 e.print_excs() 168 log.debug(e.format_excs()) 169 print 170 self.bug_found() 171 except exception.ClusterDoesNotExist, e: 172 cm = gopts.CONFIG.get_cluster_manager() 173 cls = cm.get_clusters() 174 log.error(e.msg) 175 if cls: 176 taglist = ', '.join([c.cluster_tag for c in cls]) 177 active_clusters = "(active clusters: %s)" % taglist 178 log.error(active_clusters) 179 sys.exit(1) 180 except exception.BaseException, e: 181 log.error(e.msg, extra={'__textwrap__': True}) 182 sys.exit(1) 183 except SystemExit, e: 184 # re-raise SystemExit to avoid the bug-catcher below 185 raise e 186 except Exception, e: 187 if not gopts.DEBUG: 188 traceback.print_exc() 189 log.debug(traceback.format_exc()) 190 print 191 self.bug_found()
192 193
194 -def main():
195 logger.configure_sc_logging() 196 StarClusterCLI().main()
197 198 if __name__ == '__main__': 199 try: 200 main() 201 except KeyboardInterrupt: 202 print "Interrupted, exiting." 203