home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_1956 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  27.1 KB  |  639 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import os
  5. import re
  6. import sys
  7. import signal
  8. import tempfile
  9. pjoin = os.path.join
  10. from twisted.internet import reactor, defer
  11. from twisted.internet.protocol import ProcessProtocol
  12. from twisted.internet.error import ProcessDone, ProcessTerminated
  13. from twisted.internet.utils import getProcessOutput
  14. from twisted.python import failure, log
  15. from IPython.external import argparse
  16. from IPython.external import Itpl
  17. from IPython.genutils import get_ipython_dir, get_log_dir, get_security_dir, num_cpus
  18. from IPython.kernel.fcutil import have_crypto
  19. from IPython.iplib import user_setup
  20. if os.name == 'posix':
  21.     rc_suffix = ''
  22. else:
  23.     rc_suffix = '.ini'
  24. user_setup(get_ipython_dir(), rc_suffix, mode = 'install', interactive = False)
  25. get_log_dir()
  26. get_security_dir()
  27. from IPython.kernel.config import config_manager as kernel_config_manager
  28. from IPython.kernel.error import SecurityError, FileTimeoutError
  29. from IPython.kernel.fcutil import have_crypto
  30. from IPython.kernel.twistedutil import gatherBoth, wait_for_file
  31. from IPython.kernel.util import printer
  32.  
  33. class ProcessStateError(Exception):
  34.     pass
  35.  
  36.  
  37. class UnknownStatus(Exception):
  38.     pass
  39.  
  40.  
  41. class LauncherProcessProtocol(ProcessProtocol):
  42.     
  43.     def __init__(self, process_launcher):
  44.         self.process_launcher = process_launcher
  45.  
  46.     
  47.     def connectionMade(self):
  48.         self.process_launcher.fire_start_deferred(self.transport.pid)
  49.  
  50.     
  51.     def processEnded(self, status):
  52.         value = status.value
  53.         if isinstance(value, ProcessDone):
  54.             self.process_launcher.fire_stop_deferred(0)
  55.         elif isinstance(value, ProcessTerminated):
  56.             self.process_launcher.fire_stop_deferred({
  57.                 'exit_code': value.exitCode,
  58.                 'signal': value.signal,
  59.                 'status': value.status })
  60.         else:
  61.             raise UnknownStatus('unknown exit status, this is probably a bug in Twisted')
  62.         return isinstance(value, ProcessDone)
  63.  
  64.     
  65.     def outReceived(self, data):
  66.         log.msg(data)
  67.  
  68.     
  69.     def errReceived(self, data):
  70.         log.err(data)
  71.  
  72.  
  73.  
  74. class ProcessLauncher(object):
  75.     
  76.     def __init__(self, cmd_and_args):
  77.         self.cmd = cmd_and_args[0]
  78.         self.args = cmd_and_args
  79.         self._reset()
  80.  
  81.     
  82.     def _reset(self):
  83.         self.process_protocol = None
  84.         self.pid = None
  85.         self.start_deferred = None
  86.         self.stop_deferreds = []
  87.         self.state = 'before'
  88.  
  89.     
  90.     def running(self):
  91.         if self.state == 'running':
  92.             return True
  93.         return False
  94.  
  95.     running = property(running)
  96.     
  97.     def fire_start_deferred(self, pid):
  98.         self.pid = pid
  99.         self.state = 'running'
  100.         log.msg('Process %r has started with pid=%i' % (self.args, pid))
  101.         self.start_deferred.callback(pid)
  102.  
  103.     
  104.     def start(self):
  105.         if self.state == 'before':
  106.             self.process_protocol = LauncherProcessProtocol(self)
  107.             self.start_deferred = defer.Deferred()
  108.             self.process_transport = reactor.spawnProcess(self.process_protocol, self.cmd, self.args, env = os.environ)
  109.             return self.start_deferred
  110.         s = 'the process has already been started and has state: %r' % self.state
  111.         return defer.fail(ProcessStateError(s))
  112.  
  113.     
  114.     def get_stop_deferred(self):
  115.         if self.state == 'running' or self.state == 'before':
  116.             d = defer.Deferred()
  117.             self.stop_deferreds.append(d)
  118.             return d
  119.         s = 'this process is already complete'
  120.         return defer.fail(ProcessStateError(s))
  121.  
  122.     
  123.     def fire_stop_deferred(self, exit_code):
  124.         log.msg('Process %r has stopped with %r' % (self.args, exit_code))
  125.         self.state = 'after'
  126.         for d in self.stop_deferreds:
  127.             d.callback(exit_code)
  128.         
  129.  
  130.     
  131.     def signal(self, sig):
  132.         if self.state == 'running':
  133.             self.process_transport.signalProcess(sig)
  134.         
  135.  
  136.     
  137.     def interrupt_then_kill(self, delay = 1):
  138.         self.signal('INT')
  139.         reactor.callLater(delay, self.signal, 'KILL')
  140.  
  141.  
  142.  
  143. class ControllerLauncher(ProcessLauncher):
  144.     
  145.     def __init__(self, extra_args = None):
  146.         if sys.platform == 'win32':
  147.             ipcontroller = ipcontroller
  148.             import IPython.kernel.scripts
  149.             script_location = ipcontroller.__file__.replace('.pyc', '.py')
  150.             args = [
  151.                 sys.executable,
  152.                 '-u',
  153.                 script_location]
  154.         else:
  155.             args = [
  156.                 'ipcontroller']
  157.         self.extra_args = extra_args
  158.         if extra_args is not None:
  159.             args.extend(extra_args)
  160.         
  161.         ProcessLauncher.__init__(self, args)
  162.  
  163.  
  164.  
  165. class EngineLauncher(ProcessLauncher):
  166.     
  167.     def __init__(self, extra_args = None):
  168.         if sys.platform == 'win32':
  169.             ipengine = ipengine
  170.             import IPython.kernel.scripts
  171.             script_location = ipengine.__file__.replace('.pyc', '.py')
  172.             args = [
  173.                 sys.executable,
  174.                 '-u',
  175.                 script_location]
  176.         else:
  177.             args = [
  178.                 'ipengine']
  179.         self.extra_args = extra_args
  180.         if extra_args is not None:
  181.             args.extend(extra_args)
  182.         
  183.         ProcessLauncher.__init__(self, args)
  184.  
  185.  
  186.  
  187. class LocalEngineSet(object):
  188.     
  189.     def __init__(self, extra_args = None):
  190.         self.extra_args = extra_args
  191.         self.launchers = []
  192.  
  193.     
  194.     def start(self, n):
  195.         dlist = []
  196.         for i in range(n):
  197.             el = EngineLauncher(extra_args = self.extra_args)
  198.             d = el.start()
  199.             self.launchers.append(el)
  200.             dlist.append(d)
  201.         
  202.         dfinal = gatherBoth(dlist, consumeErrors = True)
  203.         dfinal.addCallback(self._handle_start)
  204.         return dfinal
  205.  
  206.     
  207.     def _handle_start(self, r):
  208.         log.msg('Engines started with pids: %r' % r)
  209.         return r
  210.  
  211.     
  212.     def _handle_stop(self, r):
  213.         log.msg('Engines received signal: %r' % r)
  214.         return r
  215.  
  216.     
  217.     def signal(self, sig):
  218.         dlist = []
  219.         for el in self.launchers:
  220.             d = el.get_stop_deferred()
  221.             dlist.append(d)
  222.             el.signal(sig)
  223.         
  224.         dfinal = gatherBoth(dlist, consumeErrors = True)
  225.         dfinal.addCallback(self._handle_stop)
  226.         return dfinal
  227.  
  228.     
  229.     def interrupt_then_kill(self, delay = 1):
  230.         dlist = []
  231.         for el in self.launchers:
  232.             d = el.get_stop_deferred()
  233.             dlist.append(d)
  234.             el.interrupt_then_kill(delay)
  235.         
  236.         dfinal = gatherBoth(dlist, consumeErrors = True)
  237.         dfinal.addCallback(self._handle_stop)
  238.         return dfinal
  239.  
  240.  
  241.  
  242. class BatchEngineSet(object):
  243.     submit_command = ''
  244.     delete_command = ''
  245.     job_id_regexp = ''
  246.     
  247.     def __init__(self, template_file, **kwargs):
  248.         self.template_file = template_file
  249.         self.context = { }
  250.         self.context.update(kwargs)
  251.         self.batch_file = self.template_file + '-run'
  252.  
  253.     
  254.     def parse_job_id(self, output):
  255.         m = re.match(self.job_id_regexp, output)
  256.         if m is not None:
  257.             job_id = m.group()
  258.         else:
  259.             raise Exception("job id couldn't be determined: %s" % output)
  260.         self.job_id = m is not None
  261.         log.msg('Job started with job id: %r' % job_id)
  262.         return job_id
  263.  
  264.     
  265.     def write_batch_script(self, n):
  266.         self.context['n'] = n
  267.         template = open(self.template_file, 'r').read()
  268.         log.msg('Using template for batch script: %s' % self.template_file)
  269.         script_as_string = Itpl.itplns(template, self.context)
  270.         log.msg('Writing instantiated batch script: %s' % self.batch_file)
  271.         f = open(self.batch_file, 'w')
  272.         f.write(script_as_string)
  273.         f.close()
  274.  
  275.     
  276.     def handle_error(self, f):
  277.         f.printTraceback()
  278.         f.raiseException()
  279.  
  280.     
  281.     def start(self, n):
  282.         self.write_batch_script(n)
  283.         d = getProcessOutput(self.submit_command, [
  284.             self.batch_file], env = os.environ)
  285.         d.addCallback(self.parse_job_id)
  286.         d.addErrback(self.handle_error)
  287.         return d
  288.  
  289.     
  290.     def kill(self):
  291.         d = getProcessOutput(self.delete_command, [
  292.             self.job_id], env = os.environ)
  293.         return d
  294.  
  295.  
  296.  
  297. class PBSEngineSet(BatchEngineSet):
  298.     submit_command = 'qsub'
  299.     delete_command = 'qdel'
  300.     job_id_regexp = '\\d+'
  301.     
  302.     def __init__(self, template_file, **kwargs):
  303.         BatchEngineSet.__init__(self, template_file, **kwargs)
  304.  
  305.  
  306. sshx_template = '#!/bin/sh\n"$@" &> /dev/null &\necho $!\n'
  307. engine_killer_template = "#!/bin/sh\nps -fu `whoami` | grep '[i]pengine' | awk '{print $2}' | xargs kill -TERM\n"
  308.  
  309. class SSHEngineSet(object):
  310.     sshx_template = sshx_template
  311.     engine_killer_template = engine_killer_template
  312.     
  313.     def __init__(self, engine_hosts, sshx = None, ipengine = 'ipengine'):
  314.         self.temp_dir = tempfile.gettempdir()
  315.         if sshx is not None:
  316.             self.sshx = sshx
  317.         else:
  318.             self.sshx = os.path.join(self.temp_dir, '%s-main-sshx.sh' % os.environ['USER'])
  319.             f = open(self.sshx, 'w')
  320.             f.writelines(self.sshx_template)
  321.             f.close()
  322.         self.engine_command = ipengine
  323.         self.engine_hosts = engine_hosts
  324.         self.engine_killer = os.path.join(self.temp_dir, '%s-local-engine_killer.sh' % os.environ['USER'])
  325.         f = open(self.engine_killer, 'w')
  326.         f.writelines(self.engine_killer_template)
  327.         f.close()
  328.  
  329.     
  330.     def start(self, send_furl = False):
  331.         dlist = []
  332.         for host in self.engine_hosts.keys():
  333.             count = self.engine_hosts[host]
  334.             d = self._start(host, count, send_furl)
  335.             dlist.append(d)
  336.         
  337.         return gatherBoth(dlist, consumeErrors = True)
  338.  
  339.     
  340.     def _start(self, hostname, count = 1, send_furl = False):
  341.         if send_furl:
  342.             d = self._scp_furl(hostname)
  343.         else:
  344.             d = defer.succeed(None)
  345.         (None, d.addCallback)((lambda r: self._scp_sshx(hostname)))
  346.         (None, None, d.addCallback)((lambda r: self._ssh_engine(hostname, count)))
  347.         return d
  348.  
  349.     
  350.     def _scp_furl(self, hostname):
  351.         scp_cmd = 'scp ~/.ipython/security/ipcontroller-engine.furl %s:.ipython/security/' % hostname
  352.         cmd_list = scp_cmd.split()
  353.         cmd_list[1] = os.path.expanduser(cmd_list[1])
  354.         log.msg('Copying furl file: %s' % scp_cmd)
  355.         d = getProcessOutput(cmd_list[0], cmd_list[1:], env = os.environ)
  356.         return d
  357.  
  358.     
  359.     def _scp_sshx(self, hostname):
  360.         scp_cmd = 'scp %s %s:%s/%s-sshx.sh' % (self.sshx, hostname, self.temp_dir, os.environ['USER'])
  361.         print 
  362.         log.msg('Copying sshx: %s' % scp_cmd)
  363.         sshx_scp = scp_cmd.split()
  364.         d = getProcessOutput(sshx_scp[0], sshx_scp[1:], env = os.environ)
  365.         return d
  366.  
  367.     
  368.     def _ssh_engine(self, hostname, count):
  369.         exec_engine = 'ssh %s sh %s/%s-sshx.sh %s' % (hostname, self.temp_dir, os.environ['USER'], self.engine_command)
  370.         cmds = exec_engine.split()
  371.         dlist = []
  372.         log.msg('about to start engines...')
  373.         for i in range(count):
  374.             log.msg('Starting engines: %s' % exec_engine)
  375.             d = getProcessOutput(cmds[0], cmds[1:], env = os.environ)
  376.             dlist.append(d)
  377.         
  378.         return gatherBoth(dlist, consumeErrors = True)
  379.  
  380.     
  381.     def kill(self):
  382.         dlist = []
  383.         for host in self.engine_hosts.keys():
  384.             d = self._killall(host)
  385.             dlist.append(d)
  386.         
  387.         return gatherBoth(dlist, consumeErrors = True)
  388.  
  389.     
  390.     def _killall(self, hostname):
  391.         d = self._scp_engine_killer(hostname)
  392.         (None, d.addCallback)((lambda r: self._ssh_kill(hostname)))
  393.         return d
  394.  
  395.     
  396.     def _scp_engine_killer(self, hostname):
  397.         scp_cmd = 'scp %s %s:%s/%s-engine_killer.sh' % (self.engine_killer, hostname, self.temp_dir, os.environ['USER'])
  398.         cmds = scp_cmd.split()
  399.         log.msg('Copying engine_killer: %s' % scp_cmd)
  400.         d = getProcessOutput(cmds[0], cmds[1:], env = os.environ)
  401.         return d
  402.  
  403.     
  404.     def _ssh_kill(self, hostname):
  405.         kill_cmd = 'ssh %s sh %s/%s-engine_killer.sh' % (hostname, self.temp_dir, os.environ['USER'])
  406.         log.msg('Killing engine: %s' % kill_cmd)
  407.         kill_cmd = kill_cmd.split()
  408.         d = getProcessOutput(kill_cmd[0], kill_cmd[1:], env = os.environ)
  409.         return d
  410.  
  411.     
  412.     def _exec_err(self, r):
  413.         log.msg(r)
  414.  
  415.  
  416.  
  417. def check_security(args, cont_args):
  418.     if (not (args.x) or not (args.y)) and not have_crypto:
  419.         log.err("\nOpenSSL/pyOpenSSL is not available, so we can't run in secure mode.\nTry running ipcluster with the -xy flags:  ipcluster local -xy -n 4")
  420.         reactor.stop()
  421.         return False
  422.     if args.x:
  423.         cont_args.append('-x')
  424.     
  425.     if args.y:
  426.         cont_args.append('-y')
  427.     
  428.     return True
  429.  
  430.  
  431. def check_reuse(args, cont_args):
  432.     if args.r:
  433.         cont_args.append('-r')
  434.         if args.client_port == 0 or args.engine_port == 0:
  435.             log.err('\nTo reuse FURL files, you must also set the client and engine ports using\nthe --client-port and --engine-port options.')
  436.             reactor.stop()
  437.             return False
  438.         cont_args.append('--client-port=%i' % args.client_port)
  439.         cont_args.append('--engine-port=%i' % args.engine_port)
  440.     
  441.     return True
  442.  
  443.  
  444. def _err_and_stop(f):
  445.     log.err(f)
  446.     reactor.stop()
  447.  
  448.  
  449. def _delay_start(cont_pid, start_engines, furl_file, reuse):
  450.     if not reuse:
  451.         if os.path.isfile(furl_file):
  452.             os.unlink(furl_file)
  453.         
  454.     
  455.     log.msg('Waiting for controller to finish starting...')
  456.     d = wait_for_file(furl_file, delay = 0.2, max_tries = 50)
  457.     d.addCallback((lambda _: log.msg('Controller started')))
  458.     (None, d.addCallback)((lambda _: start_engines(cont_pid)))
  459.     return d
  460.  
  461.  
  462. def main_local(args):
  463.     cont_args = []
  464.     cont_args.append('--logfile=%s' % pjoin(args.logdir, 'ipcontroller'))
  465.     if not check_security(args, cont_args):
  466.         return None
  467.     if not check_reuse(args, cont_args):
  468.         return None
  469.     cl = ControllerLauncher(extra_args = cont_args)
  470.     dstart = cl.start()
  471.     
  472.     def start_engines(cont_pid):
  473.         engine_args = []
  474.         engine_args.append('--logfile=%s' % pjoin(args.logdir, 'ipengine%s-' % cont_pid))
  475.         eset = LocalEngineSet(extra_args = engine_args)
  476.         
  477.         def shutdown(signum, frame):
  478.             log.msg('Stopping local cluster')
  479.             eset.interrupt_then_kill(0.5)
  480.             cl.interrupt_then_kill(0.5)
  481.             reactor.callLater(1, reactor.stop)
  482.  
  483.         signal.signal(signal.SIGINT, shutdown)
  484.         d = eset.start(args.n)
  485.         return d
  486.  
  487.     config = kernel_config_manager.get_config_obj()
  488.     furl_file = config['controller']['engine_furl_file']
  489.     dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
  490.     dstart.addErrback(_err_and_stop)
  491.  
  492.  
  493. def main_mpi(args):
  494.     cont_args = []
  495.     cont_args.append('--logfile=%s' % pjoin(args.logdir, 'ipcontroller'))
  496.     if not check_security(args, cont_args):
  497.         return None
  498.     if not check_reuse(args, cont_args):
  499.         return None
  500.     cl = ControllerLauncher(extra_args = cont_args)
  501.     dstart = cl.start()
  502.     
  503.     def start_engines(cont_pid):
  504.         raw_args = [
  505.             args.cmd]
  506.         raw_args.extend([
  507.             '-n',
  508.             str(args.n)])
  509.         raw_args.append('ipengine')
  510.         raw_args.append('-l')
  511.         raw_args.append(pjoin(args.logdir, 'ipengine%s-' % cont_pid))
  512.         if args.mpi:
  513.             raw_args.append('--mpi=%s' % args.mpi)
  514.         
  515.         eset = ProcessLauncher(raw_args)
  516.         
  517.         def shutdown(signum, frame):
  518.             log.msg('Stopping local cluster')
  519.             eset.interrupt_then_kill(1)
  520.             cl.interrupt_then_kill(1)
  521.             reactor.callLater(2, reactor.stop)
  522.  
  523.         signal.signal(signal.SIGINT, shutdown)
  524.         d = eset.start()
  525.         return d
  526.  
  527.     config = kernel_config_manager.get_config_obj()
  528.     furl_file = config['controller']['engine_furl_file']
  529.     dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
  530.     dstart.addErrback(_err_and_stop)
  531.  
  532.  
  533. def main_pbs(args):
  534.     cont_args = []
  535.     cont_args.append('--logfile=%s' % pjoin(args.logdir, 'ipcontroller'))
  536.     if not check_security(args, cont_args):
  537.         return None
  538.     if not check_reuse(args, cont_args):
  539.         return None
  540.     cl = ControllerLauncher(extra_args = cont_args)
  541.     dstart = cl.start()
  542.     
  543.     def start_engines(r):
  544.         pbs_set = PBSEngineSet(args.pbsscript)
  545.         
  546.         def shutdown(signum, frame):
  547.             log.msg('Stopping pbs cluster')
  548.             d = pbs_set.kill()
  549.             (d.addBoth,)((lambda _: cl.interrupt_then_kill(1)))
  550.             d.addBoth((lambda _: reactor.callLater(2, reactor.stop)))
  551.  
  552.         signal.signal(signal.SIGINT, shutdown)
  553.         d = pbs_set.start(args.n)
  554.         return d
  555.  
  556.     config = kernel_config_manager.get_config_obj()
  557.     furl_file = config['controller']['engine_furl_file']
  558.     dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
  559.     dstart.addErrback(_err_and_stop)
  560.  
  561.  
  562. def main_ssh(args):
  563.     clusterfile = { }
  564.     execfile(args.clusterfile, clusterfile)
  565.     if not clusterfile.has_key('send_furl'):
  566.         clusterfile['send_furl'] = False
  567.     
  568.     cont_args = []
  569.     cont_args.append('--logfile=%s' % pjoin(args.logdir, 'ipcontroller'))
  570.     if not check_security(args, cont_args):
  571.         return None
  572.     if not check_reuse(args, cont_args):
  573.         return None
  574.     cl = ControllerLauncher(extra_args = cont_args)
  575.     dstart = cl.start()
  576.     
  577.     def start_engines(cont_pid):
  578.         ssh_set = SSHEngineSet(clusterfile['engines'], sshx = args.sshx)
  579.         
  580.         def shutdown(signum, frame):
  581.             d = ssh_set.kill()
  582.             cl.interrupt_then_kill(1)
  583.             reactor.callLater(2, reactor.stop)
  584.  
  585.         signal.signal(signal.SIGINT, shutdown)
  586.         d = ssh_set.start(clusterfile['send_furl'])
  587.         return d
  588.  
  589.     config = kernel_config_manager.get_config_obj()
  590.     furl_file = config['controller']['engine_furl_file']
  591.     dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
  592.     dstart.addErrback(_err_and_stop)
  593.  
  594.  
  595. def get_args():
  596.     base_parser = argparse.ArgumentParser(add_help = False)
  597.     base_parser.add_argument('-r', action = 'store_true', dest = 'r', help = 'try to reuse FURL files.  Use with --client-port and --engine-port')
  598.     base_parser.add_argument('--client-port', type = int, dest = 'client_port', help = 'the port the controller will listen on for client connections', default = 0)
  599.     base_parser.add_argument('--engine-port', type = int, dest = 'engine_port', help = 'the port the controller will listen on for engine connections', default = 0)
  600.     base_parser.add_argument('-x', action = 'store_true', dest = 'x', help = 'turn off client security')
  601.     base_parser.add_argument('-y', action = 'store_true', dest = 'y', help = 'turn off engine security')
  602.     base_parser.add_argument('--logdir', type = str, dest = 'logdir', help = 'directory to put log files (default=$IPYTHONDIR/log)', default = pjoin(get_ipython_dir(), 'log'))
  603.     base_parser.add_argument('-n', '--num', type = int, dest = 'n', default = 2, help = 'the number of engines to start')
  604.     parser = argparse.ArgumentParser(description = 'IPython cluster startup.  This starts a controller and        engines using various approaches.  Use the IPYTHONDIR environment        variable to change your IPython directory from the default of        .ipython or _ipython.  The log and security subdirectories of your        IPython directory will be used by this script for log files and        security files.')
  605.     subparsers = parser.add_subparsers(help = 'available cluster types.  For help, do "ipcluster TYPE --help"')
  606.     parser_local = subparsers.add_parser('local', help = 'run a local cluster', parents = [
  607.         base_parser])
  608.     parser_local.set_defaults(func = main_local)
  609.     parser_mpirun = subparsers.add_parser('mpirun', help = 'run a cluster using mpirun (mpiexec also works)', parents = [
  610.         base_parser])
  611.     parser_mpirun.add_argument('--mpi', type = str, dest = 'mpi', help = 'how to call MPI_Init (default=mpi4py)')
  612.     parser_mpirun.set_defaults(func = main_mpi, cmd = 'mpirun')
  613.     parser_mpiexec = subparsers.add_parser('mpiexec', help = 'run a cluster using mpiexec (mpirun also works)', parents = [
  614.         base_parser])
  615.     parser_mpiexec.add_argument('--mpi', type = str, dest = 'mpi', help = 'how to call MPI_Init (default=mpi4py)')
  616.     parser_mpiexec.set_defaults(func = main_mpi, cmd = 'mpiexec')
  617.     parser_pbs = subparsers.add_parser('pbs', help = 'run a pbs cluster', parents = [
  618.         base_parser])
  619.     parser_pbs.add_argument('--pbs-script', type = str, dest = 'pbsscript', help = 'PBS script template', default = 'pbs.template')
  620.     parser_pbs.set_defaults(func = main_pbs)
  621.     parser_ssh = subparsers.add_parser('ssh', help = 'run a cluster using ssh, should have ssh-keys setup', parents = [
  622.         base_parser])
  623.     parser_ssh.add_argument('--clusterfile', type = str, dest = 'clusterfile', help = 'python file describing the cluster', default = 'clusterfile.py')
  624.     parser_ssh.add_argument('--sshx', type = str, dest = 'sshx', help = 'sshx launcher helper')
  625.     parser_ssh.set_defaults(func = main_ssh)
  626.     args = parser.parse_args()
  627.     return args
  628.  
  629.  
  630. def main():
  631.     args = get_args()
  632.     reactor.callWhenRunning(args.func, args)
  633.     log.startLogging(sys.stdout)
  634.     reactor.run()
  635.  
  636. if __name__ == '__main__':
  637.     main()
  638.  
  639.