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)) | |
Mike Stip (use stip instead)
2013/02/20 18:42:07
didn't know os.pardir was a thing. neat!
| |
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 | |
1034 def ParsePythonCfg(cfg_filepath): | |
1035 """Retrieves data from a python config file.""" | |
1036 if not os.path.exists(cfg_filepath): | |
1037 return None | |
1038 base_path = os.path.dirname(os.path.abspath(cfg_filepath)) | |
1039 old_sys_path = sys.path | |
1040 sys.path = sys.path + [base_path] | |
1041 old_path = os.getcwd() | |
1042 try: | |
1043 os.chdir(base_path) | |
1044 local_vars = {} | |
1045 execfile(os.path.join(cfg_filepath), local_vars) | |
1046 return local_vars | |
1047 finally: | |
1048 os.chdir(old_path) | |
1049 sys.path = old_sys_path | |
1050 | |
1051 | |
994 def RunSlavesCfg(slaves_cfg): | 1052 def RunSlavesCfg(slaves_cfg): |
995 """Runs slaves.cfg in a consistent way.""" | 1053 """Runs slaves.cfg in a consistent way.""" |
996 if not os.path.exists(slaves_cfg): | 1054 slave_config = ParsePythonCfg(slaves_cfg) or {} |
997 return [] | 1055 return slave_config.get('slaves', []) |
998 slaves_path = os.path.dirname(os.path.abspath(slaves_cfg)) | |
999 old_sys_path = sys.path | |
1000 sys.path = sys.path + [slaves_path] | |
1001 try: | |
1002 old_path = os.getcwd() | |
1003 try: | |
1004 os.chdir(slaves_path) | |
1005 local_vars = {} | |
1006 execfile(os.path.join(slaves_cfg), local_vars) | |
1007 return local_vars['slaves'] | |
1008 finally: | |
1009 os.chdir(old_path) | |
1010 finally: | |
1011 sys.path = old_sys_path | |
1012 | 1056 |
1013 | 1057 |
1014 def convert_json(option, opt, value, parser): | 1058 def convert_json(option, opt, value, parser): |
1015 """Provide an OptionParser callback to unmarshal a JSON string.""" | 1059 """Provide an OptionParser callback to unmarshal a JSON string.""" |
1016 setattr(parser.values, option.dest, json.loads(value)) | 1060 setattr(parser.values, option.dest, json.loads(value)) |
1017 | 1061 |
1018 | 1062 |
1019 def SafeTranslate(inputstr): | 1063 def SafeTranslate(inputstr): |
1020 """Convert a free form string to one that can be used in a path. | 1064 """Convert a free form string to one that can be used in a path. |
1021 | 1065 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1054 output, error = proc.communicate() | 1098 output, error = proc.communicate() |
1055 if proc.returncode != 0: | 1099 if proc.returncode != 0: |
1056 raise ExternalError('%s failed with error %s\n' % (config_path, error)) | 1100 raise ExternalError('%s failed with error %s\n' % (config_path, error)) |
1057 | 1101 |
1058 config_list = json.loads(output).values() # pylint: disable=E1103 | 1102 config_list = json.loads(output).values() # pylint: disable=E1103 |
1059 config_list.sort(key=lambda cfg: cfg['display_position']) | 1103 config_list.sort(key=lambda cfg: cfg['display_position']) |
1060 return config_list | 1104 return config_list |
1061 except ImportError: | 1105 except ImportError: |
1062 # To get around CQ pylint failures, because CQ doesn't check out chromite. | 1106 # To get around CQ pylint failures, because CQ doesn't check out chromite. |
1063 # TODO(maruel): Remove this try block when this issue is resolved. | 1107 # TODO(maruel): Remove this try block when this issue is resolved. |
1064 print 'cbuildbot_chromite not found! Returning empty config dictionary.' | |
1065 return {} | 1108 return {} |
1066 | 1109 |
1067 | 1110 |
1068 def AddPropertiesOptions(option_parser): | 1111 def AddPropertiesOptions(option_parser): |
1069 """Registers command line options for parsing build and factory properties. | 1112 """Registers command line options for parsing build and factory properties. |
1070 | 1113 |
1071 After parsing, the options object will have the 'build_properties' and | 1114 After parsing, the options object will have the 'build_properties' and |
1072 'factory_properties' attributes. The corresponding values will be python | 1115 'factory_properties' attributes. The corresponding values will be python |
1073 dictionaries containing the properties. If the options are not given on | 1116 dictionaries containing the properties. If the options are not given on |
1074 the command line, the dictionaries will be empty. | 1117 the command line, the dictionaries will be empty. |
(...skipping 11 matching lines...) Expand all Loading... | |
1086 nargs=1, default={}, | 1129 nargs=1, default={}, |
1087 help='factory properties in JSON format') | 1130 help='factory properties in JSON format') |
1088 | 1131 |
1089 | 1132 |
1090 def AddThirdPartyLibToPath(lib, override=False): | 1133 def AddThirdPartyLibToPath(lib, override=False): |
1091 """Adds the specified dir in build/third_party to sys.path. | 1134 """Adds the specified dir in build/third_party to sys.path. |
1092 | 1135 |
1093 Setting 'override' to true will place the directory in the beginning of | 1136 Setting 'override' to true will place the directory in the beginning of |
1094 sys.path, useful for overriding previously set packages. | 1137 sys.path, useful for overriding previously set packages. |
1095 """ | 1138 """ |
1096 libpath = os.path.abspath(os.path.join(os.path.dirname(__file__), | 1139 libpath = os.path.abspath(os.path.join(BUILD_DIR, 'third_party', lib)) |
1097 '..', '..', 'third_party', lib)) | |
1098 if override: | 1140 if override: |
1099 sys.path.insert(0, libpath) | 1141 sys.path.insert(0, libpath) |
1100 else: | 1142 else: |
1101 sys.path.append(libpath) | 1143 sys.path.append(libpath) |
1102 | 1144 |
1103 | 1145 |
1104 def GetLKGR(): | 1146 def GetLKGR(): |
1105 """Connect to chromium LKGR server and get LKGR revision. | 1147 """Connect to chromium LKGR server and get LKGR revision. |
1106 | 1148 |
1107 On success, returns the LKGR and 'ok'. On error, returns None and the text of | 1149 On success, returns the LKGR and 'ok'. On error, returns None and the text of |
(...skipping 16 matching lines...) Expand all Loading... | |
1124 conn.close() | 1166 conn.close() |
1125 | 1167 |
1126 return rev, 'ok' | 1168 return rev, 'ok' |
1127 | 1169 |
1128 | 1170 |
1129 def AbsoluteCanonicalPath(*path): | 1171 def AbsoluteCanonicalPath(*path): |
1130 """Return the most canonical path Python can provide.""" | 1172 """Return the most canonical path Python can provide.""" |
1131 | 1173 |
1132 file_path = os.path.join(*path) | 1174 file_path = os.path.join(*path) |
1133 return os.path.realpath(os.path.abspath(os.path.expanduser(file_path))) | 1175 return os.path.realpath(os.path.abspath(os.path.expanduser(file_path))) |
OLD | NEW |