Skip to content

Commit 6618c83

Browse files
committed
fix(sandbox): permit non-Ubuntu rootfs and fix path resolution
Previously, only Ubuntu rootfs were allowed to be used. Now, it allows any file ending in .ext4, with the defaults being AL2023 or Ubuntu in it's absence. Also allow host paths to be resolved. The sandbox tool is run from inside the container, so it expected artifact paths to have /firecracker to be prepended. Now, it can accept host paths within the Firecracker workspace and convert them to container paths. Signed-off-by: James Curtis <jxcurtis@amazon.co.uk>
1 parent c294d31 commit 6618c83

2 files changed

Lines changed: 51 additions & 10 deletions

File tree

tools/devtool

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1177,7 +1177,7 @@ cmd_sh() {
11771177
cmd_sandbox() {
11781178
cmd_build --release
11791179
cmd_ensure_current_artifacts
1180-
cmd_sh "tmux new env PYTEST_ADDOPTS=--pdbcls=IPython.terminal.debugger:TerminalPdb PYTHONPATH=tests IPYTHONDIR=\$PWD/.ipython ipython -i ./tools/sandbox.py $@"
1180+
cmd_sh "tmux new env HOST_FC_ROOT_DIR=$FC_ROOT_DIR PYTEST_ADDOPTS=--pdbcls=IPython.terminal.debugger:TerminalPdb PYTHONPATH=tests IPYTHONDIR=\$PWD/.ipython ipython -i ./tools/sandbox.py $@"
11811181
cmd_fix_perms ".ipython"
11821182
}
11831183

tools/sandbox.py

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@
1010

1111
import argparse
1212
import json
13+
import os
1314
import re
1415
from pathlib import Path
1516

1617
import host_tools.cargo_build as build_tools
1718
from framework.artifacts import disks, kernels
18-
from framework.defs import DEFAULT_BINARY_DIR
19+
from framework.defs import DEFAULT_BINARY_DIR, FC_WORKSPACE_DIR
1920
from framework.microvm import MicroVMFactory
2021

2122
kernels = list(kernels("vmlinux-*"))
22-
rootfs = list(disks("ubuntu*ext4"))
23+
rootfs = list(disks("*.ext4"))
2324

2425

2526
def parse_byte_size(param):
@@ -35,20 +36,51 @@ def parse_byte_size(param):
3536
return int(match.group("val")) * unit[match.group("unit")]
3637

3738

39+
def translate_host_path(p):
40+
"""Rewrite a host path under HOST_FC_ROOT_DIR to its /firecracker/... equivalent."""
41+
if p is None:
42+
return None
43+
host_root = os.environ.get("HOST_FC_ROOT_DIR")
44+
if not host_root:
45+
return Path(p)
46+
p = Path(p).resolve()
47+
if p.is_relative_to(host_root):
48+
return FC_WORKSPACE_DIR / p.relative_to(host_root)
49+
if p.exists():
50+
return p
51+
raise SystemExit(
52+
f"{p} not found in container and not under host workspace {host_root}."
53+
)
54+
55+
56+
def pick_default_rootfs(candidates):
57+
"""Default to AL2023, falling back to Ubuntu, then any rootfs available."""
58+
if not candidates:
59+
return None
60+
for prefix in ("amazonlinux-", "ubuntu-"):
61+
matches = [c for c in candidates if c.name.startswith(prefix)]
62+
if matches:
63+
return matches[-1]
64+
return candidates[-1]
65+
66+
67+
default_rootfs = pick_default_rootfs(rootfs)
68+
default_kernel = kernels[-1] if kernels else None
69+
3870
parser = argparse.ArgumentParser()
3971
parser.add_argument(
4072
"--kernel",
4173
type=Path,
42-
choices=kernels,
43-
default=kernels[-1],
44-
help=f"Kernel to use. [{kernels[-1]}]",
74+
default=default_kernel,
75+
help=f"Kernel to use. Default: {default_kernel}. "
76+
f"Available: {[k.name for k in kernels]}",
4577
)
4678
parser.add_argument(
4779
"--rootfs",
4880
type=Path,
49-
choices=rootfs,
50-
default=rootfs[-1],
51-
help=f"Rootfs to use. [{rootfs[-1]}]",
81+
default=default_rootfs,
82+
help=f"Rootfs to use. Default: {default_rootfs}. "
83+
f"Available: {[r.name for r in rootfs]}",
5284
)
5385
parser.add_argument("--vcpus", type=int, default=2)
5486
parser.add_argument(
@@ -66,8 +98,17 @@ def parse_byte_size(param):
6698
"--gdb", action="store_true", default=False, help="Connect to Firecracker guest GDB"
6799
)
68100
args = parser.parse_args()
101+
args.kernel = translate_host_path(args.kernel)
102+
args.rootfs = translate_host_path(args.rootfs)
103+
args.binary_dir = translate_host_path(args.binary_dir)
104+
args.cpu_template_path = translate_host_path(args.cpu_template_path)
69105
print(args)
70106

107+
if args.kernel is None:
108+
raise SystemExit("No kernel found and --kernel was not provided.")
109+
if args.rootfs is None:
110+
raise SystemExit("No rootfs found and --rootfs was not provided.")
111+
71112
binary_dir = None
72113
if args.binary_dir:
73114
binary_dir = Path(args.binary_dir).resolve()
@@ -81,7 +122,7 @@ def parse_byte_size(param):
81122

82123
cpu_template = None
83124
if args.cpu_template_path is not None:
84-
cpu_template = json.loads(args.cpu_template_path.read_text())
125+
cpu_template = json.loads(args.cpu_template_path.read_text("utf-8"))
85126
vmfcty = MicroVMFactory(binary_dir)
86127

87128
if args.debug or args.gdb:

0 commit comments

Comments
 (0)