particle-os-tools/src/apt-layer/scriptlets/02-transactions.sh
robojerk 74c7bede5f Initial commit: Particle-OS tools repository
- Complete Particle-OS rebranding from uBlue-OS
- Professional installation system with standardized paths
- Self-initialization system with --init and --reset commands
- Enhanced error messages and dependency checking
- Comprehensive testing infrastructure
- All source scriptlets updated with runtime improvements
- Clean codebase with redundant files moved to archive
- Complete documentation suite
2025-07-11 21:14:33 -07:00

330 lines
9.8 KiB
Bash

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