185 lines
8.6 KiB
Bash
Executable File
185 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# ==============================================================================
|
||
# Sovereign Map Platform - Full Autonomous Restoration System
|
||
# منصة الخرائط السيادية - نظام الاستعادة الشامل وإعادة التشغيل على سيرفر جديد
|
||
# ==============================================================================
|
||
# Architect: Hamza Ayed - Founding Tech Architect & Sovereign Mobility Strategist
|
||
# ==============================================================================
|
||
|
||
set -euo pipefail
|
||
|
||
# ANSI Color Codes
|
||
GREEN='\033[0;32m'
|
||
BLUE='\033[0;34m'
|
||
YELLOW='\033[1;33m'
|
||
RED='\033[0;31m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m'
|
||
|
||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||
|
||
echo -e "${CYAN}==================================================================${NC}"
|
||
echo -e "${CYAN} 🛡️ منصة خرائط سيرو السيادية | معالج استعادة النظام والسيرفر${NC}"
|
||
echo -e "${CYAN}==================================================================${NC}"
|
||
|
||
if [ $# -lt 1 ]; then
|
||
echo -e "${RED}❌ خطأ: يرجى تحديد مسار ملف النسخة الاحتياطية (.tar.gz) أو مجلد النسخة.${NC}"
|
||
echo -e "الاستخدام: $0 <path_to_backup.tar.gz | path_to_backup_dir>"
|
||
echo -e "مثال: $0 /home/hamzadoctor/backups/sovereign_map_full_backup_20260926_120000.tar.gz"
|
||
exit 1
|
||
fi
|
||
|
||
INPUT_PATH="$1"
|
||
TEMP_RESTORE_DIR=""
|
||
|
||
# Determine whether input is a tarball or a directory
|
||
if [ -f "$INPUT_PATH" ] && [[ "$INPUT_PATH" == *.tar.gz ]]; then
|
||
echo -e "📦 تم التعرف على ملف أرشيف مضغوط: ${YELLOW}$INPUT_PATH${NC}"
|
||
TEMP_RESTORE_DIR=$(mktemp -d /tmp/sovereign_restore_XXXXXX)
|
||
echo -e "⏳ جاري فك ضغط الأرشيف إلى: ${CYAN}$TEMP_RESTORE_DIR${NC}..."
|
||
tar -xzf "$INPUT_PATH" -C "$TEMP_RESTORE_DIR"
|
||
# Find the unpacked inner folder
|
||
RESTORE_SRC=$(find "$TEMP_RESTORE_DIR" -maxdepth 1 -mindepth 1 -type d | head -n 1)
|
||
if [ -z "$RESTORE_SRC" ]; then
|
||
RESTORE_SRC="$TEMP_RESTORE_DIR"
|
||
fi
|
||
elif [ -d "$INPUT_PATH" ]; then
|
||
echo -e "📁 تم التعرف على مجلد نسخة احتياطية: ${YELLOW}$INPUT_PATH${NC}"
|
||
RESTORE_SRC="$INPUT_PATH"
|
||
else
|
||
echo -e "${RED}❌ المسار المحدد غير صالح: $INPUT_PATH${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
echo -e "🔍 فحص مكونات النسخة الاحتياطية في: ${GREEN}$RESTORE_SRC${NC}"
|
||
|
||
# Check for database dump
|
||
DUMP_FILE="$RESTORE_SRC/database/mapdb_custom.dump"
|
||
SQL_FILE="$RESTORE_SRC/database/mapdb_schema.sql"
|
||
|
||
if [ ! -f "$DUMP_FILE" ] && [ ! -f "$SQL_FILE" ]; then
|
||
echo -e "${RED}❌ لم يتم العثور على ملفات قاعدة البيانات (mapdb_custom.dump أو mapdb_schema.sql)${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Step 1: Ensure Docker is active
|
||
echo -e "\n${BLUE}[1/6] 🐳 فحص بيئة Docker و Docker Compose...${NC}"
|
||
if ! command -v docker &> /dev/null; then
|
||
echo -e "${RED}❌ Docker غير مثبت على هذا السيرفر! يرجى تثبيته أولاً.${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
DOCKER_COMPOSE_CMD=""
|
||
if docker compose version &> /dev/null; then
|
||
DOCKER_COMPOSE_CMD="docker compose"
|
||
elif command -v docker-compose &> /dev/null; then
|
||
DOCKER_COMPOSE_CMD="docker-compose"
|
||
else
|
||
echo -e "${RED}❌ docker compose غير متاح!${NC}"
|
||
exit 1
|
||
fi
|
||
echo -e " ✅ محرك الحاويات جاهز: ${GREEN}$($DOCKER_COMPOSE_CMD version --short)${NC}"
|
||
|
||
# Step 2: Check & prepare .env file
|
||
echo -e "\n${BLUE}[2/6] ⚙️ تهيئة متغيرات البيئة (.env)...${NC}"
|
||
cd "$ROOT_DIR"
|
||
if [ ! -f "$ROOT_DIR/.env" ] && [ -f "$RESTORE_SRC/configs/.env.backup" ]; then
|
||
echo -e " 📥 استعادة ملف .env من النسخة الاحتياطية..."
|
||
cp "$RESTORE_SRC/configs/.env.backup" "$ROOT_DIR/.env"
|
||
elif [ -f "$ROOT_DIR/.env" ]; then
|
||
echo -e " ✅ ملف .env موجود مسبقاً في مسار المشروع."
|
||
else
|
||
echo -e " ${YELLOW}⚠️ لم يوجد .env! يرجى إنشاء ملف .env بالاعتماد على .env.example${NC}"
|
||
fi
|
||
|
||
# Step 3: Restore offline MBTiles & OSM packages
|
||
echo -e "\n${BLUE}[3/6] 🗺️ استعادة المربعات السيادية وحزم التوجيه (Offline Datasets)...${NC}"
|
||
if [ -d "$RESTORE_SRC/geodata/mbtiles" ]; then
|
||
mkdir -p "$ROOT_DIR/data/mbtiles"
|
||
echo -e " 📥 استعادة ملفات الارتفاع والأقمار الصناعية (MBTiles)..."
|
||
cp -rf "$RESTORE_SRC/geodata/mbtiles/"* "$ROOT_DIR/data/mbtiles/" 2>/dev/null || true
|
||
fi
|
||
|
||
if [ -f "$RESTORE_SRC/geodata/jordan-latest.osm.pbf" ]; then
|
||
mkdir -p "$ROOT_DIR/infrastructure/osm-data"
|
||
echo -e " 📥 استعادة ملف خريطة الأردن الخام (OSM PBF)..."
|
||
cp -f "$RESTORE_SRC/geodata/jordan-latest.osm.pbf" "$ROOT_DIR/infrastructure/osm-data/"
|
||
fi
|
||
|
||
if [ -d "$RESTORE_SRC/geodata/routing-packages" ]; then
|
||
mkdir -p "$ROOT_DIR/infrastructure/osm-data/routing-packages"
|
||
echo -e " 📥 استعادة حزم التوجيه المحلية (Valhalla routing)..."
|
||
cp -rf "$RESTORE_SRC/geodata/routing-packages/"* "$ROOT_DIR/infrastructure/osm-data/routing-packages/" 2>/dev/null || true
|
||
fi
|
||
|
||
# Step 4: Boot Database & Redis Containers
|
||
echo -e "\n${BLUE}[4/6] 🐘 تشغيل حاويات الداتابيز والكاش والتأكد من جاهزيتها...${NC}"
|
||
$DOCKER_COMPOSE_CMD up -d db redis
|
||
|
||
echo -e " ⏳ في انتظار جاهزية PostgreSQL و PostGIS..."
|
||
for i in {1..30}; do
|
||
if docker exec map-db pg_isready -U mapuser -d mapdb &>/dev/null; then
|
||
echo -e " ✅ قاعدة البيانات PostGIS جاهزة للحقن!"
|
||
break
|
||
fi
|
||
sleep 2
|
||
if [ $i -eq 30 ]; then
|
||
echo -e "${RED}❌ فشل انتظار جاهزية قاعدة البيانات! تفقد سجلات docker logs map-db${NC}"
|
||
exit 1
|
||
fi
|
||
done
|
||
|
||
# Step 5: Inject PostGIS Database
|
||
echo -e "\n${BLUE}[5/6] 📥 استعادة وحقن البيانات المكانية في PostGIS...${NC}"
|
||
if [ -f "$DUMP_FILE" ]; then
|
||
echo -e " ⏳ جاري الاستعادة من ملف الـ Custom Dump المسرّع..."
|
||
# Ensure postgis extension exists
|
||
docker exec -i map-db psql -U mapuser -d mapdb -c "CREATE EXTENSION IF NOT EXISTS postgis;"
|
||
docker exec -i map-db psql -U mapuser -d mapdb -c "CREATE EXTENSION IF NOT EXISTS postgis_topology;"
|
||
|
||
# Restore dump (ignore non-fatal warnings for clean recreation)
|
||
docker exec -i map-db pg_restore -U mapuser -d mapdb --clean --if-exists --no-owner --no-acl < "$DUMP_FILE" || true
|
||
|
||
# Run VACUUM ANALYZE to optimize geometry indices
|
||
echo -e " ⚡ تحسين الفهارس المكانية (VACUUM ANALYZE)..."
|
||
docker exec -i map-db psql -U mapuser -d mapdb -c "VACUUM ANALYZE;"
|
||
echo -e " ✅ تم استعادة قاعدة البيانات وتحديث الفهارس بنجاح!"
|
||
fi
|
||
|
||
# Step 6: Start Full Application Stack & Healthcheck
|
||
echo -e "\n${BLUE}[6/6] 🚀 بناء وتشغيل كافة خدمات المنصة السيادية...${NC}"
|
||
$DOCKER_COMPOSE_CMD up -d --build api martin web dashboard routing
|
||
|
||
echo -e "\n⏳ فحص صحة الخدمات (Health Checks)..."
|
||
sleep 5
|
||
|
||
check_service() {
|
||
local name="$1"
|
||
local url="$2"
|
||
if curl -s -f -m 5 "$url" > /dev/null 2>&1; then
|
||
echo -e " ✅ خدمة ${GREEN}$name${NC} تعمل بنجاح: $url"
|
||
else
|
||
echo -e " ℹ️ خدمة ${YELLOW}$name${NC} في طور الإقلاع أو تتطلب ثوانٍ إضافية: $url"
|
||
fi
|
||
}
|
||
|
||
check_service "Backend API (NestJS)" "http://localhost:3200/api/health"
|
||
check_service "Martin Vector Tiles" "http://localhost:3202/health"
|
||
check_service "GraphHopper Routing" "http://localhost:8989/health"
|
||
check_service "Web Tactical Portal" "http://localhost:3201"
|
||
check_service "Developer Dashboard" "http://localhost:3204"
|
||
|
||
# Cleanup temp unpack dir if created
|
||
if [ -n "$TEMP_RESTORE_DIR" ] && [ -d "$TEMP_RESTORE_DIR" ]; then
|
||
rm -rf "$TEMP_RESTORE_DIR"
|
||
fi
|
||
|
||
echo -e "\n${GREEN}==================================================================${NC}"
|
||
echo -e "${GREEN} 🎉 اكتملت عملية الاستعادة بنجاح والمنصة تعمل بكامل طاقتها!${NC}"
|
||
echo -e "${GREEN}==================================================================${NC}"
|
||
echo -e "🌐 البوابة التكتيكية والمناورة: http://localhost:3201/#maneuver"
|
||
echo -e "📡 خادم الخرائط السيادي (Martin): http://localhost:3202"
|
||
echo -e "⚡ محرك التوجيه (GraphHopper): http://localhost:8989"
|
||
echo -e "💼 لوحة المطورين والإدارة: http://localhost:3204"
|
||
echo -e "------------------------------------------------------------------"
|