autoserv.py revision f7243e1e10d8157877a8c99b718f01d3a8cc43f2
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
13from common.check_version import check_python_version
14check_python_version()
15
16import sys, os, re, server_job, hosts.site_host, utils, traceback, signal
17
18# Create separate process group
19os.setpgrp()
20
21# Implement SIGTERM handler
22def handle_sigint(signum, frame):
23	signal.signal(signal.SIGTERM, signal.SIG_DFL)
24	os.killpg(os.getpgrp(), signal.SIGTERM)
25
26# Set signal handler
27signal.signal(signal.SIGTERM, handle_sigint)
28
29
30usage = """\
31usage: autoserv
32	[-m machine,[machine,...]] # list of machines to pass to control file
33	[-M machines_file]         # list of machines (from a file)
34	[-c]                       # control file is a client side control
35	[-r resultsdir]            # specify results directory (default '.')
36	[-i]                       # reinstall machines before running the job
37	[-I]                       # reinstall machines after running the job
38	[-b]                       # reboot all specified machines after the job
39	[-l label]                 # label for the job (arbitrary string)
40	[-u user]                  # username for the job (email address)
41	[-v]                       # verify the machines only
42	[-R]                       # repair the machines
43	[-n]                       # no teeing the status to stdout/stderr
44	<control file>             # name of the control file to run
45	[args ...]                 # args to pass through to the control file
46"""
47
48args = sys.argv[1:]
49parser = utils.AutoservOptionParser(args)
50
51# Get a useful value for running 'USER'
52realuser = os.environ.get('USER')
53if not realuser:
54	realuser = 'anonymous'
55
56machines = parser.parse_opts_param('-m', None, split = ',')
57machines_file = parser.parse_opts_param('-M', None)
58results  = parser.parse_opts_param('-r', os.path.abspath('.'))
59results  = os.path.abspath(results)
60label    = parser.parse_opts_param('-l', '')
61user     = parser.parse_opts_param('-u', realuser)
62client   = parser.parse_opts('-c')
63reboot   = parser.parse_opts('-b')
64install_before = parser.parse_opts('-i')
65install_after  = parser.parse_opts('-I')
66verify   = parser.parse_opts('-v')
67repair   = parser.parse_opts('-R')
68no_tee   = parser.parse_opts('-n')
69
70
71if len(parser.args) < 1 and not verify and not repair:
72	print usage
73	sys.exit(-1)
74
75if machines_file:
76	machines = []
77	for m in open(machines_file, 'r').readlines():
78		m = re.sub('#.*', '', m).strip()   # remove comments, spaces
79		if m:
80			machines.append(m)
81	print "Read list of machines from file: %s" % machines_file
82	print ','.join(machines)
83
84if machines:
85	for machine in machines:
86		if not machine or re.search('\s', machine):
87			print "Invalid machine %s" % str(machine)
88			sys.exit(1)
89	machines = list(set(machines))
90	machines.sort()
91
92# We have a control file unless it's just a verify/repair job
93if len(parser.args) > 0:
94	control = parser.args[0]
95else:
96	control = None
97
98job = server_job.server_job(control, parser.args[1:], results, label,
99							user, machines, client)
100debug_dir = os.path.join(results, 'debug')
101if no_tee:
102	job.stdout.redirect(os.path.join(debug_dir, 'autoserv.stdout'))
103	job.stderr.redirect(os.path.join(debug_dir, 'autoserv.stderr'))
104else:
105	job.stdout.tee_redirect(os.path.join(debug_dir, 'autoserv.stdout'))
106	job.stderr.tee_redirect(os.path.join(debug_dir, 'autoserv.stderr'))
107
108if repair:
109	job.repair()
110	sys.exit(0)
111elif verify:
112	job.verify()
113	sys.exit(0)
114
115try:
116	job.run(reboot, install_before, install_after)
117except:
118	job.aborted = True
119	traceback.print_exc()
120
121# if the job was aborted, return a non-zero error code
122if getattr(job, 'aborted', False):
123	sys.exit(1)
124