autoserv revision b2bea302ba5b469bcfbb093ac5b713153fc80413
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 server = parser.options.server 68 reboot = parser.options.reboot 69 install_before = parser.options.install_before 70 install_after = parser.options.install_after 71 verify = parser.options.verify 72 repair = parser.options.repair 73 no_tee = parser.options.no_tee 74 parse_job = parser.options.parse_job 75 host_protection = parser.options.host_protection 76 ssh_user = parser.options.ssh_user 77 ssh_port = parser.options.ssh_port 78 ssh_pass = parser.options.ssh_pass 79 80 # can't be both a client and a server side test 81 if client and server: 82 print "Can not specify a test as both server and client!" 83 sys.exit(1) 84 85 if len(parser.args) < 1 and not verify and not repair: 86 print parser.parser.print_help() 87 sys.exit(1) 88 89 # We have a control file unless it's just a verify/repair job 90 if len(parser.args) > 0: 91 control = parser.args[0] 92 else: 93 control = None 94 95 if machines_file: 96 machines = [] 97 for m in open(machines_file, 'r').readlines(): 98 # remove comments, spaces 99 m = re.sub('#.*', '', m).strip() 100 if m: 101 machines.append(m) 102 print "Read list of machines from file: %s" % machines_file 103 print ','.join(machines) 104 105 if machines: 106 for machine in machines: 107 if not machine or re.search('\s', machine): 108 print "Invalid machine %s" % str(machine) 109 sys.exit(1) 110 machines = list(set(machines)) 111 machines.sort() 112 113 job = server_job.server_job(control, parser.args[1:], results, label, 114 user, machines, client, parse_job, 115 ssh_user, ssh_port, ssh_pass) 116 debug_dir = os.path.join(results, 'debug') 117 stdout = os.path.join(debug_dir, 'autoserv.stdout') 118 stderr = os.path.join(debug_dir, 'autoserv.stderr') 119 if no_tee: 120 job.stdout.redirect(stdout) 121 job.stderr.redirect(stderr) 122 else: 123 job.stdout.tee_redirect(stdout) 124 job.stderr.tee_redirect(stderr) 125 126 # perform checks 127 job.precheck() 128 129 # run the job 130 exit_code = 0 131 try: 132 if repair: 133 job.repair(host_protection) 134 elif verify: 135 job.verify() 136 else: 137 try: 138 job.run(reboot, install_before, install_after) 139 finally: 140 job.cleanup_parser() 141 except: 142 job.aborted = True 143 traceback.print_exc() 144 145 if getattr(job, 'aborted', False): 146 sys.exit(1) 147 148 149def main(): 150 pid_file_manager = PidFileManager() 151 152 # grab the parser 153 parser = autoserv_parser.autoserv_parser 154 155 if len(sys.argv) == 1: 156 parser.parser.print_help() 157 sys.exit(1) 158 159 results = parser.options.results 160 results = os.path.abspath(results) 161 write_pidfile = parser.options.write_pidfile 162 if write_pidfile: 163 pid_file_manager.open_pid_file(results) 164 165 exit_code = 0 166 try: 167 try: 168 run_autoserv(pid_file_manager, results, parser) 169 except SystemExit, e: 170 exit_code = e.code 171 except: 172 traceback.print_exc() 173 # If we don't know what happened, we'll classify it as 174 # an 'abort' and return 1. 175 exit_code = 1 176 finally: 177 pid_file_manager.close_pid_file(exit_code) 178 sys.exit(exit_code) 179 180 181if __name__ == '__main__': 182 main() 183