#!/bin/bash # Traditional layer creation for Ubuntu uBlue apt-layer Tool # Provides chroot-based package installation for layer creation # Create traditional layer create_layer() { local base_image="$1" local new_image="$2" shift 2 local packages=("$@") log_layer "Creating traditional layer: $new_image" "apt-layer" log_info "Base image: $base_image" "apt-layer" log_info "Packages to install: ${packages[*]}" "apt-layer" # Start transaction start_transaction "create_layer" "$new_image" # Check if base image exists if ! composefs_image_exists "$base_image"; then log_error "Base image '$base_image' not found" "apt-layer" log_info "Available images:" "apt-layer" composefs_list_images exit 1 fi # Prepare temp_layer_dir local temp_layer_dir="$BUILD_DIR/temp-layer-$(basename "$new_image")-${TRANSACTION_ID}" local final_layer_dir="$BUILD_DIR/layer-$(basename "$new_image")" local backup_dir="$BUILD_DIR/backup-layer-$(basename "$new_image")-${TRANSACTION_ID}" add_temp_directory "$temp_layer_dir" add_temp_directory "$backup_dir" rm -rf "$temp_layer_dir" 2>/dev/null || true mkdir -p "$temp_layer_dir" update_transaction_phase "checkout_base" # Mount base image to temp_layer_dir log_info "Mounting base image..." "apt-layer" if ! composefs_mount "$base_image" "$temp_layer_dir"; then log_error "Failed to mount base image" "apt-layer" exit 1 fi update_transaction_phase "setup_chroot" # Set up chroot environment log_info "Setting up chroot environment..." "apt-layer" mount --bind /proc "$temp_layer_dir/proc" mount --bind /sys "$temp_layer_dir/sys" mount --bind /dev "$temp_layer_dir/dev" # Copy host's resolv.conf for internet access cp /etc/resolv.conf "$temp_layer_dir/etc/resolv.conf" 2>/dev/null || true # Ensure /run exists and is writable mkdir -p "$temp_layer_dir/run" chmod 755 "$temp_layer_dir/run" # Set non-interactive environment for apt export DEBIAN_FRONTEND=noninteractive update_transaction_phase "dry_run_check" # Perform dry run to check for conflicts log_info "Performing dry run to check for package conflicts..." "apt-layer" if ! dry_run_apt_install "$temp_layer_dir" "${packages[@]}"; then log_error "Dry run failed - package conflicts detected" "apt-layer" log_info "Please resolve conflicts before proceeding" "apt-layer" exit 1 fi update_transaction_phase "install_packages" # Install packages in chroot log_info "Installing packages in chroot..." "apt-layer" if ! chroot "$temp_layer_dir" apt-get update; then log_error "Failed to update package lists in chroot" "apt-layer" exit 1 fi if ! chroot "$temp_layer_dir" apt-get install -y "${packages[@]}"; then log_error "Failed to install packages in chroot" "apt-layer" exit 1 fi # Clean up package cache chroot "$temp_layer_dir" apt-get clean chroot "$temp_layer_dir" apt-get autoremove -y update_transaction_phase "cleanup_mounts" # Clean up mounts umount "$temp_layer_dir/proc" 2>/dev/null || true umount "$temp_layer_dir/sys" 2>/dev/null || true umount "$temp_layer_dir/dev" 2>/dev/null || true # Remove temporary resolv.conf rm -f "$temp_layer_dir/etc/resolv.conf" update_transaction_phase "atomic_swap" # Perform atomic directory swap if [[ -d "$final_layer_dir" ]]; then log_debug "Backing up existing layer directory" "apt-layer" if ! atomic_directory_swap "$final_layer_dir" "$backup_dir" ""; then log_error "Failed to backup existing layer directory" "apt-layer" exit 1 fi add_backup_path "$backup_dir" fi # Move temporary directory to final location if ! atomic_directory_swap "$temp_layer_dir" "$final_layer_dir" ""; then log_error "Failed to perform atomic directory swap" "apt-layer" exit 1 fi update_transaction_phase "create_commit" # Create ComposeFS image from the final layer directory log_info "Creating ComposeFS image..." "apt-layer" if ! composefs_create "$new_image" "$final_layer_dir"; then log_error "Failed to create ComposeFS image" "apt-layer" exit 1 fi # Commit transaction commit_transaction log_success "Traditional layer created successfully: $new_image" "apt-layer" } # Setup chroot environment for package installation setup_chroot_environment() { local chroot_dir="$1" log_debug "Setting up chroot environment: $chroot_dir" "apt-layer" # Create necessary directories mkdir -p "$chroot_dir"/{proc,sys,dev,run} # Mount essential filesystems mount --bind /proc "$chroot_dir/proc" mount --bind /sys "$chroot_dir/sys" mount --bind /dev "$chroot_dir/dev" # Copy DNS configuration cp /etc/resolv.conf "$chroot_dir/etc/resolv.conf" 2>/dev/null || true # Set proper permissions chmod 755 "$chroot_dir/run" # Set environment variables export DEBIAN_FRONTEND=noninteractive log_debug "Chroot environment setup completed" "apt-layer" } # Cleanup chroot environment cleanup_chroot_environment() { local chroot_dir="$1" log_debug "Cleaning up chroot environment: $chroot_dir" "apt-layer" # Unmount filesystems umount "$chroot_dir/proc" 2>/dev/null || true umount "$chroot_dir/sys" 2>/dev/null || true umount "$chroot_dir/dev" 2>/dev/null || true # Remove temporary files rm -f "$chroot_dir/etc/resolv.conf" log_debug "Chroot environment cleanup completed" "apt-layer" } # Install packages in chroot with error handling install_packages_in_chroot() { local chroot_dir="$1" shift local packages=("$@") log_info "Installing packages in chroot: ${packages[*]}" "apt-layer" # Update package lists if ! chroot "$chroot_dir" apt-get update; then log_error "Failed to update package lists in chroot" "apt-layer" return 1 fi # Install packages if ! chroot "$chroot_dir" apt-get install -y "${packages[@]}"; then log_error "Failed to install packages in chroot" "apt-layer" return 1 fi # Clean up chroot "$chroot_dir" apt-get clean chroot "$chroot_dir" apt-get autoremove -y log_success "Packages installed successfully in chroot" "apt-layer" return 0 } # Validate chroot environment validate_chroot_environment() { local chroot_dir="$1" log_debug "Validating chroot environment: $chroot_dir" "apt-layer" # Check if chroot directory exists if [[ ! -d "$chroot_dir" ]]; then log_error "Chroot directory does not exist: $chroot_dir" "apt-layer" return 1 fi # Check if essential directories exist for dir in bin lib usr etc; do if [[ ! -d "$chroot_dir/$dir" ]]; then log_error "Essential directory missing in chroot: $dir" "apt-layer" return 1 fi done # Check if apt is available if [[ ! -x "$chroot_dir/usr/bin/apt-get" ]]; then log_error "apt-get not found in chroot environment" "apt-layer" return 1 fi log_debug "Chroot environment validation passed" "apt-layer" return 0 }