Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame] | 1 | # Copyright 2012 The ChromiumOS Authors |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
Manoj Gupta | 7fad04d | 2019-06-14 20:12:25 -0700 | [diff] [blame] | 4 | |
Mike Frysinger | 2f95cfc | 2015-06-04 04:00:26 -0400 | [diff] [blame] | 5 | """Manage SDK chroots. |
| 6 | |
| 7 | This script is used for manipulating local chroot environments; creating, |
| 8 | deleting, downloading, etc. If given --enter (or no args), it defaults |
| 9 | to an interactive bash shell within the chroot. |
| 10 | |
| 11 | If given args those are passed to the chroot environment, and executed. |
| 12 | """ |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 13 | |
Mike Frysinger | 2f95cfc | 2015-06-04 04:00:26 -0400 | [diff] [blame] | 14 | import argparse |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 15 | import glob |
Chris McDonald | b55b703 | 2021-06-17 16:41:32 -0600 | [diff] [blame] | 16 | import logging |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 17 | import os |
Mike Frysinger | 23b5cf5 | 2021-06-16 23:18:00 -0400 | [diff] [blame] | 18 | from pathlib import Path |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 19 | import pwd |
Brian Norris | d37e2f7 | 2016-08-22 16:09:24 -0700 | [diff] [blame] | 20 | import re |
Mike Frysinger | 5f5c70b | 2022-07-19 12:55:21 -0400 | [diff] [blame] | 21 | import shlex |
David James | 56e6c2c | 2012-10-24 23:54:41 -0700 | [diff] [blame] | 22 | import sys |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 23 | from typing import List |
Mike Frysinger | e852b07 | 2021-05-21 12:39:03 -0400 | [diff] [blame] | 24 | import urllib.parse |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 25 | |
Chris McDonald | b55b703 | 2021-06-17 16:41:32 -0600 | [diff] [blame] | 26 | from chromite.cbuildbot import cbuildbot_alerts |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 27 | from chromite.lib import chroot_lib |
Brian Harring | b6cf914 | 2012-09-01 20:43:17 -0700 | [diff] [blame] | 28 | from chromite.lib import commandline |
Chris McDonald | b55b703 | 2021-06-17 16:41:32 -0600 | [diff] [blame] | 29 | from chromite.lib import constants |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 30 | from chromite.lib import cros_build_lib |
Benjamin Gordon | 7464523 | 2018-05-04 17:40:42 -0600 | [diff] [blame] | 31 | from chromite.lib import cros_sdk_lib |
Mike Frysinger | 9a5124e | 2023-01-26 17:16:44 -0500 | [diff] [blame] | 32 | from chromite.lib import goma_lib |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 33 | from chromite.lib import locking |
Josh Triplett | e759b23 | 2013-03-08 13:03:43 -0800 | [diff] [blame] | 34 | from chromite.lib import namespaces |
Brian Harring | ae0a532 | 2012-09-15 01:46:51 -0700 | [diff] [blame] | 35 | from chromite.lib import osutils |
Mike Frysinger | e2d8f0d | 2014-11-01 13:09:26 -0400 | [diff] [blame] | 36 | from chromite.lib import process_util |
Mike Frysinger | 253c839 | 2023-01-27 01:12:21 -0500 | [diff] [blame] | 37 | from chromite.lib import remoteexec_util |
David James | c93e6a4d | 2014-01-13 11:37:36 -0800 | [diff] [blame] | 38 | from chromite.lib import retry_util |
Michael Mortensen | bf296fb | 2020-06-18 18:21:54 -0600 | [diff] [blame] | 39 | from chromite.lib import timeout_util |
Mike Frysinger | 8e727a3 | 2013-01-16 16:57:53 -0500 | [diff] [blame] | 40 | from chromite.lib import toolchain |
Mike Frysinger | e652ba1 | 2019-09-08 00:57:43 -0400 | [diff] [blame] | 41 | from chromite.utils import key_value_store |
| 42 | |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 43 | |
Mike Frysinger | f744d03 | 2022-05-07 20:38:39 -0400 | [diff] [blame] | 44 | # Which compression algos the SDK tarball uses. We've used xz since 2012. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 45 | COMPRESSION_PREFERENCE = ("xz",) |
Zdenek Behan | fd0efe4 | 2012-04-13 04:36:40 +0200 | [diff] [blame] | 46 | |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 47 | # Proxy simulator configuration. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 48 | PROXY_HOST_IP = "192.168.240.1" |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 49 | PROXY_PORT = 8080 |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 50 | PROXY_GUEST_IP = "192.168.240.2" |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 51 | PROXY_NETMASK = 30 |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 52 | PROXY_VETH_PREFIX = "veth" |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 53 | PROXY_CONNECT_PORTS = (80, 443, 9418) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 54 | PROXY_APACHE_FALLBACK_USERS = ("www-data", "apache", "nobody") |
| 55 | PROXY_APACHE_MPMS = ("event", "worker", "prefork") |
| 56 | PROXY_APACHE_FALLBACK_PATH = ":".join( |
| 57 | "/usr/lib/apache2/mpm-%s" % mpm for mpm in PROXY_APACHE_MPMS |
| 58 | ) |
| 59 | PROXY_APACHE_MODULE_GLOBS = ("/usr/lib*/apache2/modules", "/usr/lib*/apache2") |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 60 | |
Josh Triplett | 9a495f6 | 2013-03-15 18:06:55 -0700 | [diff] [blame] | 61 | # We need these tools to run. Very common tools (tar,..) are omitted. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 62 | NEEDED_TOOLS = ("curl", "xz") |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 63 | |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 64 | # Tools needed for --proxy-sim only. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 65 | PROXY_NEEDED_TOOLS = ("ip",) |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 66 | |
Mike Frysinger | cc83883 | 2014-05-24 13:10:30 -0400 | [diff] [blame] | 67 | |
Brian Harring | 1790ac4 | 2012-09-23 08:53:33 -0700 | [diff] [blame] | 68 | def GetArchStageTarballs(version): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 69 | """Returns the URL for a given arch/version""" |
| 70 | extension = {"xz": "tar.xz"} |
| 71 | return [ |
| 72 | toolchain.GetSdkURL( |
| 73 | suburl="cros-sdk-%s.%s" % (version, extension[compressor]) |
| 74 | ) |
| 75 | for compressor in COMPRESSION_PREFERENCE |
| 76 | ] |
Brian Harring | 1790ac4 | 2012-09-23 08:53:33 -0700 | [diff] [blame] | 77 | |
| 78 | |
Mike Frysinger | f744d03 | 2022-05-07 20:38:39 -0400 | [diff] [blame] | 79 | def FetchRemoteTarballs(storage_dir, urls): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 80 | """Fetches a tarball given by url, and place it in |storage_dir|. |
Zdenek Behan | fd0efe4 | 2012-04-13 04:36:40 +0200 | [diff] [blame] | 81 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 82 | Args: |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 83 | storage_dir: Path where to save the tarball. |
| 84 | urls: List of URLs to try to download. Download will stop on first |
| 85 | success. |
Zdenek Behan | fd0efe4 | 2012-04-13 04:36:40 +0200 | [diff] [blame] | 86 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 87 | Returns: |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 88 | Full path to the downloaded file. |
Gilad Arnold | ecc86fa | 2015-05-22 12:06:04 -0700 | [diff] [blame] | 89 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 90 | Raises: |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 91 | ValueError: None of the URLs worked. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 92 | """ |
| 93 | # Note we track content length ourselves since certain versions of curl |
| 94 | # fail if asked to resume a complete file. |
| 95 | # https://sourceforge.net/tracker/?func=detail&atid=100976&aid=3482927&group_id=976 |
| 96 | status_re = re.compile(rb"^HTTP/[0-9]+(\.[0-9]+)? 200") |
| 97 | # pylint: disable=undefined-loop-variable |
| 98 | for url in urls: |
| 99 | logging.notice("Downloading tarball %s ...", urls[0].rsplit("/", 1)[-1]) |
| 100 | parsed = urllib.parse.urlparse(url) |
| 101 | tarball_name = os.path.basename(parsed.path) |
| 102 | if parsed.scheme in ("", "file"): |
| 103 | if os.path.exists(parsed.path): |
| 104 | return parsed.path |
| 105 | continue |
| 106 | content_length = 0 |
| 107 | logging.debug("Attempting download from %s", url) |
| 108 | result = retry_util.RunCurl( |
| 109 | ["-I", url], |
| 110 | print_cmd=False, |
| 111 | debug_level=logging.NOTICE, |
| 112 | capture_output=True, |
| 113 | ) |
| 114 | successful = False |
| 115 | for header in result.stdout.splitlines(): |
| 116 | # We must walk the output to find the 200 code for use cases where |
| 117 | # a proxy is involved and may have pushed down the actual header. |
| 118 | if status_re.match(header): |
| 119 | successful = True |
| 120 | elif header.lower().startswith(b"content-length:"): |
| 121 | content_length = int(header.split(b":", 1)[-1].strip()) |
| 122 | if successful: |
| 123 | break |
Brian Harring | 1790ac4 | 2012-09-23 08:53:33 -0700 | [diff] [blame] | 124 | if successful: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 125 | break |
| 126 | else: |
| 127 | raise ValueError("No valid URLs found!") |
Zdenek Behan | fd0efe4 | 2012-04-13 04:36:40 +0200 | [diff] [blame] | 128 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 129 | tarball_dest = os.path.join(storage_dir, tarball_name) |
| 130 | current_size = 0 |
| 131 | if os.path.exists(tarball_dest): |
| 132 | current_size = os.path.getsize(tarball_dest) |
| 133 | if current_size > content_length: |
| 134 | osutils.SafeUnlink(tarball_dest) |
| 135 | current_size = 0 |
Zdenek Behan | b2fa72e | 2012-03-16 04:49:30 +0100 | [diff] [blame] | 136 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 137 | if current_size < content_length: |
| 138 | retry_util.RunCurl( |
| 139 | [ |
| 140 | "--fail", |
| 141 | "-L", |
| 142 | "-y", |
| 143 | "30", |
| 144 | "-C", |
| 145 | "-", |
| 146 | "--output", |
| 147 | tarball_dest, |
| 148 | url, |
| 149 | ], |
| 150 | print_cmd=False, |
| 151 | debug_level=logging.NOTICE, |
| 152 | ) |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 153 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 154 | # Cleanup old tarballs now since we've successfull fetched; only cleanup |
| 155 | # the tarballs for our prefix, or unknown ones. This gets a bit tricky |
| 156 | # because we might have partial overlap between known prefixes. |
| 157 | for p in Path(storage_dir).glob("cros-sdk-*"): |
| 158 | if p.name == tarball_name: |
| 159 | continue |
| 160 | logging.info("Cleaning up old tarball: %s", p) |
| 161 | osutils.SafeUnlink(p) |
Zdenek Behan | 9c644dd | 2012-04-05 06:24:02 +0200 | [diff] [blame] | 162 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 163 | return tarball_dest |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 164 | |
| 165 | |
David James | 56e6c2c | 2012-10-24 23:54:41 -0700 | [diff] [blame] | 166 | def _SudoCommand(): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 167 | """Get the 'sudo' command, along with all needed environment variables.""" |
David James | 56e6c2c | 2012-10-24 23:54:41 -0700 | [diff] [blame] | 168 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 169 | # Pass in the ENVIRONMENT_ALLOWLIST and ENV_PASSTHRU variables so that |
| 170 | # scripts in the chroot know what variables to pass through. |
| 171 | cmd = ["sudo"] |
| 172 | for key in constants.CHROOT_ENVIRONMENT_ALLOWLIST + constants.ENV_PASSTHRU: |
| 173 | value = os.environ.get(key) |
| 174 | if value is not None: |
| 175 | cmd += ["%s=%s" % (key, value)] |
David James | 56e6c2c | 2012-10-24 23:54:41 -0700 | [diff] [blame] | 176 | |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 177 | # We keep PATH not for the chroot but for the re-exec & for programs we |
| 178 | # might run before we chroot into the SDK. The process that enters the SDK |
| 179 | # itself will take care of initializing PATH to the right value then. But |
| 180 | # we can't override the system's default PATH for root as that will hide |
| 181 | # /sbin. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 182 | cmd += ["CHROMEOS_SUDO_PATH=%s" % os.environ.get("PATH", "")] |
Mike Frysinger | 2bda4d1 | 2020-07-14 11:15:49 -0400 | [diff] [blame] | 183 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 184 | # Pass along current rlimit settings so we can restore them. |
Mike Frysinger | 53baf88 | 2021-06-24 23:16:50 -0400 | [diff] [blame] | 185 | cmd += [f"CHROMEOS_SUDO_RLIMITS={cros_sdk_lib.ChrootEnteror.get_rlimits()}"] |
Mike Frysinger | 12d055b | 2022-06-23 12:26:47 -0400 | [diff] [blame] | 186 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 187 | # Pass in the path to the depot_tools so that users can access them from |
| 188 | # within the chroot. |
Mike Frysinger | a95870e | 2023-03-27 15:45:34 -0400 | [diff] [blame] | 189 | cmd += [f"DEPOT_TOOLS={constants.DEPOT_TOOLS_DIR}"] |
Mike Frysinger | 749251e | 2014-01-29 05:04:27 -0500 | [diff] [blame] | 190 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 191 | return cmd |
David James | 56e6c2c | 2012-10-24 23:54:41 -0700 | [diff] [blame] | 192 | |
| 193 | |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 194 | def _ReportMissing(missing): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 195 | """Report missing utilities, then exit. |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 196 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 197 | Args: |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 198 | missing: List of missing utilities, as returned by |
| 199 | osutils.FindMissingBinaries. If non-empty, will not return. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 200 | """ |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 201 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 202 | if missing: |
| 203 | raise SystemExit( |
| 204 | "The tool(s) %s were not found.\n" |
| 205 | "Please install the appropriate package in your host.\n" |
| 206 | "Example(ubuntu):\n" |
| 207 | " sudo apt-get install <packagename>" % ", ".join(missing) |
| 208 | ) |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 209 | |
| 210 | |
| 211 | def _ProxySimSetup(options): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 212 | """Set up proxy simulator, and return only in the child environment. |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 213 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 214 | TODO: Ideally, this should support multiple concurrent invocations of |
| 215 | cros_sdk --proxy-sim; currently, such invocations will conflict with each |
| 216 | other due to the veth device names and IP addresses. Either this code would |
| 217 | need to generate fresh, unused names for all of these before forking, or it |
| 218 | would need to support multiple concurrent cros_sdk invocations sharing one |
| 219 | proxy and allowing it to exit when unused (without counting on any local |
| 220 | service-management infrastructure on the host). |
| 221 | """ |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 222 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 223 | may_need_mpm = False |
| 224 | apache_bin = osutils.Which("apache2") |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 225 | if apache_bin is None: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 226 | apache_bin = osutils.Which("apache2", PROXY_APACHE_FALLBACK_PATH) |
| 227 | if apache_bin is None: |
| 228 | _ReportMissing(("apache2",)) |
| 229 | else: |
| 230 | may_need_mpm = True |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 231 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 232 | # Module names and .so names included for ease of grepping. |
| 233 | apache_modules = [ |
| 234 | ("proxy_module", "mod_proxy.so"), |
| 235 | ("proxy_connect_module", "mod_proxy_connect.so"), |
| 236 | ("proxy_http_module", "mod_proxy_http.so"), |
| 237 | ("proxy_ftp_module", "mod_proxy_ftp.so"), |
| 238 | ] |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 239 | |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 240 | # Find the apache module directory and make sure it has the modules we need. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 241 | module_dirs = {} |
| 242 | for g in PROXY_APACHE_MODULE_GLOBS: |
| 243 | for _, so in apache_modules: |
| 244 | for f in glob.glob(os.path.join(g, so)): |
| 245 | module_dirs.setdefault(os.path.dirname(f), []).append(so) |
| 246 | for apache_module_path, modules_found in module_dirs.items(): |
| 247 | if len(modules_found) == len(apache_modules): |
| 248 | break |
| 249 | else: |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 250 | # Appease cros lint, which doesn't understand that this else block will |
| 251 | # not fall through to the subsequent code which relies on |
| 252 | # apache_module_path. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 253 | apache_module_path = None |
| 254 | raise SystemExit( |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 255 | "Could not find apache module path containing all required " |
| 256 | "modules: %s" % ", ".join(so for mod, so in apache_modules) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 257 | ) |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 258 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 259 | def check_add_module(name): |
| 260 | so = "mod_%s.so" % name |
| 261 | if os.access(os.path.join(apache_module_path, so), os.F_OK): |
| 262 | mod = "%s_module" % name |
| 263 | apache_modules.append((mod, so)) |
| 264 | return True |
| 265 | return False |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 266 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 267 | check_add_module("authz_core") |
| 268 | if may_need_mpm: |
| 269 | for mpm in PROXY_APACHE_MPMS: |
| 270 | if check_add_module("mpm_%s" % mpm): |
| 271 | break |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 272 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 273 | veth_host = "%s-host" % PROXY_VETH_PREFIX |
| 274 | veth_guest = "%s-guest" % PROXY_VETH_PREFIX |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 275 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 276 | # Set up locks to sync the net namespace setup. We need the child to create |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 277 | # the net ns first, and then have the parent assign the guest end of the |
| 278 | # veth interface to the child's new network namespace & bring up the proxy. |
| 279 | # Only then can the child move forward and rely on the network being up. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 280 | ns_create_lock = locking.PipeLock() |
| 281 | ns_setup_lock = locking.PipeLock() |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 282 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 283 | pid = os.fork() |
| 284 | if not pid: |
| 285 | # Create our new isolated net namespace. |
| 286 | namespaces.Unshare(namespaces.CLONE_NEWNET) |
Mike Frysinger | 77bf4af | 2016-02-26 17:13:15 -0500 | [diff] [blame] | 287 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 288 | # Signal the parent the ns is ready to be configured. |
| 289 | ns_create_lock.Post() |
| 290 | del ns_create_lock |
| 291 | |
| 292 | # Wait for the parent to finish setting up the ns/proxy. |
| 293 | ns_setup_lock.Wait() |
| 294 | del ns_setup_lock |
| 295 | |
| 296 | # Set up child side of the network. |
| 297 | commands = ( |
| 298 | ("ip", "link", "set", "up", "lo"), |
| 299 | ( |
| 300 | "ip", |
| 301 | "address", |
| 302 | "add", |
| 303 | "%s/%u" % (PROXY_GUEST_IP, PROXY_NETMASK), |
| 304 | "dev", |
| 305 | veth_guest, |
| 306 | ), |
| 307 | ("ip", "link", "set", veth_guest, "up"), |
| 308 | ) |
| 309 | try: |
| 310 | for cmd in commands: |
| 311 | cros_build_lib.dbg_run(cmd) |
| 312 | except cros_build_lib.RunCommandError as e: |
| 313 | cros_build_lib.Die("Proxy setup failed!\n%s", e) |
| 314 | |
| 315 | proxy_url = "http://%s:%u" % (PROXY_HOST_IP, PROXY_PORT) |
| 316 | for proto in ("http", "https", "ftp"): |
| 317 | os.environ[proto + "_proxy"] = proxy_url |
| 318 | for v in ("all_proxy", "RSYNC_PROXY", "no_proxy"): |
| 319 | os.environ.pop(v, None) |
| 320 | return |
| 321 | |
| 322 | # Set up parent side of the network. |
| 323 | uid = int(os.environ.get("SUDO_UID", "0")) |
| 324 | gid = int(os.environ.get("SUDO_GID", "0")) |
| 325 | if uid == 0 or gid == 0: |
| 326 | for username in PROXY_APACHE_FALLBACK_USERS: |
| 327 | try: |
| 328 | pwnam = pwd.getpwnam(username) |
| 329 | uid, gid = pwnam.pw_uid, pwnam.pw_gid |
| 330 | break |
| 331 | except KeyError: |
| 332 | continue |
| 333 | if uid == 0 or gid == 0: |
| 334 | raise SystemExit("Could not find a non-root user to run Apache as") |
| 335 | |
| 336 | chroot_parent, chroot_base = os.path.split(options.chroot) |
| 337 | pid_file = os.path.join(chroot_parent, ".%s-apache-proxy.pid" % chroot_base) |
| 338 | log_file = os.path.join(chroot_parent, ".%s-apache-proxy.log" % chroot_base) |
| 339 | |
| 340 | # Wait for the child to create the net ns. |
| 341 | ns_create_lock.Wait() |
Mike Frysinger | 77bf4af | 2016-02-26 17:13:15 -0500 | [diff] [blame] | 342 | del ns_create_lock |
| 343 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 344 | apache_directives = [ |
| 345 | "User #%u" % uid, |
| 346 | "Group #%u" % gid, |
| 347 | "PidFile %s" % pid_file, |
| 348 | "ErrorLog %s" % log_file, |
| 349 | "Listen %s:%u" % (PROXY_HOST_IP, PROXY_PORT), |
| 350 | "ServerName %s" % PROXY_HOST_IP, |
| 351 | "ProxyRequests On", |
| 352 | "AllowCONNECT %s" % " ".join(str(x) for x in PROXY_CONNECT_PORTS), |
| 353 | ] + [ |
| 354 | "LoadModule %s %s" % (mod, os.path.join(apache_module_path, so)) |
| 355 | for (mod, so) in apache_modules |
| 356 | ] |
| 357 | commands = ( |
| 358 | ( |
| 359 | "ip", |
| 360 | "link", |
| 361 | "add", |
| 362 | "name", |
| 363 | veth_host, |
| 364 | "type", |
| 365 | "veth", |
| 366 | "peer", |
| 367 | "name", |
| 368 | veth_guest, |
| 369 | ), |
| 370 | ( |
| 371 | "ip", |
| 372 | "address", |
| 373 | "add", |
| 374 | "%s/%u" % (PROXY_HOST_IP, PROXY_NETMASK), |
| 375 | "dev", |
| 376 | veth_host, |
| 377 | ), |
| 378 | ("ip", "link", "set", veth_host, "up"), |
| 379 | ( |
| 380 | [apache_bin, "-f", "/dev/null"] |
| 381 | + [arg for d in apache_directives for arg in ("-C", d)] |
| 382 | ), |
| 383 | ("ip", "link", "set", veth_guest, "netns", str(pid)), |
| 384 | ) |
| 385 | cmd = None # Make cros lint happy. |
| 386 | try: |
| 387 | for cmd in commands: |
| 388 | cros_build_lib.dbg_run(cmd) |
| 389 | except cros_build_lib.RunCommandError as e: |
| 390 | # Clean up existing interfaces, if any. |
| 391 | cmd_cleanup = ("ip", "link", "del", veth_host) |
| 392 | try: |
| 393 | cros_build_lib.run(cmd_cleanup, print_cmd=False) |
| 394 | except cros_build_lib.RunCommandError: |
| 395 | logging.error("running %r failed", cmd_cleanup) |
| 396 | cros_build_lib.Die("Proxy network setup failed!\n%s", e) |
| 397 | |
| 398 | # Signal the child that the net ns/proxy is fully configured now. |
| 399 | ns_setup_lock.Post() |
Mike Frysinger | 77bf4af | 2016-02-26 17:13:15 -0500 | [diff] [blame] | 400 | del ns_setup_lock |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 401 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 402 | process_util.ExitAsStatus(os.waitpid(pid, 0)[1]) |
Josh Triplett | 472a418 | 2013-03-08 11:48:57 -0800 | [diff] [blame] | 403 | |
| 404 | |
Mike Frysinger | 5f5c70b | 2022-07-19 12:55:21 -0400 | [diff] [blame] | 405 | def _BuildReExecCommand(argv, opts) -> List[str]: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 406 | """Generate new command for self-reexec.""" |
| 407 | # Make sure to preserve the active Python executable in case the version |
| 408 | # we're running as is not the default one found via the (new) $PATH. |
| 409 | cmd = _SudoCommand() + ["--"] |
| 410 | if opts.strace: |
| 411 | cmd += ["strace"] + shlex.split(opts.strace_arguments) + ["--"] |
| 412 | return cmd + [sys.executable] + argv |
Mike Frysinger | 5f5c70b | 2022-07-19 12:55:21 -0400 | [diff] [blame] | 413 | |
| 414 | |
| 415 | def _ReExecuteIfNeeded(argv, opts): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 416 | """Re-execute cros_sdk as root. |
David James | 56e6c2c | 2012-10-24 23:54:41 -0700 | [diff] [blame] | 417 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 418 | Also unshare the mount namespace so as to ensure that processes outside |
| 419 | the chroot can't mess with our mounts. |
| 420 | """ |
| 421 | if osutils.IsNonRootUser(): |
| 422 | cmd = _BuildReExecCommand(argv, opts) |
| 423 | logging.debug( |
| 424 | "Reexecing self via sudo:\n%s", cros_build_lib.CmdToStr(cmd) |
| 425 | ) |
| 426 | os.execvp(cmd[0], cmd) |
David James | 56e6c2c | 2012-10-24 23:54:41 -0700 | [diff] [blame] | 427 | |
| 428 | |
Mike Frysinger | 34db869 | 2013-11-11 14:54:08 -0500 | [diff] [blame] | 429 | def _CreateParser(sdk_latest_version, bootstrap_latest_version): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 430 | """Generate and return the parser with all the options.""" |
| 431 | usage = ( |
| 432 | "usage: %(prog)s [options] " |
| 433 | "[VAR1=val1 ... VAR2=val2] [--] [command [args]]" |
| 434 | ) |
| 435 | parser = commandline.ArgumentParser( |
| 436 | usage=usage, description=__doc__, caching=True |
| 437 | ) |
Brian Harring | 218e13c | 2012-10-10 16:21:26 -0700 | [diff] [blame] | 438 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 439 | # Global options. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 440 | parser.add_argument( |
| 441 | "--chroot", |
| 442 | dest="chroot", |
Brian Norris | e176045 | 2023-02-23 15:54:40 -0800 | [diff] [blame] | 443 | default=constants.DEFAULT_CHROOT_PATH, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 444 | type="path", |
| 445 | help=("SDK chroot dir name [%s]" % constants.DEFAULT_CHROOT_DIR), |
| 446 | ) |
| 447 | parser.add_argument( |
Dan Callaghan | ada9e03 | 2023-01-30 14:28:46 +1100 | [diff] [blame] | 448 | "--out-dir", |
| 449 | metavar="DIR", |
Brian Norris | e176045 | 2023-02-23 15:54:40 -0800 | [diff] [blame] | 450 | default=constants.DEFAULT_OUT_PATH, |
Dan Callaghan | ada9e03 | 2023-01-30 14:28:46 +1100 | [diff] [blame] | 451 | type=Path, |
| 452 | help="Use DIR for build state and output files", |
| 453 | ) |
| 454 | parser.add_argument( |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 455 | "--nouse-image", |
| 456 | dest="use_image", |
| 457 | action="store_false", |
| 458 | default=False, |
Brian Norris | 35a7ed0 | 2023-02-23 12:50:14 -0800 | [diff] [blame] | 459 | deprecated="--[no]use-image is no longer supported (b/266878468).", |
| 460 | help=argparse.SUPPRESS, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 461 | ) |
| 462 | parser.add_argument( |
| 463 | "--use-image", |
| 464 | dest="use_image", |
| 465 | action="store_true", |
| 466 | default=False, |
Brian Norris | 35a7ed0 | 2023-02-23 12:50:14 -0800 | [diff] [blame] | 467 | deprecated="--[no]use-image is no longer supported (b/266878468).", |
| 468 | help=argparse.SUPPRESS, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 469 | ) |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 470 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 471 | parser.add_argument( |
| 472 | "--chrome-root", |
| 473 | "--chrome_root", |
| 474 | type="path", |
| 475 | help="Mount this chrome root into the SDK chroot", |
| 476 | ) |
| 477 | parser.add_argument( |
| 478 | "--chrome_root_mount", |
| 479 | type="path", |
| 480 | help="Mount chrome into this path inside SDK chroot", |
| 481 | ) |
| 482 | parser.add_argument( |
| 483 | "--nousepkg", |
| 484 | action="store_true", |
| 485 | default=False, |
| 486 | help="Do not use binary packages when creating a chroot.", |
| 487 | ) |
| 488 | parser.add_argument( |
| 489 | "-u", |
| 490 | "--url", |
| 491 | dest="sdk_url", |
| 492 | help="Use sdk tarball located at this url. Use file:// " |
| 493 | "for local files.", |
| 494 | ) |
| 495 | parser.add_argument( |
| 496 | "--sdk-version", |
| 497 | help=( |
| 498 | "Use this sdk version. For prebuilt, current is %r" |
| 499 | ", for bootstrapping it is %r." |
| 500 | % (sdk_latest_version, bootstrap_latest_version) |
| 501 | ), |
| 502 | ) |
| 503 | parser.add_argument( |
Mike Frysinger | 8582456 | 2023-01-31 02:40:43 -0500 | [diff] [blame] | 504 | "--goma-dir", |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 505 | "--goma_dir", |
Mike Frysinger | 8fc8377 | 2023-02-01 15:30:47 -0500 | [diff] [blame] | 506 | type="dir_exists", |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 507 | help="Goma installed directory to mount into the chroot.", |
| 508 | ) |
| 509 | parser.add_argument( |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 510 | "--reclient-dir", |
Mike Frysinger | 8fc8377 | 2023-02-01 15:30:47 -0500 | [diff] [blame] | 511 | type="dir_exists", |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 512 | help="Reclient installed directory to mount into the chroot.", |
| 513 | ) |
| 514 | parser.add_argument( |
| 515 | "--reproxy-cfg-file", |
Mike Frysinger | 8fc8377 | 2023-02-01 15:30:47 -0500 | [diff] [blame] | 516 | type="file_exists", |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 517 | help="Config file for re-client's reproxy used for remoteexec.", |
| 518 | ) |
| 519 | parser.add_argument( |
| 520 | "--skip-chroot-upgrade", |
| 521 | dest="chroot_upgrade", |
| 522 | action="store_false", |
| 523 | default=True, |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 524 | help="Skip automatic SDK and toolchain upgrade when entering the " |
| 525 | "chroot. Never guaranteed to work, especially as ToT moves forward.", |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 526 | ) |
Yong Hong | 84ba917 | 2018-02-07 01:37:42 +0800 | [diff] [blame] | 527 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 528 | # Use type=str instead of type='path' to prevent the given path from being |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 529 | # transferred to absolute path automatically. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 530 | parser.add_argument( |
| 531 | "--working-dir", |
Mike Frysinger | 695f2fd | 2023-02-03 20:45:14 -0500 | [diff] [blame] | 532 | type=Path, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 533 | help="Run the command in specific working directory in " |
| 534 | "chroot. If the given directory is a relative " |
| 535 | "path, this program will transfer the path to " |
| 536 | "the corresponding one inside chroot.", |
| 537 | ) |
Yong Hong | 84ba917 | 2018-02-07 01:37:42 +0800 | [diff] [blame] | 538 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 539 | parser.add_argument("commands", nargs=argparse.REMAINDER) |
Mike Frysinger | 34db869 | 2013-11-11 14:54:08 -0500 | [diff] [blame] | 540 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 541 | # Commands. |
| 542 | group = parser.add_argument_group("Commands") |
Mike Frysinger | 79024a3 | 2021-04-05 03:28:35 -0400 | [diff] [blame] | 543 | group.add_argument( |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 544 | "--enter", |
| 545 | action="store_true", |
| 546 | default=False, |
| 547 | help="Enter the SDK chroot. Implies --create.", |
| 548 | ) |
Mike Frysinger | 79024a3 | 2021-04-05 03:28:35 -0400 | [diff] [blame] | 549 | group.add_argument( |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 550 | "--create", |
| 551 | action="store_true", |
| 552 | default=False, |
Alex Klein | 22690a1 | 2022-11-17 10:56:09 -0700 | [diff] [blame] | 553 | help="Create the chroot only if it does not already exist. Downloads " |
| 554 | "the SDK only if needed, even if --download explicitly passed.", |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 555 | ) |
| 556 | group.add_argument( |
| 557 | "--bootstrap", |
| 558 | action="store_true", |
| 559 | default=False, |
| 560 | help="Build everything from scratch, including the sdk. " |
| 561 | "Use this only if you need to validate a change " |
| 562 | "that affects SDK creation itself (toolchain and " |
| 563 | "build are typically the only folk who need this). " |
| 564 | "Note this will quite heavily slow down the build. " |
| 565 | "This option implies --create --nousepkg.", |
| 566 | ) |
| 567 | group.add_argument( |
| 568 | "-r", |
| 569 | "--replace", |
| 570 | action="store_true", |
| 571 | default=False, |
| 572 | help="Replace an existing SDK chroot. Basically an alias " |
| 573 | "for --delete --create.", |
| 574 | ) |
| 575 | group.add_argument( |
| 576 | "--delete", |
| 577 | action="store_true", |
| 578 | default=False, |
| 579 | help="Delete the current SDK chroot if it exists.", |
| 580 | ) |
| 581 | group.add_argument( |
| 582 | "--force", |
| 583 | action="store_true", |
| 584 | default=False, |
Brian Norris | f624bf4 | 2023-03-02 12:57:49 -0800 | [diff] [blame] | 585 | help="Force delete of the current SDK chroot even if " |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 586 | "obtaining the write lock fails.", |
| 587 | ) |
| 588 | group.add_argument( |
| 589 | "--unmount", |
| 590 | action="store_true", |
| 591 | default=False, |
Brian Norris | f624bf4 | 2023-03-02 12:57:49 -0800 | [diff] [blame] | 592 | deprecated="loopback-image (--use-image) is no longer supported " |
| 593 | "(b/266878468). If needed, consider `cros unmount /path/to/chroot`.", |
| 594 | help=argparse.SUPPRESS, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 595 | ) |
| 596 | group.add_argument( |
| 597 | "--download", |
| 598 | action="store_true", |
| 599 | default=False, |
| 600 | help="Download the sdk.", |
| 601 | ) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 602 | commands = group |
Mike Frysinger | 80dfce9 | 2014-04-21 10:58:53 -0400 | [diff] [blame] | 603 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 604 | # Namespace options. |
| 605 | group = parser.add_argument_group("Namespaces") |
| 606 | group.add_argument( |
| 607 | "--proxy-sim", |
| 608 | action="store_true", |
| 609 | default=False, |
| 610 | help="Simulate a restrictive network requiring an outbound" " proxy.", |
| 611 | ) |
| 612 | for ns, default in (("pid", True), ("net", None)): |
| 613 | group.add_argument( |
| 614 | f"--ns-{ns}", |
| 615 | default=default, |
| 616 | action="store_true", |
| 617 | help=f"Create a new {ns} namespace.", |
| 618 | ) |
| 619 | group.add_argument( |
| 620 | f"--no-ns-{ns}", |
| 621 | dest=f"ns_{ns}", |
| 622 | action="store_false", |
| 623 | help=f"Do not create a new {ns} namespace.", |
| 624 | ) |
Mike Frysinger | 5f5c70b | 2022-07-19 12:55:21 -0400 | [diff] [blame] | 625 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 626 | # Debug options. |
| 627 | group = parser.debug_group |
| 628 | group.add_argument( |
| 629 | "--strace", |
| 630 | action="store_true", |
| 631 | help="Run cros_sdk through strace after re-exec via sudo", |
| 632 | ) |
| 633 | group.add_argument( |
| 634 | "--strace-arguments", |
| 635 | default="", |
| 636 | help="Extra strace options (shell quoting permitted)", |
| 637 | ) |
Mike Frysinger | 34db869 | 2013-11-11 14:54:08 -0500 | [diff] [blame] | 638 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 639 | # Internal options. |
| 640 | group = parser.add_argument_group( |
| 641 | "Internal Chromium OS Build Team Options", |
| 642 | "Caution: these are for meant for the Chromium OS build team only", |
| 643 | ) |
| 644 | group.add_argument( |
| 645 | "--buildbot-log-version", |
| 646 | default=False, |
| 647 | action="store_true", |
| 648 | help="Log SDK version for buildbot consumption", |
| 649 | ) |
| 650 | |
| 651 | return parser, commands |
Mike Frysinger | 34db869 | 2013-11-11 14:54:08 -0500 | [diff] [blame] | 652 | |
| 653 | |
| 654 | def main(argv): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 655 | # Turn on strict sudo checks. |
| 656 | cros_build_lib.STRICT_SUDO = True |
| 657 | conf = key_value_store.LoadFile( |
Greg Edelston | 0382ca4 | 2023-05-04 14:00:15 -0600 | [diff] [blame] | 658 | constants.SDK_VERSION_FILE_FULL_PATH, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 659 | ignore_missing=True, |
| 660 | ) |
| 661 | sdk_latest_version = conf.get("SDK_LATEST_VERSION", "<unknown>") |
| 662 | bootstrap_frozen_version = conf.get("BOOTSTRAP_FROZEN_VERSION", "<unknown>") |
Manoj Gupta | 55a6309 | 2019-06-13 11:47:13 -0700 | [diff] [blame] | 663 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 664 | # Use latest SDK for bootstrapping if requested. Use a frozen version of SDK |
| 665 | # for bootstrapping if BOOTSTRAP_FROZEN_VERSION is set. |
| 666 | bootstrap_latest_version = ( |
| 667 | sdk_latest_version |
| 668 | if bootstrap_frozen_version == "<unknown>" |
| 669 | else bootstrap_frozen_version |
| 670 | ) |
| 671 | parser, commands = _CreateParser( |
| 672 | sdk_latest_version, bootstrap_latest_version |
| 673 | ) |
| 674 | options = parser.parse_args(argv) |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 675 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 676 | # Some basic checks first, before we ask for sudo credentials. |
| 677 | cros_build_lib.AssertOutsideChroot() |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 678 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 679 | host = os.uname()[4] |
| 680 | if host != "x86_64": |
| 681 | cros_build_lib.Die( |
| 682 | "cros_sdk is currently only supported on x86_64; you're running" |
| 683 | " %s. Please find a x86_64 machine." % (host,) |
| 684 | ) |
Brian Harring | 1790ac4 | 2012-09-23 08:53:33 -0700 | [diff] [blame] | 685 | |
Brian Norris | cf03191 | 2023-02-21 15:04:27 -0800 | [diff] [blame] | 686 | goma = ( |
Brian Norris | 4f251e4 | 2023-03-09 15:53:26 -0800 | [diff] [blame] | 687 | goma_lib.Goma( |
| 688 | options.goma_dir, chroot_dir=options.chroot, out_dir=options.out_dir |
| 689 | ) |
Brian Norris | cf03191 | 2023-02-21 15:04:27 -0800 | [diff] [blame] | 690 | if options.goma_dir |
| 691 | else None |
| 692 | ) |
Mike Frysinger | 9a5124e | 2023-01-26 17:16:44 -0500 | [diff] [blame] | 693 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 694 | # Merge the outside PATH setting if we re-execed ourselves. |
| 695 | if "CHROMEOS_SUDO_PATH" in os.environ: |
| 696 | os.environ["PATH"] = "%s:%s" % ( |
| 697 | os.environ.pop("CHROMEOS_SUDO_PATH"), |
| 698 | os.environ["PATH"], |
| 699 | ) |
Mike Frysinger | 2bda4d1 | 2020-07-14 11:15:49 -0400 | [diff] [blame] | 700 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 701 | _ReportMissing(osutils.FindMissingBinaries(NEEDED_TOOLS)) |
| 702 | if options.proxy_sim: |
| 703 | _ReportMissing(osutils.FindMissingBinaries(PROXY_NEEDED_TOOLS)) |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 704 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 705 | if ( |
| 706 | sdk_latest_version == "<unknown>" |
| 707 | or bootstrap_latest_version == "<unknown>" |
| 708 | ): |
| 709 | cros_build_lib.Die( |
| 710 | "No SDK version was found. " |
| 711 | "Are you in a Chromium source tree instead of Chromium OS?\n\n" |
| 712 | "Please change to a directory inside your Chromium OS source tree\n" |
| 713 | "and retry. If you need to setup a Chromium OS source tree, see\n" |
| 714 | " https://dev.chromium.org/chromium-os/developer-guide" |
| 715 | ) |
Benjamin Gordon | 040a116 | 2017-06-29 13:44:47 -0600 | [diff] [blame] | 716 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 717 | _ReExecuteIfNeeded([sys.argv[0]] + argv, options) |
David James | 471532c | 2013-01-21 10:23:31 -0800 | [diff] [blame] | 718 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 719 | lock_path = os.path.dirname(options.chroot) |
| 720 | lock_path = os.path.join( |
| 721 | lock_path, ".%s_lock" % os.path.basename(options.chroot).lstrip(".") |
| 722 | ) |
Benjamin Gordon | abb3e37 | 2017-08-09 10:21:05 -0600 | [diff] [blame] | 723 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 724 | # Expand out the aliases... |
| 725 | if options.replace: |
| 726 | options.delete = options.create = True |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 727 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 728 | if options.bootstrap: |
| 729 | options.create = True |
Brian Harring | b938c78 | 2012-02-29 15:14:38 -0800 | [diff] [blame] | 730 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 731 | # If a command is not given, default to enter. |
| 732 | # pylint: disable=protected-access |
| 733 | # This _group_actions access sucks, but upstream decided to not include an |
| 734 | # alternative to optparse's option_list, and this is what they recommend. |
| 735 | options.enter |= not any( |
| 736 | getattr(options, x.dest) for x in commands._group_actions |
| 737 | ) |
| 738 | # pylint: enable=protected-access |
Mike Frysinger | 114a7b9 | 2023-01-26 19:08:57 -0500 | [diff] [blame] | 739 | options.enter |= bool(options.commands) |
Brian Harring | 218e13c | 2012-10-10 16:21:26 -0700 | [diff] [blame] | 740 | |
Brian Norris | 35a7ed0 | 2023-02-23 12:50:14 -0800 | [diff] [blame] | 741 | if options.delete and not options.create and options.enter: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 742 | parser.error( |
Brian Norris | 35a7ed0 | 2023-02-23 12:50:14 -0800 | [diff] [blame] | 743 | "Trying to enter the chroot when --delete " |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 744 | "was specified makes no sense." |
| 745 | ) |
Brian Harring | 218e13c | 2012-10-10 16:21:26 -0700 | [diff] [blame] | 746 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 747 | chroot_exists = cros_sdk_lib.IsChrootReady(options.chroot) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 748 | # Finally, flip create if necessary. |
Brian Norris | 35a7ed0 | 2023-02-23 12:50:14 -0800 | [diff] [blame] | 749 | if options.enter: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 750 | options.create |= not chroot_exists |
| 751 | |
| 752 | # Make sure we will download if we plan to create. |
| 753 | options.download |= options.create |
| 754 | |
Mike Frysinger | 6bbd3e9 | 2023-01-27 00:05:02 -0500 | [diff] [blame] | 755 | options.Freeze() |
| 756 | |
Mike Frysinger | ded1392 | 2023-02-01 15:31:59 -0500 | [diff] [blame] | 757 | if options.reclient_dir and not options.reproxy_cfg_file: |
| 758 | cros_build_lib.Die("--reclient-dir requires --reproxy-cfg-file") |
| 759 | if not options.reclient_dir and options.reproxy_cfg_file: |
| 760 | cros_build_lib.Die( |
| 761 | "--reproxy-cfg-file only makes sense with --reclient-dir" |
| 762 | ) |
| 763 | |
Mike Frysinger | 253c839 | 2023-01-27 01:12:21 -0500 | [diff] [blame] | 764 | remoteexec = ( |
| 765 | remoteexec_util.Remoteexec( |
| 766 | options.reclient_dir, options.reproxy_cfg_file |
| 767 | ) |
| 768 | if (options.reclient_dir and options.reproxy_cfg_file) |
| 769 | else None |
| 770 | ) |
| 771 | |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 772 | chroot = chroot_lib.Chroot( |
| 773 | path=options.chroot, |
Brian Norris | 2adb74c | 2023-03-29 12:20:44 -0700 | [diff] [blame] | 774 | out_path=options.out_dir, |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 775 | cache_dir=options.cache_dir, |
| 776 | chrome_root=options.chrome_root, |
| 777 | goma=goma, |
| 778 | remoteexec=remoteexec, |
| 779 | ) |
| 780 | |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 781 | # Anything that needs to manipulate the main chroot mount or communicate |
| 782 | # with LVM needs to be done here before we enter the new namespaces. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 783 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 784 | if options.delete: |
| 785 | # Set a timeout of 300 seconds when getting the lock. |
| 786 | with locking.FileLock( |
| 787 | lock_path, "chroot lock", blocking_timeout=300 |
| 788 | ) as lock: |
| 789 | try: |
| 790 | lock.write_lock() |
| 791 | except timeout_util.TimeoutError as e: |
| 792 | logging.error( |
| 793 | "Acquiring write_lock on %s failed: %s", lock_path, e |
| 794 | ) |
| 795 | if not options.force: |
| 796 | cros_build_lib.Die( |
| 797 | "Exiting; use --force to continue w/o lock." |
| 798 | ) |
| 799 | else: |
| 800 | logging.warning( |
| 801 | "cros_sdk was invoked with force option, continuing." |
| 802 | ) |
| 803 | logging.notice("Deleting chroot.") |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 804 | cros_sdk_lib.CleanupChrootMount(chroot.path, delete=True) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 805 | |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 806 | # Enter a new set of namespaces. Everything after here cannot directly |
| 807 | # affect the hosts's mounts or alter LVM volumes. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 808 | namespaces.SimpleUnshare(net=options.ns_net, pid=options.ns_pid) |
Benjamin Gordon | 386b9eb | 2017-07-20 09:21:33 -0600 | [diff] [blame] | 809 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 810 | if not options.sdk_version: |
| 811 | sdk_version = ( |
| 812 | bootstrap_latest_version |
| 813 | if options.bootstrap |
| 814 | else sdk_latest_version |
| 815 | ) |
Yong Hong | 4e29b62 | 2018-02-05 14:31:10 +0800 | [diff] [blame] | 816 | else: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 817 | sdk_version = options.sdk_version |
| 818 | if options.buildbot_log_version: |
| 819 | cbuildbot_alerts.PrintBuildbotStepText(sdk_version) |
Brian Harring | 1790ac4 | 2012-09-23 08:53:33 -0700 | [diff] [blame] | 820 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 821 | # Based on selections, determine the tarball to fetch. |
Alex Klein | 22690a1 | 2022-11-17 10:56:09 -0700 | [diff] [blame] | 822 | urls = [] |
Mike Frysinger | bf47cce | 2021-01-20 13:46:30 -0500 | [diff] [blame] | 823 | if options.download: |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 824 | if options.sdk_url: |
| 825 | urls = [options.sdk_url] |
| 826 | else: |
| 827 | urls = GetArchStageTarballs(sdk_version) |
Brian Harring | 218e13c | 2012-10-10 16:21:26 -0700 | [diff] [blame] | 828 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 829 | with locking.FileLock(lock_path, "chroot lock") as lock: |
| 830 | if options.proxy_sim: |
| 831 | _ProxySimSetup(options) |
Brian Harring | 1790ac4 | 2012-09-23 08:53:33 -0700 | [diff] [blame] | 832 | |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 833 | sdk_cache = os.path.join(chroot.cache_dir, "sdks") |
| 834 | distfiles_cache = os.path.join(chroot.cache_dir, "distfiles") |
| 835 | osutils.SafeMakedirsNonRoot(chroot.cache_dir) |
Dan Callaghan | ada9e03 | 2023-01-30 14:28:46 +1100 | [diff] [blame] | 836 | osutils.SafeMakedirsNonRoot(options.out_dir) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 837 | |
| 838 | for target in (sdk_cache, distfiles_cache): |
| 839 | src = os.path.join(constants.SOURCE_ROOT, os.path.basename(target)) |
| 840 | if not os.path.exists(src): |
| 841 | osutils.SafeMakedirsNonRoot(target) |
| 842 | continue |
| 843 | lock.write_lock( |
| 844 | "Upgrade to %r needed but chroot is locked; please exit " |
| 845 | "all instances so this upgrade can finish." % src |
| 846 | ) |
| 847 | if not os.path.exists(src): |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 848 | # Note that while waiting for the write lock, src may've |
| 849 | # vanished; it's a rare race during the upgrade process that's a |
| 850 | # byproduct of us avoiding taking a write lock to do the src |
| 851 | # check. If we took a write lock for that check, it would |
| 852 | # effectively limit all cros_sdk for a chroot to a single |
| 853 | # instance. |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 854 | osutils.SafeMakedirsNonRoot(target) |
| 855 | elif not os.path.exists(target): |
| 856 | # Upgrade occurred, but a reversion, or something whacky |
| 857 | # occurred writing to the old location. Wipe and continue. |
| 858 | os.rename(src, target) |
| 859 | else: |
| 860 | # Upgrade occurred once already, but either a reversion or |
| 861 | # some before/after separate cros_sdk usage is at play. |
| 862 | # Wipe and continue. |
| 863 | osutils.RmDir(src) |
| 864 | |
Brian Norris | c2b71e4 | 2023-03-30 15:27:36 -0700 | [diff] [blame] | 865 | cros_sdk_lib.MigrateStatePaths(chroot, lock) |
| 866 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 867 | mounted = False |
| 868 | if options.create: |
| 869 | lock.write_lock() |
Alex Klein | ef51783 | 2023-01-13 12:06:51 -0700 | [diff] [blame] | 870 | # Recheck if the chroot is set up here before creating to make sure |
Brian Norris | f624bf4 | 2023-03-02 12:57:49 -0800 | [diff] [blame] | 871 | # we account for whatever the various delete/cleanup steps above |
| 872 | # have done. |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 873 | if cros_sdk_lib.IsChrootReady(chroot.path): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 874 | logging.debug("Chroot already exists. Skipping creation.") |
| 875 | else: |
Alex Klein | 22690a1 | 2022-11-17 10:56:09 -0700 | [diff] [blame] | 876 | sdk_tarball = FetchRemoteTarballs(sdk_cache, urls) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 877 | cros_sdk_lib.CreateChroot( |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 878 | Path(chroot.path), |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 879 | Path(sdk_tarball), |
Dan Callaghan | ada9e03 | 2023-01-30 14:28:46 +1100 | [diff] [blame] | 880 | options.out_dir, |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 881 | Path(chroot.cache_dir), |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 882 | usepkg=not options.bootstrap and not options.nousepkg, |
| 883 | chroot_upgrade=options.chroot_upgrade, |
| 884 | ) |
| 885 | mounted = True |
Alex Klein | 22690a1 | 2022-11-17 10:56:09 -0700 | [diff] [blame] | 886 | elif options.download: |
| 887 | # Allow downloading only. |
| 888 | lock.write_lock() |
| 889 | FetchRemoteTarballs(sdk_cache, urls) |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 890 | |
| 891 | if options.enter: |
| 892 | lock.read_lock() |
| 893 | if not mounted: |
Dan Callaghan | ada9e03 | 2023-01-30 14:28:46 +1100 | [diff] [blame] | 894 | cros_sdk_lib.MountChrootPaths(chroot.path, options.out_dir) |
Mike Frysinger | 53baf88 | 2021-06-24 23:16:50 -0400 | [diff] [blame] | 895 | ret = cros_sdk_lib.EnterChroot( |
Mike Frysinger | ec32bea | 2023-01-27 01:20:48 -0500 | [diff] [blame] | 896 | chroot, |
Mike Frysinger | 53baf88 | 2021-06-24 23:16:50 -0400 | [diff] [blame] | 897 | chrome_root_mount=options.chrome_root_mount, |
| 898 | cwd=options.working_dir, |
| 899 | cmd=options.commands, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 900 | ) |
| 901 | sys.exit(ret.returncode) |