Improve cleanup robustness: add signal handling, cleanup existing loop devices, better resource tracking
Some checks failed
particle-os CI / Test particle-os (push) Failing after 1s
particle-os CI / Security & Quality (push) Failing after 1s
particle-os CI / Integration Test (push) Has been skipped
Tests / test (1.21.x) (push) Failing after 1s
Tests / test (1.22.x) (push) Failing after 1s
particle-os CI / Build and Release (push) Has been skipped

This commit is contained in:
joe 2025-08-12 20:30:55 -07:00
parent 9a810d3d27
commit 2ecde247d3

View file

@ -1,7 +1,8 @@
#!/bin/bash #!/bin/bash
# Simplified bootc-image-builder for Debian # deb-bootc-image-builder - Simplified container to disk image converter
# Focuses on container-to-disk conversion without osbuild complexity # This is a simplified fork of the original Fedora bootc-image-builder
# that uses native Debian tools instead of osbuild
set -euo pipefail set -euo pipefail
@ -30,8 +31,16 @@ CONTAINER_STORAGE="/var/lib/containers/storage"
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# Global variables for cleanup
WORK_DIR=""
LOOP_DEV=""
MOUNT_POINT=""
CONTAINER_FS_DIR=""
DISK_RAW=""
# Logging functions # Logging functions
log_info() { log_info() {
echo -e "${GREEN}[INFO]${NC} $1" echo -e "${GREEN}[INFO]${NC} $1"
@ -142,30 +151,88 @@ if [[ "$AVAILABLE_SPACE" -lt 5000000 ]]; then # Less than 5GB
log_warn "This might cause issues with large containers" log_warn "This might cause issues with large containers"
fi fi
# Function to cleanup on exit # Signal handling for cleanup
cleanup() { cleanup_on_exit() {
log_info "Cleaning up..." local exit_code=$?
log_info "Cleaning up resources..."
# Unmount if still mounted # Unmount if mounted
if [[ -n "${MOUNT_POINT:-}" ]] && mountpoint -q "$MOUNT_POINT" 2>/dev/null; then if [[ -n "$MOUNT_POINT" && -d "$MOUNT_POINT" ]]; then
log_info "Unmounting $MOUNT_POINT..." if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then
sudo $UMOUNT "$MOUNT_POINT" || true log_info "Unmounting $MOUNT_POINT..."
sudo umount "$MOUNT_POINT" 2>/dev/null || true
fi
fi fi
# Detach loopback device if still attached # Detach loop device if exists
if [[ -n "${LOOP_DEV:-}" ]] && [[ -b "$LOOP_DEV" ]]; then if [[ -n "$LOOP_DEV" && -b "$LOOP_DEV" ]]; then
log_info "Detaching loopback device $LOOP_DEV..." log_info "Detaching loop device $LOOP_DEV..."
sudo $LOSETUP -d "$LOOP_DEV" || true sudo losetup -d "$LOOP_DEV" 2>/dev/null || true
fi
# Clean up any remaining loop devices that might be ours
if [[ -n "$WORK_DIR" ]]; then
log_info "Checking for orphaned loop devices..."
for loop_dev in /dev/loop*; do
if [[ -b "$loop_dev" ]]; then
local mount_point
mount_point=$(losetup -l "$loop_dev" 2>/dev/null | grep -o "/var/tmp/bootc-builder-[^[:space:]]*" || true)
if [[ -n "$mount_point" ]]; then
log_info "Detaching orphaned loop device $loop_dev..."
sudo losetup -d "$loop_dev" 2>/dev/null || true
fi
fi
done
fi fi
# Remove working directory # Remove working directory
if [[ -n "${WORK_DIR:-}" ]] && [[ -d "$WORK_DIR" ]]; then if [[ -n "$WORK_DIR" && -d "$WORK_DIR" ]]; then
log_info "Removing working directory $WORK_DIR..." log_info "Removing working directory $WORK_DIR..."
sudo rm -rf "$WORK_DIR" || true sudo rm -rf "$WORK_DIR" 2>/dev/null || true
fi fi
# Remove any remaining temporary files
if [[ -n "$DISK_RAW" && -f "$DISK_RAW" ]]; then
log_info "Removing temporary disk image $DISK_RAW..."
sudo rm -f "$DISK_RAW" 2>/dev/null || true
fi
if [[ -n "$CONTAINER_FS_DIR" && -d "$CONTAINER_FS_DIR" ]]; then
log_info "Removing container filesystem directory $CONTAINER_FS_DIR..."
sudo rm -rf "$CONTAINER_FS_DIR" 2>/dev/null || true
fi
log_info "Cleanup completed"
exit "$exit_code"
} }
trap cleanup EXIT # Set up signal handlers
trap cleanup_on_exit EXIT INT TERM
# Function to clean up any existing loop devices from previous runs
cleanup_existing_loop_devices() {
log_info "Checking for existing loop devices from previous runs..."
for loop_dev in /dev/loop*; do
if [[ -b "$loop_dev" ]]; then
local mount_point
mount_point=$(losetup -l "$loop_dev" 2>/dev/null | grep -o "/var/tmp/bootc-builder-[^[:space:]]*" || true)
if [[ -n "$mount_point" ]]; then
log_warn "Found existing loop device $loop_dev from previous run, cleaning up..."
# Try to unmount if mounted
if mountpoint -q "$mount_point" 2>/dev/null; then
sudo umount "$mount_point" 2>/dev/null || true
fi
# Detach the loop device
sudo losetup -d "$loop_dev" 2>/dev/null || true
# Remove the mount point directory
sudo rm -rf "$mount_point" 2>/dev/null || true
fi
fi
done
}
# Clean up any existing loop devices at startup
cleanup_existing_loop_devices
# Check if container image exists locally # Check if container image exists locally
log_info "Checking if container image exists locally: $CONTAINER_IMAGE" log_info "Checking if container image exists locally: $CONTAINER_IMAGE"
@ -198,8 +265,9 @@ cd "$WORK_DIR"
# Extract the container # Extract the container
log_info "Extracting container filesystem..." log_info "Extracting container filesystem..."
mkdir -p container-fs CONTAINER_FS_DIR="$WORK_DIR/container-fs"
if ! tar -xf container.tar -C container-fs; then mkdir -p "$CONTAINER_FS_DIR"
if ! tar -xf container.tar -C "$CONTAINER_FS_DIR"; then
log_error "Failed to extract container. This might be due to:" log_error "Failed to extract container. This might be due to:"
log_error "1. Insufficient disk space" log_error "1. Insufficient disk space"
log_error "2. Corrupted container archive" log_error "2. Corrupted container archive"
@ -215,7 +283,8 @@ IMAGE_SIZE="2G" # Default size, could be made configurable
log_info "Creating partitioned disk image for bootloader installation..." log_info "Creating partitioned disk image for bootloader installation..."
# Create raw image file # Create raw image file
$QEMU_IMG create -f raw disk.raw "$IMAGE_SIZE" DISK_RAW="$WORK_DIR/disk.raw"
$QEMU_IMG create -f raw "$DISK_RAW" "$IMAGE_SIZE"
# For bootloader installation, we need to create a proper disk structure # For bootloader installation, we need to create a proper disk structure
# This requires sudo for partitioning and mounting # This requires sudo for partitioning and mounting
@ -224,13 +293,13 @@ log_info "Note: This step requires sudo for disk operations"
# Create partition table and filesystem # Create partition table and filesystem
log_info "Creating partition table and filesystem..." log_info "Creating partition table and filesystem..."
sudo $PARTED disk.raw mklabel msdos sudo $PARTED "$DISK_RAW" mklabel msdos
sudo $PARTED disk.raw mkpart primary ext4 1MiB 100% sudo $PARTED "$DISK_RAW" mkpart primary ext4 1MiB 100%
sudo $PARTED disk.raw set 1 boot on sudo $PARTED "$DISK_RAW" set 1 boot on
# Setup loopback device # Setup loopback device
log_info "Setting up loopback device..." log_info "Setting up loopback device..."
LOOP_DEV=$(sudo $LOSETUP --find --show disk.raw) LOOP_DEV=$(sudo $LOSETUP --find --show "$DISK_RAW")
log_info "Using loopback device: $LOOP_DEV" log_info "Using loopback device: $LOOP_DEV"
# Force kernel to reread partition table # Force kernel to reread partition table
@ -270,7 +339,7 @@ sudo $MOUNT "$PART_DEV" "$MOUNT_POINT"
# Copy container filesystem # Copy container filesystem
log_info "Copying container filesystem to disk image..." log_info "Copying container filesystem to disk image..."
sudo rsync -a container-fs/ "$MOUNT_POINT/" sudo rsync -a "$CONTAINER_FS_DIR/" "$MOUNT_POINT/"
# Install bootloader manually since deb-bootupd doesn't support non-default sysroots # Install bootloader manually since deb-bootupd doesn't support non-default sysroots
log_info "Installing bootloader manually..." log_info "Installing bootloader manually..."
@ -330,13 +399,13 @@ sudo $LOSETUP -d "$LOOP_DEV"
log_info "Converting to $OUTPUT_FORMAT format..." log_info "Converting to $OUTPUT_FORMAT format..."
case "$OUTPUT_FORMAT" in case "$OUTPUT_FORMAT" in
qcow2) qcow2)
$QEMU_IMG convert -f raw -O qcow2 disk.raw "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').qcow2" $QEMU_IMG convert -f raw -O qcow2 "$DISK_RAW" "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').qcow2"
;; ;;
raw) raw)
cp disk.raw "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').raw" cp "$DISK_RAW" "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').raw"
;; ;;
img) img)
cp disk.raw "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').img" cp "$DISK_RAW" "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').img"
;; ;;
esac esac