Browse Source

Improve automatic Snap upgrades.

Thanks to xet7 !
Lauri Ojansivu 4 days ago
parent
commit
aab671398c
3 changed files with 570 additions and 8 deletions
  1. 188 0
      snap-src/bin/logrotate-mongodb
  2. 175 0
      snap-src/bin/logrotate-setup
  3. 207 8
      snap-src/bin/mongodb-migrate

+ 188 - 0
snap-src/bin/logrotate-mongodb

@@ -0,0 +1,188 @@
+#!/bin/bash
+
+# MongoDB Log Rotation Script for Wekan Snap
+# This script handles log rotation for MongoDB logs in the Wekan snap environment
+
+set -e
+
+# Source settings if available, otherwise use defaults
+if [ -f "$SNAP/bin/wekan-read-settings" ]; then
+    source $SNAP/bin/wekan-read-settings
+else
+    # Default values when wekan-read-settings is not available
+    SNAP_COMMON="/var/snap/wekan/common"
+    SNAP_NAME="wekan"
+fi
+
+# Configuration
+MONGODB_LOG="${SNAP_COMMON}/mongodb.log"
+MAX_SIZE_MB=100
+KEEP_COPIES=10
+COMPRESS_LOGS=true
+
+# Logging functions
+log_message() {
+    local message="$1"
+    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
+    echo "[$timestamp] $message"
+}
+
+log_error() {
+    local message="$1"
+    log_message "ERROR: $message"
+}
+
+log_success() {
+    local message="$1"
+    log_message "SUCCESS: $message"
+}
+
+log_warning() {
+    local message="$1"
+    log_message "WARNING: $message"
+}
+
+# Check if log file exists and is large enough to rotate
+check_rotation_needed() {
+    if [ ! -f "$MONGODB_LOG" ]; then
+        log_message "MongoDB log file not found: $MONGODB_LOG"
+        return 1
+    fi
+    
+    # Get log file size in MB
+    local log_size_mb=$(du -m "$MONGODB_LOG" | cut -f1)
+    
+    if [ "$log_size_mb" -lt "$MAX_SIZE_MB" ]; then
+        log_message "MongoDB log size (${log_size_mb}MB) is below rotation threshold (${MAX_SIZE_MB}MB)"
+        return 1
+    fi
+    
+    log_message "MongoDB log size (${log_size_mb}MB) exceeds rotation threshold (${MAX_SIZE_MB}MB)"
+    return 0
+}
+
+# Rotate MongoDB log file
+rotate_log() {
+    local mongodb_log="$1"
+    local max_size_mb="$2"
+    local keep_copies="$3"
+    local compress="$4"
+    
+    log_message "Starting MongoDB log rotation"
+    
+    # Create rotated log file with timestamp
+    local timestamp=$(date +%Y%m%d-%H%M%S)
+    local rotated_log="${mongodb_log}.${timestamp}"
+    
+    # Copy current log to rotated file
+    if cp "$mongodb_log" "$rotated_log"; then
+        log_message "Created rotated log file: $rotated_log"
+        
+        # Truncate original log file
+        if > "$mongodb_log"; then
+            log_message "Truncated original log file"
+        else
+            log_error "Failed to truncate original log file"
+            return 1
+        fi
+        
+        # Compress rotated log file if requested
+        if [ "$compress" = "true" ]; then
+            if gzip "$rotated_log"; then
+                log_message "Compressed rotated log file: ${rotated_log}.gz"
+            else
+                log_warning "Failed to compress rotated log file"
+            fi
+        fi
+        
+        # Clean up old rotated logs (keep only specified number)
+        local old_logs=$(ls -t "${mongodb_log}".* 2>/dev/null | tail -n +$((keep_copies + 1)))
+        if [ -n "$old_logs" ]; then
+            echo "$old_logs" | xargs rm -f
+            log_message "Cleaned up old rotated log files"
+        fi
+        
+        log_success "MongoDB log rotation completed successfully"
+        return 0
+    else
+        log_error "Failed to create rotated log file"
+        return 1
+    fi
+}
+
+# Show log file statistics
+show_log_stats() {
+    if [ ! -f "$MONGODB_LOG" ]; then
+        log_message "MongoDB log file not found: $MONGODB_LOG"
+        return 1
+    fi
+    
+    local log_size_mb=$(du -m "$MONGODB_LOG" | cut -f1)
+    local log_lines=$(wc -l < "$MONGODB_LOG" 2>/dev/null || echo "0")
+    local rotated_count=$(ls -1 "${MONGODB_LOG}".* 2>/dev/null | wc -l)
+    
+    log_message "MongoDB Log Statistics:"
+    log_message "  Current log size: ${log_size_mb}MB"
+    log_message "  Current log lines: ${log_lines}"
+    log_message "  Rotated log files: ${rotated_count}"
+    log_message "  Rotation threshold: ${MAX_SIZE_MB}MB"
+    log_message "  Keep copies: ${KEEP_COPIES}"
+}
+
+# Force rotation regardless of size
+force_rotation() {
+    log_message "Force rotating MongoDB log file"
+    
+    if [ ! -f "$MONGODB_LOG" ]; then
+        log_error "MongoDB log file not found: $MONGODB_LOG"
+        return 1
+    fi
+    
+    rotate_log "$MONGODB_LOG" "$MAX_SIZE_MB" "$KEEP_COPIES" "$COMPRESS_LOGS"
+}
+
+# Main function
+main() {
+    local action="${1:-check}"
+    
+    case "$action" in
+        "check")
+            log_message "Checking if MongoDB log rotation is needed"
+            if check_rotation_needed; then
+                log_message "Log rotation is needed"
+                rotate_log "$MONGODB_LOG" "$MAX_SIZE_MB" "$KEEP_COPIES" "$COMPRESS_LOGS"
+            else
+                log_message "Log rotation is not needed"
+            fi
+            ;;
+        "force")
+            force_rotation
+            ;;
+        "stats")
+            show_log_stats
+            ;;
+        "help"|"-h"|"--help")
+            echo "Usage: $0 [check|force|stats|help]"
+            echo ""
+            echo "Commands:"
+            echo "  check  - Check if rotation is needed and rotate if so (default)"
+            echo "  force  - Force rotation regardless of log size"
+            echo "  stats  - Show log file statistics"
+            echo "  help   - Show this help message"
+            echo ""
+            echo "Configuration:"
+            echo "  Log file: $MONGODB_LOG"
+            echo "  Max size: ${MAX_SIZE_MB}MB"
+            echo "  Keep copies: $KEEP_COPIES"
+            echo "  Compress: $COMPRESS_LOGS"
+            ;;
+        *)
+            log_error "Unknown action: $action"
+            echo "Use '$0 help' for usage information"
+            exit 1
+            ;;
+    esac
+}
+
+# Run main function
+main "$@"

+ 175 - 0
snap-src/bin/logrotate-setup

@@ -0,0 +1,175 @@
+#!/bin/bash
+
+# Wekan Log Rotation Setup Script
+# This script sets up log rotation for Wekan snap installation
+
+set -e
+
+# Configuration
+SNAP_NAME="wekan"
+SNAP_COMMON="/var/snap/${SNAP_NAME}/common"
+LOGROTATE_DIR="/etc/logrotate.d"
+WEKAN_LOGROTATE_CONF="${LOGROTATE_DIR}/${SNAP_NAME}"
+
+# Log file paths
+MONGODB_LOG="${SNAP_COMMON}/mongodb.log"
+WEKAN_APP_LOG="${SNAP_COMMON}/wekan-app.log"
+WEKAN_ERROR_LOG="${SNAP_COMMON}/wekan-error.log"
+
+# Log rotation configuration
+ROTATE_SIZE="100M"
+KEEP_DAYS="30"
+KEEP_COPIES="10"
+
+log_message() {
+    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
+}
+
+log_error() {
+    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >&2
+}
+
+# Check if running as root
+if [ "$EUID" -ne 0 ]; then
+    log_error "This script must be run as root"
+    exit 1
+fi
+
+# Check if snap is installed
+if ! snap list | grep -q "^${SNAP_NAME} "; then
+    log_error "Snap ${SNAP_NAME} is not installed"
+    exit 1
+fi
+
+log_message "Setting up log rotation for Wekan snap..."
+
+# Create logrotate configuration
+cat > "${WEKAN_LOGROTATE_CONF}" << EOF
+# Wekan Snap Log Rotation Configuration
+# Generated by wekan logrotate-setup script
+
+# MongoDB logs
+${MONGODB_LOG} {
+    daily
+    missingok
+    rotate ${KEEP_COPIES}
+    compress
+    delaycompress
+    notifempty
+    create 644 root root
+    postrotate
+        # Send SIGUSR1 to MongoDB to reopen log file
+        if [ -f "${SNAP_COMMON}/mongodb.pid" ]; then
+            kill -USR1 \$(cat "${SNAP_COMMON}/mongodb.pid") 2>/dev/null || true
+        fi
+        # Alternative: restart MongoDB service if PID file doesn't exist
+        if [ ! -f "${SNAP_COMMON}/mongodb.pid" ]; then
+            snap restart ${SNAP_NAME}.mongodb 2>/dev/null || true
+        fi
+    endscript
+}
+
+# Wekan application logs
+${WEKAN_APP_LOG} {
+    daily
+    missingok
+    rotate ${KEEP_COPIES}
+    compress
+    delaycompress
+    notifempty
+    create 644 root root
+    postrotate
+        # Send SIGUSR1 to Wekan application to reopen log file
+        if [ -f "${SNAP_COMMON}/wekan.pid" ]; then
+            kill -USR1 \$(cat "${SNAP_COMMON}/wekan.pid") 2>/dev/null || true
+        fi
+        # Alternative: restart Wekan service if PID file doesn't exist
+        if [ ! -f "${SNAP_COMMON}/wekan.pid" ]; then
+            snap restart ${SNAP_NAME}.wekan 2>/dev/null || true
+        fi
+    endscript
+}
+
+# Wekan error logs
+${WEKAN_ERROR_LOG} {
+    daily
+    missingok
+    rotate ${KEEP_COPIES}
+    compress
+    delaycompress
+    notifempty
+    create 644 root root
+    postrotate
+        # Send SIGUSR1 to Wekan application to reopen log file
+        if [ -f "${SNAP_COMMON}/wekan.pid" ]; then
+            kill -USR1 \$(cat "${SNAP_COMMON}/wekan.pid") 2>/dev/null || true
+        fi
+        # Alternative: restart Wekan service if PID file doesn't exist
+        if [ ! -f "${SNAP_COMMON}/wekan.pid" ]; then
+            snap restart ${SNAP_NAME}.wekan 2>/dev/null || true
+        fi
+    endscript
+}
+
+# Size-based rotation for large log files
+${SNAP_COMMON}/*.log {
+    size ${ROTATE_SIZE}
+    missingok
+    rotate ${KEEP_COPIES}
+    compress
+    delaycompress
+    notifempty
+    create 644 root root
+    sharedscripts
+    postrotate
+        # Generic postrotate for all log files
+        # Try to signal processes to reopen log files
+        for pidfile in "${SNAP_COMMON}"/*.pid; do
+            if [ -f "\$pidfile" ]; then
+                kill -USR1 \$(cat "\$pidfile") 2>/dev/null || true
+            fi
+        done
+        # Restart services if no PID files found
+        if [ ! -f "${SNAP_COMMON}/mongodb.pid" ] && [ ! -f "${SNAP_COMMON}/wekan.pid" ]; then
+            snap restart ${SNAP_NAME}.mongodb 2>/dev/null || true
+            snap restart ${SNAP_NAME}.wekan 2>/dev/null || true
+        fi
+    endscript
+}
+EOF
+
+log_message "Created logrotate configuration: ${WEKAN_LOGROTATE_CONF}"
+
+# Test logrotate configuration
+if logrotate -d "${WEKAN_LOGROTATE_CONF}" >/dev/null 2>&1; then
+    log_message "Logrotate configuration test passed"
+else
+    log_error "Logrotate configuration test failed"
+    exit 1
+fi
+
+# Create log directory if it doesn't exist
+mkdir -p "${SNAP_COMMON}"
+
+# Set proper permissions
+chown root:root "${WEKAN_LOGROTATE_CONF}"
+chmod 644 "${WEKAN_LOGROTATE_CONF}"
+
+# Create initial log files if they don't exist
+touch "${MONGODB_LOG}" "${WEKAN_APP_LOG}" "${WEKAN_ERROR_LOG}"
+chown root:root "${SNAP_COMMON}"/*.log
+chmod 644 "${SNAP_COMMON}"/*.log
+
+log_message "Log rotation setup completed successfully"
+log_message "Configuration file: ${WEKAN_LOGROTATE_CONF}"
+log_message "Log files will be rotated daily and when they exceed ${ROTATE_SIZE}"
+log_message "Log files will be kept for ${KEEP_DAYS} days (${KEEP_COPIES} copies)"
+log_message "To test log rotation manually: sudo logrotate -f ${WEKAN_LOGROTATE_CONF}"
+log_message "To view logrotate status: sudo logrotate -d ${WEKAN_LOGROTATE_CONF}"
+
+echo ""
+echo "Next steps:"
+echo "1. Configure MongoDB to log to file: sudo snap set ${SNAP_NAME} mongo-log-destination=snapcommon"
+echo "2. Configure Wekan to log to file (if not already done)"
+echo "3. Test log rotation: sudo logrotate -f ${WEKAN_LOGROTATE_CONF}"
+echo "4. Monitor log files: ls -la ${SNAP_COMMON}/*.log*"

+ 207 - 8
snap-src/bin/mongodb-migrate

@@ -77,6 +77,11 @@ log_success() {
     log_message "SUCCESS: $message"
 }
 
+log_warning() {
+    local message="$1"
+    log_message "WARNING: $message"
+}
+
 # Disk space checking functions
 check_disk_space() {
     local required_space_gb="$1"
@@ -222,6 +227,28 @@ check_migration_needed() {
     return 1
 }
 
+# Display MongoDB log content for debugging
+display_mongodb_log_content() {
+    local mongodb_log="${SNAP_COMMON}/mongodb.log"
+    
+    if [ ! -f "$mongodb_log" ]; then
+        log_message "MongoDB log file not found: $mongodb_log"
+        return 1
+    fi
+    
+    log_message "MongoDB log file content (last 50 lines):"
+    if [ -r "$mongodb_log" ]; then
+        tail -50 "$mongodb_log" | while read -r line; do
+            log_message "LOG: $line"
+        done
+    else
+        log_message "MongoDB log file not readable, trying with sudo"
+        sudo tail -50 "$mongodb_log" 2>/dev/null | while read -r line; do
+            log_message "LOG: $line"
+        done
+    fi
+}
+
 # Detect if MongoDB upgrade is needed by checking log file
 detect_mongodb_upgrade_needed() {
     local mongodb_log="${SNAP_COMMON}/mongodb.log"
@@ -232,20 +259,168 @@ detect_mongodb_upgrade_needed() {
         return 1
     fi
     
-    # Check for the specific error message indicating upgrade is needed
-    if grep -q "This version of MongoDB is too recent to start up on the existing data files. Try MongoDB 4.2 or earlier." "$mongodb_log"; then
-        log_message "MongoDB upgrade needed detected in log file"
+    # Display log content for debugging
+    display_mongodb_log_content
+    
+    # Check file permissions and try to read with appropriate method
+    if [ ! -r "$mongodb_log" ]; then
+        log_message "MongoDB log file not readable, trying with sudo"
+        # Try to read with sudo if not readable
+        if ! sudo grep -q "too recent to start up on the existing data files" "$mongodb_log" 2>/dev/null; then
+            log_message "No MongoDB upgrade needed detected in log file (via sudo)"
+            return 1
+        fi
+    else
+        # Check for various error messages that indicate upgrade is needed
+        # The exact message may vary between MongoDB versions
+        local upgrade_patterns=(
+            "This version of MongoDB is too recent to start up on the existing data files"
+            "too recent to start up on the existing data files"
+            "Try MongoDB 4.2 or earlier"
+            "unsupported format version"
+            "data files are incompatible"
+            "database files are incompatible"
+            "version too new"
+            "version too recent"
+        )
+        
+        local found_upgrade_needed=false
+        for pattern in "${upgrade_patterns[@]}"; do
+            if grep -q "$pattern" "$mongodb_log" 2>/dev/null; then
+                log_message "Found upgrade pattern in log: '$pattern'"
+                found_upgrade_needed=true
+                break
+            fi
+        done
+        
+        if [ "$found_upgrade_needed" = false ]; then
+            log_message "No MongoDB upgrade needed detected in log file"
+            return 1
+        fi
+    fi
+    
+    log_message "MongoDB upgrade needed detected in log file"
+    return 0
+}
+
+# Log rotation function for MongoDB logs
+rotate_mongodb_logs() {
+    local mongodb_log="${SNAP_COMMON}/mongodb.log"
+    local max_size_mb=100
+    local keep_copies=10
+    
+    # Check if log file exists and is large enough to rotate
+    if [ ! -f "$mongodb_log" ]; then
+        log_message "MongoDB log file not found, skipping rotation"
         return 0
     fi
     
-    # Also check for similar error messages that might indicate upgrade issues
-    if grep -q "too recent to start up on the existing data files" "$mongodb_log"; then
-        log_message "MongoDB upgrade needed detected in log file (alternative message)"
+    # Get log file size in MB
+    local log_size_mb=$(du -m "$mongodb_log" | cut -f1)
+    
+    if [ "$log_size_mb" -lt "$max_size_mb" ]; then
+        log_message "MongoDB log size (${log_size_mb}MB) is below rotation threshold (${max_size_mb}MB)"
         return 0
     fi
     
-    log_message "No MongoDB upgrade needed detected in log file"
-    return 1
+    log_message "Rotating MongoDB log file (size: ${log_size_mb}MB)"
+    
+    # Create rotated log file with timestamp
+    local timestamp=$(date +%Y%m%d-%H%M%S)
+    local rotated_log="${mongodb_log}.${timestamp}"
+    
+    # Copy current log to rotated file
+    if cp "$mongodb_log" "$rotated_log"; then
+        log_message "Created rotated log file: $rotated_log"
+        
+        # Truncate original log file
+        if > "$mongodb_log"; then
+            log_message "Truncated original log file"
+        else
+            log_error "Failed to truncate original log file"
+            return 1
+        fi
+        
+        # Compress rotated log file
+        if gzip "$rotated_log"; then
+            log_message "Compressed rotated log file: ${rotated_log}.gz"
+        else
+            log_warning "Failed to compress rotated log file"
+        fi
+        
+        # Clean up old rotated logs (keep only specified number)
+        local old_logs=$(ls -t "${mongodb_log}".* 2>/dev/null | tail -n +$((keep_copies + 1)))
+        if [ -n "$old_logs" ]; then
+            echo "$old_logs" | xargs rm -f
+            log_message "Cleaned up old rotated log files"
+        fi
+        
+        log_success "MongoDB log rotation completed successfully"
+        return 0
+    else
+        log_error "Failed to create rotated log file"
+        return 1
+    fi
+}
+
+# Enhanced log rotation function for migration logs
+rotate_migration_logs() {
+    local migration_log="${SNAP_COMMON}/mongodb-migration-log.txt"
+    local max_size_mb=50
+    local keep_copies=5
+    
+    # Check if migration log file exists and is large enough to rotate
+    if [ ! -f "$migration_log" ]; then
+        log_message "Migration log file not found, skipping rotation"
+        return 0
+    fi
+    
+    # Get log file size in MB
+    local log_size_mb=$(du -m "$migration_log" | cut -f1)
+    
+    if [ "$log_size_mb" -lt "$max_size_mb" ]; then
+        log_message "Migration log size (${log_size_mb}MB) is below rotation threshold (${max_size_mb}MB)"
+        return 0
+    fi
+    
+    log_message "Rotating migration log file (size: ${log_size_mb}MB)"
+    
+    # Create rotated log file with timestamp
+    local timestamp=$(date +%Y%m%d-%H%M%S)
+    local rotated_log="${migration_log}.${timestamp}"
+    
+    # Copy current log to rotated file
+    if cp "$migration_log" "$rotated_log"; then
+        log_message "Created rotated migration log file: $rotated_log"
+        
+        # Truncate original log file
+        if > "$migration_log"; then
+            log_message "Truncated original migration log file"
+        else
+            log_error "Failed to truncate original migration log file"
+            return 1
+        fi
+        
+        # Compress rotated log file
+        if gzip "$rotated_log"; then
+            log_message "Compressed rotated migration log file: ${rotated_log}.gz"
+        else
+            log_warning "Failed to compress rotated migration log file"
+        fi
+        
+        # Clean up old rotated logs (keep only specified number)
+        local old_logs=$(ls -t "${migration_log}".* 2>/dev/null | tail -n +$((keep_copies + 1)))
+        if [ -n "$old_logs" ]; then
+            echo "$old_logs" | xargs rm -f
+            log_message "Cleaned up old rotated migration log files"
+        fi
+        
+        log_success "Migration log rotation completed successfully"
+        return 0
+    else
+        log_error "Failed to create rotated migration log file"
+        return 1
+    fi
 }
 
 # Reset MONGO_LOG_DESTINATION to devnull after successful migration
@@ -493,6 +668,18 @@ perform_migration() {
 
     log_message "Starting MongoDB migration from version 3 to 7"
 
+    # Rotate MongoDB logs before migration if needed
+    log_message "Checking if MongoDB log rotation is needed"
+    if ! rotate_mongodb_logs; then
+        log_warning "MongoDB log rotation failed, continuing with migration"
+    fi
+    
+    # Rotate migration logs before migration if needed
+    log_message "Checking if migration log rotation is needed"
+    if ! rotate_migration_logs; then
+        log_warning "Migration log rotation failed, continuing with migration"
+    fi
+
     # Create backup before migration
     log_message "Creating backup before migration"
     if ! create_backup; then
@@ -572,6 +759,18 @@ EOF
 
     log_success "MongoDB migration completed successfully"
     
+    # Rotate MongoDB logs after successful migration
+    log_message "Rotating MongoDB logs after successful migration"
+    if ! rotate_mongodb_logs; then
+        log_warning "MongoDB log rotation after migration failed"
+    fi
+    
+    # Rotate migration logs after successful migration
+    log_message "Rotating migration logs after successful migration"
+    if ! rotate_migration_logs; then
+        log_warning "Migration log rotation after migration failed"
+    fi
+    
     # Reset MONGO_LOG_DESTINATION to devnull after successful migration
     reset_mongo_log_destination