Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright 2015 Google Inc. All Rights Reserved. | 2 # Copyright 2015 Google Inc. All Rights Reserved. |
| 3 # pylint: disable=F0401 | 3 # pylint: disable=F0401 |
| 4 | 4 |
| 5 """Start, restart and shut down masters as needed.""" | 5 """Start, restart and shut down masters as needed.""" |
| 6 | 6 |
| 7 import argparse | 7 import argparse |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import socket | |
| 10 import subprocess | 11 import subprocess |
| 11 import sys | 12 import sys |
| 12 | 13 |
| 13 from functools import partial | 14 from functools import partial |
| 14 | 15 |
| 15 from infra.libs import logs | 16 from infra.libs import logs |
| 16 from infra.libs.buildbot import master | 17 from infra.libs.buildbot import master |
| 17 from infra.libs.service_utils import daemon | 18 from infra.libs.service_utils import daemon |
| 18 from infra.libs.service_utils import outer_loop | 19 from infra.libs.service_utils import outer_loop |
| 19 from infra.services.master_lifecycle import buildbot_state | 20 from infra.services.master_lifecycle import buildbot_state |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 31 parser.add_argument('transition_time_utc', nargs='?', type=float, | 32 parser.add_argument('transition_time_utc', nargs='?', type=float, |
| 32 help='seconds since the UTC epoch to trigger the state') | 33 help='seconds since the UTC epoch to trigger the state') |
| 33 parser.add_argument('--list-all-states', action='store_true', | 34 parser.add_argument('--list-all-states', action='store_true', |
| 34 help='list all states with their actions and exit') | 35 help='list all states with their actions and exit') |
| 35 parser.add_argument('--enable-gclient-sync', action='store_true', | 36 parser.add_argument('--enable-gclient-sync', action='store_true', |
| 36 help='perform a gclient sync before every master start') | 37 help='perform a gclient sync before every master start') |
| 37 parser.add_argument('--emergency-file', | 38 parser.add_argument('--emergency-file', |
| 38 default='.stop_master_lifecycle', | 39 default='.stop_master_lifecycle', |
| 39 help='filename of the emergency stop file. if this file is found in the ' | 40 help='filename of the emergency stop file. if this file is found in the ' |
| 40 'master directory, exit immediately') | 41 'master directory, exit immediately') |
| 42 parser.add_argument('--hostname', | |
| 43 default=socket.getfqdn(), | |
| 44 help='override local hostname (currently %defaults)') | |
|
agable
2015/05/05 18:58:29
%defaults? I think you need parens "%(default)s".
ghost stip (do not use)
2015/05/05 23:41:34
yes I did! thanks
| |
| 41 parser.add_argument('--prod', action='store_true', | 45 parser.add_argument('--prod', action='store_true', |
| 42 help='actually run commands instead of printing them.') | 46 help='actually run commands instead of printing them.') |
| 43 parser.add_argument('--loop', action='store_true', | 47 parser.add_argument('--loop', action='store_true', |
| 44 help='repeatedly run the state machine. will not terminate unless killed') | 48 help='repeatedly run the state machine. will not terminate unless killed') |
| 45 parser.add_argument('--loop-sleep-secs', type=int, default=5, | 49 parser.add_argument('--loop-sleep-secs', type=int, default=5, |
| 46 help='how many seconds to wait between loop runs. default %(default)s') | 50 help='how many seconds to wait between loop runs. default %(default)s') |
| 47 parser.add_argument('--connection-timeout', type=int, default=30, | 51 parser.add_argument('--connection-timeout', type=int, default=30, |
| 48 help='how many seconds to wait for a master http request before timing ' | 52 help='how many seconds to wait for a master http request before timing ' |
| 49 'out.') | 53 'out.') |
| 50 outer_loop.add_argparse_options(parser) | 54 outer_loop.add_argparse_options(parser) |
| 51 logs.add_argparse_options(parser) | 55 logs.add_argparse_options(parser) |
| 52 | 56 |
| 53 args = parser.parse_args() | 57 args = parser.parse_args() |
| 54 logs.process_argparse_options(args) | 58 logs.process_argparse_options(args) |
| 55 | 59 |
| 56 if not args.list_all_states: | 60 if not args.list_all_states: |
| 57 if not args.directory: | 61 if not args.directory: |
| 58 parser.error('A master directory must be specified.') | 62 parser.error('A master directory must be specified.') |
| 59 if not args.transition_time_utc: | 63 if not args.transition_time_utc: |
| 60 parser.error('A transition time must be specified.') | 64 parser.error('A transition time must be specified.') |
| 61 if not args.desired_state: | 65 if not args.desired_state: |
| 62 parser.error('A desired state must be specified.') | 66 parser.error('A desired state must be specified.') |
| 63 return args | 67 return args |
| 64 | 68 |
| 65 | 69 |
| 70 def master_hostname_is_valid(local_hostname, abs_master_directory, logger): | |
| 71 master_hostname = master.get_mastermap_data( | |
| 72 abs_master_directory)['fullhost'] | |
| 73 if master_hostname != local_hostname: | |
| 74 logger.error('%s does not match %s, aborting. use --hostname to override.', | |
| 75 local_hostname, master_hostname) | |
| 76 return False | |
| 77 return True | |
| 78 | |
| 79 | |
| 66 def run_state_machine_pass( | 80 def run_state_machine_pass( |
| 67 logger, matchlist, abs_master_directory, emergency_file, desired_state, | 81 logger, matchlist, abs_master_directory, emergency_file, desired_state, |
| 68 transition_time_utc, enable_gclient_sync, prod, connection_timeout): | 82 transition_time_utc, enable_gclient_sync, prod, connection_timeout, |
| 83 hostname): | |
| 69 # pragma: no cover | 84 # pragma: no cover |
| 70 if os.path.exists(os.path.join(abs_master_directory, emergency_file)): | 85 if os.path.exists(os.path.join(abs_master_directory, emergency_file)): |
| 71 logger.error('%s detected in %s, aborting!', | 86 logger.error('%s detected in %s, aborting!', |
| 72 emergency_file, abs_master_directory) | 87 emergency_file, abs_master_directory) |
| 73 return 1 | 88 return 1 |
| 74 | 89 |
| 90 if not master_hostname_is_valid(hostname, abs_master_directory, logger): | |
| 91 return 1 | |
| 92 | |
| 75 evidence = buildbot_state.collect_evidence( | 93 evidence = buildbot_state.collect_evidence( |
| 76 abs_master_directory, connection_timeout=connection_timeout) | 94 abs_master_directory, connection_timeout=connection_timeout) |
| 77 evidence['desired_buildbot_state'] = { | 95 evidence['desired_buildbot_state'] = { |
| 78 'desired_state': desired_state, | 96 'desired_state': desired_state, |
| 79 'transition_time_utc': transition_time_utc, | 97 'transition_time_utc': transition_time_utc, |
| 80 } | 98 } |
| 81 | 99 |
| 82 state, action_name, action_items = matchlist.execution_list(evidence) | 100 state, action_name, action_items = matchlist.execution_list(evidence) |
| 83 execution_list = list( | 101 execution_list = list( |
| 84 master.convert_action_items_to_cli( | 102 master.convert_action_items_to_cli( |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 113 | 131 |
| 114 if args.list_all_states: | 132 if args.list_all_states: |
| 115 matchlist.print_all_states() | 133 matchlist.print_all_states() |
| 116 return 0 | 134 return 0 |
| 117 | 135 |
| 118 abs_master_directory = os.path.abspath(args.directory) | 136 abs_master_directory = os.path.abspath(args.directory) |
| 119 | 137 |
| 120 state_machine = partial(run_state_machine_pass, logger, | 138 state_machine = partial(run_state_machine_pass, logger, |
| 121 matchlist, abs_master_directory, args.emergency_file, | 139 matchlist, abs_master_directory, args.emergency_file, |
| 122 args.desired_state, args.transition_time_utc, args.enable_gclient_sync, | 140 args.desired_state, args.transition_time_utc, args.enable_gclient_sync, |
| 123 args.prod, args.connection_timeout) | 141 args.prod, args.connection_timeout, args.hostname) |
| 124 | 142 |
| 125 if args.loop: | 143 if args.loop: |
| 126 loop_opts = outer_loop.process_argparse_options(args) | 144 loop_opts = outer_loop.process_argparse_options(args) |
| 127 outer_loop.loop( | 145 outer_loop.loop( |
| 128 state_machine, lambda: args.loop_sleep_secs, **loop_opts) | 146 state_machine, lambda: args.loop_sleep_secs, **loop_opts) |
| 129 else: | 147 else: |
| 130 return state_machine() | 148 return state_machine() |
| 131 | 149 |
| 132 return 0 | 150 return 0 |
| 133 | 151 |
| 134 | 152 |
| 135 if __name__ == '__main__': # pragma: no cover | 153 if __name__ == '__main__': # pragma: no cover |
| 136 sys.exit(main()) | 154 sys.exit(main()) |
| OLD | NEW |