mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-07-26 18:38:30 +00:00
update 1.2.2.2 beta
This commit is contained in:
@@ -1772,6 +1772,74 @@ WantedBy=multi-user.target
|
||||
EOF
|
||||
}
|
||||
|
||||
# Destructive rollback executor. Reads vms_to_remove / lxcs_to_remove
|
||||
# from the rollback.json and runs `qm/pct stop + destroy --purge`
|
||||
# on each. Component uninstall is not done here yet — the installers
|
||||
# don't expose --auto-uninstall — so we just log them as TODO.
|
||||
# Idempotent: missing/already-destroyed guests are skipped.
|
||||
_rs_execute_rollback() {
|
||||
local rb_file="$1"
|
||||
[[ ! -s "$rb_file" ]] && return 0
|
||||
command -v jq >/dev/null 2>&1 || { msg_warn "$(translate 'jq not available — skipping rollback execution')"; return 0; }
|
||||
|
||||
local vmids lxcids comps
|
||||
vmids=$(jq -r '.vms_to_remove[]?' "$rb_file" 2>/dev/null)
|
||||
lxcids=$(jq -r '.lxcs_to_remove[]?' "$rb_file" 2>/dev/null)
|
||||
comps=$(jq -r '.components_to_uninstall[]?' "$rb_file" 2>/dev/null)
|
||||
|
||||
if [[ -z "$vmids" && -z "$lxcids" && -z "$comps" ]]; then
|
||||
msg_ok "$(translate 'Rollback: nothing to remove (host matches backup)')"
|
||||
return 0
|
||||
fi
|
||||
|
||||
msg_info2 "$(translate 'Executing destructive rollback (operator confirmed) ...')"
|
||||
|
||||
local id
|
||||
for id in $vmids; do
|
||||
[[ -z "$id" ]] && continue
|
||||
if qm status "$id" >/dev/null 2>&1; then
|
||||
echo " → qm stop $id (extra VM, created after backup)"
|
||||
qm stop "$id" --timeout 30 >/dev/null 2>&1 || true
|
||||
echo " → qm destroy $id --purge"
|
||||
if qm destroy "$id" --purge >/dev/null 2>&1; then
|
||||
msg_ok "$(translate 'VM removed:') $id"
|
||||
else
|
||||
msg_error "$(translate 'Failed to destroy VM:') $id"
|
||||
fi
|
||||
else
|
||||
echo " • VM $id no longer present — skip"
|
||||
fi
|
||||
done
|
||||
|
||||
for id in $lxcids; do
|
||||
[[ -z "$id" ]] && continue
|
||||
if pct status "$id" >/dev/null 2>&1; then
|
||||
echo " → pct stop $id (extra LXC, created after backup)"
|
||||
pct stop "$id" >/dev/null 2>&1 || true
|
||||
echo " → pct destroy $id --purge"
|
||||
if pct destroy "$id" --purge >/dev/null 2>&1; then
|
||||
msg_ok "$(translate 'LXC removed:') $id"
|
||||
else
|
||||
msg_error "$(translate 'Failed to destroy LXC:') $id"
|
||||
fi
|
||||
else
|
||||
echo " • LXC $id no longer present — skip"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n "$comps" ]]; then
|
||||
local comp
|
||||
for comp in $comps; do
|
||||
[[ -z "$comp" ]] && continue
|
||||
# Until each installer ships --auto-uninstall we can only
|
||||
# flag these for the operator. Once nvidia/amd/intel/coral
|
||||
# support it, this branch can shell out the same way the
|
||||
# auto-reinstall path does.
|
||||
msg_warn "$(translate 'Component to uninstall manually (no --auto-uninstall yet):') $comp"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
_rs_prepare_pending_restore() {
|
||||
local staging_root="$1"
|
||||
shift
|
||||
@@ -1821,12 +1889,17 @@ _rs_prepare_pending_restore() {
|
||||
|
||||
[[ -d "$staging_root/metadata" ]] && cp -a "$staging_root/metadata/." "$pending_dir/metadata/" 2>/dev/null || true
|
||||
|
||||
# Persist the rollback plan so apply_cluster_postboot.sh can
|
||||
# surface a clear "what differs vs backup" report after boot.
|
||||
# Read-only here — the script just informs the operator about
|
||||
# VMs/LXCs/components that exist now but not in the backup.
|
||||
# Actual destroy is left manual until --auto-uninstall lands
|
||||
# on every installer.
|
||||
# Persist the rollback plan: VMs/LXCs/components that exist
|
||||
# on the host but not in the backup. apply_cluster_postboot.sh
|
||||
# surfaces a read-only "what differs" report from this file
|
||||
# after the boot. When the operator opted into destructive
|
||||
# rollback (HB_ROLLBACK_EXECUTE=1) we also destroy those
|
||||
# guests RIGHT NOW — before the reboot — so the operator
|
||||
# sees `qm destroy` live in the Monitor terminal AND the
|
||||
# next boot comes up without those guests reserving hardware
|
||||
# (critical for GPU passthrough: a stale VM with hostpci
|
||||
# entries makes Proxmox auto-bind the GPU to vfio-pci before
|
||||
# the nvidia driver can claim it).
|
||||
local _rb_script="${SCRIPT_DIR}/restore/compute_rollback_plan.sh"
|
||||
[[ ! -x "$_rb_script" ]] && _rb_script="${LOCAL_SCRIPTS:-/usr/local/share/proxmenux/scripts}/backup_restore/restore/compute_rollback_plan.sh"
|
||||
if [[ -x "$_rb_script" ]]; then
|
||||
@@ -1834,10 +1907,16 @@ _rs_prepare_pending_restore() {
|
||||
[[ ! -s "$pending_dir/rollback.json" ]] && rm -f "$pending_dir/rollback.json"
|
||||
fi
|
||||
|
||||
if [[ "${HB_ROLLBACK_EXECUTE:-0}" == "1" && -s "$pending_dir/rollback.json" ]] \
|
||||
&& command -v jq >/dev/null 2>&1; then
|
||||
_rs_execute_rollback "$pending_dir/rollback.json"
|
||||
fi
|
||||
|
||||
cat > "$pending_dir/plan.env" <<EOF
|
||||
RESTORE_ID=${restore_id}
|
||||
CREATED_AT=${created_at}
|
||||
HB_RESTORE_INCLUDE_ZFS=${HB_RESTORE_INCLUDE_ZFS:-0}
|
||||
HB_ROLLBACK_EXECUTE=${HB_ROLLBACK_EXECUTE:-0}
|
||||
EOF
|
||||
# Persist hardware-drift skips so apply_pending_restore.sh can filter
|
||||
# them at boot. The RS_SKIP_PATHS env var only lives in the restore
|
||||
@@ -2024,6 +2103,45 @@ _rs_run_complete_guided() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# ── Destructive rollback opt-in ───────────────────────────
|
||||
# If the host has VMs / LXCs / components that are NOT in
|
||||
# the backup, ask whether we should ALSO destroy them as
|
||||
# part of "rollback to the backup state". Without this the
|
||||
# restore is additive — a stale VM with hostpci entries
|
||||
# will keep reserving the GPU for vfio-pci after the boot
|
||||
# (we hit this in the test). Skip the prompt entirely when
|
||||
# already in HB_MONITOR_FLOW: the web UI raised its own
|
||||
# destructive-ack checkbox and exported HB_ROLLBACK_EXECUTE.
|
||||
if [[ "${HB_MONITOR_FLOW:-0}" != "1" && "${HB_ROLLBACK_EXECUTE:-0}" != "1" ]]; then
|
||||
local _rb_script="${SCRIPT_DIR}/restore/compute_rollback_plan.sh"
|
||||
[[ ! -x "$_rb_script" ]] && _rb_script="${LOCAL_SCRIPTS:-/usr/local/share/proxmenux/scripts}/backup_restore/restore/compute_rollback_plan.sh"
|
||||
if [[ -x "$_rb_script" ]] && command -v jq >/dev/null 2>&1; then
|
||||
local _rb_json
|
||||
_rb_json=$(bash "$_rb_script" "$staging_root" 2>/dev/null || true)
|
||||
if [[ -n "$_rb_json" ]]; then
|
||||
local _rb_vms _rb_lxcs _rb_comps
|
||||
_rb_vms=$(jq -r '.vms_to_remove | join(", ")' <<<"$_rb_json" 2>/dev/null)
|
||||
_rb_lxcs=$(jq -r '.lxcs_to_remove | join(", ")' <<<"$_rb_json" 2>/dev/null)
|
||||
_rb_comps=$(jq -r '.components_to_uninstall| join(", ")' <<<"$_rb_json" 2>/dev/null)
|
||||
if [[ -n "$_rb_vms" || -n "$_rb_lxcs" || -n "$_rb_comps" ]]; then
|
||||
local rb_body
|
||||
rb_body="\Zb\Z1$(translate "Destructive rollback")\ZB\Zn"$'\n\n'
|
||||
rb_body+="$(translate "The following entries exist on the host but were NOT in the backup. To make the host EXACTLY match the backup state, they must be removed:")"$'\n\n'
|
||||
[[ -n "$_rb_vms" ]] && rb_body+=" \Z1•\Zn $(translate "VMs to destroy:") \Zb${_rb_vms}\ZB"$'\n'
|
||||
[[ -n "$_rb_lxcs" ]] && rb_body+=" \Z1•\Zn $(translate "LXCs to destroy:") \Zb${_rb_lxcs}\ZB"$'\n'
|
||||
[[ -n "$_rb_comps" ]] && rb_body+=" \Z1•\Zn $(translate "Components to uninstall (manual for now):") \Zb${_rb_comps}\ZB"$'\n'
|
||||
rb_body+=$'\n'"\Zb\Z1$(translate "This is IRREVERSIBLE.")\ZB\Zn"$'\n\n'
|
||||
rb_body+="$(translate "Pick Yes to destroy them now (before reboot). Pick No to keep the additive restore and clean up manually later.")"
|
||||
if dialog --backtitle "ProxMenux" --colors \
|
||||
--title "$(translate "Execute destructive rollback?")" \
|
||||
--defaultno --yesno "$rb_body" 20 88; then
|
||||
export HB_ROLLBACK_EXECUTE=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
show_proxmenux_logo
|
||||
msg_title "$(translate "Applying safe paths and preparing pending restore")"
|
||||
[[ "$hot_count" -gt 0 ]] && _rs_apply "$staging_root" hot
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
# Each must be present in <staging>/metadata/selected_paths.txt
|
||||
# or the wrapper drops it. Omit to let the TUI checklist
|
||||
# pop up so the operator can pick interactively.
|
||||
# ROLLBACK_EXECUTE — "1" to ask _rs_prepare_pending_restore to
|
||||
# run the destructive rollback (qm/pct destroy --purge)
|
||||
# on guests created after the backup. The frontend only
|
||||
# sets this after the operator ticks the "I understand…"
|
||||
# checkbox in the Complete restore confirm dialog. Has
|
||||
# no effect when MODE=custom.
|
||||
# ==========================================================
|
||||
# Note: NO `set -e` here. backup_host.sh + its sourced utils/lib
|
||||
# emit a few non-zero exit codes during load (locale checks,
|
||||
@@ -28,14 +34,16 @@
|
||||
STAGING="${STAGING:-}"
|
||||
MODE="${MODE:-full}"
|
||||
PATHS="${PATHS:-}"
|
||||
ROLLBACK_EXECUTE="${ROLLBACK_EXECUTE:-0}"
|
||||
|
||||
# Also accept --staging / --mode / --paths positional args for
|
||||
# direct CLI use outside the Monitor (handy for debugging).
|
||||
# Also accept --staging / --mode / --paths / --rollback-execute
|
||||
# positional args for direct CLI use outside the Monitor.
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--staging) shift; STAGING="${1:-}" ;;
|
||||
--mode) shift; MODE="${1:-full}" ;;
|
||||
--paths) shift; PATHS="${1:-}" ;;
|
||||
--staging) shift; STAGING="${1:-}" ;;
|
||||
--mode) shift; MODE="${1:-full}" ;;
|
||||
--paths) shift; PATHS="${1:-}" ;;
|
||||
--rollback-execute) ROLLBACK_EXECUTE=1 ;;
|
||||
*) ;;
|
||||
esac
|
||||
shift
|
||||
@@ -78,6 +86,12 @@ fi
|
||||
# panel; no need for two consecutive yes/no prompts.
|
||||
export HB_MONITOR_FLOW=1
|
||||
|
||||
# Propagate the destructive-rollback opt-in to _rs_prepare_pending_restore.
|
||||
# Only honored for MODE=full — custom restores never trigger guest destroy.
|
||||
if [[ "$MODE" == "full" && "$ROLLBACK_EXECUTE" == "1" ]]; then
|
||||
export HB_ROLLBACK_EXECUTE=1
|
||||
fi
|
||||
|
||||
case "$MODE" in
|
||||
full)
|
||||
# The TUI path runs `_rs_collect_plan_stats` before calling
|
||||
|
||||
Reference in New Issue
Block a user