| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The Swarming Authors. All rights reserved. | 2 # Copyright 2014 The Swarming Authors. All rights reserved. |
| 3 # Use of this source code is governed by the Apache v2.0 license that can be | 3 # Use of this source code is governed by the Apache v2.0 license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Tools to control application running via dev_appserver.py. | 6 """Tools to control application running via dev_appserver.py. |
| 7 | 7 |
| 8 Useful for smoke and integration tests. | 8 Useful for smoke and integration tests. |
| 9 """ | 9 """ |
| 10 | 10 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 break | 174 break |
| 175 time.sleep(0.05) | 175 time.sleep(0.05) |
| 176 if not alive: | 176 if not alive: |
| 177 logging.error('Service %s did\'t come online', self.app_id) | 177 logging.error('Service %s did\'t come online', self.app_id) |
| 178 self.stop() | 178 self.stop() |
| 179 self.dump_log() | 179 self.dump_log() |
| 180 raise Exception('Failed to start %s' % self.app_id) | 180 raise Exception('Failed to start %s' % self.app_id) |
| 181 logging.info('Service %s is ready.', self.app_id) | 181 logging.info('Service %s is ready.', self.app_id) |
| 182 self._serving = True | 182 self._serving = True |
| 183 | 183 |
| 184 def stop(self): | 184 def stop(self, leak=False): |
| 185 """Stops dev_appserver, collects its log. | 185 """Stops dev_appserver, collects its log. |
| 186 | 186 |
| 187 Returns the process error code if applicable. | 187 Returns the process error code if applicable. |
| 188 """ | 188 """ |
| 189 if not self._proc: | 189 if not self._proc: |
| 190 return None | 190 return None |
| 191 exit_code = self._proc.poll() | 191 exit_code = self._proc.poll() |
| 192 try: | 192 try: |
| 193 logging.info('Stopping %s', self.app_id) | 193 logging.info('Stopping %s', self.app_id) |
| 194 if self._proc.poll() is None: | 194 if self._proc.poll() is None: |
| 195 try: | 195 try: |
| 196 # Send SIGTERM. | 196 # Send SIGTERM. |
| 197 self._proc.terminate() | 197 self._proc.terminate() |
| 198 except OSError: | 198 except OSError: |
| 199 pass | 199 pass |
| 200 deadline = time.time() + 5 | 200 deadline = time.time() + 5 |
| 201 while self._proc.poll() is None and time.time() < deadline: | 201 while self._proc.poll() is None and time.time() < deadline: |
| 202 time.sleep(0.05) | 202 time.sleep(0.05) |
| 203 exit_code = self._proc.poll() | 203 exit_code = self._proc.poll() |
| 204 if exit_code is None: | 204 if exit_code is None: |
| 205 logging.error('Leaking PID %d', self._proc.pid) | 205 logging.error('Leaking PID %d', self._proc.pid) |
| 206 finally: | 206 finally: |
| 207 with open(os.path.join(self._temp_root, 'dev_appserver.log'), 'r') as f: | 207 with open(os.path.join(self._temp_root, 'dev_appserver.log'), 'r') as f: |
| 208 self._log = f.read() | 208 self._log = f.read() |
| 209 try: | 209 if not leak: |
| 210 shutil.rmtree(self._temp_root) | 210 try: |
| 211 except OSError as e: | 211 shutil.rmtree(self._temp_root) |
| 212 # Log but ignore it to not mask other errors. | 212 except OSError as e: |
| 213 print >> sys.stderr, str(e) | 213 # Log but ignore it to not mask other errors. |
| 214 print >> sys.stderr, str(e) |
| 214 self._client = None | 215 self._client = None |
| 215 self._port = None | 216 self._port = None |
| 216 self._proc = None | 217 self._proc = None |
| 217 self._serving = False | 218 self._serving = False |
| 218 self._temp_root = None | 219 self._temp_root = None |
| 219 return exit_code | 220 return exit_code |
| 220 | 221 |
| 221 def wait(self): | 222 def wait(self): |
| 222 """Waits for the process to exit.""" | 223 """Waits for the process to exit.""" |
| 223 self._proc.wait() | 224 self._proc.wait() |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 | 293 |
| 293 It only works with apps that use 'auth' component. | 294 It only works with apps that use 'auth' component. |
| 294 """ | 295 """ |
| 295 if self._xsrf_token is None: | 296 if self._xsrf_token is None: |
| 296 resp = self.json_request( | 297 resp = self.json_request( |
| 297 '/auth/api/v1/accounts/self/xsrf_token', | 298 '/auth/api/v1/accounts/self/xsrf_token', |
| 298 body={}, | 299 body={}, |
| 299 headers={'X-XSRF-Token-Request': '1'}) | 300 headers={'X-XSRF-Token-Request': '1'}) |
| 300 self._xsrf_token = resp.body['xsrf_token'].encode('ascii') | 301 self._xsrf_token = resp.body['xsrf_token'].encode('ascii') |
| 301 return self._xsrf_token | 302 return self._xsrf_token |
| OLD | NEW |