From c37d3fa34e4066166048ae648793fc66e9352549 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Fri, 12 Jun 2026 23:53:08 +0200 Subject: [PATCH] update 1.2.2.2 beta --- .../backup_restore/apply_pending_restore.sh | 31 +++++++++++++--- scripts/backup_restore/backup_host.sh | 36 +++++++++---------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/scripts/backup_restore/apply_pending_restore.sh b/scripts/backup_restore/apply_pending_restore.sh index 775c2ee0..5b347a1d 100644 --- a/scripts/backup_restore/apply_pending_restore.sh +++ b/scripts/backup_restore/apply_pending_restore.sh @@ -84,7 +84,14 @@ while IFS= read -r rel; do continue fi - # Hardware-drift skip filter — match exact path or descendant. + # Hardware-drift skip filter — three cases: + # 1) "$rel" is exactly a skipped path → drop the whole rel + # 2) "$rel" is under a skipped path → drop the whole rel + # 3) A skipped path is under "$rel" (e.g. rel="etc/kernel" and + # skip="/etc/kernel/proxmox-boot-uuids") → keep applying rel + # but rsync with --exclude for the specific file, and NO + # --delete (so the host's existing file is preserved) + RSYNC_EXCLUDES=() if [[ -n "$RS_SKIP_PATHS" ]]; then _abs="/$rel" _drop=0 @@ -94,6 +101,11 @@ while IFS= read -r rel; do _drop=1 break fi + # Case 3: skip is under our rel — build a relative exclude + if [[ "$_skip" == "$_abs"/* ]]; then + _rel_skip="${_skip#"$_abs"/}" + RSYNC_EXCLUDES+=(--exclude="$_rel_skip") + fi done <<<"$RS_SKIP_PATHS" if (( _drop )); then echo " drift-skip: $rel" @@ -140,10 +152,21 @@ while IFS= read -r rel; do if [[ -d "$src" ]]; then mkdir -p "$dst" >/dev/null 2>&1 || true - if rsync -aAXH --delete "$src/" "$dst/" >/dev/null 2>&1; then - ((applied++)) + # When an exclude list is present, drop --delete so the host's + # copy of the excluded file isn't removed by rsync after being + # skipped from the source side. + if [[ ${#RSYNC_EXCLUDES[@]} -gt 0 ]]; then + if rsync -aAXH "${RSYNC_EXCLUDES[@]}" "$src/" "$dst/" >/dev/null 2>&1; then + ((applied++)) + else + ((failed++)) + fi else - ((failed++)) + if rsync -aAXH --delete "$src/" "$dst/" >/dev/null 2>&1; then + ((applied++)) + else + ((failed++)) + fi fi else mkdir -p "$(dirname "$dst")" >/dev/null 2>&1 || true diff --git a/scripts/backup_restore/backup_host.sh b/scripts/backup_restore/backup_host.sh index 8d02228f..b7045428 100644 --- a/scripts/backup_restore/backup_host.sh +++ b/scripts/backup_restore/backup_host.sh @@ -1390,10 +1390,8 @@ _rs_apply() { if [[ -n "$CLUSTER_DATA_EXTRACTED" ]]; then export HB_CLUSTER_DATA_EXTRACTED="$CLUSTER_DATA_EXTRACTED" _rs_write_cluster_recovery_helper "$CLUSTER_DATA_EXTRACTED" - msg_info2 "$(translate "Cluster data (/etc/pve, /var/lib/pve-cluster) will be applied automatically at next boot once pve-cluster.service is up.")" - msg_info2 "$(translate "A safety copy + manual-apply helper are also available in case you need to re-apply later:")" - msg_info2 " $CLUSTER_DATA_EXTRACTED/apply-cluster-restore.sh" - msg_info2 "$(translate "(Optional — only run it during a maintenance window if you need to re-apply the cluster data manually.)")" + msg_info2 "$(translate "Cluster data will be applied automatically at next boot.")" + msg_info2 "$(translate "Optional safety helper if you ever need to re-apply manually:") $CLUSTER_DATA_EXTRACTED/apply-cluster-restore.sh" else unset HB_CLUSTER_DATA_EXTRACTED fi @@ -1831,23 +1829,14 @@ _rs_run_complete_guided() { fi done - if (( dialog_signal == 1 )); then - plan_body+="$(translate "PVE will regenerate these files automatically for the current hardware. The rest of the backup will be applied normally.")"$'\n\n' - plan_body+="\Zb$(translate "Continue with safe restore?")\ZB" - - if ! dialog --backtitle "ProxMenux" --colors \ - --title "$(translate "Restore plan — compatibility check")" \ - --yesno "$plan_body" 24 90; then - return 1 - fi - fi - # Persist for _rs_apply / _rs_collect_pending_paths to honor. - # We only store paths (not component:* entries) — component - # auto-reinstall already self-skips when the GPU/TPU isn't on - # this host, so we just surfaced it in the dialog for clarity. + # The drift summary is merged into the single confirmation + # dialog below — no extra yes/no popup. RS_SKIP_PATHS="${skip_paths%$'\n'}" export RS_SKIP_PATHS + # Stash the plan_body fragment so the confirm dialog can show it. + RS_DRIFT_SUMMARY="" + (( dialog_signal == 1 )) && RS_DRIFT_SUMMARY="$plan_body" fi # Build the rich confirmation body. Replaces the previous 4-strategy @@ -1893,6 +1882,17 @@ _rs_run_complete_guided() { body+=" • \Zb${label}\ZB (${eta})"$'\n' done fi + # If smart restore flagged drift skips earlier, surface them here + # so the operator sees everything in one screen instead of two + # consecutive yes/no popups. + if [[ -n "${RS_DRIFT_SUMMARY:-}" ]]; then + body+=$'\n'"\Zb$(translate "Hardware compatibility — these items will be skipped to keep the boot safe:")\ZB"$'\n' + # Trim the original header from the stashed plan_body — we only + # want the bullet list. + local _drift_bullets + _drift_bullets=$(printf '%s\n' "$RS_DRIFT_SUMMARY" | sed -n '/\Z1•\Zn/,$p') + body+="$_drift_bullets"$'\n' + fi body+=$'\n'"\Zb\Z4$(translate "A reboot is required to finish the restore.")\Zn"$'\n\n' body+="$(translate "If notifications are enabled (Telegram/Discord/ntfy/...), you will receive a \"Host restore finished\" message when all background tasks complete.")"$'\n\n' body+="\Zb$(translate "Continue?")\ZB"