particle-os-tools/src/apt-layer/scriptlets/03-traditional.sh

233 lines
7.3 KiB
Bash

#!/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
}