From 322cdf56dc984aed4da7166ccfa1990e09445b08 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Fri, 23 Jan 2026 23:58:07 -0600 Subject: Fix btrfs bugs from VM testing - Fix GRUB config path (remove GRUB_BTRFS_GRUB_DIRNAME, use default) - Create snapper config manually (D-Bus not available in chroot) - Create genesis snapshot with btrfs command (not snapper) - Add btrfs-single.conf test config - Update test-install.sh to copy lib/ directory - Update test-install.sh to handle btrfs verification VM test now passes for btrfs single-disk installation. --- custom/lib/btrfs.sh | 54 ++++++++++++++++++---------- docs/session-context.org | 42 +++++++++------------- scripts/test-configs/btrfs-single.conf | 13 +++++++ scripts/test-install.sh | 66 +++++++++++++++++++++------------- 4 files changed, 107 insertions(+), 68 deletions(-) create mode 100644 scripts/test-configs/btrfs-single.conf diff --git a/custom/lib/btrfs.sh b/custom/lib/btrfs.sh index c264fce..b30b68f 100644 --- a/custom/lib/btrfs.sh +++ b/custom/lib/btrfs.sh @@ -197,16 +197,12 @@ EOF configure_snapper() { step "Configuring Snapper" - # Snapper config for root - # Note: snapper expects /.snapshots to exist and be a subvolume - info "Creating snapper config for root..." - - arch-chroot /mnt snapper -c root create-config / || error "Failed to create snapper config" + # Create snapper config directory + mkdir -p /mnt/etc/snapper/configs - # Snapper creates its own .snapshots subvolume, but we already have @snapshots - # Delete snapper's and use ours - arch-chroot /mnt btrfs subvolume delete /.snapshots 2>/dev/null || true - mkdir -p /mnt/.snapshots + # Snapper config for root - create manually (avoids D-Bus requirement in chroot) + # Note: We already have @snapshots subvolume mounted at /.snapshots + info "Creating snapper config for root..." # Set snapper timeline settings # Keep: 6 hourly, 7 daily, 2 weekly, 1 monthly @@ -250,6 +246,10 @@ EMPTY_PRE_POST_CLEANUP="yes" EMPTY_PRE_POST_MIN_AGE="1800" EOF + # Register the config with snapper + mkdir -p /mnt/etc/sysconfig + echo 'SNAPPER_CONFIGS="root"' > /mnt/etc/sysconfig/snapper + # Enable snapper timers arch-chroot /mnt systemctl enable snapper-timeline.timer arch-chroot /mnt systemctl enable snapper-cleanup.timer @@ -280,19 +280,19 @@ GRUB_DISTRIBUTOR="Arch" GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet" GRUB_CMDLINE_LINUX="" -# Btrfs snapshot boot support -GRUB_BTRFS_GRUB_DIRNAME="/efi/grub" - # Disable os-prober (single-boot system) GRUB_DISABLE_OS_PROBER=true EOF + # Create /boot/grub directory (grub-install expects this) + mkdir -p /mnt/boot/grub + # Install GRUB to EFI info "Installing GRUB to EFI partition..." arch-chroot /mnt grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB \ || error "GRUB installation failed" - # Generate GRUB config + # Generate GRUB config (without grub-btrfs first time) info "Generating GRUB configuration..." arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg \ || error "Failed to generate GRUB config" @@ -324,15 +324,31 @@ configure_btrfs_pacman_hook() { create_btrfs_genesis_snapshot() { step "Creating Genesis Snapshot" - # Use snapper to create the genesis snapshot - arch-chroot /mnt snapper -c root create --description "genesis" \ + # Create snapshot manually (snapper requires D-Bus which isn't available in chroot) + # Snapper stores snapshots in /.snapshots//snapshot as read-only subvolumes + local snap_dir="/mnt/.snapshots/1" + mkdir -p "$snap_dir" + + # Create the snapshot of root + btrfs subvolume snapshot -r /mnt "$snap_dir/snapshot" \ || error "Failed to create genesis snapshot" - info "Genesis snapshot created." - info "Restore with: snapper -c root rollback " + # Create snapper info.xml (required for snapper to recognize the snapshot) + local timestamp + timestamp=$(date -u +"%Y-%m-%d %H:%M:%S") + cat > "$snap_dir/info.xml" << EOF + + + single + 1 + $timestamp + genesis + number + +EOF - # Show the snapshot - arch-chroot /mnt snapper -c root list + info "Genesis snapshot created at /.snapshots/1/snapshot" + info "Restore with: snapper -c root rollback 1" } ############################# diff --git a/docs/session-context.org b/docs/session-context.org index 66a1ae0..b0ce8e0 100644 --- a/docs/session-context.org +++ b/docs/session-context.org @@ -8,8 +8,6 @@ *** Project Rename: archangel - Decided to rename project from "archzfs" to "archangel" - Script name will be just "archangel" (not install-archangel) -- Checked for conflicts: pwnerfly/Archangel is dead (2020, 0 stars, no license) -- Name is clear for use *** Btrfs Implementation Approach - Phase 2: Single-disk btrfs, no encryption (test first) @@ -17,45 +15,39 @@ - Phase 2.8: LUKS encryption after basic btrfs works - Phase 3: Multi-disk (stripe, mirror, raidX) + encrypted/unencrypted -*** Partition Type Handling -- disk.sh checks global FILESYSTEM variable -- ZFS: BF00 (Solaris root) -- Btrfs: 8300 (Linux filesystem) - ** Work Completed -*** 1. Phase 1: Refactor (COMPLETE) +*** Phase 1: Refactor (COMPLETE) - [X] lib/common.sh, config.sh, disk.sh, zfs.sh created - [X] Filesystem selection prompt - [X] Renamed to archangel - [X] VM test passed -*** 2. Phase 2: Btrfs Support (IN PROGRESS) -**** Phase 2.1: lib/btrfs.sh (COMPLETE) +*** Phase 2.1: Btrfs Support (COMPLETE) - [X] Created lib/btrfs.sh with full implementation -- [X] BTRFS_OPTS: noatime,compress=zstd,space_cache=v2,discard=async - [X] 10 subvolumes matching ZFS dataset layout - [X] Mount functions with proper options - [X] fstab generation (subvol= NOT subvolid!) -- [X] Snapper configuration (timeline policy) +- [X] Snapper configuration (manual config - no D-Bus needed in chroot) - [X] GRUB + grub-btrfs configuration -- [X] Genesis snapshot via snapper +- [X] Genesis snapshot via btrfs (not snapper, avoids D-Bus) +- [X] VM TEST PASSED @ 23:57 CST -**** Updated Files -- [X] disk.sh - filesystem-aware partition type -- [X] archangel - sources btrfs.sh, install_btrfs() path -- [X] build.sh - includes lib/btrfs.sh permissions -- [X] PLAN-archangel-btrfs.org - added Phase 2.7/2.8 +**** Bugs Fixed During Testing +1. GRUB_BTRFS_GRUB_DIRNAME was wrong (/efi/grub -> /boot/grub) +2. snapper create-config needs D-Bus - switched to manual config +3. snapper create needs D-Bus - create genesis snapshot with btrfs command +4. test-install.sh now copies lib/ directory for testing -**** Syntax Checks -- [X] All lib/*.sh pass bash -n -- [X] archangel passes bash -n -- [X] All btrfs functions defined correctly +** Commits This Session +- a49f4b1: Phase 2.1: Implement btrfs support +- (pending): Fix btrfs bugs from VM testing ** Next Steps -1. Commit Phase 2.1 implementation -2. Build ISO -3. VM test btrfs installation path +1. Commit bug fixes +2. Test btrfs reboot and actual boot from installed system +3. Phase 2.7: Full reboot/snapshot testing +4. Phase 2.8: LUKS encryption ** Notes - Craig on remote console: 30 lines tall, ~145 columns wide diff --git a/scripts/test-configs/btrfs-single.conf b/scripts/test-configs/btrfs-single.conf new file mode 100644 index 0000000..44b0f26 --- /dev/null +++ b/scripts/test-configs/btrfs-single.conf @@ -0,0 +1,13 @@ +# Test config: Btrfs single disk install + +HOSTNAME=test-btrfs +TIMEZONE=UTC +LOCALE=en_US.UTF-8 +KEYMAP=us + +FILESYSTEM=btrfs +DISKS=/dev/vda + +ROOT_PASSWORD=testpass + +ENABLE_SSH=yes diff --git a/scripts/test-install.sh b/scripts/test-install.sh index de308f2..798c301 100755 --- a/scripts/test-install.sh +++ b/scripts/test-install.sh @@ -224,16 +224,18 @@ run_install() { local config_name config_name=$(basename "$config" .conf) - # Copy latest install-archzfs script to VM (in case ISO is outdated) + # Copy latest archangel script and lib/ to VM (in case ISO is outdated) sshpass -p "$SSH_PASSWORD" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ - -P "$SSH_PORT" "$PROJECT_DIR/custom/install-archzfs" root@localhost:/usr/local/bin/install-archzfs 2>/dev/null + -P "$SSH_PORT" "$PROJECT_DIR/custom/archangel" root@localhost:/usr/local/bin/archangel 2>/dev/null + sshpass -p "$SSH_PASSWORD" scp -r -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -P "$SSH_PORT" "$PROJECT_DIR/custom/lib" root@localhost:/usr/local/bin/ 2>/dev/null # Copy config file to VM sshpass -p "$SSH_PASSWORD" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ -P "$SSH_PORT" "$config" root@localhost:/root/test.conf 2>/dev/null # Run the installer (NO_ENCRYPT is set in the config file, not via flag) - ssh_cmd "install-archzfs --config-file /root/test.conf" || return 1 + ssh_cmd "archangel --config-file /root/test.conf" || return 1 return 0 } @@ -242,45 +244,61 @@ run_install() { verify_install() { local config="$1" local enable_ssh + local filesystem enable_ssh=$(grep "^ENABLE_SSH=" "$config" | cut -d= -f2) + filesystem=$(grep "^FILESYSTEM=" "$config" | cut -d= -f2) + filesystem="${filesystem:-zfs}" # Default to ZFS # Basic checks via SSH (if enabled) if [[ "$enable_ssh" == "yes" ]]; then - # Check if we can still SSH (install script reboots, so this won't work) - # Instead, check the install log for success indicators - if ssh_cmd "grep -q 'Installation complete' /tmp/install-archzfs-*.log 2>/dev/null"; then + # Check install log for success indicators + if ssh_cmd "grep -q 'Installation complete' /tmp/archangel-*.log 2>/dev/null"; then info "Install log shows success" else warn "Could not verify install log" fi - # Check pool was created - if ssh_cmd "zpool list zroot" >/dev/null 2>&1; then - info "ZFS pool 'zroot' exists" - else - error "ZFS pool 'zroot' not found" - return 1 - fi - - # Check genesis snapshot - if ssh_cmd "zfs list -t snapshot | grep -q genesis"; then - info "Genesis snapshot exists" - else - warn "Genesis snapshot not found (may not have completed)" + if [[ "$filesystem" == "zfs" ]]; then + # ZFS-specific checks + if ssh_cmd "zpool list zroot" >/dev/null 2>&1; then + info "ZFS pool 'zroot' exists" + else + error "ZFS pool 'zroot' not found" + return 1 + fi + + if ssh_cmd "zfs list -t snapshot | grep -q genesis"; then + info "ZFS genesis snapshot exists" + else + warn "ZFS genesis snapshot not found" + fi + elif [[ "$filesystem" == "btrfs" ]]; then + # Btrfs-specific checks + if ssh_cmd "btrfs subvolume list /mnt" >/dev/null 2>&1; then + info "Btrfs subvolumes exist" + else + error "Btrfs subvolumes not found" + return 1 + fi + + if ssh_cmd "arch-chroot /mnt snapper -c root list 2>/dev/null | grep -q genesis"; then + info "Btrfs genesis snapshot exists" + else + warn "Btrfs genesis snapshot not found" + fi fi - # Check Avahi mDNS packages installed on target system + # Check Avahi mDNS packages if ssh_cmd "arch-chroot /mnt pacman -Q avahi nss-mdns >/dev/null 2>&1"; then info "Avahi packages installed" else - warn "Avahi packages not found on installed system" + warn "Avahi packages not found" fi - # Check avahi-daemon enabled on target system if ssh_cmd "arch-chroot /mnt systemctl is-enabled avahi-daemon >/dev/null 2>&1"; then info "Avahi daemon enabled" else - warn "Avahi daemon not enabled on installed system" + warn "Avahi daemon not enabled" fi else # For no-SSH tests, check serial console output @@ -356,7 +374,7 @@ run_test() { stop_vm "$config_name" # Save logs - ssh_cmd "cat /tmp/install-archzfs-*.log" > "$LOG_DIR/${config_name}-install.log" 2>/dev/null || true + ssh_cmd "cat /tmp/archangel-*.log" > "$LOG_DIR/${config_name}-install.log" 2>/dev/null || true cp "$SERIAL_LOG" "$LOG_DIR/${config_name}-serial.log" 2>/dev/null || true cleanup_disks "$config_name" -- cgit v1.2.3