From 90a90e40ad763ed9d4b34b77c5d24f55f082665d Mon Sep 17 00:00:00 2001 From: Deckard Date: Wed, 15 Oct 2025 00:22:52 -0400 Subject: [PATCH] cleanup of install and monitoring --- README.md | 2 +- docker-compose-azerothcore-database.env | 6 +- docker-compose-azerothcore-database.yml | 12 +- docker-compose-azerothcore-modules.env | 6 +- docker-compose-azerothcore-services.env | 6 +- docker-compose-azerothcore-tools.env | 6 +- scripts/cleanup.sh | 6 +- scripts/db-import-conditional.sh | 162 +++++++++++++++++------- scripts/deploy-and-check.sh | 4 +- scripts/setup-server.sh | 6 +- scripts/status.sh | 50 ++++++++ 11 files changed, 189 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index d184f42..5289582 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ AUTH_EXTERNAL_PORT=3784 # Storage location STORAGE_ROOT=./storage # Local setup -# STORAGE_ROOT=/nfs/containers # NFS/network storage +# STORAGE_ROOT=/nfs/azerothcore # NFS/network storage # Database settings MYSQL_ROOT_PASSWORD=your-secure-password diff --git a/docker-compose-azerothcore-database.env b/docker-compose-azerothcore-database.env index 337d322..d175893 100644 --- a/docker-compose-azerothcore-database.env +++ b/docker-compose-azerothcore-database.env @@ -3,10 +3,10 @@ # ============================================== # DEPLOYMENT CONFIGURATION # ============================================== -# Storage root path - local: ./storage, production: /nfs/containers or custom mount -STORAGE_ROOT=/nfs/containers +# Storage root path - local: ./storage, production: /nfs/azerothcore or custom mount +STORAGE_ROOT=/nfs/azerothcore # Storage configuration for database layer -STORAGE_PATH=${STORAGE_ROOT}/azerothcore +STORAGE_PATH=${STORAGE_ROOT} # ============================================== # SERVER CONFIGURATION diff --git a/docker-compose-azerothcore-database.yml b/docker-compose-azerothcore-database.yml index 250d4e2..61cbd69 100644 --- a/docker-compose-azerothcore-database.yml +++ b/docker-compose-azerothcore-database.yml @@ -158,6 +158,7 @@ services: - ${STORAGE_PATH}/config:/azerothcore/env/dist/etc - ${STORAGE_PATH}/logs:/azerothcore/env/dist/logs - ${STORAGE_PATH}/mysql-data:/var/lib/mysql-persistent + - ./scripts/db-import-conditional.sh:/tmp/db-import-conditional.sh:ro environment: AC_DATA_DIR: "/azerothcore/data" AC_LOGS_DIR: "/azerothcore/logs" @@ -176,20 +177,15 @@ services: DB_WORLD_NAME: ${DB_WORLD_NAME} DB_CHARACTERS_NAME: ${DB_CHARACTERS_NAME} CONTAINER_USER: ${CONTAINER_USER} - command: + entrypoint: - sh - -c - | - # Install curl for downloading conditional db import script (as root) - microdnf install -y curl || yum install -y curl || (apt-get update && apt-get install -y curl) - # Set ownership for config directories chown ${CONTAINER_USER} /azerothcore/env/dist/etc 2>/dev/null || true - # Download conditional db import script from GitHub - echo "šŸ“„ Downloading conditional database import script from GitHub..." - curl -fsSL https://raw.githubusercontent.com/uprightbass360/acore-compose/main/scripts/db-import-conditional.sh -o /tmp/db-import-conditional.sh - chmod +x /tmp/db-import-conditional.sh + # Use local conditional db import script + echo "šŸ“„ Using local database import script..." /tmp/db-import-conditional.sh restart: "no" diff --git a/docker-compose-azerothcore-modules.env b/docker-compose-azerothcore-modules.env index 516a4e9..2720ba1 100644 --- a/docker-compose-azerothcore-modules.env +++ b/docker-compose-azerothcore-modules.env @@ -6,11 +6,11 @@ # ============================================== # DEPLOYMENT CONFIGURATION # ============================================== -# Storage root path - local: ./storage, production: /nfs/containers or custom mount +# Storage root path - local: ./storage, production: /nfs/azerothcore or custom mount # !!Set this for your environment root!!! -STORAGE_ROOT=/nfs/containers +STORAGE_ROOT=/nfs/azerothcore # Storage configuration (must match database layer) -STORAGE_PATH=${STORAGE_ROOT}/azerothcore +STORAGE_PATH=${STORAGE_ROOT} # ============================================== # USER MAPPING CONFIGURATION (for NFS compatibility) diff --git a/docker-compose-azerothcore-services.env b/docker-compose-azerothcore-services.env index cd95c8d..a469478 100644 --- a/docker-compose-azerothcore-services.env +++ b/docker-compose-azerothcore-services.env @@ -6,10 +6,10 @@ # ============================================== # DEPLOYMENT CONFIGURATION # ============================================== -# Storage root path - local: ./storage, production: /nfs/containers or custom mount -STORAGE_ROOT=/nfs/containers +# Storage root path - local: ./storage, production: /nfs/azerothcore or custom mount +STORAGE_ROOT=/nfs/azerothcore # Storage configuration (must match database layer) -STORAGE_PATH=${STORAGE_ROOT}/azerothcore +STORAGE_PATH=${STORAGE_ROOT} # ============================================== # USER MAPPING CONFIGURATION (for NFS compatibility) diff --git a/docker-compose-azerothcore-tools.env b/docker-compose-azerothcore-tools.env index fb56397..e0d8c8d 100644 --- a/docker-compose-azerothcore-tools.env +++ b/docker-compose-azerothcore-tools.env @@ -7,10 +7,10 @@ # ============================================== # TOOL STORAGE PATHS # ============================================== -# Storage root path - local: ./storage, production: /nfs/containers or custom mount -STORAGE_ROOT=/nfs/containers +# Storage root path - local: ./storage, production: /nfs/azerothcore or custom mount +STORAGE_ROOT=/nfs/azerothcore # Storage for tools (unified with core stack) -STORAGE_PATH=${STORAGE_ROOT}/azerothcore +STORAGE_PATH=${STORAGE_ROOT} # ============================================== # USER MAPPING CONFIGURATION (for NFS compatibility) diff --git a/scripts/cleanup.sh b/scripts/cleanup.sh index c1c3d1e..6de6e09 100755 --- a/scripts/cleanup.sh +++ b/scripts/cleanup.sh @@ -290,8 +290,8 @@ nuclear_cleanup() { cleanup_storage_preserve_backups() { if [ -d "./storage" ]; then # Find the storage path from environment files - STORAGE_ROOT=$(grep "^STORAGE_ROOT=" docker-compose-azerothcore-database*.env 2>/dev/null | head -1 | cut -d'=' -f2 || echo "/nfs/containers") - BACKUP_PATH="${STORAGE_ROOT}/azerothcore/backups" + STORAGE_ROOT=$(grep "^STORAGE_ROOT=" docker-compose-azerothcore-database*.env 2>/dev/null | head -1 | cut -d'=' -f2 || echo "/nfs/azerothcore") + BACKUP_PATH="${STORAGE_ROOT}/backups" # Temporarily move backups if they exist if [ -d "${BACKUP_PATH}" ]; then @@ -305,7 +305,7 @@ nuclear_cleanup() { # Restore backups if they were preserved if [ -d "/tmp/azerothcore-backups-preserve/backups" ]; then - sudo mkdir -p "${STORAGE_ROOT}/azerothcore" 2>/dev/null || mkdir -p "${STORAGE_ROOT}/azerothcore" + sudo mkdir -p "${STORAGE_ROOT}" 2>/dev/null || mkdir -p "${STORAGE_ROOT}" sudo mv /tmp/azerothcore-backups-preserve/backups "${BACKUP_PATH}" 2>/dev/null || mv /tmp/azerothcore-backups-preserve/backups "${BACKUP_PATH}" sudo rm -rf /tmp/azerothcore-backups-preserve 2>/dev/null || rm -rf /tmp/azerothcore-backups-preserve print_status "SUCCESS" "Backups preserved at ${BACKUP_PATH}" diff --git a/scripts/db-import-conditional.sh b/scripts/db-import-conditional.sh index 7f02935..1c41a2a 100755 --- a/scripts/db-import-conditional.sh +++ b/scripts/db-import-conditional.sh @@ -4,10 +4,23 @@ set -e echo "šŸ”§ Conditional AzerothCore Database Import" echo "========================================" -# Restoration status markers +# Restoration status markers - use writable location RESTORE_STATUS_DIR="/var/lib/mysql-persistent" +MARKER_STATUS_DIR="/tmp" RESTORE_SUCCESS_MARKER="$RESTORE_STATUS_DIR/.restore-completed" RESTORE_FAILED_MARKER="$RESTORE_STATUS_DIR/.restore-failed" +RESTORE_SUCCESS_MARKER_TMP="$MARKER_STATUS_DIR/.restore-completed" +RESTORE_FAILED_MARKER_TMP="$MARKER_STATUS_DIR/.restore-failed" + +# Ensure we can write to the status directory, fallback to tmp +mkdir -p "$RESTORE_STATUS_DIR" 2>/dev/null || true +if ! touch "$RESTORE_STATUS_DIR/.test-write" 2>/dev/null; then + echo "āš ļø Cannot write to $RESTORE_STATUS_DIR, using $MARKER_STATUS_DIR for markers" + RESTORE_SUCCESS_MARKER="$RESTORE_SUCCESS_MARKER_TMP" + RESTORE_FAILED_MARKER="$RESTORE_FAILED_MARKER_TMP" +else + rm -f "$RESTORE_STATUS_DIR/.test-write" 2>/dev/null || true +fi echo "šŸ” Checking restoration status..." @@ -42,53 +55,36 @@ echo "šŸ” Checking for backups to restore..." BACKUP_DIRS="/backups" -# Function to find and validate the most recent backup -find_latest_backup() { - # Priority 1: Legacy single backup file - if [ -f "/var/lib/mysql-persistent/backup.sql" ]; then - if head -10 "/var/lib/mysql-persistent/backup.sql" | grep -q "CREATE DATABASE\|INSERT INTO\|CREATE TABLE"; then - echo "/var/lib/mysql-persistent/backup.sql" - return 0 - fi - fi - # Priority 2: Modern timestamped backups - if [ -d "$BACKUP_DIRS" ] && [ "$(ls -A $BACKUP_DIRS)" ]; then - # Try daily backups first - if [ -d "$BACKUP_DIRS/daily" ] && [ "$(ls -A $BACKUP_DIRS/daily)" ]; then - local latest_daily=$(ls -1t $BACKUP_DIRS/daily | head -n 1) - if [ -n "$latest_daily" ] && [ -d "$BACKUP_DIRS/daily/$latest_daily" ]; then - # Validate backup has actual data - if ls "$BACKUP_DIRS/daily/$latest_daily"/*.sql.gz >/dev/null 2>&1; then - for backup_file in "$BACKUP_DIRS/daily/$latest_daily"/*.sql.gz; do - if [ -f "$backup_file" ] && [ -s "$backup_file" ]; then - if zcat "$backup_file" | head -20 | grep -q "CREATE DATABASE\|INSERT INTO\|CREATE TABLE"; then - echo "$BACKUP_DIRS/daily/$latest_daily" - return 0 - fi - fi - done - fi - fi - fi - fi - return 1 -} - -# Function to restore from timestamped backup directory +# Function to restore from backup (directory or single file) restore_from_directory() { - local backup_dir="$1" - echo "šŸ”„ Restoring from backup directory: $backup_dir" + local backup_path="$1" + echo "šŸ”„ Restoring from backup: $backup_path" local restore_success=true - # Restore each database backup - for backup_file in "$backup_dir"/*.sql.gz; do + # Handle single .sql file (legacy backup) + if [ -f "$backup_path" ] && [[ "$backup_path" == *.sql ]]; then + echo "šŸ“„ Restoring legacy backup file: $(basename "$backup_path")" + if timeout 300 mysql -h ${CONTAINER_MYSQL} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} < "$backup_path"; then + echo "āœ… Successfully restored legacy backup" + return 0 + else + echo "āŒ Failed to restore legacy backup" + return 1 + fi + fi + + # Handle directory with .sql.gz files (modern timestamped backups) + if [ -d "$backup_path" ]; then + echo "šŸ”„ Restoring from backup directory: $backup_path" + # Restore each database backup + for backup_file in "$backup_path"/*.sql.gz; do if [ -f "$backup_file" ]; then local db_name=$(basename "$backup_file" .sql.gz) echo "šŸ“„ Restoring database: $db_name" - if zcat "$backup_file" | mysql -h ${CONTAINER_MYSQL} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD}; then + if timeout 300 zcat "$backup_file" | mysql -h ${CONTAINER_MYSQL} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD}; then echo "āœ… Successfully restored $db_name" else echo "āŒ Failed to restore $db_name" @@ -97,16 +93,76 @@ restore_from_directory() { fi done - if [ "$restore_success" = true ]; then - return 0 - else - return 1 + if [ "$restore_success" = true ]; then + return 0 + else + return 1 + fi fi + + # If we get here, backup_path is neither a valid .sql file nor a directory + echo "āŒ Invalid backup path: $backup_path (not a .sql file or directory)" + return 1 } -# Attempt backup restoration -backup_path=$(find_latest_backup) -if [ $? -eq 0 ] && [ -n "$backup_path" ]; then +# Attempt backup restoration with full functionality restored +echo "šŸ”„ Checking for backups..." +backup_path="" + +# Priority 1: Legacy single backup file with content validation +echo "šŸ” Checking for legacy backup file..." +if [ -f "/var/lib/mysql-persistent/backup.sql" ]; then + echo "šŸ“„ Found legacy backup file, validating content..." + if timeout 10 head -10 "/var/lib/mysql-persistent/backup.sql" 2>/dev/null | grep -q "CREATE DATABASE\|INSERT INTO\|CREATE TABLE"; then + echo "āœ… Legacy backup file validated" + backup_path="/var/lib/mysql-persistent/backup.sql" + else + echo "āš ļø Legacy backup file exists but appears invalid or empty" + fi +else + echo "šŸ” No legacy backup found" +fi + +# Priority 2: Modern timestamped backups (only if no legacy backup found) +if [ -z "$backup_path" ] && [ -d "$BACKUP_DIRS" ]; then + echo "šŸ“ Backup directory exists, checking for timestamped backups..." + if [ "$(ls -A $BACKUP_DIRS 2>/dev/null | wc -l)" -gt 0 ]; then + # Check daily backups first + if [ -d "$BACKUP_DIRS/daily" ] && [ "$(ls -A $BACKUP_DIRS/daily 2>/dev/null | wc -l)" -gt 0 ]; then + echo "šŸ“… Found daily backup directory, finding latest..." + latest_daily=$(ls -1t $BACKUP_DIRS/daily 2>/dev/null | head -n 1) + if [ -n "$latest_daily" ] && [ -d "$BACKUP_DIRS/daily/$latest_daily" ]; then + echo "šŸ“¦ Checking backup directory: $latest_daily" + # Check if directory has .sql.gz files + if ls "$BACKUP_DIRS/daily/$latest_daily"/*.sql.gz >/dev/null 2>&1; then + # Validate at least one backup file has content + echo "šŸ” Validating backup content..." + for backup_file in "$BACKUP_DIRS/daily/$latest_daily"/*.sql.gz; do + if [ -f "$backup_file" ] && [ -s "$backup_file" ]; then + # Use timeout to prevent hanging on zcat + if timeout 10 zcat "$backup_file" 2>/dev/null | head -20 | grep -q "CREATE DATABASE\|INSERT INTO\|CREATE TABLE"; then + echo "āœ… Valid backup found: $(basename $backup_file)" + backup_path="$BACKUP_DIRS/daily/$latest_daily" + break + fi + fi + done + else + echo "āš ļø No .sql.gz files found in backup directory" + fi + fi + else + echo "šŸ“… No daily backup directory found" + fi + else + echo "šŸ“ Backup directory is empty" + fi +else + echo "šŸ“ No backup directory found or legacy backup already selected" +fi + +echo "šŸ”„ Final backup path result: '$backup_path'" +if [ -n "$backup_path" ]; then echo "šŸ“¦ Found backup: $(basename $backup_path)" if restore_from_directory "$backup_path"; then echo "āœ… Database restoration completed successfully!" @@ -210,7 +266,12 @@ if ./dbimport; then echo "āœ… Database import completed successfully!" # Create import completion marker - echo "$(date): Database import completed successfully" > "$RESTORE_STATUS_DIR/.import-completed" + if touch "$RESTORE_STATUS_DIR/.import-completed" 2>/dev/null; then + echo "$(date): Database import completed successfully" > "$RESTORE_STATUS_DIR/.import-completed" + else + echo "$(date): Database import completed successfully" > "$MARKER_STATUS_DIR/.import-completed" + echo "āš ļø Using temporary location for completion marker" + fi # Verify import was successful echo "šŸ” Verifying import results..." @@ -230,7 +291,12 @@ if ./dbimport; then fi else echo "āŒ Database import failed!" - echo "$(date): Database import failed" > "$RESTORE_STATUS_DIR/.import-failed" + if touch "$RESTORE_STATUS_DIR/.import-failed" 2>/dev/null; then + echo "$(date): Database import failed" > "$RESTORE_STATUS_DIR/.import-failed" + else + echo "$(date): Database import failed" > "$MARKER_STATUS_DIR/.import-failed" + echo "āš ļø Using temporary location for failed marker" + fi exit 1 fi diff --git a/scripts/deploy-and-check.sh b/scripts/deploy-and-check.sh index 70078dd..50ff4ec 100755 --- a/scripts/deploy-and-check.sh +++ b/scripts/deploy-and-check.sh @@ -138,7 +138,7 @@ wait_for_service() { case "$service_name" in "Client Data") local last_log=$(docker logs "$container_name" --tail 1 2>/dev/null | head -c 80 || echo "...") - printf "${YELLOW}ā³${NC} ${elapsed}s elapsed, ${remaining}s remaining | Status: $status | Latest: $last_log\n" + printf "%sā³%s %ss elapsed, %ss remaining | Status: %s | Latest: %s\n" "${YELLOW}" "${NC}" "${elapsed}" "${remaining}" "$status" "$last_log" ;; "Database Import") printf "${YELLOW}ā³${NC} ${elapsed}s elapsed, ${remaining}s remaining | Status: $status | Importing databases...\n" @@ -330,7 +330,7 @@ deploy_stack() { # Wait for client data extraction print_status "INFO" "Waiting for client data download and extraction (this may take 15-25 minutes)..." print_status "INFO" "Press Ctrl+C to exit if needed..." - wait_for_service "Client Data" 999999 "docker logs ac-client-data 2>/dev/null | grep -q 'Game data setup complete'" + wait_for_service "Client Data" 480 "docker logs ac-client-data 2>/dev/null | grep -q 'Game data setup complete'" # Wait for worldserver to be healthy wait_for_service "World Server" 24 "check_container_health ac-worldserver" diff --git a/scripts/setup-server.sh b/scripts/setup-server.sh index 93bb94b..74ca965 100755 --- a/scripts/setup-server.sh +++ b/scripts/setup-server.sh @@ -294,7 +294,7 @@ main() { else echo "Storage options:" echo "1) ./storage (local directory)" - echo "2) /nfs/containers (NFS mount)" + echo "2) /nfs/azerothcore (NFS mount)" echo "3) Custom path" while true; do @@ -305,7 +305,7 @@ main() { break ;; 2) - STORAGE_ROOT="/nfs/containers" + STORAGE_ROOT="/nfs/azerothcore" break ;; 3) @@ -348,7 +348,7 @@ main() { # Create directories if requested if [ "$PRE_CREATE_DIRECTORIES" = true ]; then print_status "INFO" "Creating storage directories..." - STORAGE_PATH="${STORAGE_ROOT}/azerothcore" + STORAGE_PATH="${STORAGE_ROOT}" # Create all required directories DIRECTORIES=( diff --git a/scripts/status.sh b/scripts/status.sh index c7c2316..c5b64a3 100755 --- a/scripts/status.sh +++ b/scripts/status.sh @@ -167,6 +167,12 @@ display_service_status() { printf "${CYAN}%-20s${NC} " "$service_display_name" get_container_status "$container_name" + # Show image name if container exists + if docker ps -a --format "table {{.Names}}" | grep -q "^${container_name}$"; then + local image_name=$(docker inspect --format='{{.Config.Image}}' "$container_name" 2>/dev/null || echo "unknown") + printf " ${CYAN}šŸ·ļø Image: $image_name${NC}\n" + fi + if [ "$SHOW_LOGS" = true ]; then show_service_logs "$container_name" "$service_display_name" fi @@ -191,6 +197,45 @@ get_client_data_progress() { fi } +# Function to get enabled modules info +get_enabled_modules() { + printf "${CYAN}%-20s${NC} " "Enabled Modules" + + # Check if modules are enabled by looking for environment files + local modules_enabled=false + local module_count=0 + local modules_list="" + + if [ -f "docker-compose-azerothcore-modules.env" ] || [ -f "docker-compose-azerothcore-modules-custom.env" ]; then + # Check for playerbots module + if docker ps --format "table {{.Names}}" | grep -q "^ac-modules$"; then + if docker logs ac-modules 2>/dev/null | grep -q "playerbot\|playerbots"; then + modules_list="playerbots" + module_count=$((module_count + 1)) + modules_enabled=true + fi + fi + + # Check for eluna module + if docker ps --format "table {{.Names}}" | grep -q "^ac-eluna$"; then + if [ -n "$modules_list" ]; then + modules_list="$modules_list, eluna" + else + modules_list="eluna" + fi + module_count=$((module_count + 1)) + modules_enabled=true + fi + fi + + if [ "$modules_enabled" = true ]; then + printf "${GREEN}ā—${NC} $module_count modules active\n" + printf " ${CYAN}šŸ“¦ Modules: $modules_list${NC}\n" + else + printf "${YELLOW}ā—${NC} No modules enabled\n" + fi +} + # Main status display function show_status() { # Capture all output to a temp file, then display at once @@ -228,6 +273,11 @@ show_status() { display_service_status "ac-post-install" "Post-Install" "Configuration automation" echo "" + # Enabled Modules + printf "${MAGENTA}=== MODULE STATUS ===${NC}\n" + get_enabled_modules + echo "" + # Network and ports printf "${MAGENTA}=== NETWORK STATUS ===${NC}\n" if docker network ls | grep -q azerothcore; then