bricks@449: #!/usr/bin/env python bricks@449: bricks@449: import os.path bricks@449: import sys bricks@449: import shlex bricks@449: import traceback bricks@449: import time bricks@449: bricks@449: from optparse import OptionParser bricks@449: bricks@449: CONFIG_FILE = os.environ.get("JOBDAEMON_CFG", "jobdaemon.cfg") bricks@449: bricks@449: SLEEP = int(os.environ.get("JOBDAEMON_SLEEP", "60")) bricks@449: bricks@449: def fork(job): bricks@449: pid = os.fork() bricks@449: if pid: return pid bricks@449: os.execv(job[0], job) bricks@449: return -1 # never reached bricks@449: bricks@449: class Jobs(object): bricks@449: bricks@449: def __init__(self, filename): bricks@449: self.load_config(filename) bricks@449: bricks@449: def load_config(self, filename): bricks@449: print >> sys.stderr, "loading config file '%s'" % filename bricks@449: plan, jobs = [], [] bricks@449: f = open(filename, "r") bricks@449: try: bricks@449: while True: bricks@449: line = f.readline() bricks@449: if not line: break bricks@449: line = line.strip() bricks@449: if not line or line.startswith("#"): bricks@449: continue bricks@449: if line.startswith("BLOCKER:"): bricks@449: line = line[len("BLOCKER:"):].strip() bricks@449: plan.append((jobs, line)) bricks@449: jobs = [] bricks@449: continue bricks@449: jobs.append(shlex.split(line)) bricks@449: finally: bricks@449: f.close() bricks@449: bricks@449: if jobs: plan.append((jobs, None)) bricks@449: bricks@449: self.plan = plan bricks@449: bricks@449: def run_jobs(self, jobs): bricks@449: pids = [] bricks@449: for job in jobs: bricks@449: try: bricks@449: pids.append(fork(job)) bricks@449: except: bricks@449: traceback.print_exc() bricks@449: bricks@449: for pid in pids: bricks@449: try: bricks@449: os.waitpid(pid, 0) bricks@449: except: bricks@449: traceback.print_exc() bricks@449: bricks@449: def run(self): bricks@449: for jobs, blocker in self.plan: bricks@449: self.run_jobs(jobs) bricks@449: if blocker: bricks@449: try: bricks@449: os.system(blocker) bricks@449: except: bricks@449: traceback.print_exc() bricks@449: bricks@449: def main(): bricks@449: bricks@449: global config_changed bricks@449: bricks@449: parser = OptionParser() bricks@449: bricks@449: parser.add_option( bricks@449: "-c", "--config", dest="config", bricks@449: help="load configuration from file", bricks@449: metavar="FILE", default=CONFIG_FILE) bricks@449: bricks@449: parser.add_option( bricks@449: "-s", "--sleep", dest="sleep_time", bricks@449: help="sleep time between runs", bricks@449: type="int", bricks@449: metavar="TIME", default=SLEEP) bricks@449: bricks@449: (options, _) = parser.parse_args() bricks@449: bricks@449: if not os.path.isfile(options.config): bricks@449: print >> sys.stderr, "config file '%s' does not exists." bricks@449: sys.exit(1) bricks@449: bricks@449: modtime = os.stat(options.config).st_mtime bricks@449: bricks@449: jobs = Jobs(options.config) bricks@449: bricks@449: while True: bricks@449: if os.path.isfile(options.config): bricks@449: nmodtime = os.stat(options.config).st_mtime bricks@449: if nmodtime > modtime: bricks@449: modtime = nmodtime bricks@449: jobs = Jobs(options.config) bricks@449: jobs.run() bricks@449: time.sleep(options.sleep_time) bricks@449: bricks@449: if __name__ == '__main__': bricks@449: main()