Files
Server_Monitorizare_v2/scripts/restore_backup.sh
T

258 lines
8.9 KiB
Bash
Executable File

#!/bin/bash
# =============================================================================
# Server Monitorizare v2 - Migration Restore Script
# =============================================================================
# Restores a backup archive produced by backup_system.sh onto a new server.
#
# Usage:
# ./scripts/restore_backup.sh <backup.tar.gz> [--db-only] [--ansible-only]
#
# What it does:
# 1. Extracts the archive to a temp staging area
# 2. Restores the SQLite database (with a safety backup of any existing DB)
# 3. Restores Ansible inventory, playbooks, ssh_keys, ansible.cfg
# 4. Restores WMT releases and ansible_settings.json
# 5. Fixes SSH key permissions (must be 600 for Ansible)
# 6. Prints post-restore checklist
#
# For a fresh server install, run this AFTER:
# pip install -r requirements.txt
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP_DIR="$(dirname "$SCRIPT_DIR")"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
log() { echo "[$(date '+%H:%M:%S')] $*"; }
ok() { echo " [OK] $*"; }
warn() { echo " [WARN] $*"; }
err() { echo " [ERROR] $*" >&2; }
usage() {
echo "Usage: $0 <path/to/backup.tar.gz> [--db-only | --ansible-only]"
echo ""
echo "Options:"
echo " --db-only Restore only the SQLite database"
echo " --ansible-only Restore only Ansible files (inventory, playbooks, ssh_keys)"
echo ""
echo "Example:"
echo " $0 data/backups/smv2_backup_20260708_020000.tar.gz"
exit 1
}
# ---------------------------------------------------------------------------
# Parse args
# ---------------------------------------------------------------------------
ARCHIVE="${1:-}"
MODE="all" # all | db-only | ansible-only
YES=0 # set to 1 by --yes to skip interactive confirmation
[[ -n "$ARCHIVE" ]] || usage
[[ -f "$ARCHIVE" ]] || { err "Archive not found: $ARCHIVE"; exit 1; }
for arg in "${@:2}"; do
case "$arg" in
--db-only) MODE="db-only" ;;
--ansible-only) MODE="ansible-only" ;;
--yes|-y) YES=1 ;;
*) err "Unknown option: $arg"; usage ;;
esac
done
# ---------------------------------------------------------------------------
# Extract archive
# ---------------------------------------------------------------------------
log "Extracting archive: $ARCHIVE"
STAGE_DIR=$(mktemp -d)
trap 'rm -rf "$STAGE_DIR"' EXIT
tar -xzf "$ARCHIVE" -C "$STAGE_DIR"
log "Extracted to staging: $STAGE_DIR"
# Show manifest if present
if [[ -f "$STAGE_DIR/BACKUP_MANIFEST.txt" ]]; then
echo ""
echo "=== Backup Manifest ==="
cat "$STAGE_DIR/BACKUP_MANIFEST.txt"
echo "========================"
echo ""
fi
# ---------------------------------------------------------------------------
# Confirm before proceeding
# ---------------------------------------------------------------------------
if [[ "$YES" == "1" ]]; then
log "Non-interactive mode (--yes) — proceeding automatically."
else
read -r -p "Proceed with restore to $APP_DIR ? [y/N] " confirm
[[ "${confirm,,}" == "y" ]] || { log "Aborted."; exit 0; }
fi
# ---------------------------------------------------------------------------
# Restore: SQLite database
# ---------------------------------------------------------------------------
restore_db() {
local src="$STAGE_DIR/enhanced_monitoring.db"
local dst="$APP_DIR/data/enhanced_monitoring.db"
if [[ ! -f "$src" ]]; then
warn "No database file in archive — skipping DB restore"
return
fi
mkdir -p "$APP_DIR/data"
# Safety backup of any existing database
if [[ -f "$dst" ]]; then
local safety_bak="${dst}.pre_restore_${TIMESTAMP}.bak"
cp "$dst" "$safety_bak"
ok "Existing DB saved as safety backup: $(basename "$safety_bak")"
fi
cp "$src" "$dst"
ok "Database restored: $dst ($(du -sh "$dst" | cut -f1))"
# Quick sanity check
local dev_count; dev_count=$(sqlite3 "$dst" "SELECT COUNT(*) FROM devices;" 2>/dev/null || echo "?")
ok "Devices in restored DB: $dev_count"
}
# ---------------------------------------------------------------------------
# Restore: Ansible files
# ---------------------------------------------------------------------------
restore_ansible() {
local src="$STAGE_DIR/ansible"
if [[ ! -d "$src" ]]; then
warn "No ansible/ directory in archive — skipping"
return
fi
# Backup existing ansible dir if present
if [[ -d "$APP_DIR/ansible" ]]; then
local bak="$APP_DIR/ansible.pre_restore_${TIMESTAMP}.bak"
mv "$APP_DIR/ansible" "$bak"
ok "Existing ansible/ moved to: $(basename "$bak")"
fi
cp -a "$src" "$APP_DIR/ansible"
# Critical: SSH private key must be 600 or Ansible rejects it
if [[ -f "$APP_DIR/ansible/ssh_keys/app_key" ]]; then
chmod 600 "$APP_DIR/ansible/ssh_keys/app_key"
ok "SSH private key permissions set to 600"
fi
ok "Ansible directory restored"
ok "Playbooks: $(ls "$APP_DIR/ansible/playbooks/"*.yml 2>/dev/null | wc -l) files"
ok "Inventory hosts: $(grep -c 'ansible_host:' "$APP_DIR/ansible/inventory/dynamic_inventory.yaml" 2>/dev/null || echo 0)"
}
# ---------------------------------------------------------------------------
# Restore: WMT releases
# ---------------------------------------------------------------------------
restore_wmt_releases() {
local src="$STAGE_DIR/wmt_releases"
if [[ ! -d "$src" ]]; then return; fi
mkdir -p "$APP_DIR/data/wmt_releases"
# Only copy files not already present (don't overwrite newer releases)
for f in "$src"/*; do
local fname; fname=$(basename "$f")
if [[ ! -f "$APP_DIR/data/wmt_releases/$fname" ]]; then
cp "$f" "$APP_DIR/data/wmt_releases/"
ok "WMT release restored: $fname"
else
ok "WMT release already present (skipped): $fname"
fi
done
}
# ---------------------------------------------------------------------------
# Restore: ansible_settings.json
# ---------------------------------------------------------------------------
restore_settings() {
local src="$STAGE_DIR/ansible_settings.json"
if [[ ! -f "$src" ]]; then return; fi
local dst="$APP_DIR/data/ansible_settings.json"
if [[ -f "$dst" ]]; then
cp "$dst" "${dst}.pre_restore_${TIMESTAMP}.bak"
fi
cp "$src" "$dst"
ok "ansible_settings.json restored"
}
# ---------------------------------------------------------------------------
# Restore: config/
# ---------------------------------------------------------------------------
restore_config() {
local src="$STAGE_DIR/config"
if [[ ! -d "$src" ]]; then return; fi
if [[ -d "$APP_DIR/config" ]]; then
ok "config/ already present — skipping (manual merge may be needed)"
warn "Backup config is in: $STAGE_DIR/config/ (not auto-applied)"
return
fi
cp -a "$src" "$APP_DIR/config"
ok "config/ restored"
}
# ---------------------------------------------------------------------------
# Dispatch
# ---------------------------------------------------------------------------
log "Restore mode: $MODE"
case "$MODE" in
all)
restore_db
restore_ansible
restore_wmt_releases
restore_settings
restore_config
;;
db-only)
restore_db
;;
ansible-only)
restore_ansible
restore_settings
;;
esac
# ---------------------------------------------------------------------------
# Post-restore checklist
# ---------------------------------------------------------------------------
echo ""
echo "================================================================"
echo " Post-Restore Checklist"
echo "================================================================"
echo " 1. Install Python dependencies (if fresh server):"
echo " cd $APP_DIR && pip install -r requirements.txt"
echo ""
echo " 2. Start the application:"
echo " cd $APP_DIR && python main.py"
echo ""
echo " 3. Verify device list loads at: http://<new-server-ip>:5000"
echo ""
echo " 4. Test Ansible connectivity:"
echo " cd $APP_DIR/ansible && ansible -i inventory/dynamic_inventory.yaml all -m ping --limit 1"
echo ""
echo " 5. If the new server IP has changed, update any WMT devices"
echo " pointing to the old server URL (wmt_global_config.server_log_url)"
echo " via the admin UI or:"
echo " sqlite3 data/enhanced_monitoring.db \\"
echo " \"UPDATE wmt_global_config SET server_log_url='http://<NEW_IP>:5000/api/log';\""
echo ""
echo " 6. Re-install cron backup on the new server:"
echo " bash $SCRIPT_DIR/backup_system.sh install-cron"
echo ""
echo "================================================================"
log "Restore completed."