From 82626f04b4570a575b62374342e74cf0d1f75c85 Mon Sep 17 00:00:00 2001 From: cabbage Date: Sun, 6 Sep 2026 05:12:52 +0000 Subject: [PATCH] docs: record headless Windows test VM runbook --- docs/implementation-plan.v1.md | 134 +++++++++++++++++++++++++++++++++ docs/testing.md | 11 ++- 2 files changed, 142 insertions(+), 3 deletions(-) diff --git a/docs/implementation-plan.v1.md b/docs/implementation-plan.v1.md index 1fbda55..e083034 100644 --- a/docs/implementation-plan.v1.md +++ b/docs/implementation-plan.v1.md @@ -765,6 +765,140 @@ host against this checklist and refuse destructive suites unless the machine is explicitly marked disposable/resettable and the clean snapshot identity is recorded. +#### 2.6.1 Provisioned headless VirtualBox smoke lane + +A resettable Windows lane is already provisioned on the SSH host alias +`helium-remote`. It is the first native execution target and is suitable for +unit-adjacent native checks, supervisor/service/tray smoke, and protocol E2E +work. It is deliberately a minimum smoke lane, not a replacement for the +larger Windows release matrix above: it has one active user, no standard-user +fixture, no ambiguous multi-session fixture, and no Server Core variant. + +| Item | Value | +| --- | --- | +| Hypervisor | VirtualBox `7.2.16r174877` on the Arch Linux `helium-remote` host | +| VM name / UUID | `rvbox-win10-test` / `6cdc114f-71e5-4167-a394-e922e14e6f5c` | +| VM group / config | `/RVBox/Tests`; `/home/cabbage/VirtualBox VMs/RVBox/Tests/rvbox-win10-test/rvbox-win10-test.vbox` | +| Guest OS | Windows 10 Pro 22H2, build `19045.2006`, en-US, BIOS boot | +| Resources | 2 vCPU, 4096 MiB RAM, 32 MiB VRAM, 40 GiB dynamically allocated VDI | +| Disk / source media | `/home/cabbage/VMs/rvbox-win10-test.vdi`; source ISO `/media/Data2/Downloaded/Win10_22H2_English_x64.iso` (Windows image index 6) | +| Devices/network | NAT NIC; audio, USB, 3D, clipboard, drag-and-drop, and VRDE disabled | +| Guest control | Guest Additions installed and verified (`GuestAdditionsRunLevel=3`) | +| Test account | local `rvboxtest`; one active console session (session 1); split-token local administrator | +| Baseline | snapshot `baseline-disk-first` (UUID `9430a9a4-754a-4b22-beaa-8dfd90043f5b`), current known-good snapshot; parent `baseline-clean` is retained | +| Initial state | VM is normally left powered off; restore the baseline before each destructive run | + +The guest password, SSH key, and any host account secret are test secrets. Keep +them in the operator/CI secret store or a mode-600 password file outside the +repository; never put them in this plan, a command-line argument, a run +manifest, or collected logs. `VBoxManage guestcontrol` supports +`--passwordfile`; prefer that option over an inline password. The account name +and VM metadata above are not credentials. + +Use a local, non-secret environment description when operating the lane. The +host alias must resolve through the operator's SSH config; another controller +may substitute an equivalent target, but must record the resulting host/VM +identity in the run manifest: + +```sh +export RVBOX_TEST_VBOX_HOST=helium-remote +export RVBOX_TEST_VBOX_VM=rvbox-win10-test +export RVBOX_TEST_VBOX_SNAPSHOT=baseline-disk-first +export RVBOX_TEST_GUEST_USER=rvboxtest +export RVBOX_TEST_GUEST_PASSWORD_FILE=/secure/outside-repo/rvbox-win10-test.password +``` + +All host lifecycle commands run on Helium through SSH; all guest commands run +through VirtualBox Guest Control. Do not assume that `VBoxManage` is installed +on the Linux controller or that WinRM/OpenSSH is enabled inside this fixture. +The future Windows harness may use a different management backend, but this +lane's backend must validate fixed VM names/UUIDs and use argument vectors (not +shell-concatenated user input): + +```sh +# Read-only identity/state check. +ssh "$RVBOX_TEST_VBOX_HOST" \ + 'VBoxManage showvminfo "rvbox-win10-test" --machinereadable' + +# Restore only while powered off, then boot without a GUI. +ssh "$RVBOX_TEST_VBOX_HOST" \ + 'VBoxManage snapshot "rvbox-win10-test" restore "baseline-disk-first"' +ssh "$RVBOX_TEST_VBOX_HOST" \ + 'VBoxManage startvm "rvbox-win10-test" --type headless' + +# Poll these properties before a test; GuestAdditionsRunLevel=3 is required +# for Guest Control, and LoggedInUsers/NoLoggedInUsers selects the session case. +ssh "$RVBOX_TEST_VBOX_HOST" \ + 'VBoxManage guestproperty enumerate "rvbox-win10-test"' +``` + +The harness must wait for the VM to report `running`, then poll Guest +Properties until Guest Additions is ready and the requested login fixture is +observed. NAT address `10.0.2.15` was observed during provisioning but is DHCP +state, not an identity or a stable endpoint; use Guest Control for management +and discover any test networking separately. A failed readiness poll is a +stopped-resumable run, not permission to start a second VM with the same name. + +For a guest command, create/use the secret file on the host where +`VBoxManage` executes and pass explicit executable/argument vectors. For +example, the following verifies the effective account without opening a shell +through `PATH`: + +```sh +ssh "$RVBOX_TEST_VBOX_HOST" \ + 'VBoxManage guestcontrol "rvbox-win10-test" run \ + --username "rvboxtest" \ + --passwordfile "/secure/outside-repo/rvbox-win10-test.password" \ + --exe "C:\\Windows\\System32\\whoami.exe" \ + --wait-stdout --wait-stderr --' +``` + +Copy CI-built binaries/configuration to a host staging directory with `scp`, +then use `guestcontrol ... copyto` into a run-specific guest test root. Collect +only bounded, redacted artifacts with `guestcontrol ... copyfrom` before reset. +Do not use shared folders or expose the service store to the tray; this VM has +no shared-folder contract. + +Use this shutdown/reset sequence for every native run: + +1. Stop admission and ask the guest/service to shut down cleanly through Guest + Control; wait for `VMState=poweroff`. +2. If Guest Control is unavailable, send `VBoxManage controlvm ... + acpipowerbutton` and poll. Use `controlvm ... poweroff` only for a hung, + disposable test; it intentionally loses guest state. +3. Collect diagnostics while the VM is still available, then restore + `baseline-disk-first` and verify the snapshot UUID/current marker. +4. Leave the VM powered off after cleanup. Never delete either baseline + snapshot, unregister the VM, or modify `win10_dev` (that name refers to a + stale unregistered configuration with a missing disk on this host). + +For headless diagnosis, capture a bounded screenshot on Helium and copy it to +the controller: + +```sh +ssh "$RVBOX_TEST_VBOX_HOST" \ + 'VBoxManage controlvm "rvbox-win10-test" screenshotpng /tmp/rvbox-win10-test.png' +scp "$RVBOX_TEST_VBOX_HOST:/tmp/rvbox-win10-test.png" ./artifacts/ +``` + +Keyboard scancodes are a last-resort recovery aid for BIOS prompts, UAC, or +logon when Guest Control cannot reach the guest; they are not a test-control +API. Prefer deterministic in-guest commands and restore the snapshot after any +manual interaction. When reprovisioning is unavoidable, use the same ISO, +Windows image index 6, 2-vCPU/4-GiB/40-GiB profile, NAT/no-audio/no-USB device +profile, Guest Additions, and a newly generated test password. VirtualBox +unattended installation may attach both the original ISO and an auxiliary VISO; +ensure the original media is bootable (or inject the BIOS key), detach install +media after setup, set `boot1=disk`, and take a fresh named baseline only after +Guest Additions and Guest Control have been verified. + +This fixture is now available for native testing, so remove any generic +“Windows host unavailable” skip only when the harness can acquire this VM's +exclusive lease and perform the reset/health checks above. Keep the missing +standard-user, ambiguous-session, Server Core, and oldest-supported-build cases +explicitly represented as separate blocked matrix entries until their own +resettable fixtures exist. + ## 3. Repository and build bootstrap (Phase 0) ### 3.1 Establish the repository layout diff --git a/docs/testing.md b/docs/testing.md index 696a543..4a7cf0c 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -60,6 +60,11 @@ cleanup. `test/coverage.toml` is the incremental requirement-to-test inventory. The `make verify` lint stage checks unique stable IDs and verifies every implemented -test reference against source. Native Windows integration/E2E entries remain -explicitly blocked until the resettable Windows host is available; Wine or a -protocol stub is not treated as equivalent coverage. +test reference against source. A resettable Windows smoke VM is now available; +its exact headless VirtualBox/Guest Control runbook is in section 2.6.1 of +`docs/implementation-plan.v1.md`. Native Windows integration/E2E entries may +run there once the Windows harness acquires the exclusive lease and performs +the documented snapshot/health checks. The VM is only the minimum smoke lane, +so standard-user, ambiguous-session, Server Core, and oldest-build entries +remain explicitly blocked until their own fixtures exist. Wine or a protocol +stub is not treated as equivalent coverage.