| OLD | NEW |
| 1 # Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 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 logging | 6 import logging |
| 7 import threading | 7 import threading |
| 8 | 8 |
| 9 from infra.services.service_manager import service | 9 from infra.services.service_manager import service |
| 10 from infra_libs import ts_mon | 10 from infra_libs import ts_mon |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 perform the given action on the Service. | 34 perform the given action on the Service. |
| 35 | 35 |
| 36 This thread also polls the service occasionally and restarts it if it crashed. | 36 This thread also polls the service occasionally and restarts it if it crashed. |
| 37 """ | 37 """ |
| 38 | 38 |
| 39 failures = ts_mon.CounterMetric('service_manager/failures') | 39 failures = ts_mon.CounterMetric('service_manager/failures') |
| 40 reconfigs = ts_mon.CounterMetric('service_manager/reconfigs') | 40 reconfigs = ts_mon.CounterMetric('service_manager/reconfigs') |
| 41 upgrades = ts_mon.CounterMetric('service_manager/upgrades') | 41 upgrades = ts_mon.CounterMetric('service_manager/upgrades') |
| 42 | 42 |
| 43 def __init__(self, poll_interval, state_directory, service_config, | 43 def __init__(self, poll_interval, state_directory, service_config, |
| 44 cloudtail_path, |
| 44 wait_condition=None): | 45 wait_condition=None): |
| 45 """ | 46 """ |
| 46 Args: | 47 Args: |
| 47 poll_interval: How often (in seconds) to restart failed services. | 48 poll_interval: How often (in seconds) to restart failed services. |
| 48 state_directory: A file will be created in this directory (with the same | 49 state_directory: A file will be created in this directory (with the same |
| 49 name as the service) when it is running containing its PID and | 50 name as the service) when it is running containing its PID and |
| 50 starttime. | 51 starttime. |
| 51 service_config: A dictionary containing the service's config. See README | 52 service_config: A dictionary containing the service's config. See README |
| 52 for a description of the fields. | 53 for a description of the fields. |
| 54 cloudtail_path: Path to the cloudtail binary to use for logging, or None |
| 55 if logging is disabled. |
| 53 """ | 56 """ |
| 54 | 57 |
| 55 super(ServiceThread, self).__init__() | 58 super(ServiceThread, self).__init__() |
| 56 | 59 |
| 57 if wait_condition is None: # pragma: no cover | 60 if wait_condition is None: # pragma: no cover |
| 58 wait_condition = threading.Condition() | 61 wait_condition = threading.Condition() |
| 59 | 62 |
| 60 self._poll_interval = poll_interval | 63 self._poll_interval = poll_interval |
| 61 self._state_directory = state_directory | 64 self._state_directory = state_directory |
| 62 self._service = service.Service(state_directory, service_config) | 65 self._cloudtail_path = cloudtail_path |
| 66 self._service = service.Service(self._state_directory, |
| 67 service_config, |
| 68 self._cloudtail_path) |
| 63 | 69 |
| 64 self._condition = wait_condition # Protects _state. | 70 self._condition = wait_condition # Protects _state. |
| 65 self._state = _State() # _condition must be held. | 71 self._state = _State() # _condition must be held. |
| 66 self._state_changed = False | 72 self._state_changed = False |
| 67 | 73 |
| 68 self._started = False # Whether we started the service already. | 74 self._started = False # Whether we started the service already. |
| 69 | 75 |
| 70 def _wait(self): | 76 def _wait(self): |
| 71 with self._condition: | 77 with self._condition: |
| 72 if not self._state_changed: # pragma: no cover | 78 if not self._state_changed: # pragma: no cover |
| (...skipping 18 matching lines...) Expand all Loading... |
| 91 state = self._wait() | 97 state = self._wait() |
| 92 | 98 |
| 93 if state.exit: | 99 if state.exit: |
| 94 return | 100 return |
| 95 elif state.new_config is not None: | 101 elif state.new_config is not None: |
| 96 # Stop the service if it's currently running. | 102 # Stop the service if it's currently running. |
| 97 self._service.stop() | 103 self._service.stop() |
| 98 | 104 |
| 99 # Recreate it with the new config and start it. | 105 # Recreate it with the new config and start it. |
| 100 self.reconfigs.increment(fields={'service': self._service.name}) | 106 self.reconfigs.increment(fields={'service': self._service.name}) |
| 101 self._service = service.Service( | 107 self._service = service.Service(self._state_directory, |
| 102 self._state_directory, state.new_config) | 108 state.new_config, |
| 109 self._cloudtail_path) |
| 103 self._service.start() | 110 self._service.start() |
| 104 self._started = True | 111 self._started = True |
| 105 elif state.should_run == False: | 112 elif state.should_run == False: |
| 106 # Ensure the service is stopped. | 113 # Ensure the service is stopped. |
| 107 self._service.stop() | 114 self._service.stop() |
| 108 self._started = False | 115 self._started = False |
| 109 elif state.should_run == True: | 116 elif state.should_run == True: |
| 110 try: | 117 try: |
| 111 state = self._service.get_running_process_state() | 118 state = self._service.get_running_process_state() |
| 112 except service.UnexpectedProcessStateError: | 119 except service.UnexpectedProcessStateError: |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 with self._change_state(): | 162 with self._change_state(): |
| 156 self._state.exit = True | 163 self._state.exit = True |
| 157 | 164 |
| 158 if join: # pragma: no cover | 165 if join: # pragma: no cover |
| 159 self.join() | 166 self.join() |
| 160 | 167 |
| 161 def restart_with_new_config(self, new_config): | 168 def restart_with_new_config(self, new_config): |
| 162 with self._change_state(): | 169 with self._change_state(): |
| 163 self._state.new_config = new_config | 170 self._state.new_config = new_config |
| 164 self._state.should_run = True | 171 self._state.should_run = True |
| OLD | NEW |