test: reset Windows native runs from clean baseline
This commit is contained in:
+77
-12
@@ -18,7 +18,8 @@ Actions:
|
||||
status read-only VM/snapshot identity and state check
|
||||
prepare restore the declared baseline, boot headless, and verify Guest Additions
|
||||
stage copy a bundle containing rvbox.exe and client.toml into the guest test root
|
||||
run create/update and start the RVBox SCM service from the staged bundle
|
||||
install install and start RVBox from the staged bundle through a fixture-only full-admin principal
|
||||
run start the already-installed RVBox SCM service from the staged bundle
|
||||
collect copy bounded guest artifacts to the local test-run directory
|
||||
stop stop RVBox through SCM and request a graceful guest shutdown
|
||||
reset stop the guest if necessary, restore the declared baseline, and leave it off
|
||||
@@ -29,6 +30,8 @@ Optional environment:
|
||||
RVBOX_TEST_VBOX_HOST, RVBOX_TEST_VBOX_VM, RVBOX_TEST_VBOX_VM_UUID,
|
||||
RVBOX_TEST_VBOX_SNAPSHOT, RVBOX_TEST_VBOX_SNAPSHOT_UUID,
|
||||
RVBOX_TEST_GUEST_USER, RVBOX_TEST_GUEST_PASSWORD_FILE (overrides)
|
||||
RVBOX_TEST_PROVISIONER_USER, RVBOX_TEST_PROVISIONER_PASSWORD_FILE
|
||||
(required by install; a fixture-only full-token administrator)
|
||||
RVBOX_TEST_HOST_STAGE_ROOT (default /home/cabbage/.local/state/rvbox-test-runs)
|
||||
RVBOX_TEST_RUN_ROOT (default .test-runs/windows-vm)
|
||||
EOF
|
||||
@@ -77,7 +80,7 @@ while [ "$#" -gt 0 ]; do
|
||||
esac
|
||||
done
|
||||
|
||||
case $action in status|prepare|stage|run|collect|stop|reset|recover) ;; *) usage >&2; fail "unknown action $action" ;; esac
|
||||
case $action in status|prepare|stage|install|run|collect|stop|reset|recover) ;; *) usage >&2; fail "unknown action $action" ;; esac
|
||||
if [ "$action" != status ]; then
|
||||
[ -n "$run_id" ] || fail "$action requires --run-id"
|
||||
safe_id "$run_id"
|
||||
@@ -97,10 +100,12 @@ if [ -n "$endpoint" ]; then safe_word endpoint "$endpoint"; fi
|
||||
: "${RVBOX_TEST_VBOX_HOST:=helium-remote}"
|
||||
: "${RVBOX_TEST_VBOX_VM:=rvbox-win10-test}"
|
||||
: "${RVBOX_TEST_VBOX_VM_UUID:=6cdc114f-71e5-4167-a394-e922e14e6f5c}"
|
||||
: "${RVBOX_TEST_VBOX_SNAPSHOT:=baseline-disk-first}"
|
||||
: "${RVBOX_TEST_VBOX_SNAPSHOT_UUID:=9430a9a4-754a-4b22-beaa-8dfd90043f5b}"
|
||||
: "${RVBOX_TEST_VBOX_SNAPSHOT:=baseline-clean}"
|
||||
: "${RVBOX_TEST_VBOX_SNAPSHOT_UUID:=5e79176a-3e56-4c5d-bb61-a405a6dcdd59}"
|
||||
: "${RVBOX_TEST_GUEST_USER:=rvboxtest}"
|
||||
: "${RVBOX_TEST_GUEST_PASSWORD_FILE:=/home/cabbage/.local/share/rvbox-secrets/rvbox-win10-test.password}"
|
||||
provisioner_user=${RVBOX_TEST_PROVISIONER_USER:-}
|
||||
provisioner_password_file=${RVBOX_TEST_PROVISIONER_PASSWORD_FILE:-}
|
||||
|
||||
for name in RVBOX_TEST_VBOX_HOST RVBOX_TEST_VBOX_VM RVBOX_TEST_VBOX_VM_UUID \
|
||||
RVBOX_TEST_VBOX_SNAPSHOT RVBOX_TEST_VBOX_SNAPSHOT_UUID \
|
||||
@@ -115,6 +120,8 @@ safe_word RVBOX_TEST_VBOX_SNAPSHOT "$RVBOX_TEST_VBOX_SNAPSHOT"
|
||||
safe_word RVBOX_TEST_VBOX_SNAPSHOT_UUID "$RVBOX_TEST_VBOX_SNAPSHOT_UUID"
|
||||
safe_word RVBOX_TEST_GUEST_USER "$RVBOX_TEST_GUEST_USER"
|
||||
safe_word RVBOX_TEST_GUEST_PASSWORD_FILE "$RVBOX_TEST_GUEST_PASSWORD_FILE"
|
||||
if [ -n "$provisioner_user" ]; then safe_word RVBOX_TEST_PROVISIONER_USER "$provisioner_user"; fi
|
||||
if [ -n "$provisioner_password_file" ]; then safe_word RVBOX_TEST_PROVISIONER_PASSWORD_FILE "$provisioner_password_file"; fi
|
||||
|
||||
host_stage_root=${RVBOX_TEST_HOST_STAGE_ROOT:-/home/cabbage/.local/state/rvbox-test-runs}
|
||||
run_root=${RVBOX_TEST_RUN_ROOT:-$repo_root/.test-runs/windows-vm}
|
||||
@@ -145,6 +152,8 @@ host_stage=$8
|
||||
guest_root=$9
|
||||
shift 9
|
||||
endpoint=$1
|
||||
provisioner_user=$2
|
||||
provisioner_password_file=$3
|
||||
[ "$endpoint" = - ] && endpoint=
|
||||
|
||||
fail() { printf '%s\n' "remote test-host: $*" >&2; exit 2; }
|
||||
@@ -206,6 +215,41 @@ guest_run() {
|
||||
printf '%s\n' "$output" | tr -d '\r' | grep -qx 'RVBOX_GUEST_OK'
|
||||
}
|
||||
|
||||
provisioner_run() {
|
||||
# The clean baseline deliberately has no RVBox service. Guest Control's
|
||||
# normal test account has a filtered UAC token, so only the fixture-only
|
||||
# full-token administrator may perform the first machine-wide install.
|
||||
[ -n "$provisioner_user" ] || fail "install requires RVBOX_TEST_PROVISIONER_USER"
|
||||
[ -n "$provisioner_password_file" ] || fail "install requires RVBOX_TEST_PROVISIONER_PASSWORD_FILE"
|
||||
output=$(VBoxManage guestcontrol "$vm" --username "$provisioner_user" --passwordfile "$provisioner_password_file" \
|
||||
run "$@" </dev/null 2>&1) || true
|
||||
printf '%s\n' "$output"
|
||||
printf '%s\n' "$output" | tr -d '\r' | grep -qx 'RVBOX_GUEST_OK'
|
||||
}
|
||||
|
||||
assert_provisioner_elevated() {
|
||||
# This fixture is en-US. Check the mandatory label before allowing any
|
||||
# machine-wide mutation, so an accidentally filtered automation account
|
||||
# fails closed instead of silently weakening the test contract.
|
||||
provisioner_run --exe 'C:\\Windows\\System32\\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
/d /s /c 'whoami /groups | findstr /c:"High Mandatory Level" >NUL && echo RVBOX_GUEST_OK' >/dev/null || \
|
||||
fail "fixture provisioner is not a full high-integrity administrator"
|
||||
}
|
||||
|
||||
assert_clean_guest() {
|
||||
# A missing service is the authoritative clean-baseline condition. The
|
||||
# test service name is unique, so do not delete or alter any other service.
|
||||
guest_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
/d /s /c 'sc.exe query RVBoxClient >NUL 2>&1 & if errorlevel 1060 (echo RVBOX_GUEST_OK) else exit /b 1' >/dev/null || \
|
||||
fail "reset baseline is not clean: RVBoxClient is already installed"
|
||||
}
|
||||
|
||||
assert_staged_guest() {
|
||||
guest_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
/d /s /c "if exist \"$guest_root\\rvbox.exe\" if exist \"$guest_root\\client.toml\" echo RVBOX_GUEST_OK" >/dev/null || \
|
||||
fail "staged guest bundle is missing rvbox.exe or client.toml"
|
||||
}
|
||||
|
||||
wait_guest_additions() {
|
||||
attempt=0
|
||||
while [ "$attempt" -lt 60 ]; do
|
||||
@@ -257,7 +301,8 @@ case "$action" in
|
||||
step prepare-vm-started
|
||||
wait_guest_additions
|
||||
step prepare-guest-additions-ready
|
||||
step prepare-bootstrap-complete
|
||||
assert_clean_guest
|
||||
step prepare-clean-baseline-verified
|
||||
;;
|
||||
probe-identity)
|
||||
assert_identity
|
||||
@@ -298,10 +343,29 @@ case "$action" in
|
||||
VBoxManage guestcontrol "$vm" --username "$guest_user" --passwordfile "$password_file" \
|
||||
copyto "$host_stage/ca.pem" "$guest_root\\ca.pem" </dev/null
|
||||
;;
|
||||
install)
|
||||
assert_identity
|
||||
require_lease
|
||||
[ "$(state)" = running ] || fail "install requires a running prepared VM"
|
||||
assert_clean_guest
|
||||
assert_staged_guest
|
||||
assert_provisioner_elevated
|
||||
# Guest Control cannot reliably wait for GUI-subsystem rvbox.exe. It
|
||||
# may report a non-zero wrapper result after the process has started,
|
||||
# therefore SCM state is the completion proof for this exact install.
|
||||
VBoxManage guestcontrol "$vm" --username "$provisioner_user" --passwordfile "$provisioner_password_file" \
|
||||
run --exe "$guest_root\\rvbox.exe" --unquoted-args -- \
|
||||
--install-service --config "$guest_root\\client.toml" </dev/null >/dev/null 2>&1 || true
|
||||
wait_service RUNNING
|
||||
step install-scm-service-running
|
||||
printf 'service=RVBoxClient state=RUNNING install=clean-baseline\n'
|
||||
;;
|
||||
run)
|
||||
assert_identity
|
||||
require_lease
|
||||
[ "$(state)" = running ] || fail "run requires a running prepared VM"
|
||||
assert_staged_guest
|
||||
assert_provisioner_elevated
|
||||
if [ -n "$endpoint" ]; then
|
||||
endpoint_host=${endpoint%:*}
|
||||
endpoint_port=${endpoint##*:}
|
||||
@@ -309,15 +373,15 @@ case "$action" in
|
||||
-NoProfile -NonInteractive -Command "if (-not (Test-NetConnection -ComputerName '$endpoint_host' -Port $endpoint_port -InformationLevel Quiet)) { exit 1 }; Write-Output RVBOX_GUEST_OK" >/dev/null
|
||||
fi
|
||||
image="\\\"$guest_root\\rvbox.exe\\\" --service --config \\\"$guest_root\\client.toml\\\""
|
||||
guest_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
provisioner_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
/d /s /c "sc.exe query RVBoxClient >NUL 2>&1 && echo RVBOX_GUEST_OK" >/dev/null || \
|
||||
fail "RVBoxClient is not fixture-bootstrapped or the test token lacks SCM query access"
|
||||
guest_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
fail "RVBoxClient is not installed; run install from the clean baseline first"
|
||||
provisioner_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
/d /s /c "sc.exe config RVBoxClient binPath= \"$image\" start= demand >NUL 2>&1 && echo RVBOX_GUEST_OK" >/dev/null || \
|
||||
fail "fixture service does not grant the test token SERVICE_CHANGE_CONFIG"
|
||||
guest_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
fail "fixture provisioner could not change RVBoxClient configuration"
|
||||
provisioner_run --exe 'C:\Windows\System32\cmd.exe' --wait-stdout --wait-stderr --unquoted-args -- \
|
||||
/d /s /c '(sc.exe start RVBoxClient >NUL 2>&1 || sc.exe query RVBoxClient | findstr /c:"RUNNING" >NUL) && echo RVBOX_GUEST_OK' >/dev/null || \
|
||||
fail "fixture service did not accept SCM start"
|
||||
fail "fixture provisioner could not start RVBoxClient"
|
||||
wait_service RUNNING
|
||||
printf 'service=RVBoxClient state=RUNNING\n'
|
||||
;;
|
||||
@@ -382,7 +446,8 @@ REMOTE
|
||||
"$1" "$RVBOX_TEST_VBOX_VM" "$RVBOX_TEST_VBOX_VM_UUID" \
|
||||
"$RVBOX_TEST_VBOX_SNAPSHOT" "$RVBOX_TEST_VBOX_SNAPSHOT_UUID" \
|
||||
"$RVBOX_TEST_GUEST_USER" "$RVBOX_TEST_GUEST_PASSWORD_FILE" \
|
||||
"$host_stage" "$guest_root" "$remote_endpoint" </dev/null
|
||||
"$host_stage" "$guest_root" "$remote_endpoint" \
|
||||
"$provisioner_user" "$provisioner_password_file" </dev/null
|
||||
}
|
||||
|
||||
case $action in
|
||||
|
||||
Reference in New Issue
Block a user