OLD | NEW |
---|---|
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import contextlib | 5 import contextlib |
6 import datetime | 6 import datetime |
7 import distutils.util | |
7 import json | 8 import json |
8 import logging | 9 import logging |
9 import os | 10 import os |
10 import re | 11 import re |
11 import shutil | 12 import shutil |
12 import subprocess | 13 import subprocess |
13 import sys | 14 import sys |
14 import tempfile | 15 import tempfile |
15 | 16 |
16 | 17 |
17 from infra.libs.time_functions import zulu | 18 from infra.libs.time_functions import zulu |
18 | 19 |
19 | 20 |
20 LOGGER = logging.getLogger(__name__) | 21 LOGGER = logging.getLogger(__name__) |
21 | 22 |
23 MM_REPO = 'https://chrome-internal.googlesource.com/infradata/master-manager' | |
24 | |
22 | 25 |
23 class MasterNotFoundException(Exception): | 26 class MasterNotFoundException(Exception): |
24 pass | 27 pass |
25 | 28 |
26 | 29 |
27 def add_argparse_options(parser): | 30 def add_argparse_options(parser): |
28 parser.add_argument('masters', type=str, nargs='+', help='Master to restart.') | 31 parser.add_argument('masters', type=str, nargs='+', help='Master to restart.') |
29 parser.add_argument( | 32 parser.add_argument( |
30 '-m', '--minutes-in-future', default=15, type=int, | 33 '-m', '--minutes-in-future', default=15, type=int, |
31 help='how many minutes in the future to schedule the restart. ' | 34 help='how many minutes in the future to schedule the restart. ' |
32 'use 0 for "now." default %(default)d') | 35 'use 0 for "now." default %(default)d') |
36 parser.add_argument( | |
37 '--force', action='store_true', | |
Ryan Tseng
2015/09/08 22:10:39
+ short arg "-f"
ghost stip (do not use)
2015/09/09 00:08:53
Done.
| |
38 help='don\'t ask for confirmation, just commit') | |
33 | 39 |
34 | 40 |
35 def get_restart_time(delta): | 41 def get_restart_time(delta): |
36 """Returns a zulu time string of when to restart a master, now + delta.""" | 42 """Returns a zulu time string of when to restart a master, now + delta.""" |
37 restart_time = datetime.datetime.utcnow() + delta | 43 restart_time = datetime.datetime.utcnow() + delta |
38 return zulu.to_zulu_string(restart_time) | 44 return zulu.to_zulu_string(restart_time) |
39 | 45 |
40 | 46 |
41 @contextlib.contextmanager | 47 @contextlib.contextmanager |
42 def get_master_state_checkout(): | 48 def get_master_state_checkout(): |
43 target_dir = tempfile.mkdtemp() | 49 target_dir = tempfile.mkdtemp() |
44 mm_repo = 'https://chrome-internal.googlesource.com/infradata/master-manager' | |
45 try: | 50 try: |
46 LOGGER.info('Cloning %s into %s' % (mm_repo, target_dir)) | 51 LOGGER.info('Cloning %s into %s' % (MM_REPO, target_dir)) |
47 subprocess.call(['git', 'clone', mm_repo, target_dir]) | 52 subprocess.call(['git', 'clone', MM_REPO, target_dir]) |
48 LOGGER.info('done') | 53 LOGGER.info('done') |
49 yield target_dir | 54 yield target_dir |
50 finally: | 55 finally: |
51 shutil.rmtree(target_dir) | 56 shutil.rmtree(target_dir) |
52 | 57 |
53 | 58 |
54 def commit(target, masters): | 59 def commit(target, masters, timestring, force): |
55 """Commits the local CL via the CQ.""" | 60 """Commits the local CL via the CQ.""" |
56 desc = 'Restarting masters %s' % ', '.join(masters) | 61 desc = 'Restarting masters %s' % ', '.join(masters) |
57 subprocess.check_call( | 62 subprocess.check_call( |
58 ['git', 'commit', '--all', '--message', desc], cwd=target) | 63 ['git', 'commit', '--all', '--message', desc], cwd=target) |
64 | |
65 print | |
66 print 'Restarting the following masters at %s' % timestring | |
Ryan Tseng
2015/09/08 22:10:39
Suggestion:
Restarting the following masters in 5
ghost stip (do not use)
2015/09/09 00:08:54
Done.
| |
67 for master in sorted(masters): | |
68 print ' %s' % master | |
69 print | |
Ryan Tseng
2015/09/08 22:10:39
+print "This will upload a CL for master_manager.g
ghost stip (do not use)
2015/09/09 00:08:54
Done.
| |
70 | |
71 if not force: | |
72 print 'Commit? [Y/n]:', | |
73 input_string = raw_input() | |
74 if input_string != '' and not distutils.util.strtobool(input_string): | |
Ryan Tseng
2015/09/08 22:10:39
https://big.corp.google.com/~jmcmaster/testing/201
ghost stip (do not use)
2015/09/09 00:08:54
problem is, this has to return to stop control flo
| |
75 print 'Aborting.' | |
76 return | |
77 | |
78 print 'To cancel, edit desired_master_state.json in %s.' % MM_REPO | |
79 print | |
80 | |
59 LOGGER.info('Uploading to Rietveld and CQ.') | 81 LOGGER.info('Uploading to Rietveld and CQ.') |
60 subprocess.check_call( | 82 subprocess.check_call( |
61 ['git', 'cl', 'upload', '-m', desc, '-t', desc, | 83 ['git', 'cl', 'upload', '-m', desc, '-t', desc, |
62 '--tbr-owners', '-c', '-f'], cwd=target) | 84 '--tbr-owners', '-c', '-f'], cwd=target) |
63 | 85 |
64 | 86 |
65 def run(masters, delta): | 87 def run(masters, delta, force): |
66 """Restart all the masters in the list of masters. | 88 """Restart all the masters in the list of masters. |
67 | 89 |
68 Schedules the restart for now + delta. | 90 Schedules the restart for now + delta. |
69 """ | 91 """ |
70 # Step 1: Acquire a clean master state checkout. | 92 # Step 1: Acquire a clean master state checkout. |
71 # This repo is too small to consider caching. | 93 # This repo is too small to consider caching. |
72 master_state_dir = get_master_state_checkout() | 94 master_state_dir = get_master_state_checkout() |
73 with get_master_state_checkout() as master_state_dir: | 95 with get_master_state_checkout() as master_state_dir: |
74 master_state_json = os.path.join( | 96 master_state_json = os.path.join( |
75 master_state_dir, 'desired_master_state.json') | 97 master_state_dir, 'desired_master_state.json') |
(...skipping 15 matching lines...) Expand all Loading... | |
91 'desired_state': 'running', 'transition_time_utc': restart_time | 113 'desired_state': 'running', 'transition_time_utc': restart_time |
92 }) | 114 }) |
93 | 115 |
94 LOGGER.info('Writing back to JSON file, %d new entries' % len(master_state)) | 116 LOGGER.info('Writing back to JSON file, %d new entries' % len(master_state)) |
95 with open(master_state_json, 'w') as f: | 117 with open(master_state_json, 'w') as f: |
96 json.dump( | 118 json.dump( |
97 master_state, f, sort_keys=True, indent=2, separators=(',', ':')) | 119 master_state, f, sort_keys=True, indent=2, separators=(',', ':')) |
98 | 120 |
99 # Step 3: Send the patch to Rietveld and commit it via the CQ. | 121 # Step 3: Send the patch to Rietveld and commit it via the CQ. |
100 LOGGER.info('Committing back into repository') | 122 LOGGER.info('Committing back into repository') |
101 commit(master_state_dir, masters) | 123 commit(master_state_dir, masters, restart_time, force) |
OLD | NEW |