Thursday, October 22, 2026

Thin XFS LVs provisioning and Libvirt hooks for State Isolated KVM Server on Debian forky

Following below is review/verification approach to Thin XFS LVs provisioning and Libvirt hooks proposed by Google AI. This post is an immediate follow up of  https://lxer.com/module/newswire/view/368300/index.html  . Regarding Debian forky OverlayFS BTRFS/XFS setup see https://lxer.com/module/newswire/view/368197/index.html                                                                                          

Version of /etc/libvirt/hooks/qemu for Debian 14 

root@debian14forky:~# cat /etc/libvirt/hooks/qemu
#!/bin/bash
GUEST_NAME="$1"
ACTION="$2"
PHASE="$3"
STORAGE_DIR="/var/lib/libvirt/images"
BACKUP_DIR="${STORAGE_DIR}/.snapshots_${GUEST_NAME}"

[ ! -d "$STORAGE_DIR" ] && exit 0

# --- State Changes Layer: Reflink Clones ---
if [ "$ACTION" = "prepare" ] || [ "$ACTION" = "stopped" ]; then
   # Fire off the automated LVM snapshot service asynchronously
   /usr/bin/systemctl start lvm-thin-snapshot.service &

   (
       /usr/bin/sleep 2
       /usr/bin/mkdir -p "$BACKUP_DIR"

       for disk_path in "${STORAGE_DIR}"/*"${GUEST_NAME}"*.qcow2; do
           [ ! -f "$disk_path" ] && continue
           disk_file=$(/usr/bin/basename "$disk_path")
           timestamp=$(/usr/bin/date +%Y%m%d_%H%M%S)

           # Atomic copy-on-write VFS creation
           /usr/bin/cp --reflink=always "$disk_path" "${BACKUP_DIR}/${disk_file}.snap_${timestamp}"
            
           # Align permissions with Debian virtual user accounts
           /usr/bin/chown libvirt-qemu:kvm "${BACKUP_DIR}/${disk_file}.snap_${timestamp}" 2>/dev/null
       done

       # Keep the last 5 operational states
       /usr/bin/ls -tp "${BACKUP_DIR}"/* | /usr/bin/grep -v '/$' | /usr/bin/tail -n +6 | /usr/bin/xargs -I {} /usr/bin/rm -- "{}" 2>/dev/null
   ) & disown

# --- Domain Mapping Tracking: Define/Undefine ---
elif [ "$ACTION" = "define" ] || [ "$ACTION" = "undefine" ]; then
   /usr/bin/systemctl start lvm-thin-snapshot.service &
fi

exit 0

root@debian14forky:~# cat /etc/systemd/system/lvm-thin-snapshot.service
[Unit]
Description=Rotate Pristine LVM Thin Pool Snapshot on Libvirt Changes
After=local-fs.target

[Service]
Type=oneshot
User=root
Environment=VG_NAME=vg_debian
Environment=SNAP_NAME=snap_working_vms
Environment=THIN_VOL=vol_debian_thin
Environment=IMG_DIR=/var/lib/libvirt/images

ExecStart=/bin/bash -c '\
   echo "Current allocated qcow2 image count: $(ls -1 ${IMG_DIR}/*.qcow2 2>/dev/null | wc -l)"; \
   echo "Removing old snapshot if present..."; \
   /usr/sbin/lvremove -f "${VG_NAME}/${SNAP_NAME}" 2>/dev/null || true; \
   echo "Creating pristine baseline snapshot..."; \
   /usr/sbin/lvcreate -s --name "${SNAP_NAME}" "${VG_NAME}/${THIN_VOL}"'

[Install]
WantedBy=multi-user.target

 
Version of Recovery from simulated disaster for Debian forky

root@debian14forky:~# cat ./virtSetup016_debian
#!/bin/bash
#=============================================================
# DEBIAN 14 PRODUCTION DISASTER RECOVERY ENGINE (SYNCHRONOUS FENCED)
#=============================================================
set -e

TARGET_MNT="/var/lib/libvirt/images"
VG_NAME="vg_debian"
THIN_VOL="vol_debian_thin"
SNAP_NAME="snap_working_vms"
GUEST_NAME="ArchPlasma" # Toggle to "ArchPlasma" when testing the other VM

echo "=== PHASE 1: RE-ARM IMMUNE STORAGE MATRIX BASELINE ==="
# Forcefully clear stale snapshots and index the current healthy file footprint
sudo lvremove -f ${VG_NAME}/${SNAP_NAME} 2>/dev/null || true
sudo lvcreate -s --name ${SNAP_NAME} ${VG_NAME}/${THIN_VOL}
sudo lvs ${VG_NAME}

echo "=== PHASE 2: CATASTROPHIC DISASTER SIMULATION ==="
sudo virsh destroy ${GUEST_NAME} 2>/dev/null || true

# Hook check loop: wait for the asynchronous VFS reflink lifecycle copy to finish
echo "==> Waiting for hook script background backup copy to complete..."
while pgrep -f "cp --reflink=always" >/dev/null || systemctl is-active --quiet lvm-thin-snapshot.service; do
   echo "    [WAIT] Hook script is actively saving safety copies. Stalling 2 seconds..."
   sleep 2
done
echo "==> Hook script finished! Storage layer is quiet."

# Catastrophically corrupt the target virtual disk image with random blocks
sudo dd if=/dev/urandom of=${TARGET_MNT}/${GUEST_NAME}.qcow2 bs=1M count=500 conv=notrunc

echo "=== PHASE 3: SYNCHRONOUS WAIT-FOR-EXIT CODE FENCE ==="
# Sever the monolithic hypervisor interfaces and persistent socket networks
sudo systemctl stop libvirtd.socket libvirtd-ro.socket libvirtd-admin.socket libvirtd.service 2>/dev/null || true
sudo pkill -9 qemu 2>/dev/null || true
sudo fuser -kM "${TARGET_MNT}" 2>/dev/null || true

echo "==> Initiating standard physical unmount loop..."
COUNTER=1
while [ $COUNTER -le 20 ]; do
   echo "    [TRY $COUNTER/20] Testing standard umount..."
   if sudo umount ${TARGET_MNT} 2>/dev/null; then
       echo "==> SUCCESS: Filesystem detached cleanly with exit code 0."
       break
   fi
   echo "    [WAIT] Kernel block maps busy. Stalling 3 seconds for clean flush..."
   sleep 3
   COUNTER=$((COUNTER + 1))
done


if [ $COUNTER -gt 20 ]; then
   echo "ERROR: Kernel refused to release filesystem within 60 seconds. Aborting."
   exit 1
fi

echo "=== PHASE 4: ATOMIC METADATA MERGE ==="
# Because the mount is completely dead, this block merge commits instantly
sudo lvconvert --merge ${VG_NAME}/${SNAP_NAME}

echo "=== PHASE 5: PURGE VOLATILE DESCRIPTORS & RE-ALIGN SECURITY ==="
sudo mount ${TARGET_MNT}

# Clear any deadlocked lock templates and volatile state trackers
sudo rm -f ${TARGET_MNT}/*.lock 2>/dev/null
sudo rm -rf /var/run/libvirt/qemu/* 2>/dev/null
sudo rm -rf /var/cache/libvirt/qemu/* 2>/dev/null

# Re-align user attributes explicitly to Debian's privilege accounts
sudo chown libvirt-qemu:kvm ${TARGET_MNT}/${GUEST_NAME}.qcow2
sudo chmod 600 ${TARGET_MNT}/${GUEST_NAME}.qcow2

# TEMPORARY SECURITY OVERRULE: Bypass stale DAC memory cache issues on ignition
sudo virsh dumpxml ${GUEST_NAME} > /tmp/${GUEST_NAME}_recovery.xml 2>/dev/null || true
if ! grep -q 'seclabel type="none"' /tmp/${GUEST_NAME}_recovery.xml 2>/dev/null; then
   sed -i '/<\/devices>/a \  <seclabel type="none" model="dac"\/>' /tmp/${GUEST_NAME}_recovery.xml 2>/dev/null || true
   sudo virsh undefine ${GUEST_NAME} 2>/dev/null || true
   sudo virsh define /tmp/${GUEST_NAME}_recovery.xml >/dev/null 2>&1 || true
fi
rm -f /tmp/${GUEST_NAME}_recovery.xml

# Restart systemd cgroups and restore daemon listen layers
sudo systemctl restart systemd-machined
sudo systemctl start libvirtd.socket libvirtd-ro.socket libvirtd-admin.socket libvirtd.service

echo "=== PHASE 6: POWER ON RECOVERED GUEST ==="
sudo virsh start ${GUEST_NAME}
echo "==========================================="
sudo virsh list --all


 

No comments:

Post a Comment