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

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: comments and some tests 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
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 611 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 self.send_response({}) 622 self.send_response({})
623 623
624 624
625 class BotTaskUpdateHandler(_BotApiHandler): 625 class BotTaskUpdateHandler(_BotApiHandler):
626 """Receives updates from a Bot for a task. 626 """Receives updates from a Bot for a task.
627 627
628 The handler verifies packets are processed in order and will refuse 628 The handler verifies packets are processed in order and will refuse
629 out-of-order packets. 629 out-of-order packets.
630 """ 630 """
631 ACCEPTED_KEYS = { 631 ACCEPTED_KEYS = {
632 u'bot_overhead', u'cipd_stats', u'cost_usd', u'duration', u'exit_code', 632 u'bot_overhead', u'cipd_pins', u'cipd_stats', u'cost_usd', u'duration',
633 u'hard_timeout', u'id', u'io_timeout', u'isolated_stats', u'output', 633 u'exit_code', u'hard_timeout', u'id', u'io_timeout', u'isolated_stats',
634 u'output_chunk_start', u'outputs_ref', u'task_id', 634 u'output', u'output_chunk_start', u'outputs_ref', u'task_id',
635 } 635 }
636 REQUIRED_KEYS = {u'id', u'task_id'} 636 REQUIRED_KEYS = {u'id', u'task_id'}
637 637
638 @auth.public # auth happens in bot_auth.validate_bot_id_and_fetch_config() 638 @auth.public # auth happens in bot_auth.validate_bot_id_and_fetch_config()
639 def post(self, task_id=None): 639 def post(self, task_id=None):
640 # Unlike handshake and poll, we do not accept invalid keys here. This code 640 # Unlike handshake and poll, we do not accept invalid keys here. This code
641 # path is much more strict. 641 # path is much more strict.
642 request = self.parse_body() 642 request = self.parse_body()
643 msg = log_unexpected_subset_keys( 643 msg = log_unexpected_subset_keys(
644 self.ACCEPTED_KEYS, self.REQUIRED_KEYS, request, self.request, 'bot', 644 self.ACCEPTED_KEYS, self.REQUIRED_KEYS, request, self.request, 'bot',
645 'keys') 645 'keys')
646 if msg: 646 if msg:
647 self.abort_with_error(400, error=msg) 647 self.abort_with_error(400, error=msg)
648 648
649 bot_id = request['id'] 649 bot_id = request['id']
650 task_id = request['task_id'] 650 task_id = request['task_id']
651 651
652 # Make sure bot self-reported ID matches the authentication token. Raises 652 # Make sure bot self-reported ID matches the authentication token. Raises
653 # auth.AuthorizationError if not. 653 # auth.AuthorizationError if not.
654 bot_auth.validate_bot_id_and_fetch_config(bot_id) 654 bot_auth.validate_bot_id_and_fetch_config(bot_id)
655 655
656 bot_overhead = request.get('bot_overhead') 656 bot_overhead = request.get('bot_overhead')
657 cipd_pins = request.get('cipd_pins')
658 cipd_stats = request.get('cipd_stats')
657 cost_usd = request.get('cost_usd', 0) 659 cost_usd = request.get('cost_usd', 0)
658 duration = request.get('duration') 660 duration = request.get('duration')
659 exit_code = request.get('exit_code') 661 exit_code = request.get('exit_code')
660 hard_timeout = request.get('hard_timeout') 662 hard_timeout = request.get('hard_timeout')
661 io_timeout = request.get('io_timeout') 663 io_timeout = request.get('io_timeout')
662 isolated_stats = request.get('isolated_stats') 664 isolated_stats = request.get('isolated_stats')
663 cipd_stats = request.get('cipd_stats')
664 output = request.get('output') 665 output = request.get('output')
665 output_chunk_start = request.get('output_chunk_start') 666 output_chunk_start = request.get('output_chunk_start')
666 outputs_ref = request.get('outputs_ref') 667 outputs_ref = request.get('outputs_ref')
667 668
668 if (isolated_stats or cipd_stats) and bot_overhead is None: 669 if (isolated_stats or cipd_stats) and bot_overhead is None:
669 ereporter2.log_request( 670 ereporter2.log_request(
670 request=self.request, 671 request=self.request,
671 source='server', 672 source='server',
672 category='task_failure', 673 category='task_failure',
673 message='Failed to update task: %s' % task_id) 674 message='Failed to update task: %s' % task_id)
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 logging.error('Failed to decode output\n%s\n%r', e, output) 711 logging.error('Failed to decode output\n%s\n%r', e, output)
711 output = output.encode('ascii', 'replace') 712 output = output.encode('ascii', 'replace')
712 except TypeError as e: 713 except TypeError as e:
713 # Save the output as-is instead. The error will be logged in ereporter2 714 # Save the output as-is instead. The error will be logged in ereporter2
714 # and returning a HTTP 500 would only force the bot to stay in a retry 715 # and returning a HTTP 500 would only force the bot to stay in a retry
715 # loop. 716 # loop.
716 logging.error('Failed to decode output\n%s\n%r', e, output) 717 logging.error('Failed to decode output\n%s\n%r', e, output)
717 if outputs_ref: 718 if outputs_ref:
718 outputs_ref = task_request.FilesRef(**outputs_ref) 719 outputs_ref = task_request.FilesRef(**outputs_ref)
719 720
721 if cipd_pins:
722 cipd_pins = [task_request.CipdPackage(**pin) for pin in cipd_pins]
723
720 try: 724 try:
721 state = task_scheduler.bot_update_task( 725 state = task_scheduler.bot_update_task(
722 run_result_key=run_result_key, 726 run_result_key=run_result_key,
723 bot_id=bot_id, 727 bot_id=bot_id,
724 output=output, 728 output=output,
725 output_chunk_start=output_chunk_start, 729 output_chunk_start=output_chunk_start,
726 exit_code=exit_code, 730 exit_code=exit_code,
727 duration=duration, 731 duration=duration,
728 hard_timeout=hard_timeout, 732 hard_timeout=hard_timeout,
729 io_timeout=io_timeout, 733 io_timeout=io_timeout,
730 cost_usd=cost_usd, 734 cost_usd=cost_usd,
731 outputs_ref=outputs_ref, 735 outputs_ref=outputs_ref,
736 cipd_pins=cipd_pins,
732 performance_stats=performance_stats) 737 performance_stats=performance_stats)
733 if not state: 738 if not state:
734 logging.info('Failed to update, please retry') 739 logging.info('Failed to update, please retry')
735 self.abort_with_error(500, error='Failed to update, please retry') 740 self.abort_with_error(500, error='Failed to update, please retry')
736 741
737 if state in (task_result.State.COMPLETED, task_result.State.TIMED_OUT): 742 if state in (task_result.State.COMPLETED, task_result.State.TIMED_OUT):
738 action = 'task_completed' 743 action = 'task_completed'
739 elif state == task_result.State.CANCELED: 744 elif state == task_result.State.CANCELED:
740 action = 'task_canceled' 745 action = 'task_canceled'
741 else: 746 else:
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 ('/swarming/api/v1/bot/poll', BotPollHandler), 842 ('/swarming/api/v1/bot/poll', BotPollHandler),
838 ('/swarming/api/v1/bot/server_ping', ServerPingHandler), 843 ('/swarming/api/v1/bot/server_ping', ServerPingHandler),
839 ('/swarming/api/v1/bot/task_update', BotTaskUpdateHandler), 844 ('/swarming/api/v1/bot/task_update', BotTaskUpdateHandler),
840 ('/swarming/api/v1/bot/task_update/<task_id:[a-f0-9]+>', 845 ('/swarming/api/v1/bot/task_update/<task_id:[a-f0-9]+>',
841 BotTaskUpdateHandler), 846 BotTaskUpdateHandler),
842 ('/swarming/api/v1/bot/task_error', BotTaskErrorHandler), 847 ('/swarming/api/v1/bot/task_error', BotTaskErrorHandler),
843 ('/swarming/api/v1/bot/task_error/<task_id:[a-f0-9]+>', 848 ('/swarming/api/v1/bot/task_error/<task_id:[a-f0-9]+>',
844 BotTaskErrorHandler), 849 BotTaskErrorHandler),
845 ] 850 ]
846 return [webapp2.Route(*i) for i in routes] 851 return [webapp2.Route(*i) for i in routes]
OLDNEW
« no previous file with comments | « no previous file | appengine/swarming/handlers_bot_test.py » ('j') | appengine/swarming/message_conversion.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698