113540Sandrea.mondelli@ucf.edu#!/usr/bin/env python2.7
21376Sbinkertn@umich.edu# Copyright (c) 2005 The Regents of The University of Michigan
31376Sbinkertn@umich.edu# All rights reserved.
41376Sbinkertn@umich.edu#
51376Sbinkertn@umich.edu# Redistribution and use in source and binary forms, with or without
61376Sbinkertn@umich.edu# modification, are permitted provided that the following conditions are
71376Sbinkertn@umich.edu# met: redistributions of source code must retain the above copyright
81376Sbinkertn@umich.edu# notice, this list of conditions and the following disclaimer;
91376Sbinkertn@umich.edu# redistributions in binary form must reproduce the above copyright
101376Sbinkertn@umich.edu# notice, this list of conditions and the following disclaimer in the
111376Sbinkertn@umich.edu# documentation and/or other materials provided with the distribution;
121376Sbinkertn@umich.edu# neither the name of the copyright holders nor the names of its
131376Sbinkertn@umich.edu# contributors may be used to endorse or promote products derived from
141376Sbinkertn@umich.edu# this software without specific prior written permission.
151376Sbinkertn@umich.edu#
161376Sbinkertn@umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171376Sbinkertn@umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181376Sbinkertn@umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191376Sbinkertn@umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201376Sbinkertn@umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211376Sbinkertn@umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221376Sbinkertn@umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231376Sbinkertn@umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241376Sbinkertn@umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251376Sbinkertn@umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261376Sbinkertn@umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271376Sbinkertn@umich.edu#
281376Sbinkertn@umich.edu# Authors: Nathan Binkert
291376Sbinkertn@umich.edu#          Steve Reinhardt
301376Sbinkertn@umich.edu#          Ali Saidi
311376Sbinkertn@umich.edu
321881Sbinkertn@umich.eduimport os, os.path, shutil, signal, socket, sys
331376Sbinkertn@umich.edufrom os import environ as env
341376Sbinkertn@umich.edufrom os.path import join as joinpath, expanduser
351376Sbinkertn@umich.edu
361881Sbinkertn@umich.edudef date():
371881Sbinkertn@umich.edu    import time
381881Sbinkertn@umich.edu    return time.strftime('%a %b %e %H:%M:%S %Z %Y', time.localtime())
391881Sbinkertn@umich.edu
401881Sbinkertn@umich.edudef cleandir(dir):
411881Sbinkertn@umich.edu    for root, dirs, files in os.walk(dir, False):
421881Sbinkertn@umich.edu        for name in files:
431881Sbinkertn@umich.edu            os.remove(joinpath(root, name))
441881Sbinkertn@umich.edu        for name in dirs:
451881Sbinkertn@umich.edu            os.rmdir(joinpath(root, name))
461881Sbinkertn@umich.edu
471376Sbinkertn@umich.educlass rsync:
481376Sbinkertn@umich.edu    def __init__(self):
491376Sbinkertn@umich.edu        self.sudo = False
501376Sbinkertn@umich.edu        self.rsync = 'rsync'
511376Sbinkertn@umich.edu        self.compress = False
521376Sbinkertn@umich.edu        self.archive = True
531376Sbinkertn@umich.edu        self.delete = False
541376Sbinkertn@umich.edu        self.options = ''
551376Sbinkertn@umich.edu
561376Sbinkertn@umich.edu    def do(self, src, dst):
571376Sbinkertn@umich.edu        args = []
581376Sbinkertn@umich.edu        if self.sudo:
591376Sbinkertn@umich.edu            args.append('sudo')
601376Sbinkertn@umich.edu
611376Sbinkertn@umich.edu        args.append(self.rsync)
621376Sbinkertn@umich.edu        if (self.archive):
631376Sbinkertn@umich.edu            args.append('-a')
641376Sbinkertn@umich.edu        if (self.compress):
651376Sbinkertn@umich.edu            args.append('-z')
661376Sbinkertn@umich.edu        if (self.delete):
671376Sbinkertn@umich.edu            args.append('--delete')
681376Sbinkertn@umich.edu        if len(self.options):
691376Sbinkertn@umich.edu            args.append(self.options)
701376Sbinkertn@umich.edu        args.append(src)
711376Sbinkertn@umich.edu        args.append(dst)
721376Sbinkertn@umich.edu
731376Sbinkertn@umich.edu        return os.spawnvp(os.P_WAIT, args[0], args)
741376Sbinkertn@umich.edu
751881Sbinkertn@umich.educlass JobDir(object):
761881Sbinkertn@umich.edu    def __init__(self, dir):
771881Sbinkertn@umich.edu        self.dir = dir
781376Sbinkertn@umich.edu
791881Sbinkertn@umich.edu    def file(self, filename):
801881Sbinkertn@umich.edu        return joinpath(self.dir, filename)
811376Sbinkertn@umich.edu
821881Sbinkertn@umich.edu    def create(self):
831881Sbinkertn@umich.edu        if os.path.exists(self.dir):
841881Sbinkertn@umich.edu            if not os.path.isdir(self.dir):
851881Sbinkertn@umich.edu                sys.exit('%s is not a directory.  Cannot build job' % self.dir)
861881Sbinkertn@umich.edu        else:
871881Sbinkertn@umich.edu            os.mkdir(self.dir)
881376Sbinkertn@umich.edu
891881Sbinkertn@umich.edu    def exists(self):
901881Sbinkertn@umich.edu        return os.path.isdir(self.dir)
911881Sbinkertn@umich.edu
921881Sbinkertn@umich.edu    def clean(self):
931881Sbinkertn@umich.edu        cleandir(self.dir)
941881Sbinkertn@umich.edu
951881Sbinkertn@umich.edu    def hasfile(self, filename):
961881Sbinkertn@umich.edu        return os.path.isfile(self.file(filename))
971881Sbinkertn@umich.edu
981881Sbinkertn@umich.edu    def echofile(self, filename, string):
991881Sbinkertn@umich.edu        filename = self.file(filename)
1001881Sbinkertn@umich.edu        try:
1011881Sbinkertn@umich.edu            f = file(filename, 'w')
1021881Sbinkertn@umich.edu            print >>f, string
1031881Sbinkertn@umich.edu            f.flush()
1041881Sbinkertn@umich.edu            f.close()
1051881Sbinkertn@umich.edu        except IOError,e:
1061881Sbinkertn@umich.edu            sys.exit(e)
1071881Sbinkertn@umich.edu
1081881Sbinkertn@umich.edu    def rmfile(self, filename):
1091881Sbinkertn@umich.edu        filename = self.file(filename)
1101881Sbinkertn@umich.edu        if os.path.isfile(filename):
1111881Sbinkertn@umich.edu            os.unlink(filename)
1121881Sbinkertn@umich.edu
1131881Sbinkertn@umich.edu    def readval(self, filename):
1141881Sbinkertn@umich.edu        filename = self.file(filename)
1151881Sbinkertn@umich.edu        f = file(filename, 'r')
1161881Sbinkertn@umich.edu        value = f.readline().strip()
1171881Sbinkertn@umich.edu        f.close()
1181881Sbinkertn@umich.edu        return value
1191881Sbinkertn@umich.edu
1201881Sbinkertn@umich.edu    def setstatus(self, string):
1211881Sbinkertn@umich.edu        filename = self.file('.status')
1221881Sbinkertn@umich.edu        try:
1231881Sbinkertn@umich.edu            f = file(filename, 'a')
1241881Sbinkertn@umich.edu            print >>f, string
1251881Sbinkertn@umich.edu            f.flush()
1261881Sbinkertn@umich.edu            f.close()
1271881Sbinkertn@umich.edu        except IOError,e:
1281881Sbinkertn@umich.edu            sys.exit(e)
1291881Sbinkertn@umich.edu
1301881Sbinkertn@umich.edu    def getstatus(self):
1311881Sbinkertn@umich.edu        filename = self.file('.status')
1321881Sbinkertn@umich.edu        try:
1331881Sbinkertn@umich.edu            f = file(filename, 'r')
1341881Sbinkertn@umich.edu        except IOError, e:
1351881Sbinkertn@umich.edu            return 'none'
1361881Sbinkertn@umich.edu
1371881Sbinkertn@umich.edu        # fast forward to the end
1381881Sbinkertn@umich.edu        for line in f: pass
1391881Sbinkertn@umich.edu
1401881Sbinkertn@umich.edu        # the first word on the last line is the status
1411881Sbinkertn@umich.edu        return line.split(' ')[0]
1421881Sbinkertn@umich.edu
1431881Sbinkertn@umich.edu    def __str__(self):
1441881Sbinkertn@umich.edu        return self.dir
1451376Sbinkertn@umich.edu
1461376Sbinkertn@umich.eduif __name__ == '__main__':
1471376Sbinkertn@umich.edu    rootdir = env.setdefault('ROOTDIR', os.getcwd())
1481816Sbinkertn@umich.edu    pbs_jobid = env['PBS_JOBID']
1491816Sbinkertn@umich.edu    pbs_jobname = env['PBS_JOBNAME']
1501376Sbinkertn@umich.edu    basedir = joinpath(rootdir, 'Base')
1511816Sbinkertn@umich.edu    jobname = env.setdefault('JOBNAME', pbs_jobname)
1521916Sbinkertn@umich.edu    jobfile = env.setdefault('JOBFILE', joinpath(rootdir, 'Test.py'))
1531816Sbinkertn@umich.edu    outdir = env.setdefault('OUTPUT_DIR', joinpath(rootdir, jobname))
1541816Sbinkertn@umich.edu    env['POOLJOB'] = 'True'
1551376Sbinkertn@umich.edu
1561816Sbinkertn@umich.edu    if os.path.isdir("/work"):
1571816Sbinkertn@umich.edu        workbase = "/work"
1581816Sbinkertn@umich.edu    else:
1591816Sbinkertn@umich.edu        workbase = "/tmp/"
1601816Sbinkertn@umich.edu
1611816Sbinkertn@umich.edu    workdir = joinpath(workbase, '%s.%s' % (env['USER'], pbs_jobid))
1621881Sbinkertn@umich.edu    host = socket.gethostname()
1631376Sbinkertn@umich.edu
1641376Sbinkertn@umich.edu    os.umask(0022)
1651376Sbinkertn@umich.edu
1661881Sbinkertn@umich.edu    jobdir = JobDir(outdir)
1671881Sbinkertn@umich.edu
1681881Sbinkertn@umich.edu    started = date()
1691881Sbinkertn@umich.edu    jobdir.echofile('.running', started)
1701881Sbinkertn@umich.edu    jobdir.rmfile('.queued')
1711881Sbinkertn@umich.edu    jobdir.echofile('.host', host)
1721881Sbinkertn@umich.edu
1731881Sbinkertn@umich.edu    jobdir.setstatus('running on %s on %s' % (host, started))
1741376Sbinkertn@umich.edu
1751376Sbinkertn@umich.edu    if os.path.isdir(workdir):
1761376Sbinkertn@umich.edu        cleandir(workdir)
1771376Sbinkertn@umich.edu    else:
1781376Sbinkertn@umich.edu        os.mkdir(workdir)
1791376Sbinkertn@umich.edu
1801881Sbinkertn@umich.edu    if False and os.path.isdir('/z/dist'):
1811376Sbinkertn@umich.edu        sync = rsync()
1821376Sbinkertn@umich.edu        sync.delete = True
1831376Sbinkertn@umich.edu        sync.sudo = True
1841376Sbinkertn@umich.edu        sync.do('poolfs::dist/m5/', '/z/dist/m5/')
1851376Sbinkertn@umich.edu
1861376Sbinkertn@umich.edu    try:
1871376Sbinkertn@umich.edu        os.chdir(workdir)
1881376Sbinkertn@umich.edu    except OSError,e:
1891376Sbinkertn@umich.edu        sys.exit(e)
1901376Sbinkertn@umich.edu
1911881Sbinkertn@umich.edu    os.symlink(jobdir.file('output'), 'status.out')
1921376Sbinkertn@umich.edu
1931712Sstever@eecs.umich.edu    args = [ joinpath(basedir, 'm5'), joinpath(basedir, 'run.py') ]
1941376Sbinkertn@umich.edu    if not len(args):
1951376Sbinkertn@umich.edu        sys.exit("no arguments")
1961376Sbinkertn@umich.edu
1971881Sbinkertn@umich.edu    print 'starting job... %s' % started
1981376Sbinkertn@umich.edu    print ' '.join(args)
1991376Sbinkertn@umich.edu    print
2001376Sbinkertn@umich.edu    sys.stdout.flush()
2011376Sbinkertn@umich.edu
2021376Sbinkertn@umich.edu    childpid = os.fork()
2031376Sbinkertn@umich.edu    if not childpid:
2041376Sbinkertn@umich.edu        # Execute command
2051376Sbinkertn@umich.edu        sys.stdin.close()
2061881Sbinkertn@umich.edu        fd = os.open(jobdir.file("output"),
2071376Sbinkertn@umich.edu                     os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
2081376Sbinkertn@umich.edu        os.dup2(fd, sys.stdout.fileno())
2091376Sbinkertn@umich.edu        os.dup2(fd, sys.stderr.fileno())
2101376Sbinkertn@umich.edu        os.execvp(args[0], args)
2111376Sbinkertn@umich.edu
2121376Sbinkertn@umich.edu    def handler(signum, frame):
2131376Sbinkertn@umich.edu        if childpid != 0:
2141376Sbinkertn@umich.edu            os.kill(childpid, signum)
2151376Sbinkertn@umich.edu
2161376Sbinkertn@umich.edu    signal.signal(signal.SIGHUP, handler)
2171376Sbinkertn@umich.edu    signal.signal(signal.SIGINT, handler)
2181376Sbinkertn@umich.edu    signal.signal(signal.SIGQUIT, handler)
2191376Sbinkertn@umich.edu    signal.signal(signal.SIGTERM, handler)
2201376Sbinkertn@umich.edu    signal.signal(signal.SIGCONT, handler)
2211376Sbinkertn@umich.edu    signal.signal(signal.SIGUSR1, handler)
2221376Sbinkertn@umich.edu    signal.signal(signal.SIGUSR2, handler)
2231376Sbinkertn@umich.edu
2241376Sbinkertn@umich.edu    done = 0
2251376Sbinkertn@umich.edu    while not done:
2261376Sbinkertn@umich.edu        try:
2271376Sbinkertn@umich.edu            thepid,ec = os.waitpid(childpid, 0)
2281376Sbinkertn@umich.edu            if ec:
2291376Sbinkertn@umich.edu                print 'Exit code ', ec
2301881Sbinkertn@umich.edu                status = 'failure'
2311376Sbinkertn@umich.edu            else:
2321881Sbinkertn@umich.edu                status = 'success'
2331376Sbinkertn@umich.edu            done = 1
2341376Sbinkertn@umich.edu        except OSError:
2351376Sbinkertn@umich.edu            pass
2361376Sbinkertn@umich.edu
2371881Sbinkertn@umich.edu    complete = date()
2381881Sbinkertn@umich.edu    print '\njob complete... %s' % complete
2391881Sbinkertn@umich.edu    jobdir.echofile('.%s' % status, complete)
2401881Sbinkertn@umich.edu    jobdir.rmfile('.running')
2411881Sbinkertn@umich.edu    jobdir.setstatus('%s on %s' % (status, complete))
242