particle-os-tools/src/apt-layer/scriptlets/10-rpm-ostree-compat.sh

448 lines
12 KiB
Bash

#!/bin/bash
# rpm-ostree compatibility layer for Ubuntu uBlue apt-layer Tool
# Provides 1:1 command compatibility with rpm-ostree
# rpm-ostree install compatibility
rpm_ostree_install() {
local packages=("$@")
log_info "rpm-ostree install compatibility: ${packages[*]}" "apt-layer"
# Use live overlay for package installation
if ! live_install "${packages[@]}"; then
log_error "rpm-ostree install failed" "apt-layer"
return 1
fi
log_success "rpm-ostree install completed successfully" "apt-layer"
return 0
}
# rpm-ostree upgrade compatibility
rpm_ostree_upgrade() {
log_info "rpm-ostree upgrade compatibility" "apt-layer"
# Use true system upgrade (not package upgrade)
if ! system_upgrade; then
log_error "rpm-ostree upgrade failed" "apt-layer"
return 1
fi
log_success "rpm-ostree upgrade completed successfully" "apt-layer"
return 0
}
# rpm-ostree rebase compatibility
rpm_ostree_rebase() {
local new_base="$1"
log_info "rpm-ostree rebase compatibility: $new_base" "apt-layer"
# Use intelligent rebase with conflict resolution
if ! intelligent_rebase "$new_base"; then
log_error "rpm-ostree rebase failed" "apt-layer"
return 1
fi
log_success "rpm-ostree rebase completed successfully" "apt-layer"
return 0
}
# rpm-ostree rollback compatibility
rpm_ostree_rollback() {
local target_commit="${1:-}"
log_info "rpm-ostree rollback compatibility: ${target_commit:-latest}" "apt-layer"
if [[ -z "$target_commit" ]]; then
# Rollback to previous deployment
target_commit=$(get_previous_deployment)
if [[ -z "$target_commit" ]]; then
log_error "No previous deployment found for rollback" "apt-layer"
return 1
fi
fi
# Use commit-based rollback
if ! commit_rollback "$target_commit"; then
log_error "rpm-ostree rollback failed" "apt-layer"
return 1
fi
log_success "rpm-ostree rollback completed successfully" "apt-layer"
return 0
}
# rpm-ostree status compatibility
rpm_ostree_status() {
log_info "rpm-ostree status compatibility" "apt-layer"
# Show atomic deployment status
atomic_status
# Show live overlay status
echo ""
echo "=== Live Overlay Status ==="
get_live_overlay_status
# Show package diff if pending deployment
local pending_deployment
pending_deployment=$(get_pending_deployment)
if [[ -n "$pending_deployment" ]]; then
echo ""
echo "=== Pending Changes ==="
show_package_diff "$(get_current_deployment)" "$pending_deployment"
fi
}
# rpm-ostree diff compatibility
rpm_ostree_diff() {
local from_commit="${1:-}"
local to_commit="${2:-}"
log_info "rpm-ostree diff compatibility: $from_commit -> $to_commit" "apt-layer"
# If no commits specified, compare current to pending
if [[ -z "$from_commit" ]]; then
from_commit=$(get_current_deployment)
fi
if [[ -z "$to_commit" ]]; then
to_commit=$(get_pending_deployment)
if [[ -z "$to_commit" ]]; then
log_error "No target commit specified and no pending deployment" "apt-layer"
return 1
fi
fi
# Show package-level diff
show_package_diff "$from_commit" "$to_commit"
}
# rpm-ostree db list compatibility
rpm_ostree_db_list() {
log_info "rpm-ostree db list compatibility" "apt-layer"
# List all deployments
list_deployments
}
# rpm-ostree db diff compatibility
rpm_ostree_db_diff() {
local from_commit="${1:-}"
local to_commit="${2:-}"
log_info "rpm-ostree db diff compatibility: $from_commit -> $to_commit" "apt-layer"
# If no commits specified, compare current to pending
if [[ -z "$from_commit" ]]; then
from_commit=$(get_current_deployment)
fi
if [[ -z "$to_commit" ]]; then
to_commit=$(get_pending_deployment)
if [[ -z "$to_commit" ]]; then
log_error "No target commit specified and no pending deployment" "apt-layer"
return 1
fi
fi
# Show detailed package diff
show_detailed_package_diff "$from_commit" "$to_commit"
}
# rpm-ostree cleanup compatibility
rpm_ostree_cleanup() {
local purge="${1:-}"
log_info "rpm-ostree cleanup compatibility: purge=$purge" "apt-layer"
# Clean up old deployments
cleanup_old_deployments
# Clean up old ComposeFS images
cleanup_old_composefs_images
if [[ "$purge" == "--purge" ]]; then
# Also clean up old bootloader entries
cleanup_old_bootloader_entries
fi
log_success "rpm-ostree cleanup completed successfully" "apt-layer"
}
# rpm-ostree cancel compatibility
rpm_ostree_cancel() {
log_info "rpm-ostree cancel compatibility" "apt-layer"
# Clear pending deployment
clear_pending_deployment
# Clean up live overlay
stop_live_overlay
log_success "rpm-ostree cancel completed successfully" "apt-layer"
}
# rpm-ostree initramfs compatibility
rpm_ostree_initramfs() {
local action="${1:-}"
log_info "rpm-ostree initramfs compatibility: $action" "apt-layer"
case "$action" in
--enable)
enable_initramfs_rebuild
;;
--disable)
disable_initramfs_rebuild
;;
--rebuild)
rebuild_initramfs
;;
*)
log_error "Invalid initramfs action: $action" "apt-layer"
return 1
;;
esac
}
# rpm-ostree kargs compatibility
rpm_ostree_kargs() {
local action="${1:-}"
shift
log_info "rpm-ostree kargs compatibility: $action" "apt-layer"
case "$action" in
--get)
get_kernel_args
;;
--set)
set_kernel_args "$@"
;;
--append)
append_kernel_args "$@"
;;
--delete)
delete_kernel_args "$@"
;;
--reset)
reset_kernel_args
;;
*)
log_error "Invalid kargs action: $action" "apt-layer"
return 1
;;
esac
}
# rpm-ostree usroverlay compatibility
rpm_ostree_usroverlay() {
local action="${1:-}"
log_info "rpm-ostree usroverlay compatibility: $action" "apt-layer"
case "$action" in
--mount)
mount_usr_overlay
;;
--unmount)
unmount_usr_overlay
;;
--status)
usr_overlay_status
;;
*)
log_error "Invalid usroverlay action: $action" "apt-layer"
return 1
;;
esac
}
# rpm-ostree composefs compatibility
rpm_ostree_composefs() {
local action="${1:-}"
shift
log_info "rpm-ostree composefs compatibility: $action" "apt-layer"
case "$action" in
--mount)
composefs_mount "$@"
;;
--unmount)
composefs_unmount "$@"
;;
--list)
composefs_list_images
;;
--info)
composefs_image_info "$@"
;;
*)
log_error "Invalid composefs action: $action" "apt-layer"
return 1
;;
esac
}
# Helper functions for rpm-ostree compatibility
# Get previous deployment
get_previous_deployment() {
local current_deployment
current_deployment=$(get_current_deployment)
if [[ -n "$current_deployment" ]]; then
local parent_commit
parent_commit=$(jq -r ".deployments[\"$current_deployment\"].parent_commit" "$DEPLOYMENT_DB" 2>/dev/null || echo "")
echo "$parent_commit"
fi
}
# Show package diff between commits
show_package_diff() {
local from_commit="$1"
local to_commit="$2"
log_info "Showing package diff: $from_commit -> $to_commit" "apt-layer"
# Get package lists from both commits
local from_packages=()
local to_packages=()
if [[ -n "$from_commit" ]]; then
from_packages=($(get_packages_from_commit "$from_commit"))
fi
if [[ -n "$to_commit" ]]; then
to_packages=($(get_packages_from_commit "$to_commit"))
fi
# Calculate differences
local added_packages=()
local removed_packages=()
local updated_packages=()
# Find added packages
for pkg in "${to_packages[@]}"; do
if [[ ! " ${from_packages[*]} " =~ " ${pkg} " ]]; then
added_packages+=("$pkg")
fi
done
# Find removed packages
for pkg in "${from_packages[@]}"; do
if [[ ! " ${to_packages[*]} " =~ " ${pkg} " ]]; then
removed_packages+=("$pkg")
fi
done
# Show results
if [[ ${#added_packages[@]} -gt 0 ]]; then
echo "Added packages:"
printf " %s\n" "${added_packages[@]}"
fi
if [[ ${#removed_packages[@]} -gt 0 ]]; then
echo "Removed packages:"
printf " %s\n" "${removed_packages[@]}"
fi
if [[ ${#added_packages[@]} -eq 0 ]] && [[ ${#removed_packages[@]} -eq 0 ]]; then
echo "No package changes detected"
fi
}
# Get packages from commit
get_packages_from_commit() {
local commit_id="$1"
local composefs_image
# Get ComposeFS image name
composefs_image=$(jq -r ".deployments[\"$commit_id\"].composefs_image" "$DEPLOYMENT_DB" 2>/dev/null || echo "")
if [[ -z "$composefs_image" ]]; then
return 1
fi
# Mount and extract package list
local temp_mount="/tmp/apt-layer-commit-$$"
mkdir -p "$temp_mount"
if composefs_mount "$composefs_image" "$temp_mount"; then
# Extract package list
chroot "$temp_mount" dpkg -l | grep '^ii' | awk '{print $2}' 2>/dev/null || true
# Cleanup
composefs_unmount "$temp_mount"
rmdir "$temp_mount"
fi
}
# Cleanup functions
cleanup_old_deployments() {
log_info "Cleaning up old deployments..." "apt-layer"
# Keep last 5 deployments
local deployments
deployments=($(jq -r '.deployments | keys[]' "$DEPLOYMENT_DB" 2>/dev/null | sort -r | tail -n +6))
for commit_id in "${deployments[@]}"; do
log_info "Removing old deployment: $commit_id" "apt-layer"
# Remove from database
jq --arg commit_id "$commit_id" 'del(.deployments[$commit_id])' \
"$DEPLOYMENT_DB" > "${DEPLOYMENT_DB}.tmp" && mv "${DEPLOYMENT_DB}.tmp" "$DEPLOYMENT_DB"
# Remove history file
rm -f "$DEPLOYMENT_HISTORY_DIR/$commit_id.json"
# Remove deployment directory
rm -rf "/var/lib/particle-os/deployments/$commit_id"
done
}
cleanup_old_composefs_images() {
log_info "Cleaning up old ComposeFS images..." "apt-layer"
# Get list of images still referenced by deployments
local referenced_images
referenced_images=($(jq -r '.deployments[].composefs_image' "$DEPLOYMENT_DB" 2>/dev/null || true))
# Get all ComposeFS images
local all_images
all_images=($(composefs_list_images))
# Remove unreferenced images
for image in "${all_images[@]}"; do
if [[ ! " ${referenced_images[*]} " =~ " ${image} " ]]; then
log_info "Removing unreferenced image: $image" "apt-layer"
composefs_remove_image "$image"
fi
done
}
cleanup_old_bootloader_entries() {
log_info "Cleaning up old bootloader entries..." "apt-layer"
# Get current and pending deployments
local current_deployment
current_deployment=$(get_current_deployment)
local pending_deployment
pending_deployment=$(get_pending_deployment)
# Remove old bootloader entries
local boot_dir="/boot/loader/entries"
for entry in "$boot_dir"/apt-layer-*.conf; do
if [[ -f "$entry" ]]; then
local commit_id
commit_id=$(basename "$entry" .conf | sed 's/apt-layer-//')
# Keep current and pending deployments
if [[ "$commit_id" != "$current_deployment" ]] && [[ "$commit_id" != "$pending_deployment" ]]; then
log_info "Removing old bootloader entry: $entry" "apt-layer"
rm -f "$entry"
fi
fi
done
}