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