Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: appengine/swarming/handlers_bot.py

Issue 2267363004: Add CIPD pin reporting to swarming. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@master
Patch Set: Fix bottest Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « appengine/swarming/cipd_test.py ('k') | appengine/swarming/handlers_bot_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2015 The LUCI Authors. All rights reserved. 1 # Copyright 2015 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 """Internal bot API handlers.""" 5 """Internal bot API handlers."""
6 6
7 import base64 7 import base64
8 import json 8 import json
9 import logging 9 import logging
10 import re 10 import re
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 self.send_response({}) 625 self.send_response({})
626 626
627 627
628 class BotTaskUpdateHandler(_BotApiHandler): 628 class BotTaskUpdateHandler(_BotApiHandler):
629 """Receives updates from a Bot for a task. 629 """Receives updates from a Bot for a task.
630 630
631 The handler verifies packets are processed in order and will refuse 631 The handler verifies packets are processed in order and will refuse
632 out-of-order packets. 632 out-of-order packets.
633 """ 633 """
634 ACCEPTED_KEYS = { 634 ACCEPTED_KEYS = {
635 u'bot_overhead', u'cipd_stats', u'cost_usd', u'duration', u'exit_code', 635 u'bot_overhead', u'cipd_pins', u'cipd_stats', u'cost_usd', u'duration',
636 u'hard_timeout', u'id', u'io_timeout', u'isolated_stats', u'output', 636 u'exit_code', u'hard_timeout', u'id', u'io_timeout', u'isolated_stats',
637 u'output_chunk_start', u'outputs_ref', u'task_id', 637 u'output', u'output_chunk_start', u'outputs_ref', u'task_id',
638 } 638 }
639 REQUIRED_KEYS = {u'id', u'task_id'} 639 REQUIRED_KEYS = {u'id', u'task_id'}
640 640
641 @auth.public # auth happens in bot_auth.validate_bot_id_and_fetch_config() 641 @auth.public # auth happens in bot_auth.validate_bot_id_and_fetch_config()
642 def post(self, task_id=None): 642 def post(self, task_id=None):
643 # Unlike handshake and poll, we do not accept invalid keys here. This code 643 # Unlike handshake and poll, we do not accept invalid keys here. This code
644 # path is much more strict. 644 # path is much more strict.
645 request = self.parse_body() 645 request = self.parse_body()
646 msg = log_unexpected_subset_keys( 646 msg = log_unexpected_subset_keys(
647 self.ACCEPTED_KEYS, self.REQUIRED_KEYS, request, self.request, 'bot', 647 self.ACCEPTED_KEYS, self.REQUIRED_KEYS, request, self.request, 'bot',
648 'keys') 648 'keys')
649 if msg: 649 if msg:
650 self.abort_with_error(400, error=msg) 650 self.abort_with_error(400, error=msg)
651 651
652 bot_id = request['id'] 652 bot_id = request['id']
653 task_id = request['task_id'] 653 task_id = request['task_id']
654 654
655 # Make sure bot self-reported ID matches the authentication token. Raises 655 # Make sure bot self-reported ID matches the authentication token. Raises
656 # auth.AuthorizationError if not. 656 # auth.AuthorizationError if not.
657 bot_auth.validate_bot_id_and_fetch_config(bot_id) 657 bot_auth.validate_bot_id_and_fetch_config(bot_id)
658 658
659 bot_overhead = request.get('bot_overhead') 659 bot_overhead = request.get('bot_overhead')
660 cipd_pins = request.get('cipd_pins')
661 cipd_stats = request.get('cipd_stats')
660 cost_usd = request.get('cost_usd', 0) 662 cost_usd = request.get('cost_usd', 0)
661 duration = request.get('duration') 663 duration = request.get('duration')
662 exit_code = request.get('exit_code') 664 exit_code = request.get('exit_code')
663 hard_timeout = request.get('hard_timeout') 665 hard_timeout = request.get('hard_timeout')
664 io_timeout = request.get('io_timeout') 666 io_timeout = request.get('io_timeout')
665 isolated_stats = request.get('isolated_stats') 667 isolated_stats = request.get('isolated_stats')
666 cipd_stats = request.get('cipd_stats')
667 output = request.get('output') 668 output = request.get('output')
668 output_chunk_start = request.get('output_chunk_start') 669 output_chunk_start = request.get('output_chunk_start')
669 outputs_ref = request.get('outputs_ref') 670 outputs_ref = request.get('outputs_ref')
670 671
671 if (isolated_stats or cipd_stats) and bot_overhead is None: 672 if (isolated_stats or cipd_stats) and bot_overhead is None:
672 ereporter2.log_request( 673 ereporter2.log_request(
673 request=self.request, 674 request=self.request,
674 source='server', 675 source='server',
675 category='task_failure', 676 category='task_failure',
676 message='Failed to update task: %s' % task_id) 677 message='Failed to update task: %s' % task_id)
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 logging.error('Failed to decode output\n%s\n%r', e, output) 714 logging.error('Failed to decode output\n%s\n%r', e, output)
714 output = output.encode('ascii', 'replace') 715 output = output.encode('ascii', 'replace')
715 except TypeError as e: 716 except TypeError as e:
716 # Save the output as-is instead. The error will be logged in ereporter2 717 # Save the output as-is instead. The error will be logged in ereporter2
717 # and returning a HTTP 500 would only force the bot to stay in a retry 718 # and returning a HTTP 500 would only force the bot to stay in a retry
718 # loop. 719 # loop.
719 logging.error('Failed to decode output\n%s\n%r', e, output) 720 logging.error('Failed to decode output\n%s\n%r', e, output)
720 if outputs_ref: 721 if outputs_ref:
721 outputs_ref = task_request.FilesRef(**outputs_ref) 722 outputs_ref = task_request.FilesRef(**outputs_ref)
722 723
724 if cipd_pins:
725 cipd_pins = task_result.CipdPins(
726 client_package=task_request.CipdPackage(
727 **cipd_pins['client_package']),
728 packages=[
729 task_request.CipdPackage(**args) for args in cipd_pins['packages']]
730 )
731
723 try: 732 try:
724 state = task_scheduler.bot_update_task( 733 state = task_scheduler.bot_update_task(
725 run_result_key=run_result_key, 734 run_result_key=run_result_key,
726 bot_id=bot_id, 735 bot_id=bot_id,
727 output=output, 736 output=output,
728 output_chunk_start=output_chunk_start, 737 output_chunk_start=output_chunk_start,
729 exit_code=exit_code, 738 exit_code=exit_code,
730 duration=duration, 739 duration=duration,
731 hard_timeout=hard_timeout, 740 hard_timeout=hard_timeout,
732 io_timeout=io_timeout, 741 io_timeout=io_timeout,
733 cost_usd=cost_usd, 742 cost_usd=cost_usd,
734 outputs_ref=outputs_ref, 743 outputs_ref=outputs_ref,
744 cipd_pins=cipd_pins,
735 performance_stats=performance_stats) 745 performance_stats=performance_stats)
736 if not state: 746 if not state:
737 logging.info('Failed to update, please retry') 747 logging.info('Failed to update, please retry')
738 self.abort_with_error(500, error='Failed to update, please retry') 748 self.abort_with_error(500, error='Failed to update, please retry')
739 749
740 if state in (task_result.State.COMPLETED, task_result.State.TIMED_OUT): 750 if state in (task_result.State.COMPLETED, task_result.State.TIMED_OUT):
741 action = 'task_completed' 751 action = 'task_completed'
742 elif state == task_result.State.CANCELED: 752 elif state == task_result.State.CANCELED:
743 action = 'task_canceled' 753 action = 'task_canceled'
744 else: 754 else:
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 ('/swarming/api/v1/bot/poll', BotPollHandler), 850 ('/swarming/api/v1/bot/poll', BotPollHandler),
841 ('/swarming/api/v1/bot/server_ping', ServerPingHandler), 851 ('/swarming/api/v1/bot/server_ping', ServerPingHandler),
842 ('/swarming/api/v1/bot/task_update', BotTaskUpdateHandler), 852 ('/swarming/api/v1/bot/task_update', BotTaskUpdateHandler),
843 ('/swarming/api/v1/bot/task_update/<task_id:[a-f0-9]+>', 853 ('/swarming/api/v1/bot/task_update/<task_id:[a-f0-9]+>',
844 BotTaskUpdateHandler), 854 BotTaskUpdateHandler),
845 ('/swarming/api/v1/bot/task_error', BotTaskErrorHandler), 855 ('/swarming/api/v1/bot/task_error', BotTaskErrorHandler),
846 ('/swarming/api/v1/bot/task_error/<task_id:[a-f0-9]+>', 856 ('/swarming/api/v1/bot/task_error/<task_id:[a-f0-9]+>',
847 BotTaskErrorHandler), 857 BotTaskErrorHandler),
848 ] 858 ]
849 return [webapp2.Route(*i) for i in routes] 859 return [webapp2.Route(*i) for i in routes]
OLDNEW
« no previous file with comments | « appengine/swarming/cipd_test.py ('k') | appengine/swarming/handlers_bot_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698