Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(375)

Side by Side Diff: infra/tools/master_manager/__main__.py

Issue 1108523002: Add buildbot state machine and master_manager tool. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@daemon_bot_lib_merge
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright 2015 Google Inc. All Rights Reserved.
3 # pylint: disable=F0401
4
5 """Start, restart and shut down masters as needed."""
6
7 import argparse
8 from functools import partial
9 import json
10 import os
11 import subprocess
12 import sys
13
14 from infra.services.master_lifecycle import buildbot_state
15 from infra.libs.buildbot import master
16 from infra.libs.service_utils import daemon
17 from infra.libs.service_utils import outer_loop
18
19
20 def parse_args(): # pragma: no cover
ghost stip (do not use) 2015/04/24 07:06:55 this file basically has no unittests. I'm not sure
21 parser = argparse.ArgumentParser(
22 description='Manage the state of a buildbot master.')
23 parser.add_argument('directory', nargs='?',
24 help='location of the master to manage')
25 parser.add_argument('--desired-state-file', default='desired_state.json',
26 help='location of the master to manage')
agable 2015/04/27 20:23:08 Um
ghost stip (do not use) 2015/04/29 01:30:33 Acknowledged.
27 parser.add_argument('--list-all-states', action='store_true',
28 help='list all states with their actions and exit')
29 parser.add_argument('--enable-gclient-sync', action='store_true',
30 help='perform a gclient sync before each master start')
agable 2015/04/27 20:23:08 Before each? Before any? At least once during the
ghost stip (do not use) 2015/04/29 01:30:33 Done.
31 parser.add_argument('--emergency-file',
32 default='.stop_master_lifecycle',
33 help='perform a gclient sync before each master start')
agable 2015/04/27 20:23:08 Um
agable 2015/04/27 20:23:08 Um
ghost stip (do not use) 2015/04/29 01:30:33 Acknowledged.
34 parser.add_argument('--prod', action='store_true',
35 help='actually run commands instead of printing them.')
agable 2015/04/27 20:23:08 Note loudly in the --help that this script runs in
ghost stip (do not use) 2015/04/29 01:30:33 Done.
36 parser.add_argument('--loop', action='store_true',
37 help='repeatedly run the state machine. will not terminate unless killed')
38 parser.add_argument('--loop-sleep-secs', type=int, default=5,
39 help='how many seconds to wait between loop runs. default %(default)s')
40 parser.add_argument('--connection-timeout', type=int, default=30,
41 help='how many seconds to wait for a master http request before timing '
42 'out.')
43 outer_loop.add_argparse_options(parser)
44 args = parser.parse_args()
45
46 if not args.list_all_states and not args.directory:
47 parser.error('A master directory must be specified.')
48 return args
49
50
51 def run_state_machine_pass(
agable 2015/04/27 20:23:08 Seems like this function could be tested with a fa
52 matchlist, abs_master_directory, emergency_file, desired_state_file,
53 enable_gclient_sync, prod, connection_timeout): # pragma: no cover
54 if os.path.exists(os.path.join(abs_master_directory, emergency_file)):
55 print '%s detected in %s, aborting!' % (
56 emergency_file, abs_master_directory)
57 return 1
58
59 desired_state_file = os.path.abspath(desired_state_file)
60 master_directory = os.path.basename(abs_master_directory)
61 evidence = buildbot_state.collect_evidence(
62 abs_master_directory, connection_timeout=connection_timeout)
63 with open(desired_state_file) as f:
64 evidence['desired_buildbot_state'] = json.load(f).get(master_directory)
65 if not evidence['desired_buildbot_state']:
66 raise KeyError('Couldn\'t get evidence for master %s from %s.' %
67 (master_directory, desired_state_file))
68
69 state, action_name, action_items = matchlist.execution_list(evidence)
70 execution_list = list(
71 master.convert_action_items_to_cli(
72 action_items, abs_master_directory,
73 enable_gclient=enable_gclient_sync))
74 print 'current state', state
agable 2015/04/27 20:23:08 Use infra.libs.logs
ghost stip (do not use) 2015/04/29 01:30:33 Done.
75 print 'performing action', action_name
76
77 if execution_list:
78 if prod:
79 print 'production run, executing:'
80 else:
81 print 'dry run, not executing:'
82 for cmd in execution_list:
83 print '* %s (in %s)' % (cmd['cmd'], cmd['cwd'])
84 if prod:
85 with daemon.flock(cmd['lockfile']) as acquired:
86 if acquired:
87 subprocess.check_call([str(x) for x in cmd['cmd']], cwd=cmd['cwd'])
88 else:
89 print ' lock could not be acquired, no action taken.'
90 else:
91 print 'no action to be taken.'
92 return 0
93
94
95 def main(): # pragma: no cover
96 args = parse_args()
97 matchlist = buildbot_state.construct_pattern_matcher()
98
99 if args.list_all_states:
100 matchlist.print_all_states()
101 return 0
102
103 abs_master_directory = os.path.abspath(args.directory)
104
105 state_machine = partial(run_state_machine_pass,
106 matchlist, abs_master_directory, args.emergency_file,
107 args.desired_state_file, args.enable_gclient_sync, args.prod,
108 args.connection_timeout)
109
110 if args.loop:
111 loop_opts = outer_loop.process_argparse_options(args)
112 outer_loop.loop(
113 state_machine, lambda: args.loop_sleep_secs, **loop_opts)
114 else:
115 return state_machine()
116
117 return 0
118
119
120 if __name__ == '__main__': # pragma: no cover
121 sys.exit(main())
OLDNEW
« infra/services/master_lifecycle/buildbot_state.py ('K') | « infra/tools/master_manager/__init__.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698