1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
# Copyright (c) 2025 Oracle and/or its affiliates
# SPDX-License-Identifier: LGPL-2.1-or-later
import argparse
import os
from pathlib import Path
import shlex
import subprocess
import sys
from typing import List
from vmtest.config import ARCHITECTURES, HOST_ARCHITECTURE
_PASSTHROUGH_ENV_VARS = (
"TERM",
"COLORTERM",
"http_proxy",
"https_proxy",
"ftp_proxy",
"no_proxy",
)
# When entering a chroot, we want a clean environment. These functions preserve
# only a few specific environment variables and execute a login shell, which
# will define anything else important.
def chroot_sh_args(new_root: str) -> List[str]:
return [
"chroot",
new_root,
"env",
"-i",
*(
f"{var}={value}"
for var in _PASSTHROUGH_ENV_VARS
if (value := os.getenv(var)) is not None
),
"/bin/sh",
"-l",
"-c",
]
def chroot_sh_cmd(new_root: str) -> str:
return " ".join(
[
"chroot",
new_root,
"env",
"-i",
*(f'${{{var}+{var}="${var}"}}' for var in _PASSTHROUGH_ENV_VARS),
"/bin/sh",
"-l",
"-c",
]
)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="run commands in the root filesystems for vmtest",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"-d",
"--directory",
metavar="DIR",
type=Path,
default="build/vmtest",
help="directory for vmtest artifacts",
)
parser.add_argument(
"-a",
"--architecture",
type=str,
choices=sorted(ARCHITECTURES),
default=None if HOST_ARCHITECTURE is None else HOST_ARCHITECTURE.name,
required=HOST_ARCHITECTURE is None,
help="architecture to run in",
)
parser.add_argument(
"command",
type=str,
nargs=argparse.REMAINDER,
help="command to run in rootfs (default: bash -i)",
)
args = parser.parse_args()
arch = ARCHITECTURES[args.architecture]
dir = args.directory / arch.name / "rootfs"
command = (
" ".join([shlex.quote(arg) for arg in args.command])
if args.command
else "bash -i"
)
sys.exit(
subprocess.run(
[
"unshare",
"--map-root-user",
"--map-auto",
"--fork",
"--pid",
f"--mount-proc={dir / 'proc'}",
*chroot_sh_args(dir),
command,
],
).returncode
)
|