diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-25 12:21:15 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-25 12:21:15 -0400 |
| commit | 353b17968bf48100bbd18ed746e0fbe2fe88141f (patch) | |
| tree | cf8f001bc98a9018bba6d658c48e8346c945e97d | |
| parent | 3ff0ca70b9b7333ec100bd4d4212923a077553c5 (diff) | |
| download | archsetup-353b17968bf48100bbd18ed746e0fbe2fe88141f.tar.gz archsetup-353b17968bf48100bbd18ed746e0fbe2fe88141f.zip | |
The VM harness only built one btrfs base image, so every ZFS-conditional check in the Testinfra suite skipped and the ZFS install path went untested in automation. I added an FS_PROFILE selector (btrfs default, zfs) so `make test FS_PROFILE=zfs` can target a ZFS root.
init_vm_paths derives the image name from FS_PROFILE and validates it. btrfs keeps the legacy unsuffixed archsetup-base.qcow2 so existing images and invocations are untouched. The zfs profile gets archsetup-base-zfs.qcow2. create-base-vm.sh picks archsetup-test.conf vs the new archsetup-test-zfs.conf (FILESYSTEM=zfs, NO_ENCRYPT=yes for an unattended install), and the Makefile resolves the matching image for its base-VM check.
The archsetup run config stays shared. archsetup reads no filesystem key. It detects ZFS from the live root via is_zfs_root, so the ZFS branch fires on its own once the base image is ZFS. The design doc is reconciled to that: no separate archsetup-vm-zfs.conf, and the non-ZFS profile is btrfs, not ext4.
Building the ZFS base image and running the ZFS sweep green is next.
| -rw-r--r-- | Makefile | 26 | ||||
| -rw-r--r-- | docs/design/2026-06-25-zfs-vm-test-coverage.org | 39 | ||||
| -rw-r--r-- | scripts/testing/archsetup-test-zfs.conf | 21 | ||||
| -rwxr-xr-x | scripts/testing/create-base-vm.sh | 11 | ||||
| -rwxr-xr-x | scripts/testing/lib/vm-utils.sh | 17 | ||||
| -rwxr-xr-x | scripts/testing/run-test.sh | 10 |
6 files changed, 105 insertions, 19 deletions
@@ -7,6 +7,17 @@ .PHONY: help deps test-unit test test-keep test-vm-base package-diff +# Filesystem profile for the VM harness: btrfs (default) or zfs. Selects the +# base image the scripts build/use; exported so create-base-vm.sh + run-test.sh +# pick the matching archangel config and image. e.g. make test FS_PROFILE=zfs +FS_PROFILE ?= btrfs +export FS_PROFILE +ifeq ($(FS_PROFILE),btrfs) +BASE_IMAGE := vm-images/archsetup-base.qcow2 +else +BASE_IMAGE := vm-images/archsetup-base-$(FS_PROFILE).qcow2 +endif + # Default target - show help help: @echo "archsetup - install and test" @@ -19,6 +30,9 @@ help: @echo " test-vm-base Create base VM only (runs archangel)" @echo " package-diff Compare archsetup's declared packages vs this system" @echo "" + @echo "Filesystem profile (test, test-keep, test-vm-base):" + @echo " FS_PROFILE=btrfs (default) or zfs, e.g. make test FS_PROFILE=zfs" + @echo "" @echo "Dotfile stow operations now live in the dotfiles repo:" @echo " cd ~/.dotfiles && make stow|restow|reset|unstow|import <de>" @echo "" @@ -51,18 +65,18 @@ test-vm-base: # Test - run full VM integration test suite (creates base VM if needed) test: - @if [ ! -f vm-images/archsetup-base.qcow2 ] || \ - ! qemu-img snapshot -l vm-images/archsetup-base.qcow2 2>/dev/null | grep -q "clean-install"; then \ - echo "Base VM not found or missing snapshot, creating..."; \ + @if [ ! -f $(BASE_IMAGE) ] || \ + ! qemu-img snapshot -l $(BASE_IMAGE) 2>/dev/null | grep -q "clean-install"; then \ + echo "Base VM not found or missing snapshot, creating ($(FS_PROFILE))..."; \ bash scripts/testing/create-base-vm.sh; \ fi @bash scripts/testing/run-test.sh # Test and keep VM running (for manual testing after archsetup) test-keep: - @if [ ! -f vm-images/archsetup-base.qcow2 ] || \ - ! qemu-img snapshot -l vm-images/archsetup-base.qcow2 2>/dev/null | grep -q "clean-install"; then \ - echo "Base VM not found or missing snapshot, creating..."; \ + @if [ ! -f $(BASE_IMAGE) ] || \ + ! qemu-img snapshot -l $(BASE_IMAGE) 2>/dev/null | grep -q "clean-install"; then \ + echo "Base VM not found or missing snapshot, creating ($(FS_PROFILE))..."; \ bash scripts/testing/create-base-vm.sh; \ fi @bash scripts/testing/run-test.sh --keep diff --git a/docs/design/2026-06-25-zfs-vm-test-coverage.org b/docs/design/2026-06-25-zfs-vm-test-coverage.org index 694478f..d9625e0 100644 --- a/docs/design/2026-06-25-zfs-vm-test-coverage.org +++ b/docs/design/2026-06-25-zfs-vm-test-coverage.org @@ -70,9 +70,10 @@ test VM (skip the passphrase prompt; encryption isn't what we're validating). current/non-ZFS), picks the matching archangel config, and writes a profile-named image: =vm-images/archsetup-base.qcow2= (default) vs =vm-images/archsetup-base-zfs.qcow2=. Same =clean-install= snapshot name. -- =run-test.sh= + Makefile take the same =FS_PROFILE= and select the image + - the matching archsetup config (=archsetup-vm.conf= vs =archsetup-vm-zfs.conf=, - the latter with the ZFS filesystem settings). =make test FS_PROFILE=zfs=. +- =run-test.sh= + Makefile take the same =FS_PROFILE= and select the image (via + =init_vm_paths=). The archsetup run config (=archsetup-vm.conf=) is *shared* — + archsetup auto-detects ZFS from the live root, so no per-profile run config is + needed. =make test FS_PROFILE=zfs=. ** C. Bare-metal runner migration Mirror the VM runner's fix in =run-test-baremetal.sh=: @@ -109,12 +110,30 @@ analyze_log_diff, categorize_errors, generate_issue_report, VALIDATION_*. - *P-E* delete the dead shell-sweep functions (the standing P5 follow-up). * Open questions -1. *Does archangel support a ZFS-root config out of the box?* Verify before P-A; - if not, that's its own sub-task (or a feature request to archangel). -2. *Two images vs one image + two snapshots?* Lean two images — ZFS vs ext4 are - different on-disk layouts; cleaner than juggling snapshots on one disk. -3. *Profile on run-test.sh vs a separate run-test-zfs.sh?* Lean a =FS_PROFILE= - param on the existing runner — avoids duplicating the harness. -4. *Disk size / RAM for the ZFS VM* (ZFS wants more RAM than the 4G default?). +1. *Does archangel support a ZFS-root config out of the box?* RESOLVED (yes). + ZFS is archangel's *default* filesystem (=FILESYSTEM=zfs=, validated by + =installer/lib/config.sh:validate_filesystem=), with =NO_ENCRYPT=yes= for an + unattended unencrypted install and a ready =installer/velox-zfs.conf.example= + to model. No archangel work needed. +2. *Two images vs one image + two snapshots?* RESOLVED — two images. ZFS vs + btrfs are different on-disk layouts; cleaner than juggling snapshots on one + disk. =btrfs= keeps the legacy unsuffixed =archsetup-base.qcow2=; =zfs= gets + =archsetup-base-zfs.qcow2=. +3. *Profile on run-test.sh vs a separate run-test-zfs.sh?* RESOLVED — + =FS_PROFILE= env param on the existing runner + Makefile, no duplicate + harness. +4. *Disk size / RAM for the ZFS VM* — start at the 4G RAM / 50G disk defaults; + bump =VM_RAM= only if the ZFS install OOMs (decide at P-C build time). 5. *Should the bare-metal runner stay at all once a ZFS VM exists*, or does the ZFS VM profile make it redundant for everything except real-hardware smoke? + Defer until after P-D. + +* Design corrections (found during P-A/P-B grounding) +- The "non-ZFS" base is *btrfs*, not ext4 — =archsetup-test.conf= sets + =FILESYSTEM=btrfs=. The profile axis is zfs vs btrfs throughout. +- *No =archsetup-vm-zfs.conf= is needed.* archsetup reads no filesystem key; it + auto-detects ZFS from the live root via =is_zfs_root()= (=findmnt -n -o FSTYPE + /=, archsetup:688). The ZFS branch (sanoid, zfs-scrub timer, mkinitcpio udev + hook, docker zfs storage driver) fires whenever the running root is ZFS. So + only the *archangel* base config and the base *image* differ per profile; the + archsetup run config (=archsetup-vm.conf=) is shared. diff --git a/scripts/testing/archsetup-test-zfs.conf b/scripts/testing/archsetup-test-zfs.conf new file mode 100644 index 0000000..a5459cf --- /dev/null +++ b/scripts/testing/archsetup-test-zfs.conf @@ -0,0 +1,21 @@ +# archsetup-test-zfs.conf - Archangel config for archsetup ZFS test VMs +# Used by create-base-vm.sh (FS_PROFILE=zfs) for fully automated base VM creation +# +# Usage: archangel --config-file /root/archsetup-test.conf +# +# Note: User creation is handled by archsetup, not archangel. +# See archsetup-vm.conf for archsetup configuration (shared across profiles - +# archsetup detects ZFS from the live root, so it needs no filesystem setting). +# +# Unencrypted ZFS root: encryption isn't what the harness validates, and +# NO_ENCRYPT=yes skips the passphrase prompt for a fully unattended install. + +FILESYSTEM=zfs +HOSTNAME=archsetup-test +TIMEZONE=America/Chicago +LOCALE=en_US.UTF-8 +KEYMAP=us +DISKS=/dev/vda +NO_ENCRYPT=yes +ROOT_PASSWORD=archsetup +ENABLE_SSH=yes diff --git a/scripts/testing/create-base-vm.sh b/scripts/testing/create-base-vm.sh index b8a4e2b..e626813 100755 --- a/scripts/testing/create-base-vm.sh +++ b/scripts/testing/create-base-vm.sh @@ -20,10 +20,19 @@ source "$SCRIPT_DIR/lib/vm-utils.sh" # Configuration VM_IMAGES_DIR="$PROJECT_ROOT/vm-images" -CONFIG_FILE="$SCRIPT_DIR/archsetup-test.conf" LIVE_ISO_PASSWORD="archangel" SNAPSHOT_NAME="clean-install" +# FS_PROFILE (btrfs default / zfs) picks the archangel base-install config. +# btrfs -> archsetup-test.conf, zfs -> archsetup-test-zfs.conf. The matching +# base image name is derived from FS_PROFILE by init_vm_paths. +FS_PROFILE="${FS_PROFILE:-btrfs}" +if [ "$FS_PROFILE" = "btrfs" ]; then + CONFIG_FILE="$SCRIPT_DIR/archsetup-test.conf" +else + CONFIG_FILE="$SCRIPT_DIR/archsetup-test-${FS_PROFILE}.conf" +fi + # Initialize logging mkdir -p "$PROJECT_ROOT/test-results" LOGFILE="$PROJECT_ROOT/test-results/create-base-vm-$(date +'%Y%m%d-%H%M%S').log" diff --git a/scripts/testing/lib/vm-utils.sh b/scripts/testing/lib/vm-utils.sh index f86e583..6d9f6f6 100755 --- a/scripts/testing/lib/vm-utils.sh +++ b/scripts/testing/lib/vm-utils.sh @@ -14,6 +14,12 @@ VM_CPUS="${VM_CPUS:-4}" VM_RAM="${VM_RAM:-4096}" # MB VM_DISK_SIZE="${VM_DISK_SIZE:-50}" # GB +# Filesystem profile: selects which base image + archangel config the harness +# targets. "btrfs" is the historical default (its image name stays unsuffixed +# so existing base images keep working); "zfs" gets its own image, since the +# two on-disk layouts can't share a disk. Honoured by init_vm_paths below. +FS_PROFILE="${FS_PROFILE:-btrfs}" + # SSH configuration SSH_PORT="${SSH_PORT:-2222}" SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10" @@ -42,8 +48,17 @@ init_vm_paths() { local images_dir="${1:-$VM_IMAGES_DIR}" [ -z "$images_dir" ] && fatal "VM_IMAGES_DIR not set" + case "$FS_PROFILE" in + btrfs|zfs) ;; + *) fatal "Invalid FS_PROFILE: $FS_PROFILE (must be 'btrfs' or 'zfs')" ;; + esac + VM_IMAGES_DIR="$images_dir" - DISK_PATH="$VM_IMAGES_DIR/archsetup-base.qcow2" + # btrfs keeps the legacy unsuffixed name; other profiles get a suffix so + # their images sit side by side without clobbering each other. + local img_suffix="" + [ "$FS_PROFILE" != "btrfs" ] && img_suffix="-$FS_PROFILE" + DISK_PATH="$VM_IMAGES_DIR/archsetup-base${img_suffix}.qcow2" OVMF_VARS="$VM_IMAGES_DIR/OVMF_VARS.fd" PID_FILE="$VM_IMAGES_DIR/qemu.pid" MONITOR_SOCK="$VM_IMAGES_DIR/qemu-monitor.sock" diff --git a/scripts/testing/run-test.sh b/scripts/testing/run-test.sh index a22ae98..f962df3 100755 --- a/scripts/testing/run-test.sh +++ b/scripts/testing/run-test.sh @@ -50,6 +50,9 @@ while [[ $# -gt 0 ]]; do echo " --keep Keep VM in post-test state (for debugging)" echo " --script Specify custom archsetup script to test" echo " --snapshot Snapshot name to revert to (default: clean-install)" + echo "" + echo "Env: FS_PROFILE=btrfs|zfs (default btrfs) selects the base image" + echo " built by create-base-vm.sh. e.g. FS_PROFILE=zfs $0" exit 1 ;; esac @@ -100,6 +103,7 @@ init_logging "$LOGFILE" init_vm_paths "$VM_IMAGES_DIR" section "ArchSetup Test Run: $TIMESTAMP" +info "Filesystem profile: $FS_PROFILE (image: $(basename "$DISK_PATH"))" # Verify archsetup script exists if [ ! -f "$ARCHSETUP_SCRIPT" ]; then @@ -108,7 +112,11 @@ fi # Check disk exists if [ ! -f "$DISK_PATH" ]; then - info "Create it first: ./scripts/testing/create-base-vm.sh" + if [ "$FS_PROFILE" = "btrfs" ]; then + info "Create it first: ./scripts/testing/create-base-vm.sh" + else + info "Create it first: FS_PROFILE=$FS_PROFILE ./scripts/testing/create-base-vm.sh" + fi fatal "Base disk not found: $DISK_PATH" fi |
