diff --git a/scripts/bootc-image-builder.sh b/scripts/bootc-image-builder.sh index 46dda5d..aa10c8c 100755 --- a/scripts/bootc-image-builder.sh +++ b/scripts/bootc-image-builder.sh @@ -1,7 +1,8 @@ #!/bin/bash -# Simplified bootc-image-builder for Debian -# Focuses on container-to-disk conversion without osbuild complexity +# deb-bootc-image-builder - Simplified container to disk image converter +# This is a simplified fork of the original Fedora bootc-image-builder +# that uses native Debian tools instead of osbuild set -euo pipefail @@ -30,8 +31,16 @@ CONTAINER_STORAGE="/var/lib/containers/storage" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' +BLUE='\033[0;34m' NC='\033[0m' # No Color +# Global variables for cleanup +WORK_DIR="" +LOOP_DEV="" +MOUNT_POINT="" +CONTAINER_FS_DIR="" +DISK_RAW="" + # Logging functions log_info() { 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" fi -# Function to cleanup on exit -cleanup() { - log_info "Cleaning up..." +# Signal handling for cleanup +cleanup_on_exit() { + local exit_code=$? + log_info "Cleaning up resources..." - # Unmount if still mounted - if [[ -n "${MOUNT_POINT:-}" ]] && mountpoint -q "$MOUNT_POINT" 2>/dev/null; then - log_info "Unmounting $MOUNT_POINT..." - sudo $UMOUNT "$MOUNT_POINT" || true + # Unmount if mounted + if [[ -n "$MOUNT_POINT" && -d "$MOUNT_POINT" ]]; then + if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then + log_info "Unmounting $MOUNT_POINT..." + sudo umount "$MOUNT_POINT" 2>/dev/null || true + fi fi - # Detach loopback device if still attached - if [[ -n "${LOOP_DEV:-}" ]] && [[ -b "$LOOP_DEV" ]]; then - log_info "Detaching loopback device $LOOP_DEV..." - sudo $LOSETUP -d "$LOOP_DEV" || true + # Detach loop device if exists + if [[ -n "$LOOP_DEV" && -b "$LOOP_DEV" ]]; then + log_info "Detaching loop device $LOOP_DEV..." + 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 # 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..." - sudo rm -rf "$WORK_DIR" || true + sudo rm -rf "$WORK_DIR" 2>/dev/null || true 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 log_info "Checking if container image exists locally: $CONTAINER_IMAGE" @@ -198,8 +265,9 @@ cd "$WORK_DIR" # Extract the container log_info "Extracting container filesystem..." -mkdir -p container-fs -if ! tar -xf container.tar -C container-fs; then +CONTAINER_FS_DIR="$WORK_DIR/container-fs" +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 "1. Insufficient disk space" 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..." # 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 # 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 log_info "Creating partition table and filesystem..." -sudo $PARTED disk.raw mklabel msdos -sudo $PARTED disk.raw mkpart primary ext4 1MiB 100% -sudo $PARTED disk.raw set 1 boot on +sudo $PARTED "$DISK_RAW" mklabel msdos +sudo $PARTED "$DISK_RAW" mkpart primary ext4 1MiB 100% +sudo $PARTED "$DISK_RAW" set 1 boot on # Setup 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" # Force kernel to reread partition table @@ -270,7 +339,7 @@ sudo $MOUNT "$PART_DEV" "$MOUNT_POINT" # Copy container filesystem 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 log_info "Installing bootloader manually..." @@ -330,13 +399,13 @@ sudo $LOSETUP -d "$LOOP_DEV" log_info "Converting to $OUTPUT_FORMAT format..." case "$OUTPUT_FORMAT" in 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) - cp disk.raw "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').raw" + cp "$DISK_RAW" "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').raw" ;; img) - cp disk.raw "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').img" + cp "$DISK_RAW" "$OUTPUT_DIR/$(basename "$CONTAINER_IMAGE" | tr ':' '_').img" ;; esac