From 615aecf80f6d5e028254bf3c10b07dd70b045dfd Mon Sep 17 00:00:00 2001 From: MacRimi Date: Wed, 6 Aug 2025 20:04:12 +0200 Subject: [PATCH] Update common funtions --- scripts/global/common-functions.sh | 262 +++++++++++++++++++++------- scripts/global/common-functions_.sh | 181 +++++++++++++++++++ scripts/global/update-pve.sh | 200 +++++++++++++++++++++ 3 files changed, 581 insertions(+), 62 deletions(-) create mode 100644 scripts/global/common-functions_.sh create mode 100644 scripts/global/update-pve.sh diff --git a/scripts/global/common-functions.sh b/scripts/global/common-functions.sh index 95521f8..3e452f3 100644 --- a/scripts/global/common-functions.sh +++ b/scripts/global/common-functions.sh @@ -1,6 +1,6 @@ #!/bin/bash # ========================================================== -# Common Functions for Proxmox Updates +# Common Functions for Proxmox VE Scripts # ========================================================== # Configuration @@ -8,7 +8,7 @@ REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main" BASE_DIR="/usr/local/share/proxmenux" UTILS_FILE="$BASE_DIR/utils.sh" VENV_PATH="/opt/googletrans-env" - +TOOLS_JSON="/usr/local/share/proxmenux/installed_tools.json" if [[ -f "$UTILS_FILE" ]]; then source "$UTILS_FILE" @@ -17,12 +17,36 @@ fi load_language initialize_cache + +get_pve_info() { + local pve_full_version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+\.[0-9]+\.[0-9]+' | head -1) + local pve_major=$(echo "$pve_full_version" | cut -d. -f1) + local os_codename="$(grep "VERSION_CODENAME=" /etc/os-release | cut -d"=" -f 2 | xargs)" + + if [ -z "$os_codename" ]; then + os_codename=$(lsb_release -cs 2>/dev/null) + fi + + local target_codename + if [ "$pve_major" -ge 9 ] 2>/dev/null; then + target_codename="trixie" + else + target_codename="$os_codename" + if [ -z "$target_codename" ]; then + target_codename="bookworm" + fi + fi + + echo "$pve_full_version|$pve_major|$os_codename|$target_codename" +} + + lvm_repair_check() { msg_info "$(translate "Checking and repairing old LVM PV headers (if needed)...")" - # Check if LVM tools are available + if ! command -v pvs >/dev/null 2>&1; then - msg_ok "$(translate "LVM tools not available, skipping LVM check")" + msg_info "$(translate "LVM tools not available, skipping LVM check")" register_tool "lvm_repair" true return fi @@ -47,12 +71,10 @@ lvm_repair_check() { for vg in "${!vg_map[@]}"; do msg_warn "$(translate "Old PV header(s) found in VG $vg. Updating metadata...")" - vgck --updatemetadata "$vg" - vgchange -ay "$vg" - if [ $? -ne 0 ]; then - msg_warn "$(translate "Metadata update failed for VG $vg. Review manually.")" - else + if vgck --updatemetadata "$vg" 2>/dev/null && vgchange -ay "$vg" 2>/dev/null; then msg_ok "$(translate "Metadata updated successfully for VG $vg")" + else + msg_warn "$(translate "Metadata update failed for VG $vg. Review manually.")" fi done @@ -60,14 +82,18 @@ lvm_repair_check() { register_tool "lvm_repair" true } + cleanup_duplicate_repos() { - local OS_CODENAME="$1" + local target_codename="$1" + + msg_info "$(translate "Cleaning up duplicate repositories...")" + local sources_file="/etc/apt/sources.list" local temp_file=$(mktemp) local cleaned_count=0 declare -A seen_repos - # Clean main sources.list + while IFS= read -r line || [[ -n "$line" ]]; do if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "$line" ]]; then echo "$line" >> "$temp_file" @@ -92,9 +118,8 @@ cleanup_duplicate_repos() { mv "$temp_file" "$sources_file" chmod 644 "$sources_file" - # Clean Proxmox repository files + local pve_files=(/etc/apt/sources.list.d/*proxmox*.list /etc/apt/sources.list.d/*pve*.list) - local pve_content="deb http://download.proxmox.com/debian/pve ${OS_CODENAME} pve-no-subscription" local pve_public_repo="/etc/apt/sources.list.d/pve-public-repo.list" local pve_public_repo_exists=false @@ -115,67 +140,180 @@ cleanup_duplicate_repos() { done if [ $cleaned_count -gt 0 ]; then - msg_ok "$(translate "Cleaned up $cleaned_count duplicate repositories")" + msg_ok "$(translate "Cleaned up $cleaned_count duplicate/old repositories")" + else + msg_ok "$(translate "No duplicate repositories found")" fi - apt update + apt update > /dev/null 2>&1 } -show_update_menu() { - local current_version="$1" - local target_version="$2" - local upgradable_count="$3" - local security_count="$4" + +get_available_pve_version() { + local available_version=$(apt-cache policy pve-manager 2>/dev/null | grep -oP 'Candidate: \K[0-9]+\.[0-9]+\.[0-9]+' | head -1) + + if [ -n "$available_version" ]; then + echo "$available_version" + else + + pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+\.[0-9]+\.[0-9]+' | head -1 + fi +} + + +perform_final_cleanup() { + msg_info "$(translate "Performing system cleanup...")" + apt-get -y autoremove > /dev/null 2>&1 + apt-get -y autoclean > /dev/null 2>&1 + msg_ok "$(translate "Cleanup finished")" +} + + +configure_repositories() { + local pve_major="$1" + local current_codename="$2" + local target_codename="$3" + local changes_made=false + + msg_info "$(translate "Configuring Proxmox VE ${pve_major}.x repositories...")" - local menu_text="$(translate "System Update Information")\n\n" - menu_text+="$(translate "Current PVE Version"): $current_version\n" - - if [ -n "$target_version" ] && [ "$target_version" != "$current_version" ]; then - menu_text+="$(translate "Available PVE Version"): $target_version\n" + if [ -f /etc/apt/sources.list.d/pve-enterprise.list ] && grep -q "^deb" /etc/apt/sources.list.d/pve-enterprise.list; then + msg_info "$(translate "Disabling enterprise Proxmox repository...")" + sed -i "s/^deb/#deb/g" /etc/apt/sources.list.d/pve-enterprise.list + msg_ok "$(translate "Enterprise Proxmox repository disabled")" + changes_made=true + fi + + if [ -f /etc/apt/sources.list.d/ceph.list ] && grep -q "^deb" /etc/apt/sources.list.d/ceph.list; then + msg_info "$(translate "Disabling enterprise Proxmox Ceph repository...")" + sed -i "s/^deb/#deb/g" /etc/apt/sources.list.d/ceph.list + msg_ok "$(translate "Enterprise Proxmox Ceph repository disabled")" + changes_made=true fi - menu_text+="\n$(translate "Package Updates Available"): $upgradable_count\n" - menu_text+="$(translate "Security Updates"): $security_count\n\n" - - if [ "$upgradable_count" -eq 0 ]; then - menu_text+="$(translate "System is already up to date")" - whiptail --title "$(translate "Update Status")" --msgbox "$menu_text" 15 70 - return 1 + + if [ "$pve_major" -ge 9 ] 2>/dev/null; then + + [ -f /etc/apt/sources.list.d/pve-public-repo.list ] && rm -f /etc/apt/sources.list.d/pve-public-repo.list + [ -f /etc/apt/sources.list.d/pve-install-repo.list ] && rm -f /etc/apt/sources.list.d/pve-install-repo.list + + msg_info "$(translate "Creating Proxmox VE ${pve_major}.x no-subscription repository...")" + cat > /etc/apt/sources.list.d/proxmox.sources << EOF +Types: deb +URIs: http://download.proxmox.com/debian/pve +Suites: ${target_codename} +Components: pve-no-subscription +Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg +EOF + msg_ok "$(translate "Proxmox VE ${pve_major}.x no-subscription repository created")" + changes_made=true else - menu_text+="$(translate "Do you want to proceed with the system update?")" - if whiptail --title "$(translate "Proxmox Update")" --yesno "$menu_text" 18 70; then + + if [ ! -f /etc/apt/sources.list.d/pve-public-repo.list ] || ! grep -q "pve-no-subscription" /etc/apt/sources.list.d/pve-public-repo.list; then + msg_info "$(translate "Enabling free public Proxmox repository...")" + echo "deb http://download.proxmox.com/debian/pve $target_codename pve-no-subscription" > /etc/apt/sources.list.d/pve-public-repo.list + msg_ok "$(translate "Free public Proxmox repository enabled")" + changes_made=true + fi + fi + + + local sources_file="/etc/apt/sources.list" + cp "$sources_file" "${sources_file}.backup.$(date +%Y%m%d_%H%M%S)" + + + if grep -q -E "(debian-security -security|debian main$|debian -updates)" "$sources_file"; then + msg_info "$(translate "Cleaning malformed repository entries...")" + sed -i '/^deb.*debian-security -security/d' "$sources_file" + sed -i '/^deb.*debian main$/d' "$sources_file" + sed -i '/^deb.*debian -updates/d' "$sources_file" + changes_made=true + msg_ok "$(translate "Malformed repository entries cleaned")" + fi + + + if grep -q "ftp.es.debian.org" "$sources_file"; then + sed -i 's|ftp.es.debian.org|deb.debian.org|g' "$sources_file" + changes_made=true + fi + + + if [ "$current_codename" != "$target_codename" ]; then + msg_info "$(translate "Updating Debian repositories from $current_codename to $target_codename...")" + sed -i "s/$current_codename/$target_codename/g" "$sources_file" + changes_made=true + fi + + + cat > "$sources_file" << EOF +# Debian $target_codename repositories +deb http://deb.debian.org/debian $target_codename main contrib non-free non-free-firmware +deb http://deb.debian.org/debian $target_codename-updates main contrib non-free non-free-firmware +deb http://security.debian.org/debian-security $target_codename-security main contrib non-free non-free-firmware +EOF + + msg_ok "$(translate "Debian repositories configured for $target_codename")" + + + local firmware_conf="/etc/apt/apt.conf.d/no-firmware-warnings.conf" + if [ ! -f "$firmware_conf" ]; then + echo 'APT::Get::Update::SourceListWarnings::NonFreeFirmware "false";' > "$firmware_conf" + fi + + echo "$changes_made" +} + + +show_update_menu() { + local pve_major="$1" + local current_version="$2" + local available_version="$3" + local upgradable="$4" + local security_updates="$5" + + if [ "$upgradable" -eq 0 ]; then + if command -v whiptail >/dev/null 2>&1; then + whiptail --title "$(translate "System Status")" \ + --msgbox "$(translate "System is already up to date.\n\nCurrent PVE version: $current_version\nNo packages need updating.")" 12 60 + fi + return 1 + fi + + + local menu_text="$(translate "Update Information:") + +$(translate "Current PVE version"): $current_version" + + + if [ "$available_version" != "$current_version" ] && [ -n "$available_version" ]; then + menu_text="$menu_text +$(translate "Available PVE version"): $available_version" + fi + + menu_text="$menu_text + +$(translate "Packages to upgrade"): $upgradable +$(translate "Security updates"): $security_updates + +$(translate "Do you want to proceed with the system update?")" + + if command -v whiptail >/dev/null 2>&1; then + if whiptail --title "$(translate "Proxmox VE ${pve_major}.x System Update")" \ + --yesno "$menu_text" 16 70; then + return 0 + else + return 1 + fi + else + + echo "$menu_text" + echo + read -p "$(translate "Continue with update? (y/N): ")" -r response + if [[ "$response" =~ ^[Yy]$ ]]; then return 0 else return 1 fi fi } - -get_available_pve_version() { - local current_major="$1" - local os_codename="$2" - - local available_version="" - - if [ "$current_major" -eq 8 ]; then - available_version=$(apt-cache policy pve-manager 2>/dev/null | grep "Candidate:" | awk '{print $2}' | grep -oP '\d+\.\d+\.\d+' || echo "") - elif [ "$current_major" -eq 9 ]; then - available_version=$(apt-cache policy pve-manager 2>/dev/null | grep "Candidate:" | awk '{print $2}' | grep -oP '\d+\.\d+\.\d+' || echo "") - fi - - echo "$available_version" -} - -perform_final_cleanup() { - msg_info "$(translate "Performing final system cleanup...")" - - apt-get -y autoremove > /dev/null 2>&1 - - apt-get -y autoclean > /dev/null 2>&1 - - find /var/cache/pve-manager/ -name "*.js*" -delete 2>/dev/null || true - find /var/lib/pve-manager/ -name "*.js*" -delete 2>/dev/null || true - - msg_ok "$(translate "Final cleanup completed")" -} diff --git a/scripts/global/common-functions_.sh b/scripts/global/common-functions_.sh new file mode 100644 index 0000000..95521f8 --- /dev/null +++ b/scripts/global/common-functions_.sh @@ -0,0 +1,181 @@ +#!/bin/bash +# ========================================================== +# Common Functions for Proxmox Updates +# ========================================================== + +# Configuration +REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main" +BASE_DIR="/usr/local/share/proxmenux" +UTILS_FILE="$BASE_DIR/utils.sh" +VENV_PATH="/opt/googletrans-env" + + +if [[ -f "$UTILS_FILE" ]]; then + source "$UTILS_FILE" +fi + +load_language +initialize_cache + +lvm_repair_check() { + msg_info "$(translate "Checking and repairing old LVM PV headers (if needed)...")" + + # Check if LVM tools are available + if ! command -v pvs >/dev/null 2>&1; then + msg_ok "$(translate "LVM tools not available, skipping LVM check")" + register_tool "lvm_repair" true + return + fi + + pvs_output=$(LC_ALL=C pvs -v 2>&1 | grep "old PV header" || true) + if [ -z "$pvs_output" ]; then + msg_ok "$(translate "No PVs with old headers found.")" + register_tool "lvm_repair" true + return + fi + + declare -A vg_map + while read -r line; do + pv=$(echo "$line" | grep -o '/dev/[^ ]*' || true) + if [ -n "$pv" ]; then + vg=$(pvs -o vg_name --noheadings "$pv" 2>/dev/null | awk '{print $1}' || true) + if [ -n "$vg" ]; then + vg_map["$vg"]=1 + fi + fi + done <<< "$pvs_output" + + for vg in "${!vg_map[@]}"; do + msg_warn "$(translate "Old PV header(s) found in VG $vg. Updating metadata...")" + vgck --updatemetadata "$vg" + vgchange -ay "$vg" + if [ $? -ne 0 ]; then + msg_warn "$(translate "Metadata update failed for VG $vg. Review manually.")" + else + msg_ok "$(translate "Metadata updated successfully for VG $vg")" + fi + done + + msg_ok "$(translate "LVM PV headers check completed")" + register_tool "lvm_repair" true +} + +cleanup_duplicate_repos() { + local OS_CODENAME="$1" + local sources_file="/etc/apt/sources.list" + local temp_file=$(mktemp) + local cleaned_count=0 + declare -A seen_repos + + # Clean main sources.list + while IFS= read -r line || [[ -n "$line" ]]; do + if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "$line" ]]; then + echo "$line" >> "$temp_file" + continue + fi + + if [[ "$line" =~ ^deb ]]; then + read -r _ url dist components <<< "$line" + local key="${url}_${dist}" + if [[ -v "seen_repos[$key]" ]]; then + echo "# $line" >> "$temp_file" + cleaned_count=$((cleaned_count + 1)) + else + echo "$line" >> "$temp_file" + seen_repos[$key]="$components" + fi + else + echo "$line" >> "$temp_file" + fi + done < "$sources_file" + + mv "$temp_file" "$sources_file" + chmod 644 "$sources_file" + + # Clean Proxmox repository files + local pve_files=(/etc/apt/sources.list.d/*proxmox*.list /etc/apt/sources.list.d/*pve*.list) + local pve_content="deb http://download.proxmox.com/debian/pve ${OS_CODENAME} pve-no-subscription" + local pve_public_repo="/etc/apt/sources.list.d/pve-public-repo.list" + local pve_public_repo_exists=false + + if [ -f "$pve_public_repo" ] && grep -q "^deb.*pve-no-subscription" "$pve_public_repo"; then + pve_public_repo_exists=true + fi + + for file in "${pve_files[@]}"; do + if [ -f "$file" ] && grep -q "^deb.*pve-no-subscription" "$file"; then + if ! $pve_public_repo_exists && [[ "$file" == "$pve_public_repo" ]]; then + sed -i 's/^# *deb/deb/' "$file" + pve_public_repo_exists=true + elif [[ "$file" != "$pve_public_repo" ]]; then + sed -i 's/^deb/# deb/' "$file" + cleaned_count=$((cleaned_count + 1)) + fi + fi + done + + if [ $cleaned_count -gt 0 ]; then + msg_ok "$(translate "Cleaned up $cleaned_count duplicate repositories")" + fi + + apt update +} + +show_update_menu() { + local current_version="$1" + local target_version="$2" + local upgradable_count="$3" + local security_count="$4" + + + local menu_text="$(translate "System Update Information")\n\n" + menu_text+="$(translate "Current PVE Version"): $current_version\n" + + if [ -n "$target_version" ] && [ "$target_version" != "$current_version" ]; then + menu_text+="$(translate "Available PVE Version"): $target_version\n" + fi + + menu_text+="\n$(translate "Package Updates Available"): $upgradable_count\n" + menu_text+="$(translate "Security Updates"): $security_count\n\n" + + if [ "$upgradable_count" -eq 0 ]; then + menu_text+="$(translate "System is already up to date")" + whiptail --title "$(translate "Update Status")" --msgbox "$menu_text" 15 70 + return 1 + else + menu_text+="$(translate "Do you want to proceed with the system update?")" + if whiptail --title "$(translate "Proxmox Update")" --yesno "$menu_text" 18 70; then + return 0 + else + return 1 + fi + fi +} + +get_available_pve_version() { + local current_major="$1" + local os_codename="$2" + + local available_version="" + + if [ "$current_major" -eq 8 ]; then + available_version=$(apt-cache policy pve-manager 2>/dev/null | grep "Candidate:" | awk '{print $2}' | grep -oP '\d+\.\d+\.\d+' || echo "") + elif [ "$current_major" -eq 9 ]; then + available_version=$(apt-cache policy pve-manager 2>/dev/null | grep "Candidate:" | awk '{print $2}' | grep -oP '\d+\.\d+\.\d+' || echo "") + fi + + echo "$available_version" +} + +perform_final_cleanup() { + msg_info "$(translate "Performing final system cleanup...")" + + apt-get -y autoremove > /dev/null 2>&1 + + apt-get -y autoclean > /dev/null 2>&1 + + find /var/cache/pve-manager/ -name "*.js*" -delete 2>/dev/null || true + find /var/lib/pve-manager/ -name "*.js*" -delete 2>/dev/null || true + + msg_ok "$(translate "Final cleanup completed")" +} diff --git a/scripts/global/update-pve.sh b/scripts/global/update-pve.sh new file mode 100644 index 0000000..947b097 --- /dev/null +++ b/scripts/global/update-pve.sh @@ -0,0 +1,200 @@ +#!/bin/bash +# ========================================================== +# Universal Proxmox VE Update Script +# ========================================================== + +# Configuration +REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main" +BASE_DIR="/usr/local/share/proxmenux" +UTILS_FILE="$BASE_DIR/utils.sh" +VENV_PATH="/opt/googletrans-env" +TOOLS_JSON="/usr/local/share/proxmenux/installed_tools.json" + +if [[ -f "$UTILS_FILE" ]]; then + source "$UTILS_FILE" +fi + +load_language +initialize_cache + + +ensure_tools_json() { + [ -f "$TOOLS_JSON" ] || echo "{}" > "$TOOLS_JSON" +} + +register_tool() { + local tool="$1" + local state="$2" + ensure_tools_json + jq --arg t "$tool" --argjson v "$state" '.[$t]=$v' "$TOOLS_JSON" > "$TOOLS_JSON.tmp" && mv "$TOOLS_JSON.tmp" "$TOOLS_JSON" +} + + +download_common_functions() { + if ! source <(curl -s "$REPO_URL/global/common-functions.sh"); then + return 1 + fi +} + +update_proxmox() { + local start_time=$(date +%s) + local log_file="/var/log/proxmox-update-$(date +%Y%m%d-%H%M%S).log" + + + download_common_functions + + + local pve_info=$(get_pve_info) + local pve_full_version=$(echo "$pve_info" | cut -d'|' -f1) + local pve_major=$(echo "$pve_info" | cut -d'|' -f2) + local current_codename=$(echo "$pve_info" | cut -d'|' -f3) + local target_codename=$(echo "$pve_info" | cut -d'|' -f4) + + clear + show_proxmenux_logo + echo -e + msg_title "$(translate "Proxmox VE ${pve_major}.x System Update")" + msg_info2 "$(translate "Detected: Proxmox VE ${pve_major}.x (Current: $current_codename, Target: $target_codename)")" + echo + + + local available_space=$(df /var/cache/apt/archives | awk 'NR==2 {print int($4/1024)}') + if [ "$available_space" -lt 1024 ]; then + msg_error "$(translate "Insufficient disk space. Available: ${available_space}MB")" + echo -e + msg_success "$(translate "Press Enter to return to menu...")" + read -r + return 1 + fi + + if ! ping -c 1 download.proxmox.com >/dev/null 2>&1; then + msg_error "$(translate "Cannot reach Proxmox repositories")" + echo -e + msg_success "$(translate "Press Enter to return to menu...")" + read -r + return 1 + fi + + + local changes_made=$(configure_repositories "$pve_major" "$current_codename" "$target_codename") + + + cleanup_duplicate_repos "$target_codename" + + + msg_info "$(translate "Updating package lists...")" + update_output=$(apt-get update 2>&1) + update_exit_code=$? + + if [ $update_exit_code -eq 0 ]; then + msg_ok "$(translate "Package lists updated successfully")" + else + if echo "$update_output" | grep -q "NO_PUBKEY\|GPG error"; then + msg_info "$(translate "Fixing GPG key issues...")" + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $(echo "$update_output" | grep "NO_PUBKEY" | sed 's/.*NO_PUBKEY //' | head -1) 2>/dev/null + if apt-get update > "$log_file" 2>&1; then + msg_ok "$(translate "Package lists updated after GPG fix")" + else + msg_error "$(translate "Failed to update package lists")" + return 1 + fi + else + msg_error "$(translate "Failed to update package lists")" + return 1 + fi + fi + + + if [ "$pve_major" -ge 9 ] 2>/dev/null; then + msg_info "$(translate "Verifying Proxmox VE ${pve_major}.x repositories...")" + if apt policy 2>/dev/null | grep -q "${target_codename}.*pve-no-subscription"; then + msg_ok "$(translate "Proxmox VE ${pve_major}.x repositories verified")" + else + msg_warn "$(translate "Proxmox VE ${pve_major}.x repositories verification inconclusive, continuing...")" + fi + fi + + + local available_pve_version=$(get_available_pve_version) + local upgradable=$(apt list --upgradable 2>/dev/null | grep -c "upgradable") + local security_updates=$(apt list --upgradable 2>/dev/null | grep -c "security") + + + if ! show_update_menu "$pve_major" "$pve_full_version" "$available_pve_version" "$upgradable" "$security_updates"; then + msg_info2 "$(translate "Update cancelled by user")" + perform_final_cleanup + echo -e + msg_success "$(translate "Press Enter to return to menu...")" + read -r + return 0 + fi + + + msg_info "$(translate "Removing conflicting utilities...")" + local conflicting_packages=$(dpkg -l 2>/dev/null | grep -E "^ii.*(ntp|openntpd|systemd-timesyncd)" | awk '{print $2}') + if [ -n "$conflicting_packages" ]; then + DEBIAN_FRONTEND=noninteractive apt-get -y purge $conflicting_packages >> "$log_file" 2>&1 + msg_ok "$(translate "Conflicting utilities removed")" + fi + + + msg_info "$(translate "Performing system upgrade...")" + if [ "$pve_major" -ge 9 ] 2>/dev/null; then + apt-get install pv -y > /dev/null 2>&1 + fi + + if DEBIAN_FRONTEND=noninteractive apt-get -y \ + -o Dpkg::Options::='--force-confdef' \ + -o Dpkg::Options::='--force-confold' \ + dist-upgrade >> "$log_file" 2>&1; then + msg_ok "$(translate "System upgrade completed successfully")" + else + msg_error "$(translate "System upgrade failed. Check log: $log_file")" + return 1 + fi + + + msg_info "$(translate "Installing essential Proxmox packages...")" + local essential_packages=("zfsutils-linux" "proxmox-backup-restore-image" "chrony") + local missing_packages=() + + for package in "${essential_packages[@]}"; do + if ! dpkg -l 2>/dev/null | grep -q "^ii $package "; then + missing_packages+=("$package") + fi + done + + if [ ${#missing_packages[@]} -gt 0 ]; then + DEBIAN_FRONTEND=noninteractive apt-get -y install "${missing_packages[@]}" >> "$log_file" 2>&1 + msg_ok "$(translate "Essential Proxmox packages installed")" + fi + + + lvm_repair_check + + + perform_final_cleanup + + + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + local minutes=$((duration / 60)) + local seconds=$((duration % 60)) + + echo "" + echo -e "${TAB}${BGN}$(translate "=== PVE ${pve_major} UPDATE COMPLETED ===")${CL}" + echo -e "${TAB}${GN}$(translate "Duration")${CL}: ${DGN}${minutes}m ${seconds}s${CL}" + echo -e "${TAB}${GN}$(translate "Log file")${CL}: ${DGN}$log_file${CL}" + echo -e "${TAB}${GN}$(translate "Packages upgraded")${CL}: ${DGN}$upgradable${CL}" + echo -e "${TAB}${GN}$(translate "Proxmox VE")${CL}: ${DGN}${pve_major}.x (Debian $target_codename)${CL}" + echo "" + + msg_ok "$(translate "Proxmox VE ${pve_major}.x system update completed successfully")" + + +} + + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + update_proxmox +fi