OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 """ Set of basic operations/utilities that are used by the build. """ | 5 """ Set of basic operations/utilities that are used by the build. """ |
6 | 6 |
7 import copy | 7 import copy |
8 import errno | 8 import errno |
9 import fnmatch | 9 import fnmatch |
10 import glob | 10 import glob |
11 import math | 11 import math |
12 import os | 12 import os |
13 import shutil | 13 import shutil |
| 14 import socket |
14 import stat | 15 import stat |
15 import string # pylint: disable=W0402 | 16 import string # pylint: disable=W0402 |
16 import subprocess | 17 import subprocess |
17 import sys | 18 import sys |
18 import threading | 19 import threading |
19 import time | 20 import time |
20 import urllib | 21 import urllib |
21 import zipfile | 22 import zipfile |
22 | 23 |
23 try: | 24 try: |
24 import json # pylint: disable=F0401 | 25 import json # pylint: disable=F0401 |
25 except ImportError: | 26 except ImportError: |
26 import simplejson as json | 27 import simplejson as json |
27 | 28 |
28 | 29 |
| 30 BUILD_DIR = os.path.realpath(os.path.join( |
| 31 os.path.dirname(__file__), os.pardir, os.pardir)) |
| 32 |
| 33 |
29 # Local errors. | 34 # Local errors. |
30 class MissingArgument(Exception): pass | 35 class MissingArgument(Exception): pass |
31 class PathNotFound(Exception): pass | 36 class PathNotFound(Exception): pass |
32 class ExternalError(Exception): pass | 37 class ExternalError(Exception): pass |
33 | 38 |
34 def IsWindows(): | 39 def IsWindows(): |
35 return sys.platform == 'cygwin' or sys.platform.startswith('win') | 40 return sys.platform == 'cygwin' or sys.platform.startswith('win') |
36 | 41 |
37 def IsLinux(): | 42 def IsLinux(): |
38 return sys.platform.startswith('linux') | 43 return sys.platform.startswith('linux') |
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 command = ['scp', '-r', '-p', srctree, host + ':' + dst] | 977 command = ['scp', '-r', '-p', srctree, host + ':' + dst] |
973 result = RunCommand(command) | 978 result = RunCommand(command) |
974 if result: | 979 if result: |
975 raise ExternalError('Failed to scp "%s" to "%s" (%s)' % | 980 raise ExternalError('Failed to scp "%s" to "%s" (%s)' % |
976 (srctree, host + ':' + dst, result)) | 981 (srctree, host + ':' + dst, result)) |
977 | 982 |
978 | 983 |
979 def ListMasters(cue='master.cfg', include_public=True, include_internal=True): | 984 def ListMasters(cue='master.cfg', include_public=True, include_internal=True): |
980 """Returns all the masters found.""" | 985 """Returns all the masters found.""" |
981 # Look for "internal" masters first. | 986 # Look for "internal" masters first. |
982 path_internal = os.path.join(os.path.dirname(__file__), '..', '..', '..', | 987 path_internal = os.path.join( |
983 'build_internal', 'masters/*/' + cue) | 988 BUILD_DIR, os.pardir, 'build_internal', 'masters/*/' + cue) |
984 path = os.path.join(os.path.dirname(__file__), '..', '..', | 989 path = os.path.join(BUILD_DIR, 'masters/*/' + cue) |
985 'masters/*/' + cue) | |
986 filenames = [] | 990 filenames = [] |
987 if include_public: | 991 if include_public: |
988 filenames += glob.glob(path) | 992 filenames += glob.glob(path) |
989 if include_internal: | 993 if include_internal: |
990 filenames += glob.glob(path_internal) | 994 filenames += glob.glob(path_internal) |
991 return [os.path.abspath(os.path.dirname(f)) for f in filenames] | 995 return [os.path.abspath(os.path.dirname(f)) for f in filenames] |
992 | 996 |
993 | 997 |
| 998 def GetAllSlaves(): |
| 999 """Return all slave objects from masters.""" |
| 1000 slaves = [] |
| 1001 for master in ListMasters(cue='slaves.cfg'): |
| 1002 cur_slaves = RunSlavesCfg(os.path.join(master, 'slaves.cfg')) |
| 1003 for slave in cur_slaves: |
| 1004 slave['mastername'] = os.path.basename(master) |
| 1005 slaves.extend(cur_slaves) |
| 1006 return slaves |
| 1007 |
| 1008 |
| 1009 def GetActiveSlavename(): |
| 1010 testing_slavename = os.getenv('TESTING_SLAVENAME') |
| 1011 if testing_slavename: |
| 1012 return testing_slavename |
| 1013 return socket.getfqdn().split('.', 1)[0].lower() |
| 1014 |
| 1015 |
| 1016 def EntryToSlaveName(entry): |
| 1017 """Produces slave name from the slaves config dict.""" |
| 1018 return entry.get('slavename') or entry.get('hostname') |
| 1019 |
| 1020 |
| 1021 def GetActiveMaster(slavename=None): |
| 1022 """Parses all the slaves.cfg and returns the name of the active master |
| 1023 determined by the hostname. Returns None otherwise. |
| 1024 |
| 1025 It will be matched against *both* the 'slavename' and 'hostname' fields |
| 1026 in slaves.cfg. |
| 1027 """ |
| 1028 slavename = slavename or GetActiveSlavename() |
| 1029 for slave in GetAllSlaves(): |
| 1030 if slavename == EntryToSlaveName(slave): |
| 1031 return slave['master'] |
| 1032 |
| 1033 |
994 def ParsePythonCfg(cfg_filepath): | 1034 def ParsePythonCfg(cfg_filepath): |
995 """Retrieves data from a python config file.""" | 1035 """Retrieves data from a python config file.""" |
996 if not os.path.exists(cfg_filepath): | 1036 if not os.path.exists(cfg_filepath): |
997 return None | 1037 return None |
998 base_path = os.path.dirname(os.path.abspath(cfg_filepath)) | 1038 base_path = os.path.dirname(os.path.abspath(cfg_filepath)) |
999 old_sys_path = sys.path | 1039 old_sys_path = sys.path |
1000 sys.path = sys.path + [base_path] | 1040 sys.path = sys.path + [base_path] |
1001 old_path = os.getcwd() | 1041 old_cwd = os.getcwd() |
1002 try: | 1042 try: |
1003 os.chdir(base_path) | 1043 os.chdir(base_path) |
1004 local_vars = {} | 1044 local_vars = {} |
1005 execfile(os.path.join(cfg_filepath), local_vars) | 1045 execfile(os.path.join(cfg_filepath), local_vars) |
1006 del local_vars['__builtins__'] | 1046 del local_vars['__builtins__'] |
1007 return local_vars | 1047 return local_vars |
1008 finally: | 1048 finally: |
1009 os.chdir(old_path) | 1049 os.chdir(old_cwd) |
1010 sys.path = old_sys_path | 1050 sys.path = old_sys_path |
1011 | 1051 |
1012 | 1052 |
1013 def RunSlavesCfg(slaves_cfg): | 1053 def RunSlavesCfg(slaves_cfg): |
1014 """Runs slaves.cfg in a consistent way.""" | 1054 """Runs slaves.cfg in a consistent way.""" |
1015 if not os.path.exists(slaves_cfg): | 1055 slave_config = ParsePythonCfg(slaves_cfg) or {} |
1016 return [] | 1056 return slave_config.get('slaves', []) |
1017 slaves_path = os.path.dirname(os.path.abspath(slaves_cfg)) | |
1018 old_sys_path = sys.path | |
1019 sys.path = sys.path + [slaves_path] | |
1020 try: | |
1021 old_path = os.getcwd() | |
1022 try: | |
1023 os.chdir(slaves_path) | |
1024 local_vars = {} | |
1025 execfile(os.path.join(slaves_cfg), local_vars) | |
1026 return local_vars['slaves'] | |
1027 finally: | |
1028 os.chdir(old_path) | |
1029 finally: | |
1030 sys.path = old_sys_path | |
1031 | 1057 |
1032 | 1058 |
1033 def convert_json(option, opt, value, parser): | 1059 def convert_json(option, opt, value, parser): |
1034 """Provide an OptionParser callback to unmarshal a JSON string.""" | 1060 """Provide an OptionParser callback to unmarshal a JSON string.""" |
1035 setattr(parser.values, option.dest, json.loads(value)) | 1061 setattr(parser.values, option.dest, json.loads(value)) |
1036 | 1062 |
1037 | 1063 |
1038 def SafeTranslate(inputstr): | 1064 def SafeTranslate(inputstr): |
1039 """Convert a free form string to one that can be used in a path. | 1065 """Convert a free form string to one that can be used in a path. |
1040 | 1066 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 output, error = proc.communicate() | 1099 output, error = proc.communicate() |
1074 if proc.returncode != 0: | 1100 if proc.returncode != 0: |
1075 raise ExternalError('%s failed with error %s\n' % (config_path, error)) | 1101 raise ExternalError('%s failed with error %s\n' % (config_path, error)) |
1076 | 1102 |
1077 config_list = json.loads(output).values() # pylint: disable=E1103 | 1103 config_list = json.loads(output).values() # pylint: disable=E1103 |
1078 config_list.sort(key=lambda cfg: cfg['display_position']) | 1104 config_list.sort(key=lambda cfg: cfg['display_position']) |
1079 return config_list | 1105 return config_list |
1080 except ImportError: | 1106 except ImportError: |
1081 # To get around CQ pylint failures, because CQ doesn't check out chromite. | 1107 # To get around CQ pylint failures, because CQ doesn't check out chromite. |
1082 # TODO(maruel): Remove this try block when this issue is resolved. | 1108 # TODO(maruel): Remove this try block when this issue is resolved. |
1083 print 'cbuildbot_chromite not found! Returning empty config dictionary.' | |
1084 return {} | 1109 return {} |
1085 | 1110 |
1086 | 1111 |
1087 def AddPropertiesOptions(option_parser): | 1112 def AddPropertiesOptions(option_parser): |
1088 """Registers command line options for parsing build and factory properties. | 1113 """Registers command line options for parsing build and factory properties. |
1089 | 1114 |
1090 After parsing, the options object will have the 'build_properties' and | 1115 After parsing, the options object will have the 'build_properties' and |
1091 'factory_properties' attributes. The corresponding values will be python | 1116 'factory_properties' attributes. The corresponding values will be python |
1092 dictionaries containing the properties. If the options are not given on | 1117 dictionaries containing the properties. If the options are not given on |
1093 the command line, the dictionaries will be empty. | 1118 the command line, the dictionaries will be empty. |
(...skipping 11 matching lines...) Expand all Loading... |
1105 nargs=1, default={}, | 1130 nargs=1, default={}, |
1106 help='factory properties in JSON format') | 1131 help='factory properties in JSON format') |
1107 | 1132 |
1108 | 1133 |
1109 def AddThirdPartyLibToPath(lib, override=False): | 1134 def AddThirdPartyLibToPath(lib, override=False): |
1110 """Adds the specified dir in build/third_party to sys.path. | 1135 """Adds the specified dir in build/third_party to sys.path. |
1111 | 1136 |
1112 Setting 'override' to true will place the directory in the beginning of | 1137 Setting 'override' to true will place the directory in the beginning of |
1113 sys.path, useful for overriding previously set packages. | 1138 sys.path, useful for overriding previously set packages. |
1114 """ | 1139 """ |
1115 libpath = os.path.abspath(os.path.join(os.path.dirname(__file__), | 1140 libpath = os.path.abspath(os.path.join(BUILD_DIR, 'third_party', lib)) |
1116 '..', '..', 'third_party', lib)) | |
1117 if override: | 1141 if override: |
1118 sys.path.insert(0, libpath) | 1142 sys.path.insert(0, libpath) |
1119 else: | 1143 else: |
1120 sys.path.append(libpath) | 1144 sys.path.append(libpath) |
1121 | 1145 |
1122 | 1146 |
1123 def GetLKGR(): | 1147 def GetLKGR(): |
1124 """Connect to chromium LKGR server and get LKGR revision. | 1148 """Connect to chromium LKGR server and get LKGR revision. |
1125 | 1149 |
1126 On success, returns the LKGR and 'ok'. On error, returns None and the text of | 1150 On success, returns the LKGR and 'ok'. On error, returns None and the text of |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 'This is almost certainly incorrect.' % (build_dir, platform_key)) | 1203 'This is almost certainly incorrect.' % (build_dir, platform_key)) |
1180 if use_out: | 1204 if use_out: |
1181 legacy_path = 'out' | 1205 legacy_path = 'out' |
1182 else: | 1206 else: |
1183 legacy_path = legacy_paths[platform_key] | 1207 legacy_path = legacy_paths[platform_key] |
1184 build_dir = os.path.join(os.path.dirname(build_dir), legacy_path) | 1208 build_dir = os.path.join(os.path.dirname(build_dir), legacy_path) |
1185 print >> sys.stderr, ('Assuming you meant "%s"' % build_dir) | 1209 print >> sys.stderr, ('Assuming you meant "%s"' % build_dir) |
1186 bad = True | 1210 bad = True |
1187 | 1211 |
1188 return (build_dir, bad) | 1212 return (build_dir, bad) |
OLD | NEW |