448 lines
12 KiB
Bash
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
|
|
}
|