| OLD | NEW |
| 1 # Copyright 2013 The LUCI Authors. All rights reserved. | 1 # Copyright 2013 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 """Swarming bot main process. | 5 """Swarming bot main process. |
| 6 | 6 |
| 7 This is the program that communicates with the Swarming server, ensures the code | 7 This is the program that communicates with the Swarming server, ensures the code |
| 8 is always up to date and executes a child process to run tasks and upload | 8 is always up to date and executes a child process to run tasks and upload |
| 9 results back. | 9 results back. |
| 10 | 10 |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 'dimensions': {u'id': ['none']}, | 509 'dimensions': {u'id': ['none']}, |
| 510 'state': {}, | 510 'state': {}, |
| 511 'version': generate_version(), | 511 'version': generate_version(), |
| 512 } | 512 } |
| 513 base_dir = os.path.dirname(THIS_FILE) | 513 base_dir = os.path.dirname(THIS_FILE) |
| 514 # Use temporary Bot object to call get_attributes. Attributes are needed to | 514 # Use temporary Bot object to call get_attributes. Attributes are needed to |
| 515 # construct the "real" bot.Bot. | 515 # construct the "real" bot.Bot. |
| 516 attributes = get_attributes( | 516 attributes = get_attributes( |
| 517 bot.Bot( | 517 bot.Bot( |
| 518 remote_client.createRemoteClient(config['server'], | 518 remote_client.createRemoteClient(config['server'], |
| 519 None, config['is_grpc']), | 519 None, config.get('swarming_grpc_proxy')), |
| 520 attributes, | 520 attributes, |
| 521 config['server'], | 521 config['server'], |
| 522 config['server_version'], | 522 config['server_version'], |
| 523 base_dir, | 523 base_dir, |
| 524 _on_shutdown_hook)) | 524 _on_shutdown_hook)) |
| 525 | 525 |
| 526 # Make remote client callback use the returned bot object. We assume here | 526 # Make remote client callback use the returned bot object. We assume here |
| 527 # RemoteClient doesn't call its callback in the constructor (since 'botobj' is | 527 # RemoteClient doesn't call its callback in the constructor (since 'botobj' is |
| 528 # undefined during the construction). | 528 # undefined during the construction). |
| 529 botobj = bot.Bot( | 529 botobj = bot.Bot( |
| 530 remote_client.createRemoteClient( | 530 remote_client.createRemoteClient( |
| 531 config['server'], | 531 config['server'], |
| 532 lambda: _get_authentication_headers(botobj), | 532 lambda: _get_authentication_headers(botobj), |
| 533 config['is_grpc']), | 533 config.get('swarming_grpc_proxy')), |
| 534 attributes, | 534 attributes, |
| 535 config['server'], | 535 config['server'], |
| 536 config['server_version'], | 536 config['server_version'], |
| 537 base_dir, | 537 base_dir, |
| 538 _on_shutdown_hook) | 538 _on_shutdown_hook) |
| 539 return botobj | 539 return botobj |
| 540 | 540 |
| 541 | 541 |
| 542 def _cleanup_bot_directory(botobj): | 542 def _cleanup_bot_directory(botobj): |
| 543 """Delete anything not expected in the swarming bot directory. | 543 """Delete anything not expected in the swarming bot directory. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 568 """Returns flags to pass to run_isolated. | 568 """Returns flags to pass to run_isolated. |
| 569 | 569 |
| 570 These are not meant to be processed by task_runner.py. | 570 These are not meant to be processed by task_runner.py. |
| 571 """ | 571 """ |
| 572 settings = _get_settings(botobj) | 572 settings = _get_settings(botobj) |
| 573 partition = settings['free_partition'] | 573 partition = settings['free_partition'] |
| 574 size = os_utilities.get_disk_size(THIS_FILE) | 574 size = os_utilities.get_disk_size(THIS_FILE) |
| 575 min_free = ( | 575 min_free = ( |
| 576 _min_free_disk({'size_mb': size}, partition) + | 576 _min_free_disk({'size_mb': size}, partition) + |
| 577 partition['wiggle']) | 577 partition['wiggle']) |
| 578 return [ | 578 args = [ |
| 579 '--cache', os.path.join(botobj.base_dir, 'isolated_cache'), | 579 '--cache', os.path.join(botobj.base_dir, 'isolated_cache'), |
| 580 '--min-free-space', str(min_free), | 580 '--min-free-space', str(min_free), |
| 581 '--named-cache-root', os.path.join(botobj.base_dir, 'c'), | 581 '--named-cache-root', os.path.join(botobj.base_dir, 'c'), |
| 582 '--max-cache-size', str(settings['caches']['isolated']['size']), | 582 '--max-cache-size', str(settings['caches']['isolated']['size']), |
| 583 '--max-items', str(settings['caches']['isolated']['items']), | 583 '--max-items', str(settings['caches']['isolated']['items']), |
| 584 ] | 584 ] |
| 585 | 585 |
| 586 # Get the gRPC proxy from the config, but allow an environment variable to |
| 587 # override. |
| 588 grpc_proxy = get_config().get('isolate_grpc_proxy') |
| 589 grpc_proxy = os.environ.get('ISOLATE_GRPC_PROXY', grpc_proxy) |
| 590 if grpc_proxy is not None: |
| 591 logging.info('Isolate will use gRPC proxy %s', grpc_proxy) |
| 592 args.extend(['--grpc-proxy', grpc_proxy]) |
| 593 return args |
| 594 |
| 586 | 595 |
| 587 def _clean_cache(botobj): | 596 def _clean_cache(botobj): |
| 588 """Asks run_isolated to clean its cache. | 597 """Asks run_isolated to clean its cache. |
| 589 | 598 |
| 590 This may take a while but it ensures that in the case of a run_isolated run | 599 This may take a while but it ensures that in the case of a run_isolated run |
| 591 failed and it temporarily used more space than _min_free_disk, it can cleans | 600 failed and it temporarily used more space than _min_free_disk, it can cleans |
| 592 up the mess properly. | 601 up the mess properly. |
| 593 | 602 |
| 594 It will remove unexpected files, remove corrupted files, trim the cache size | 603 It will remove unexpected files, remove corrupted files, trim the cache size |
| 595 based on the policies and update state.json. | 604 based on the policies and update state.json. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 config = get_config() | 706 config = get_config() |
| 698 if config['enable_ts_monitoring']: | 707 if config['enable_ts_monitoring']: |
| 699 _init_ts_mon() | 708 _init_ts_mon() |
| 700 try: | 709 try: |
| 701 # First thing is to get an arbitrary url. This also ensures the network is | 710 # First thing is to get an arbitrary url. This also ensures the network is |
| 702 # up and running, which is necessary before trying to get the FQDN below. | 711 # up and running, which is necessary before trying to get the FQDN below. |
| 703 # There's no need to do error handling here - the "ping" is just to "wake | 712 # There's no need to do error handling here - the "ping" is just to "wake |
| 704 # up" the network; if there's something seriously wrong, the handshake will | 713 # up" the network; if there's something seriously wrong, the handshake will |
| 705 # fail and we'll handle it there. | 714 # fail and we'll handle it there. |
| 706 remote = remote_client.createRemoteClient(config['server'], None, | 715 remote = remote_client.createRemoteClient(config['server'], None, |
| 707 config['is_grpc']) | 716 config.get('swarming_grpc_proxy')) |
| 708 remote.ping() | 717 remote.ping() |
| 709 except Exception: | 718 except Exception: |
| 710 # url_read() already traps pretty much every exceptions. This except | 719 # url_read() already traps pretty much every exceptions. This except |
| 711 # clause is kept there "just in case". | 720 # clause is kept there "just in case". |
| 712 logging.exception('server_ping threw') | 721 logging.exception('server_ping threw') |
| 713 | 722 |
| 714 # If we are on GCE, we want to make sure GCE metadata server responds, since | 723 # If we are on GCE, we want to make sure GCE metadata server responds, since |
| 715 # we use the metadata to derive bot ID, dimensions and state. | 724 # we use the metadata to derive bot ID, dimensions and state. |
| 716 if platforms.is_gce(): | 725 if platforms.is_gce(): |
| 717 logging.info('Running on GCE, waiting for the metadata server') | 726 logging.info('Running on GCE, waiting for the metadata server') |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 global _ERROR_HANDLER_WAS_REGISTERED | 1181 global _ERROR_HANDLER_WAS_REGISTERED |
| 1173 try: | 1182 try: |
| 1174 with contextlib.closing(zipfile.ZipFile(THIS_FILE, 'r')) as f: | 1183 with contextlib.closing(zipfile.ZipFile(THIS_FILE, 'r')) as f: |
| 1175 config = json.load(f.open('config/config.json', 'r')) | 1184 config = json.load(f.open('config/config.json', 'r')) |
| 1176 if config['server'].endswith('/'): | 1185 if config['server'].endswith('/'): |
| 1177 raise ValueError('Invalid server entry %r' % config['server']) | 1186 raise ValueError('Invalid server entry %r' % config['server']) |
| 1178 except (IOError, OSError, TypeError, ValueError): | 1187 except (IOError, OSError, TypeError, ValueError): |
| 1179 logging.exception('Invalid config.json!') | 1188 logging.exception('Invalid config.json!') |
| 1180 config = { | 1189 config = { |
| 1181 'enable_ts_monitoring': False, | 1190 'enable_ts_monitoring': False, |
| 1182 'is_grpc': False, | |
| 1183 'server': '', | 1191 'server': '', |
| 1184 'server_version': 'version1', | 1192 'server_version': 'version1', |
| 1185 } | 1193 } |
| 1186 if not _ERROR_HANDLER_WAS_REGISTERED and config['server']: | 1194 if not _ERROR_HANDLER_WAS_REGISTERED and config['server']: |
| 1187 on_error.report_on_exception_exit(config['server']) | 1195 on_error.report_on_exception_exit(config['server']) |
| 1188 _ERROR_HANDLER_WAS_REGISTERED = True | 1196 _ERROR_HANDLER_WAS_REGISTERED = True |
| 1189 return config | 1197 return config |
| 1190 | 1198 |
| 1191 | 1199 |
| 1192 def main(argv): | 1200 def main(argv): |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1223 error = None | 1231 error = None |
| 1224 if len(args.unsupported) != 0: | 1232 if len(args.unsupported) != 0: |
| 1225 error = 'Unexpected arguments: %s' % args | 1233 error = 'Unexpected arguments: %s' % args |
| 1226 try: | 1234 try: |
| 1227 return _run_bot(error) | 1235 return _run_bot(error) |
| 1228 finally: | 1236 finally: |
| 1229 _call_hook_safe( | 1237 _call_hook_safe( |
| 1230 True, bot.Bot(None, None, None, None, base_dir, None), | 1238 True, bot.Bot(None, None, None, None, base_dir, None), |
| 1231 'on_bot_shutdown') | 1239 'on_bot_shutdown') |
| 1232 logging.info('main() returning') | 1240 logging.info('main() returning') |
| OLD | NEW |