diff --git a/src/sbx/cli.py b/src/sbx/cli.py index f72174b..5506097 100644 --- a/src/sbx/cli.py +++ b/src/sbx/cli.py @@ -380,6 +380,22 @@ def _start_existing_vm_if_needed( ) print(f"sbx: If it still fails, run `sbx recreate {vm_id} --force`.", file=sys.stderr) return 1 + current = vm_state.existing_vm_start_config(vm_id) + if current is not None: + config = current[1] + for key in ("kernel_path", "rootfs_path"): + value = config.get(key) + if value is not None and not Path(str(value)).expanduser().exists(): + print( + f"sbx: VM '{vm_id}' references missing boot artifact: {value}", + file=sys.stderr, + ) + print( + "sbx: This VM was likely created from a temporary or removed image.", + file=sys.stderr, + ) + print(f"sbx: Run `sbx recreate {vm_id} --force`.", file=sys.stderr) + return 1 command = ["sandbox", "start", vm_id, "--boot-timeout", f"{boot_timeout:g}"] completed = runtime.run_smolvm_capture(command) if completed is None: diff --git a/src/sbx/image/build_debian.py b/src/sbx/image/build_debian.py index 20d6d87..3da0699 100644 --- a/src/sbx/image/build_debian.py +++ b/src/sbx/image/build_debian.py @@ -187,7 +187,7 @@ def _docker_run_kernel_builder( "run", "--rm", "-v", - f"{work_dir}:/work", + f"{work_dir}:/work:z", "-w", "/work", tag, diff --git a/tests/test_build_debian_image.py b/tests/test_build_debian_image.py index ec8cca7..0f65377 100644 --- a/tests/test_build_debian_image.py +++ b/tests/test_build_debian_image.py @@ -275,7 +275,9 @@ def fake_run(command: list[str], *, check: bool) -> None: runs.append(command) if command[:3] == ["docker", "run", "--rm"] and "bash" in command: assert check is True - work_dir = Path(command[command.index("-v") + 1].split(":", 1)[0]) + volume = command[command.index("-v") + 1] + assert volume.endswith(":/work:z") + work_dir = Path(volume.split(":", 1)[0]) assert (work_dir / "build.sh").is_file() assert (work_dir / "check-config.sh").is_file() assert "CONFIG_VETH=y" in (work_dir / "config.fragment").read_text() diff --git a/tests/test_cli.py b/tests/test_cli.py index 5625502..a94920d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1195,6 +1195,33 @@ def fake_run_capture( assert "sbx recreate vm1 --force" in capsys.readouterr().err +def test_start_existing_vm_with_missing_kernel_suggests_recreate( + monkeypatch: pytest.MonkeyPatch, + capsys: pytest.CaptureFixture[str], +) -> None: + missing_kernel = "/tmp/sbx-no-credentials-deleted/.smolvm/images/sbx/vmlinux.bin" + monkeypatch.setattr( + vm_state, + "existing_vm_start_config", + lambda vm_id: ( + "stopped", + {"kernel_path": missing_kernel, "rootfs_path": "/tmp/not-checked.ext4"}, + ), + ) + monkeypatch.setattr( + cli.runtime, + "run_smolvm_capture", + lambda argv: (_ for _ in ()).throw(AssertionError("must not start QEMU")), + ) + + rc = cli._start_existing_vm_if_needed("vm1", "stopped", 60) + + assert rc == 1 + err = capsys.readouterr().err + assert missing_kernel in err + assert "sbx recreate vm1 --force" in err + + def test_failed_managed_run_hides_json_and_prints_hint( monkeypatch: pytest.MonkeyPatch, tmp_path: Path,