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

Side by Side Diff: scripts/slave/goma_utils.py

Issue 2178193003: Move goma_teardown, goma_setup and determine_goma_jobs to goma_utils.py (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Move some code to goma_utils Created 4 years, 4 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 | « scripts/slave/compile.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Functions specific to handle goma related info. 5 """Functions specific to handle goma related info.
6 """ 6 """
7 7
8 import base64 8 import base64
9 import datetime 9 import datetime
10 import getpass 10 import getpass
11 import glob 11 import glob
12 import gzip 12 import gzip
13 import json 13 import json
14 import multiprocessing
14 import os 15 import os
15 import re 16 import re
16 import shutil 17 import shutil
17 import socket 18 import socket
19 import subprocess
18 import sys 20 import sys
19 import tempfile 21 import tempfile
20 import time 22 import time
21 23
22 from common import chromium_utils 24 from common import chromium_utils
23 from slave import slave_utils 25 from slave import slave_utils
24 26
25 # The Google Cloud Storage bucket to store logs related to goma. 27 # The Google Cloud Storage bucket to store logs related to goma.
26 GOMA_LOG_GS_BUCKET = 'chrome-goma-log' 28 GOMA_LOG_GS_BUCKET = 'chrome-goma-log'
27 29
28 # Platform dependent location of run command. 30 # Platform dependent location of run command.
29 PLATFORM_RUN_CMD = { 31 PLATFORM_RUN_CMD = {
30 # os.name: run_cmd to use. 32 # os.name: run_cmd to use.
31 'nt': 'C:\\infra-python\\run.py', 33 'nt': 'C:\\infra-python\\run.py',
32 'posix': '/opt/infra-python/run.py', 34 'posix': '/opt/infra-python/run.py',
33 } 35 }
34 36
35 TIMESTAMP_PATTERN = re.compile('(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2})') 37 TIMESTAMP_PATTERN = re.compile('(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2})')
36 TIMESTAMP_FORMAT = '%Y/%m/%d %H:%M:%S' 38 TIMESTAMP_FORMAT = '%Y/%m/%d %H:%M:%S'
37 39
40 # Define a bunch of directory paths (same as bot_update.py)
41 CURRENT_DIR = os.path.abspath(os.getcwd())
42 BUILDER_DIR = os.path.dirname(CURRENT_DIR)
43 SLAVE_DIR = os.path.dirname(BUILDER_DIR)
44 # GOMA_CACHE_DIR used for caching long-term data.
45 DEFAULT_GOMA_CACHE_DIR = os.path.join(SLAVE_DIR, 'goma_cache')
46
47
38 48
39 def GetShortHostname(): 49 def GetShortHostname():
40 """Get this machine's short hostname in lower case.""" 50 """Get this machine's short hostname in lower case."""
41 return socket.gethostname().split('.')[0].lower() 51 return socket.gethostname().split('.')[0].lower()
42 52
43 53
44 def GetGomaTmpDirectory(): 54 def GetGomaTmpDirectory():
45 """Get goma's temp directory.""" 55 """Get goma's temp directory."""
46 candidates = ['GOMA_TMP_DIR', 'TEST_TMPDIR', 'TMPDIR', 'TMP'] 56 candidates = ['GOMA_TMP_DIR', 'TEST_TMPDIR', 'TMPDIR', 'TMP']
47 for candidate in candidates: 57 for candidate in candidates:
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 retcode = chromium_utils.RunCommand( 358 retcode = chromium_utils.RunCommand(
349 cmd, filter_obj=cmd_filter, 359 cmd, filter_obj=cmd_filter,
350 max_time=30) 360 max_time=30)
351 if retcode: 361 if retcode:
352 print('Execution of send_ts_mon_values failed with code %s' 362 print('Execution of send_ts_mon_values failed with code %s'
353 % retcode) 363 % retcode)
354 print '\n'.join(cmd_filter.text) 364 print '\n'.join(cmd_filter.text)
355 365
356 except Exception as ex: 366 except Exception as ex:
357 print('error while sending ts mon json_file=%s: %s' % (json_file, ex)) 367 print('error while sending ts mon json_file=%s: %s' % (json_file, ex))
368
369
370 def goma_setup(options, env):
Yoshisato Yanagisawa 2016/07/27 02:54:46 options is data structure made in compile.py, why
371 """Sets up goma if necessary.
372
373 If using the Goma compiler, first call goma_ctl to ensure the proxy is
374 available, and returns (True, instance of cloudtail subprocess).
375 If it failed to start up compiler_proxy, modify options.compiler and
376 options.goma_dir and returns (False, None)
377
378 Args:
379 options (Option): options for goma
380 env (dict): env for compiler_proxy
381
382 Returns:
383 (bool, subprocess.Popen):
384 first element represents whether compiler_proxy starts successfully
385 second element is subprocess instance of cloudtail
386
387 """
388 if options.compiler not in ('goma', 'goma-clang'):
389 # Unset goma_dir to make sure we'll not use goma.
390 options.goma_dir = None
391 return False, None
392
393 hostname = GetShortHostname()
394 # HACK(shinyak, yyanagisawa, goma): Windows NO_NACL_GOMA (crbug.com/390764)
Yoshisato Yanagisawa 2016/07/27 02:54:46 Can you remove this HACK, and injected from compil
ukai 2016/07/27 06:52:54 do we still need this hack?
Yoshisato Yanagisawa 2016/07/27 07:02:31 I do not think so. I feel a bit guilty but I feel
395 # Building NaCl untrusted code using goma brings large performance
396 # improvement but it sometimes cause build failure by race condition.
397 # Let me enable goma build on goma canary buildslaves to confirm the issue
398 # has been fixed by a workaround.
399 # vm*-m4 are trybots. build*-m1 and vm*-m1 are all goma canary bots.
400 if hostname in ['build28-m1', 'build58-m1', 'vm191-m1', 'vm480-m1',
401 'vm820-m1', 'vm821-m1', 'vm848-m1']:
402 env['NO_NACL_GOMA'] = 'false'
403
404 if options.goma_fail_fast:
405 # startup fails when initial ping failed.
406 env['GOMA_FAIL_FAST'] = 'true'
407 else:
408 # If a network error continues 30 minutes, compiler_proxy make the compile
409 # failed. When people use goma, they expect using goma is faster than
410 # compile locally. If goma cannot guarantee that, let it make compile
411 # as error.
412 env['GOMA_ALLOWED_NETWORK_ERROR_DURATION'] = '1800'
413
414 # HACK(yyanagisawa): reduce GOMA_BURST_MAX_PROCS crbug.com/592306
415 # Recently, I sometimes see buildbot slave time out, one possibility I come
416 # up with is burst mode use up resource.
417 # Let me temporary set small values to GOMA_BURST_MAX_PROCS to confirm
418 # the possibility is true or false.
419 max_subprocs = '3'
420 max_heavy_subprocs = '1'
421 number_of_processors = 0
422 try:
423 number_of_processors = multiprocessing.cpu_count()
424 except NotImplementedError:
425 print 'cpu_count() is not implemented, using default value.'
426 number_of_processors = 1
427 if number_of_processors > 3:
428 max_subprocs = str(number_of_processors - 1)
429 max_heavy_subprocs = str(number_of_processors / 2)
430 env['GOMA_BURST_MAX_SUBPROCS'] = max_subprocs
431 env['GOMA_BURST_MAX_SUBPROCS_LOW'] = max_subprocs
432 env['GOMA_BURST_MAX_SUBPROCS_HEAVY'] = max_heavy_subprocs
433
434 # Caches CRLs in GOMA_CACHE_DIR.
435 # Since downloading CRLs is usually slow, caching them may improves
436 # compiler_proxy start time.
437 if not os.path.exists(options.goma_cache_dir):
438 os.mkdir(options.goma_cache_dir, 0700)
439 env['GOMA_CACHE_DIR'] = options.goma_cache_dir
440
441 # Enable DepsCache. DepsCache caches the list of files to send goma server.
442 # This will greatly improve build speed when cache is warmed.
443 # The cache file is stored in the target output directory.
444 env['GOMA_DEPS_CACHE_DIR'] = (
445 options.goma_deps_cache_dir or options.target_output_dir)
446
447 if not env.get('GOMA_HERMETIC'):
448 env['GOMA_HERMETIC'] = options.goma_hermetic
449 if options.goma_enable_remote_link:
450 env['GOMA_ENABLE_REMOTE_LINK'] = options.goma_enable_remote_link
451 if options.goma_store_local_run_output:
452 env['GOMA_STORE_LOCAL_RUN_OUTPUT'] = options.goma_store_local_run_output
453 if options.goma_enable_compiler_info_cache:
454 # Will be stored in GOMA_CACHE_DIR.
455 env['GOMA_COMPILER_INFO_CACHE_FILE'] = 'goma-compiler-info.cache'
456
457 if options.build_data_dir:
458 env['GOMA_DUMP_STATS_FILE'] = os.path.join(options.build_data_dir,
459 'goma_stats_proto')
460
461 # goma is requested.
462 goma_key = os.path.join(options.goma_dir, 'goma.key')
463 if os.path.exists(goma_key):
464 env['GOMA_API_KEY_FILE'] = goma_key
465 if options.goma_service_account_json_file:
466 env['GOMA_SERVICE_ACCOUNT_JSON_FILE'] = \
467 options.goma_service_account_json_file
468 if chromium_utils.IsWindows():
469 env['GOMA_RPC_EXTRA_PARAMS'] = '?win'
470
471 # HACK(yyanagisawa): update environment files on |env| update.
472 # For compiling on Windows, environment in environment files are used.
473 # It means even if enviroment such as GOMA_DISABLED is updated in
474 # compile.py, the update will be ignored.
475 # We need to update environment files to reflect the update.
476 if chromium_utils.IsWindows() and NeedEnvFileUpdateOnWin(env):
477 print 'Updating environment.{x86,x64} files.'
478 UpdateWindowsEnvironment(options.target_output_dir, env)
479
480
481 goma_start_command = ['restart']
482 goma_ctl_cmd = [sys.executable,
483 os.path.join(options.goma_dir, 'goma_ctl.py')]
484 result = chromium_utils.RunCommand(goma_ctl_cmd + goma_start_command, env=env)
485 if not result:
486 # goma started sucessfully.
487 # Making cloudtail to upload the latest log.
488 # TODO(yyanagisawa): install cloudtail from CIPD.
489 cloudtail_path = '/opt/infra-tools/cloudtail'
490 if chromium_utils.IsWindows():
491 cloudtail_path = 'C:\\infra-tools\\cloudtail'
492 try:
493 cloudtail_proc = subprocess.Popen(
494 [cloudtail_path, 'tail', '--log-id', 'goma_compiler_proxy', '--path',
495 GetLatestGomaCompilerProxyInfo()])
496 except Exception as e:
497 print 'failed to invoke cloudtail: %s' % e
498 return True, None
499 return True, cloudtail_proc
500
501 if options.goma_jsonstatus:
502 chromium_utils.RunCommand(
503 goma_ctl_cmd + ['jsonstatus', options.goma_jsonstatus], env=env)
504 SendGomaTsMon(options.goma_jsonstatus, -1)
505
506 # Try to stop compiler_proxy so that it flushes logs and stores
507 # GomaStats.
508 if options.build_data_dir:
509 env['GOMACTL_CRASH_REPORT_ID_FILE'] = os.path.join(options.build_data_dir,
510 'crash_report_id_file')
511 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env)
512
513 override_gsutil = None
514 if options.gsutil_py_path:
515 override_gsutil = [sys.executable, options.gsutil_py_path]
516
517 # Upload compiler_proxy.INFO to investigate the reason of compiler_proxy
518 # start-up failure.
519 UploadGomaCompilerProxyInfo(override_gsutil=override_gsutil)
520 # Upload GomaStats to make it monitored.
521 if env.get('GOMA_DUMP_STATS_FILE'):
522 SendGomaStats(env['GOMA_DUMP_STATS_FILE'],
523 env.get('GOMACTL_CRASH_REPORT_ID_FILE'),
524 options.build_data_dir)
525
526 if options.goma_disable_local_fallback:
527 print 'error: failed to start goma; fallback has been disabled'
528 raise Exception('failed to start goma')
529
530 print 'warning: failed to start goma. falling back to non-goma'
531 # Drop goma from options.compiler
532 options.compiler = options.compiler.replace('goma-', '')
533 if options.compiler == 'goma':
534 options.compiler = None
535 # Reset options.goma_dir.
536 options.goma_dir = None
537 env['GOMA_DISABLED'] = '1'
538 return False, None
539
540
541 def goma_teardown(options, env, exit_status, cloudtail_proc):
Yoshisato Yanagisawa 2016/07/27 02:54:47 The same, is it impossible for you to eliminate de
542 """Tears down goma if necessary. """
543 if (options.compiler in ('goma', 'goma-clang') and
544 options.goma_dir):
545 override_gsutil = None
546 if options.gsutil_py_path:
547 override_gsutil = [sys.executable, options.gsutil_py_path]
548
549 # If goma compiler_proxy crashes during the build, there could be crash
550 # dump.
551 if options.build_data_dir:
552 env['GOMACTL_CRASH_REPORT_ID_FILE'] = os.path.join(options.build_data_dir,
553 'crash_report_id_file')
554 goma_ctl_cmd = [sys.executable,
555 os.path.join(options.goma_dir, 'goma_ctl.py')]
556 if options.goma_jsonstatus:
557 chromium_utils.RunCommand(
558 goma_ctl_cmd + ['jsonstatus', options.goma_jsonstatus], env=env)
559 SendGomaTsMon(options.goma_jsonstatus, exit_status)
560 # Always stop the proxy for now to allow in-place update.
561 chromium_utils.RunCommand(goma_ctl_cmd + ['stop'], env=env)
562 UploadGomaCompilerProxyInfo(override_gsutil=override_gsutil)
563 if env.get('GOMA_DUMP_STATS_FILE'):
564 SendGomaStats(env['GOMA_DUMP_STATS_FILE'],
565 env.get('GOMACTL_CRASH_REPORT_ID_FILE'),
566 options.build_data_dir)
567 if cloudtail_proc:
568 cloudtail_proc.terminate()
569 cloudtail_proc.wait()
570
571
572 def determine_goma_jobs():
573 # We would like to speed up build on Windows a bit, since it is slowest.
574 number_of_processors = 0
575 try:
576 number_of_processors = multiprocessing.cpu_count()
577 except NotImplementedError:
578 print 'cpu_count() is not implemented, using default value 50.'
579 return 50
580
581 assert number_of_processors > 0
582
583 # When goma is used, 10 * number_of_processors is basically good in
584 # various situations according to our measurement. Build speed won't
585 # be improved if -j is larger than that.
586 #
587 # Since Mac had process number limitation before, we had to set
588 # the upper limit to 50. Now that the process number limitation is 2000,
589 # so we would be able to use 10 * number_of_processors.
590 # For the safety, we'd like to set the upper limit to 200.
591 #
592 # Note that currently most try-bot build slaves have 8 processors.
593 if chromium_utils.IsMac() or chromium_utils.IsWindows():
594 return min(10 * number_of_processors, 200)
595
596 # For Linux, we also would like to use 10 * cpu. However, not sure
597 # backend resource is enough, so let me set Linux and Linux x64 builder
598 # only for now.
599 hostname = GetShortHostname()
600 if hostname in (
601 ['build14-m1', 'build48-m1'] +
602 # Also increasing cpus for v8/blink trybots.
603 ['build%d-m4' % x for x in xrange(45, 48)] +
604 # Also increasing cpus for LTO buildbots.
605 ['slave%d-c1' % x for x in [20, 33] + range(78, 108)]):
606 return min(10 * number_of_processors, 200)
607
608 return 50
609
610
611 def NeedEnvFileUpdateOnWin(env):
612 """Returns true if environment file need to be updated."""
613 # Following GOMA_* are applied to compiler_proxy not gomacc,
614 # you do not need to update environment files.
615 ignore_envs = (
616 'GOMA_API_KEY_FILE',
617 'GOMA_DEPS_CACHE_DIR',
618 'GOMA_HERMETIC',
619 'GOMA_RPC_EXTRA_PARAMS',
620 'GOMA_ALLOWED_NETWORK_ERROR_DURATION'
621 )
622 for key in env.overrides:
623 if key not in ignore_envs:
624 return True
625 return False
OLDNEW
« no previous file with comments | « scripts/slave/compile.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698