aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-01-23 23:58:07 -0600
committerCraig Jennings <c@cjennings.net>2026-01-23 23:58:07 -0600
commitbf62150d61d3e52b07095be21aff9ac5abe9d03f (patch)
treef68229e1bc41e5f1addbbe8bcf4b850f00c6c2a0
parente4ee55f9706d5567f45b6b4f6f007c09709fdfea (diff)
downloadarchangel-bf62150d61d3e52b07095be21aff9ac5abe9d03f.tar.gz
archangel-bf62150d61d3e52b07095be21aff9ac5abe9d03f.zip
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.
-rw-r--r--custom/lib/btrfs.sh54
-rw-r--r--docs/session-context.org42
-rw-r--r--scripts/test-configs/btrfs-single.conf13
-rwxr-xr-xscripts/test-install.sh66
4 files changed, 107 insertions, 68 deletions
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/<num>/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 <number>"
+ # 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
+<?xml version="1.0"?>
+<snapshot>
+ <type>single</type>
+ <num>1</num>
+ <date>$timestamp</date>
+ <description>genesis</description>
+ <cleanup>number</cleanup>
+</snapshot>
+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"