# Transaction management for Particle-OS apt-layer Tool # Provides atomic operations with automatic rollback and recovery # System initialization functions initialize_particle_os_system() { log_info "Initializing Particle-OS system..." "apt-layer" # Create configuration directory mkdir -p "/usr/local/etc/particle-os" # Create workspace directory mkdir -p "/var/lib/particle-os" # Create log directory mkdir -p "/var/log/particle-os" # Create cache directory mkdir -p "/var/cache/particle-os" # Create configuration file if it doesn't exist if [[ ! -f "/usr/local/etc/particle-config.sh" ]]; then create_default_configuration fi # Set proper permissions chmod 755 "/var/lib/particle-os" chmod 755 "/var/log/particle-os" chmod 755 "/var/cache/particle-os" chmod 644 "/usr/local/etc/particle-config.sh" log_success "Particle-OS system initialized successfully" "apt-layer" } create_default_configuration() { log_info "Creating default configuration..." "apt-layer" cat > "/usr/local/etc/particle-config.sh" << 'EOF' #!/bin/bash # Particle-OS Configuration File # Generated automatically on $(date) # Core paths export PARTICLE_WORKSPACE="/var/lib/particle-os" export PARTICLE_CONFIG_DIR="/usr/local/etc/particle-os" export PARTICLE_LOG_DIR="/var/log/particle-os" export PARTICLE_CACHE_DIR="/var/cache/particle-os" # Build and temporary directories export PARTICLE_BUILD_DIR="$PARTICLE_WORKSPACE/build" export PARTICLE_TEMP_DIR="$PARTICLE_WORKSPACE/temp" export PARTICLE_BACKUP_DIR="$PARTICLE_WORKSPACE/backup" # Layer management export PARTICLE_LAYERS_DIR="$PARTICLE_WORKSPACE/layers" export PARTICLE_IMAGES_DIR="$PARTICLE_WORKSPACE/images" export PARTICLE_MOUNTS_DIR="$PARTICLE_WORKSPACE/mounts" # ComposeFS integration export PARTICLE_COMPOSEFS_DIR="$PARTICLE_WORKSPACE/composefs" export PARTICLE_COMPOSEFS_SCRIPT="/usr/local/bin/composefs-alternative.sh" # Boot management export PARTICLE_BOOTC_SCRIPT="/usr/local/bin/bootc-alternative.sh" export PARTICLE_BOOTUPD_SCRIPT="/usr/local/bin/bootupd-alternative.sh" # Transaction management export PARTICLE_TRANSACTION_LOG="$PARTICLE_LOG_DIR/transactions.log" export PARTICLE_TRANSACTION_STATE="$PARTICLE_CACHE_DIR/transaction.state" # Logging configuration export PARTICLE_LOG_LEVEL="INFO" export PARTICLE_LOG_FILE="$PARTICLE_LOG_DIR/apt-layer.log" # Security settings export PARTICLE_SIGNING_ENABLED="false" export PARTICLE_VERIFY_SIGNATURES="false" # Container settings export PARTICLE_CONTAINER_RUNTIME="podman" export PARTICLE_CHROOT_ENABLED="true" # Default package sources export PARTICLE_DEFAULT_SOURCES="main restricted universe multiverse" # Performance settings export PARTICLE_PARALLEL_JOBS="4" export PARTICLE_CACHE_ENABLED="true" # Load configuration if it exists if [[ -f "$PARTICLE_CONFIG_DIR/particle-config.sh" ]]; then source "$PARTICLE_CONFIG_DIR/particle-config.sh" fi EOF log_success "Default configuration created: /usr/local/etc/particle-config.sh" "apt-layer" } reset_particle_os_system() { log_warning "Resetting Particle-OS system..." "apt-layer" # Backup existing configuration if [[ -f "/usr/local/etc/particle-config.sh" ]]; then cp "/usr/local/etc/particle-config.sh" "/usr/local/etc/particle-config.sh.backup.$(date +%Y%m%d_%H%M%S)" log_info "Existing configuration backed up" "apt-layer" fi # Remove existing directories rm -rf "/var/lib/particle-os" rm -rf "/var/log/particle-os" rm -rf "/var/cache/particle-os" # Reinitialize system initialize_particle_os_system log_success "Particle-OS system reset successfully" "apt-layer" } # Transaction management functions start_transaction() { local operation="$1" local target="$2" TRANSACTION_ID=$(date +%Y%m%d_%H%M%S)_$$ TRANSACTION_PHASE="started" TRANSACTION_TARGET="$target" log_transaction "Starting transaction $TRANSACTION_ID: $operation -> $target" "apt-layer" # Save transaction state save_transaction_state # Log transaction start echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - START - $TRANSACTION_ID - $operation - $target" >> "$TRANSACTION_LOG" } update_transaction_phase() { local phase="$1" TRANSACTION_PHASE="$phase" log_transaction "Transaction $TRANSACTION_ID phase: $phase" "apt-layer" # Update transaction state save_transaction_state # Log phase update echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - PHASE - $TRANSACTION_ID - $phase" >> "$TRANSACTION_LOG" } commit_transaction() { log_transaction "Committing transaction $TRANSACTION_ID" "apt-layer" # Log successful completion echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - COMMIT - $TRANSACTION_ID - SUCCESS" >> "$TRANSACTION_LOG" # Clear transaction state clear_transaction_state log_success "Transaction $TRANSACTION_ID completed successfully" "apt-layer" } rollback_transaction() { log_transaction "Rolling back transaction $TRANSACTION_ID" "apt-layer" if [[ -n "$TRANSACTION_BACKUP" ]] && [[ -d "$TRANSACTION_BACKUP" ]]; then log_info "Restoring from backup: $TRANSACTION_BACKUP" "apt-layer" # Restore from backup if atomic_directory_swap "$TRANSACTION_BACKUP" "$TRANSACTION_TARGET" ""; then log_success "Rollback completed successfully" "apt-layer" else log_error "Rollback failed - manual intervention may be required" "apt-layer" fi else log_warning "No backup available for rollback" "apt-layer" fi # Log rollback echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - ROLLBACK - $TRANSACTION_ID - $TRANSACTION_PHASE" >> "$TRANSACTION_LOG" # Clear transaction state clear_transaction_state } save_transaction_state() { if [[ -n "$TRANSACTION_ID" ]]; then cat > "$TRANSACTION_STATE" << EOF TRANSACTION_ID="$TRANSACTION_ID" TRANSACTION_PHASE="$TRANSACTION_PHASE" TRANSACTION_TARGET="$TRANSACTION_TARGET" TRANSACTION_BACKUP="$TRANSACTION_BACKUP" TRANSACTION_TEMP_DIRS=(${TRANSACTION_TEMP_DIRS[*]}) EOF fi } clear_transaction_state() { TRANSACTION_ID="" TRANSACTION_PHASE="" TRANSACTION_TARGET="" TRANSACTION_BACKUP="" TRANSACTION_TEMP_DIRS=() # Remove state file rm -f "$TRANSACTION_STATE" } load_transaction_state() { if [[ -f "$TRANSACTION_STATE" ]]; then source "$TRANSACTION_STATE" return 0 else return 1 fi } check_incomplete_transactions() { log_info "Checking for incomplete transactions..." "apt-layer" if load_transaction_state; then log_warning "Found incomplete transaction: $TRANSACTION_ID (phase: $TRANSACTION_PHASE)" "apt-layer" log_info "Target: $TRANSACTION_TARGET" "apt-layer" if [[ -n "$TRANSACTION_BACKUP" ]] && [[ -d "$TRANSACTION_BACKUP" ]]; then log_info "Backup available: $TRANSACTION_BACKUP" "apt-layer" fi # Ask user what to do echo echo "Incomplete transaction detected. Choose an action:" echo "1) Attempt rollback (recommended)" echo "2) Continue transaction (risky)" echo "3) Clear transaction state (manual cleanup required)" echo "4) Exit" echo read -p "Enter choice (1-4): " choice case "$choice" in 1) log_info "Attempting rollback..." "apt-layer" rollback_transaction ;; 2) log_warning "Continuing incomplete transaction..." "apt-layer" log_info "Transaction will resume from phase: $TRANSACTION_PHASE" "apt-layer" ;; 3) log_warning "Clearing transaction state..." "apt-layer" clear_transaction_state ;; 4) log_info "Exiting..." "apt-layer" exit 0 ;; *) log_error "Invalid choice, exiting..." "apt-layer" exit 1 ;; esac else log_info "No incomplete transactions found" "apt-layer" fi } # Dry run functionality for package installation dry_run_apt_install() { local packages=("$@") local chroot_dir="${1:-}" log_info "Performing dry run for packages: ${packages[*]}" "apt-layer" local apt_cmd if [[ -n "$chroot_dir" ]]; then apt_cmd="chroot '$chroot_dir' apt-get install --simulate" else apt_cmd="apt-get install --simulate" fi # Add packages to command apt_cmd+=" ${packages[*]}" log_debug "Running: $apt_cmd" "apt-layer" # Execute dry run if eval "$apt_cmd" >/dev/null 2>&1; then log_success "Dry run completed successfully - no conflicts detected" "apt-layer" return 0 else log_error "Dry run failed - potential conflicts detected" "apt-layer" log_info "Run the command manually to see detailed output:" "apt-layer" log_info "$apt_cmd" "apt-layer" return 1 fi } # Transaction logging utilities log_transaction_event() { local event="$1" local details="$2" echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) - $event - $TRANSACTION_ID - $details" >> "$TRANSACTION_LOG" } # Transaction validation validate_transaction_state() { if [[ -z "$TRANSACTION_ID" ]]; then log_error "No active transaction" "apt-layer" return 1 fi if [[ -z "$TRANSACTION_TARGET" ]]; then log_error "Transaction target not set" "apt-layer" return 1 fi return 0 } # Transaction cleanup utilities add_temp_directory() { local temp_dir="$1" TRANSACTION_TEMP_DIRS+=("$temp_dir") save_transaction_state } add_backup_path() { local backup_path="$1" TRANSACTION_BACKUP="$backup_path" save_transaction_state }