From 503ba8845c960f295c2efda24d5c5bd42c2bb72b Mon Sep 17 00:00:00 2001 From: "sebastian.serfling" Date: Wed, 18 Mar 2026 11:20:08 +0000 Subject: [PATCH] restore.sh aktualisiert --- restore.sh | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/restore.sh b/restore.sh index 5b68ad5..41ffaeb 100644 --- a/restore.sh +++ b/restore.sh @@ -2,7 +2,7 @@ # ============================================================================= # /opt/windmill-restore/restore.sh # Windmill Backup Restore Worker -# Version: 1.0.13 +# Version: 1.0.11 # # Unterstützt sowohl VM (qm) als auch CT (pct) Backups. # Backup-Typ wird automatisch aus dem Backup-Pfad erkannt (vm/ oder ct/). @@ -41,6 +41,7 @@ RSYNC_TARGET="" PBS_STORAGE="" WEBHOOK_URL="" WEBHOOK_TOKEN="" +BACKUP_SIZE_BYTES=0 while [[ $# -gt 0 ]]; do case $1 in @@ -54,6 +55,7 @@ while [[ $# -gt 0 ]]; do --webhook-url) WEBHOOK_URL="$2"; shift 2 ;; --webhook-token) WEBHOOK_TOKEN="$2"; shift 2 ;; --server-hostname) SERVER_HOSTNAME="$2"; shift 2 ;; + --backup-size) BACKUP_SIZE_BYTES="$2"; shift 2 ;; *) echo "Unbekannter Parameter: $1" >&2; exit 1 ;; esac done @@ -141,6 +143,7 @@ send_webhook() { "status": "%s", "error_message": "%s", "server_hostname": "%s", + "free_space_gb": %d, "vm_name": "%s", "vm_id_original": %d, "vm_id_restored": %d, @@ -155,7 +158,7 @@ send_webhook() { "log_file": "%s" }' \ "$JOB_UUID" "$CLIENT_NAME" "$wh_status" "$wh_error" \ - "$SERVER_HOSTNAME" "${VM_NAME:-$SAFE_CLIENT}" \ + "$SERVER_HOSTNAME" "$FREE_GB" "${VM_NAME:-$SAFE_CLIENT}" \ "$VM_ID_ORIGINAL" "$VM_ID_RESTORED" \ "$duration" "$ACTUAL_DISK_BYTES" \ "$ZIP_SIZE_BYTES" "$ZIP_DURATION" \ @@ -230,13 +233,31 @@ echo " 7z-Passwort geladen ✓" # ═════════════════════════════════════════════════════════════════════════════ # [1/13] SPACE-CHECK +# Prüft ob genug Platz für Restore + 50% für ZIP vorhanden ist. +# Benötigter Platz: backup_size_bytes * 1.5 aus dem Webhook-Parameter +# Falls nicht genug → Webhook mit failed senden und Exit # ═════════════════════════════════════════════════════════════════════════════ echo "" echo "==> [1/13] Prüfe freien Speicherplatz auf $RESTORE_MOUNT..." mkdir -p "$ZIP_DIR" FREE_KB=$(df "$RESTORE_MOUNT" 2>/dev/null | awk 'NR==2{print $4}' || echo "0") FREE_GB=$(( FREE_KB / 1024 / 1024 )) +FREE_BYTES=$(( FREE_KB * 1024 )) echo " Frei: ${FREE_GB} GB" + +# Benötigten Platz berechnen: Backup-Größe * 1.5 +# BACKUP_SIZE_BYTES kommt als Parameter --backup-size +REQUIRED_BYTES=$(( BACKUP_SIZE_BYTES * 3 / 2 )) +REQUIRED_GB=$(( REQUIRED_BYTES / 1024 / 1024 / 1024 )) +echo " Benötigt: ~${REQUIRED_GB} GB (Restore + 50% für ZIP)" + +if [[ $BACKUP_SIZE_BYTES -gt 0 ]] && [[ $FREE_BYTES -lt $REQUIRED_BYTES ]]; then + ERROR_MSG="Nicht genug Speicherplatz: ${FREE_GB}GB frei, ~${REQUIRED_GB}GB benötigt" + echo " FEHLER: $ERROR_MSG" + trap - ERR + send_webhook "failed" "$ERROR_MSG" + exit 0 +fi [[ $FREE_GB -lt 50 ]] && echo " WARNUNG: Weniger als 50 GB frei!" # ═════════════════════════════════════════════════════════════════════════════ @@ -267,6 +288,62 @@ for i in range(1000, 2000): ) echo " Restore-ID: $VM_ID_RESTORED" +# ═════════════════════════════════════════════════════════════════════════════ +# [2.5/13] CONFIG-ONLY CHECK +# Config-only Restore um VM-Name zu ermitteln und zu prüfen ob ZIP bereits +# auf dem Backup-Server existiert → bei Fund: Restore überspringen +# ═════════════════════════════════════════════════════════════════════════════ +echo "" +echo "==> [2.5/13] Config-only Restore zum Prüfen..." + +CONFIG_VM_NAME="" +if [[ "$BACKUP_TYPE" == "ct" ]]; then + pct restore "$VM_ID_RESTORED" "$PVE_BACKUP_REF" --storage "$RESTORE_PATH" --config-only 1 2>/dev/null || true + CONFIG_VM_NAME=$(grep -m1 "^hostname:" /etc/pve/lxc/${VM_ID_RESTORED}.conf 2>/dev/null | awk -F': ' '{print $2}' | tr -d '[:space:]' || echo "") + pct destroy "$VM_ID_RESTORED" --purge 1 2>/dev/null || true +else + qmrestore "$PVE_BACKUP_REF" "$VM_ID_RESTORED" --storage "$RESTORE_PATH" --config-only 1 2>/dev/null || true + CONFIG_VM_NAME=$(grep -m1 "^name:" /etc/pve/qemu-server/${VM_ID_RESTORED}.conf 2>/dev/null | awk -F': ' '{print $2}' | tr -d '[:space:]' || echo "") + qm destroy "$VM_ID_RESTORED" --purge 1 2>/dev/null || true +fi + +echo " VM-Name aus Config: ${CONFIG_VM_NAME:-unbekannt}" + +# Prüfen ob ZIP bereits auf Backup-Server vorhanden +if [[ -n "$CONFIG_VM_NAME" ]]; then + if [[ "$SKIP_RSYNC" == "1" ]]; then + # Lokaler Modus: direkt prüfen + ZIP_CHECK="${RSYNC_TARGET}/${LAST_DATE}/${CONFIG_VM_NAME}-${VM_ID_ORIGINAL}.7z" + if [[ -f "$ZIP_CHECK" ]]; then + echo " ZIP bereits vorhanden (lokal): $ZIP_CHECK" + echo " Überspringe Restore – sende success Webhook." + VM_NAME="$CONFIG_VM_NAME" + ZIP_SIZE_BYTES=$(stat -c%s "$ZIP_CHECK" 2>/dev/null || echo "0") + RSYNC_OK="true" + RSYNC_SIZE_BYTES=$ZIP_SIZE_BYTES + QM_AGENT_OK="skipped" + trap - ERR + send_webhook "success" "" + exit 0 + fi + else + ZIP_CHECK="${RSYNC_TARGET}/${LAST_DATE}/${CONFIG_VM_NAME}-${VM_ID_ORIGINAL}.7z" + if ssh "$BACKUP_SERVER_HOST" "test -f '$ZIP_CHECK'" 2>/dev/null; then + echo " ZIP bereits vorhanden (remote): $ZIP_CHECK" + echo " Überspringe Restore – sende success Webhook." + VM_NAME="$CONFIG_VM_NAME" + ZIP_SIZE_BYTES=$(ssh "$BACKUP_SERVER_HOST" "stat -c%s '$ZIP_CHECK'" 2>/dev/null || echo "0") + RSYNC_OK="true" + RSYNC_SIZE_BYTES=$ZIP_SIZE_BYTES + QM_AGENT_OK="skipped" + trap - ERR + send_webhook "success" "" + exit 0 + fi + fi + echo " Kein vorhandenes ZIP gefunden – starte vollständigen Restore." +fi + # ═════════════════════════════════════════════════════════════════════════════ # [3/13] RESTORE # VM → qmrestore