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

Side by Side Diff: appengine/swarming/swarming_bot/bot_code/task_runner.py

Issue 2069903003: swarming: custom cipd package paths (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@cipd-win
Patch Set: fix _validate_cipd_path Created 4 years, 6 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 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 """Runs a Swarming task. 5 """Runs a Swarming task.
6 6
7 Downloads all the necessary files to run the task, executes the command and 7 Downloads all the necessary files to run the task, executes the command and
8 streams results back to the Swarming server. 8 streams results back to the Swarming server.
9 9
10 The process exit code is 0 when the task was executed, even if the task itself 10 The process exit code is 0 when the task was executed, even if the task itself
11 failed. If there's any failure in the setup or teardown, like invalid packet 11 failed. If there's any failure in the setup or teardown, like invalid packet
12 response, failure to contact the server, etc, a non zero exit code is used. It's 12 response, failure to contact the server, etc, a non zero exit code is used. It's
13 up to the calling process (bot_main.py) to signal that there was an internal 13 up to the calling process (bot_main.py) to signal that there was an internal
14 failure and to cancel this task run and ask the server to retry it. 14 failure and to cancel this task run and ask the server to retry it.
15 """ 15 """
16 16
17 import base64 17 import base64
18 import json 18 import json
19 import logging 19 import logging
20 import optparse 20 import optparse
21 import os 21 import os
22 import signal 22 import signal
23 import sys 23 import sys
24 import time 24 import time
25 25
26 from utils import file_path
26 from utils import net 27 from utils import net
27 from utils import on_error 28 from utils import on_error
28 from utils import subprocess42 29 from utils import subprocess42
29 from utils import zip_package 30 from utils import zip_package
30 31
31 import bot_auth 32 import bot_auth
32 import file_reader 33 import file_reader
33 34
34 35
35 # Path to this file or the zip containing this file. 36 # Path to this file or the zip containing this file.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 75
75 def get_run_isolated(): 76 def get_run_isolated():
76 """Returns the path to itself to run run_isolated. 77 """Returns the path to itself to run run_isolated.
77 78
78 Mocked in test to point to the real run_isolated.py script. 79 Mocked in test to point to the real run_isolated.py script.
79 """ 80 """
80 return [sys.executable, THIS_FILE, 'run_isolated'] 81 return [sys.executable, THIS_FILE, 'run_isolated']
81 82
82 83
83 def get_isolated_cmd( 84 def get_isolated_cmd(
84 work_dir, task_details, isolated_result, min_free_space, bot_file): 85 work_dir, task_details, isolated_result, bot_file, package_list,
86 min_free_space):
85 """Returns the command to call run_isolated. Mocked in tests.""" 87 """Returns the command to call run_isolated. Mocked in tests."""
86 assert (bool(task_details.command) != 88 assert (bool(task_details.command) !=
87 bool(task_details.isolated and task_details.isolated.get('input'))) 89 bool(task_details.isolated and task_details.isolated.get('input')))
88 bot_dir = os.path.dirname(work_dir) 90 bot_dir = os.path.dirname(work_dir)
89 if os.path.isfile(isolated_result): 91 if os.path.isfile(isolated_result):
90 os.remove(isolated_result) 92 os.remove(isolated_result)
91 cmd = get_run_isolated() 93 cmd = get_run_isolated()
92 94
93 if task_details.isolated: 95 if task_details.isolated:
94 cmd.extend( 96 cmd.extend(
95 [ 97 [
96 '-I', task_details.isolated['server'].encode('utf-8'), 98 '-I', task_details.isolated['server'].encode('utf-8'),
97 '--namespace', task_details.isolated['namespace'].encode('utf-8'), 99 '--namespace', task_details.isolated['namespace'].encode('utf-8'),
98 ]) 100 ])
99 isolated_input = task_details.isolated.get('input') 101 isolated_input = task_details.isolated.get('input')
100 if isolated_input: 102 if isolated_input:
101 cmd.extend( 103 cmd.extend(
102 [ 104 [
103 '--isolated', isolated_input, 105 '--isolated', isolated_input,
104 ]) 106 ])
105 107
106 if task_details.cipd_input and task_details.cipd_input.get('packages'): 108 if task_details.cipd_input and task_details.cipd_input.get('packages'):
107 to_pkg = lambda p: '%s:%s' % (p['package_name'], p['version']) 109 package_json = {
110 # cipd_input and run_isolated.py use the same format for 'packages'
111 # property. It is a list of package JSON objects.
112 'packages': task_details.cipd_input['packages'],
113 }
114 with open(package_list, 'wb') as f:
115 json.dump(package_json, f)
108 cmd.extend( 116 cmd.extend(
109 [ 117 [
110 '--cipd-cache', os.path.join(bot_dir, 'cipd_cache'), 118 '--cipd-cache', os.path.join(bot_dir, 'cipd_cache'),
111 '--cipd-client-package', 119 '--cipd-client-package',
112 to_pkg(task_details.cipd_input.get('client_package')), 120 task_details.cipd_input['client_package']['package_name'],
121 '--cipd-client-version',
122 task_details.cipd_input['client_package']['version'],
123 '--cipd-package-list', package_list,
113 '--cipd-server', task_details.cipd_input.get('server'), 124 '--cipd-server', task_details.cipd_input.get('server'),
114 ]) 125 ])
115 for p in task_details.cipd_input['packages']:
116 cmd.extend(['--cipd-package', to_pkg(p)])
117 126
118 cmd.extend( 127 cmd.extend(
119 [ 128 [
120 '--json', isolated_result, 129 '--json', isolated_result,
121 '--log-file', os.path.join(bot_dir, 'logs', 'run_isolated.log'), 130 '--log-file', os.path.join(bot_dir, 'logs', 'run_isolated.log'),
122 '--cache', os.path.join(bot_dir, 'isolated_cache'), 131 '--cache', os.path.join(bot_dir, 'isolated_cache'),
123 '--root-dir', os.path.join(work_dir, 'isolated'), 132 '--root-dir', os.path.join(work_dir, 'isolated'),
124 ]) 133 ])
125 if min_free_space: 134 if min_free_space:
126 cmd.extend(('--min-free-space', str(min_free_space))) 135 cmd.extend(('--min-free-space', str(min_free_space)))
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 # Signal the command is about to be started. 371 # Signal the command is about to be started.
363 last_packet = start = now = monotonic_time() 372 last_packet = start = now = monotonic_time()
364 params = { 373 params = {
365 'cost_usd': cost_usd_hour * (now - task_start) / 60. / 60., 374 'cost_usd': cost_usd_hour * (now - task_start) / 60. / 60.,
366 'id': task_details.bot_id, 375 'id': task_details.bot_id,
367 'task_id': task_details.task_id, 376 'task_id': task_details.task_id,
368 } 377 }
369 post_update(swarming_server, headers_cb(), params, None, '', 0) 378 post_update(swarming_server, headers_cb(), params, None, '', 0)
370 379
371 isolated_result = os.path.join(work_dir, 'isolated_result.json') 380 isolated_result = os.path.join(work_dir, 'isolated_result.json')
381 package_list = os.path.join(work_dir, 'package_list.json')
372 cmd = get_isolated_cmd( 382 cmd = get_isolated_cmd(
373 work_dir, task_details, isolated_result, min_free_space, bot_file) 383 work_dir, task_details, isolated_result, bot_file, package_list,
384 min_free_space)
374 # Hard timeout enforcement is deferred to run_isolated. Grace is doubled to 385 # Hard timeout enforcement is deferred to run_isolated. Grace is doubled to
375 # give one 'grace_period' slot to the child process and one slot to upload 386 # give one 'grace_period' slot to the child process and one slot to upload
376 # the results back. 387 # the results back.
377 task_details.hard_timeout = 0 388 task_details.hard_timeout = 0
378 if task_details.grace_period: 389 if task_details.grace_period:
379 task_details.grace_period *= 2 390 task_details.grace_period *= 2
380 391
381 try: 392 try:
382 # TODO(maruel): Support both channels independently and display stderr in 393 # TODO(maruel): Support both channels independently and display stderr in
383 # red. 394 # red.
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 swarming_server, headers_cb(), params, exit_code, 568 swarming_server, headers_cb(), params, exit_code,
558 stdout, output_chunk_start) 569 stdout, output_chunk_start)
559 return { 570 return {
560 u'exit_code': exit_code, 571 u'exit_code': exit_code,
561 u'hard_timeout': had_hard_timeout, 572 u'hard_timeout': had_hard_timeout,
562 u'io_timeout': had_io_timeout, 573 u'io_timeout': had_io_timeout,
563 u'must_signal_internal_failure': must_signal_internal_failure, 574 u'must_signal_internal_failure': must_signal_internal_failure,
564 u'version': OUT_VERSION, 575 u'version': OUT_VERSION,
565 } 576 }
566 finally: 577 finally:
567 try: 578 file_path.try_remove(unicode(isolated_result))
568 os.remove(isolated_result) 579 file_path.try_remove(unicode(package_list))
569 except OSError:
570 pass
571 stop_headers_reader() 580 stop_headers_reader()
572 581
573 582
574 def main(args): 583 def main(args):
575 subprocess42.inhibit_os_error_reporting() 584 subprocess42.inhibit_os_error_reporting()
576 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__) 585 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
577 parser.add_option('--in-file', help='Name of the request file') 586 parser.add_option('--in-file', help='Name of the request file')
578 parser.add_option( 587 parser.add_option(
579 '--out-file', help='Name of the JSON file to write a task summary to') 588 '--out-file', help='Name of the JSON file to write a task summary to')
580 parser.add_option( 589 parser.add_option(
(...skipping 19 matching lines...) Expand all
600 options.start = now 609 options.start = now
601 610
602 try: 611 try:
603 load_and_run( 612 load_and_run(
604 options.in_file, options.swarming_server, options.cost_usd_hour, 613 options.in_file, options.swarming_server, options.cost_usd_hour,
605 options.start, options.out_file, options.min_free_space, 614 options.start, options.out_file, options.min_free_space,
606 options.bot_file) 615 options.bot_file)
607 return 0 616 return 0
608 finally: 617 finally:
609 logging.info('quitting') 618 logging.info('quitting')
OLDNEW
« no previous file with comments | « appengine/swarming/server/task_request_test.py ('k') | appengine/swarming/swarming_bot/bot_code/task_runner_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698