| # Copyright (c) 2005 The Regents of The University of Michigan | |
| # All rights reserved. | |
| # | |
| # Redistribution and use in source and binary forms, with or without | |
| # modification, are permitted provided that the following conditions are | |
| # met: redistributions of source code must retain the above copyright | |
| # notice, this list of conditions and the following disclaimer; | |
| # redistributions in binary form must reproduce the above copyright | |
| # notice, this list of conditions and the following disclaimer in the | |
| # documentation and/or other materials provided with the distribution; | |
| # neither the name of the copyright holders nor the names of its | |
| # contributors may be used to endorse or promote products derived from | |
| # this software without specific prior written permission. | |
| # | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| # | |
| # Authors: Nathan Binkert | |
| import os, popen2, re, sys | |
| class MyPOpen(object): | |
| def __init__(self, cmd, input = None, output = None, bufsize = -1): | |
| self.status = -1 | |
| if input is None: | |
| p2c_read, p2c_write = os.pipe() | |
| self.tochild = os.fdopen(p2c_write, 'w', bufsize) | |
| else: | |
| p2c_write = None | |
| if isinstance(input, file): | |
| p2c_read = input.fileno() | |
| elif isinstance(input, str): | |
| input = file(input, 'r') | |
| p2c_read = input.fileno() | |
| elif isinstance(input, int): | |
| p2c_read = input | |
| else: | |
| raise AttributeError | |
| if output is None: | |
| c2p_read, c2p_write = os.pipe() | |
| self.fromchild = os.fdopen(c2p_read, 'r', bufsize) | |
| else: | |
| c2p_read = None | |
| if isinstance(output, file): | |
| c2p_write = output.fileno() | |
| elif isinstance(output, str): | |
| output = file(output, 'w') | |
| c2p_write = output.fileno() | |
| elif isinstance(output, int): | |
| c2p_write = output | |
| else: | |
| raise AttributeError | |
| self.pid = os.fork() | |
| if self.pid == 0: | |
| os.dup2(p2c_read, sys.stdin.fileno()) | |
| os.dup2(c2p_write, sys.stdout.fileno()) | |
| os.dup2(c2p_write, sys.stderr.fileno()) | |
| try: | |
| os.execvp(cmd[0], cmd) | |
| finally: | |
| os._exit(1) | |
| os.close(p2c_read) | |
| os.close(c2p_write) | |
| def poll(self): | |
| if self.status < 0: | |
| pid, status = os.waitpid(self.pid, os.WNOHANG) | |
| if pid == self.pid: | |
| self.status = status | |
| return self.status | |
| def wait(self): | |
| if self.status < 0: | |
| pid, status = os.waitpid(self.pid, 0) | |
| if pid == self.pid: | |
| self.status = status | |
| return self.status | |
| class qsub: | |
| def __init__(self): | |
| self.afterok = None | |
| self.hold = False | |
| self.join = False | |
| self.keep_stdout = False | |
| self.keep_stderr = False | |
| self.node_type = None | |
| self.mail_abort = False | |
| self.mail_begin = False | |
| self.mail_end = False | |
| self.name = None | |
| self.stdout = None | |
| self.priority = None | |
| self.queue = None | |
| self.pbshost = None | |
| self.qsub = 'qsub' | |
| self.env = {} | |
| def build(self, script, args = []): | |
| self.cmd = [ self.qsub ] | |
| if self.env: | |
| arg = '-v' | |
| arg += ','.join([ '%s=%s' % i for i in self.env.iteritems() ]) | |
| self.cmd.append(arg) | |
| if self.hold: | |
| self.cmd.append('-h') | |
| if self.stdout: | |
| self.cmd.append('-olocalhost:' + self.stdout) | |
| if self.keep_stdout and self.keep_stderr: | |
| self.cmd.append('-koe') | |
| elif self.keep_stdout: | |
| self.cmd.append('-ko') | |
| elif self.keep_stderr: | |
| self.cmd.append('-ke') | |
| else: | |
| self.cmd.append('-kn') | |
| if self.join: | |
| self.cmd.append('-joe') | |
| if self.node_type: | |
| self.cmd.append('-lnodes=' + self.node_type) | |
| if self.mail_abort or self.mail_begin or self.mail_end: | |
| flags = '' | |
| if self.mail_abort: | |
| flags.append('a') | |
| if self.mail_begin: | |
| flags.append('b') | |
| if self.mail_end: | |
| flags.append('e') | |
| if len(flags): | |
| self.cmd.append('-m ' + flags) | |
| else: | |
| self.cmd.append('-mn') | |
| if self.name: | |
| self.cmd.append("-N%s" % self.name) | |
| if self.priority: | |
| self.cmd.append('-p' + self.priority) | |
| if self.queue: | |
| self.cmd.append('-q' + self.queue) | |
| if self.afterok: | |
| self.cmd.append('-Wdepend=afterok:%s' % self.afterok) | |
| self.cmd.extend(args) | |
| self.script = script | |
| self.command = ' '.join(self.cmd + [ self.script ]) | |
| def do(self): | |
| pbs = MyPOpen(self.cmd + [ self.script ]) | |
| self.result = pbs.fromchild.read() | |
| ec = pbs.wait() | |
| if ec != 0 and self.pbshost: | |
| cmd = ' '.join(self.cmd + [ '-' ]) | |
| cmd = [ 'ssh', '-x', self.pbshost, cmd ] | |
| self.command = ' '.join(cmd) | |
| ssh = MyPOpen(cmd, input = self.script) | |
| self.result = ssh.fromchild.read() | |
| ec = ssh.wait() | |
| return ec |