autoserv revision a6f1308334f91fc5b9463cebe34a08d3be733f7c
1#!/usr/bin/python -u 2# 3# Copyright 2007 Google Inc. Released under the GPL v2 4 5""" 6Run an control file through the server side engine 7""" 8 9__author__ = """\ 10mbligh@google.com (Martin J. Bligh) 11""" 12 13import sys, os, re, traceback, signal 14 15import common 16from autotest_lib.server import server_job, utils 17from autotest_lib.server import autoserv_parser 18 19 20class PidFileManager(object): 21 pid_file = None 22 23 def open_pid_file(self, results_dir): 24 pid_file_path = os.path.join(results_dir, '.autoserv_execute') 25 assert not os.path.exists(pid_file_path) 26 self.pid_file = open(pid_file_path, 'w') 27 self.pid_file.write(str(os.getpid()) + '\n') 28 self.pid_file.flush() 29 30 31 def close_pid_file(self, exit_code, signal_code=0): 32 if not self.pid_file: 33 return 34 real_exit_code = (exit_code << 8) | (signal_code & 0xFF) 35 self.pid_file.write(str(real_exit_code) + '\n') 36 self.pid_file.close() 37 self.pid_file = None 38 39 40def run_autoserv(pid_file_manager, results, parser): 41 # send stdin to /dev/null 42 dev_null = os.open(os.devnull, os.O_RDONLY) 43 os.dup2(dev_null, sys.stdin.fileno()) 44 os.close(dev_null) 45 46 # Create separate process group 47 os.setpgrp() 48 49 # Implement SIGTERM handler 50 def handle_sigint(signum, frame): 51 pid_file_manager.close_pid_file(1, signal.SIGTERM) 52 os.killpg(os.getpgrp(), signal.SIGKILL) 53 54 # Set signal handler 55 signal.signal(signal.SIGTERM, handle_sigint) 56 57 # Get a useful value for running 'USER' 58 realuser = os.environ.get('USER') 59 if not realuser: 60 realuser = 'anonymous' 61 62 machines = parser.options.machines.split(',') 63 machines_file = parser.options.machines_file 64 label = parser.options.label 65 user = parser.options.user 66 client = parser.options.client 67 reboot = parser.options.reboot 68 install_before = parser.options.install_before 69 install_after = parser.options.install_after 70 verify = parser.options.verify 71 repair = parser.options.repair 72 no_tee = parser.options.no_tee 73 parse_job = parser.options.parse_job 74 ssh_user = parser.options.ssh_user 75 ssh_port = parser.options.ssh_port 76 ssh_pass = parser.options.ssh_pass 77 78 if len(parser.args) < 1 and not verify and not repair: 79 print parser.parser.print_help() 80 sys.exit(1) 81 82 # We have a control file unless it's just a verify/repair job 83 if len(parser.args) > 0: 84 control = parser.args[0] 85 else: 86 control = None 87 88 if machines_file: 89 machines = [] 90 for m in open(machines_file, 'r').readlines(): 91 # remove comments, spaces 92 m = re.sub('#.*', '', m).strip() 93 if m: 94 machines.append(m) 95 print "Read list of machines from file: %s" % machines_file 96 print ','.join(machines) 97 98 if machines: 99 for machine in machines: 100 if not machine or re.search('\s', machine): 101 print "Invalid machine %s" % str(machine) 102 sys.exit(1) 103 machines = list(set(machines)) 104 machines.sort() 105 106 job = server_job.server_job(control, parser.args[1:], results, label, 107 user, machines, client, parse_job, 108 ssh_user, ssh_port, ssh_pass) 109 debug_dir = os.path.join(results, 'debug') 110 stdout = os.path.join(debug_dir, 'autoserv.stdout') 111 stderr = os.path.join(debug_dir, 'autoserv.stderr') 112 if no_tee: 113 job.stdout.redirect(stdout) 114 job.stderr.redirect(stderr) 115 else: 116 job.stdout.tee_redirect(stdout) 117 job.stderr.tee_redirect(stderr) 118 119 # run the job 120 exit_code = 0 121 try: 122 if repair: 123 job.repair() 124 elif verify: 125 job.verify() 126 else: 127 try: 128 job.run(reboot, install_before, install_after) 129 finally: 130 job.cleanup_parser() 131 except: 132 job.aborted = True 133 traceback.print_exc() 134 135 if getattr(job, 'aborted', False): 136 sys.exit(1) 137 138 139def main(): 140 pid_file_manager = PidFileManager() 141 142 # grab the parser 143 parser = autoserv_parser.autoserv_parser 144 145 if len(sys.argv) == 1: 146 parser.parser.print_help() 147 sys.exit(1) 148 149 results = parser.options.results 150 results = os.path.abspath(results) 151 write_pidfile = parser.options.write_pidfile 152 if write_pidfile: 153 pid_file_manager.open_pid_file(results) 154 155 exit_code = 0 156 try: 157 try: 158 run_autoserv(pid_file_manager, results, parser) 159 except SystemExit, e: 160 exit_code = e.code 161 except: 162 traceback.print_exc() 163 # If we don't know what happened, we'll classify it as 164 # an 'abort' and return 1. 165 exit_code = 1 166 finally: 167 pid_file_manager.close_pid_file(exit_code) 168 sys.exit(exit_code) 169 170 171if __name__ == '__main__': 172 main() 173