mb-backup-manager/scripts/imports/view_backup_sessions.sh

414 lines
13 KiB
Bash

#!/bin/bash
# Configuration
backupPath='/mnt/backups'
password_file="/etc/restic-password"
LOG_DIR="$HOME/mb-backups/logs"
LOG_FILE="${LOG_DIR}/backup_sessions.log"
ERROR_LOG_FILE="${LOG_DIR}/backup_sessions_error.log"
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Logging function
log_message() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Error logging function
log_error() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1" | tee -a "$ERROR_LOG_FILE"
}
# Function: Display usage
display_usage() {
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " sessions - Show all complete backup sessions"
echo " incomplete - Show incomplete backup sessions"
echo " all - Show all snapshots grouped by session"
echo " validate <tag> - Validate a specific backup session"
echo ""
echo "Examples:"
echo " $0 sessions"
echo " $0 validate manual-backup-2024-01-15_10-30-45"
exit 1
}
# Function: Validate repository access
validate_repository() {
log_message "Validating repository access..."
if [ ! -d "$backupPath" ]; then
log_error "Backup path '$backupPath' does not exist or is not accessible."
echo "Restic repository path not found. Please verify that the path exists and is mounted."
exit 1
fi
if ! RESTIC_PASSWORD=$(cat "$password_file") restic -r "$backupPath" snapshots &>/dev/null; then
log_message "Attempting to fix permissions for '$backupPath'..."
sudo chown -R "$(whoami)":"$(whoami)" "$backupPath" 2>/dev/null || true
sudo chmod -R u+rwX "$backupPath" 2>/dev/null || true
if ! RESTIC_PASSWORD=$(cat "$password_file") restic -r "$backupPath" snapshots &>/dev/null; then
log_error "Unable to access Restic repository at '$backupPath'."
echo "Restic repository is inaccessible. Please check the path, permissions, or mount status."
exit 1
fi
fi
log_message "Repository access validated successfully."
}
# Function: Get all snapshots with session analysis
get_all_snapshots() {
log_message "Retrieving all snapshots for session analysis..."
local snapshots_json
snapshots_json=$(RESTIC_PASSWORD=$(cat "$password_file") restic -r "$backupPath" snapshots --json 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$snapshots_json" ]; then
log_error "Failed to retrieve snapshots from repository."
return 1
fi
echo "$snapshots_json"
return 0
}
# Function: Extract backup session tags
extract_session_tags() {
local snapshots_json="$1"
# Extract all session tags (manual-backup-* and automated-backup-*)
echo "$snapshots_json" | jq -r '.[].tags[]' | grep -E '^(manual|automated)-backup-[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}$' | sort | uniq
}
# Function: Analyze backup session completeness
analyze_session_completeness() {
local snapshots_json="$1"
local session_tag="$2"
# Get all snapshots for this session
local session_snapshots
session_snapshots=$(echo "$snapshots_json" | jq -r ".[] | select(.tags[] | contains(\"$session_tag\"))")
# Count snapshots in session
local snapshot_count
snapshot_count=$(echo "$session_snapshots" | jq -s '. | length')
# Extract component tags
local has_core=false
local has_media=false
local has_db=false
if echo "$session_snapshots" | jq -r '.tags[]' | grep -q "^core_files$"; then
has_core=true
fi
if echo "$session_snapshots" | jq -r '.tags[]' | grep -q "^media_themes$"; then
has_media=true
fi
if echo "$session_snapshots" | jq -r '.tags[]' | grep -q "^wordpress_db$"; then
has_db=true
fi
# Determine session status
local status="INCOMPLETE"
local missing_components=()
if [ "$has_core" = true ] && [ "$has_media" = true ] && [ "$has_db" = true ] && [ "$snapshot_count" -eq 3 ]; then
status="COMPLETE"
else
if [ "$has_core" = false ]; then
missing_components+=("core_files")
fi
if [ "$has_media" = false ]; then
missing_components+=("media_themes")
fi
if [ "$has_db" = false ]; then
missing_components+=("wordpress_db")
fi
fi
# Get session timestamp
local session_time
session_time=$(echo "$session_snapshots" | jq -r '.time' | head -n1)
# Output session info
echo "$session_tag|$status|$snapshot_count|$session_time|$(IFS=,; echo "${missing_components[*]}")"
}
# Function: Display complete backup sessions
display_complete_sessions() {
log_message "Displaying complete backup sessions..."
local snapshots_json
snapshots_json=$(get_all_snapshots)
if [ $? -ne 0 ]; then
echo "Failed to retrieve snapshots."
return 1
fi
local session_tags
session_tags=$(extract_session_tags "$snapshots_json")
if [ -z "$session_tags" ]; then
echo "No backup sessions found."
return 0
fi
echo "=== COMPLETE BACKUP SESSIONS ==="
echo "Format: [Session Tag] [Date/Time] [Status]"
echo "========================================"
local complete_sessions=0
while IFS= read -r session_tag; do
if [ -n "$session_tag" ]; then
local session_info
session_info=$(analyze_session_completeness "$snapshots_json" "$session_tag")
local status
status=$(echo "$session_info" | cut -d'|' -f2)
if [ "$status" = "COMPLETE" ]; then
local session_time
session_time=$(echo "$session_info" | cut -d'|' -f4)
printf "%-45s %s [%s]\n" "$session_tag" "$session_time" "$status"
((complete_sessions++))
fi
fi
done <<< "$session_tags"
echo "========================================"
echo "Total complete backup sessions: $complete_sessions"
echo ""
echo "To restore a complete session, use:"
echo " ./restore_full_backup_session.sh <session_tag>"
}
# Function: Display incomplete backup sessions
display_incomplete_sessions() {
log_message "Displaying incomplete backup sessions..."
local snapshots_json
snapshots_json=$(get_all_snapshots)
if [ $? -ne 0 ]; then
echo "Failed to retrieve snapshots."
return 1
fi
local session_tags
session_tags=$(extract_session_tags "$snapshots_json")
if [ -z "$session_tags" ]; then
echo "No backup sessions found."
return 0
fi
echo "=== INCOMPLETE BACKUP SESSIONS ==="
echo "Format: [Session Tag] [Date/Time] [Status] [Missing Components]"
echo "================================================================="
local incomplete_sessions=0
while IFS= read -r session_tag; do
if [ -n "$session_tag" ]; then
local session_info
session_info=$(analyze_session_completeness "$snapshots_json" "$session_tag")
local status
status=$(echo "$session_info" | cut -d'|' -f2)
if [ "$status" = "INCOMPLETE" ]; then
local session_time missing_components
session_time=$(echo "$session_info" | cut -d'|' -f4)
missing_components=$(echo "$session_info" | cut -d'|' -f5)
printf "%-45s %s [%s] Missing: %s\n" "$session_tag" "$session_time" "$status" "$missing_components"
((incomplete_sessions++))
fi
fi
done <<< "$session_tags"
echo "================================================================="
echo "Total incomplete backup sessions: $incomplete_sessions"
echo ""
echo "WARNING: Incomplete sessions cannot be used for full restoration."
}
# Function: Display all sessions with details
display_all_sessions() {
log_message "Displaying all backup sessions with details..."
local snapshots_json
snapshots_json=$(get_all_snapshots)
if [ $? -ne 0 ]; then
echo "Failed to retrieve snapshots."
return 1
fi
local session_tags
session_tags=$(extract_session_tags "$snapshots_json")
if [ -z "$session_tags" ]; then
echo "No backup sessions found."
return 0
fi
echo "=== ALL BACKUP SESSIONS ==="
echo "Format: [Session Tag] [Date/Time] [Status] [Snapshot Count] [Missing Components]"
echo "============================================================================="
local total_sessions=0
local complete_sessions=0
while IFS= read -r session_tag; do
if [ -n "$session_tag" ]; then
local session_info
session_info=$(analyze_session_completeness "$snapshots_json" "$session_tag")
local status session_time snapshot_count missing_components
status=$(echo "$session_info" | cut -d'|' -f2)
snapshot_count=$(echo "$session_info" | cut -d'|' -f3)
session_time=$(echo "$session_info" | cut -d'|' -f4)
missing_components=$(echo "$session_info" | cut -d'|' -f5)
if [ "$status" = "COMPLETE" ]; then
printf "%-45s %s [%s] (%d snapshots)\n" "$session_tag" "$session_time" "$status" "$snapshot_count"
((complete_sessions++))
else
printf "%-45s %s [%s] (%d snapshots) Missing: %s\n" "$session_tag" "$session_time" "$status" "$snapshot_count" "$missing_components"
fi
((total_sessions++))
fi
done <<< "$session_tags"
echo "============================================================================="
echo "Total sessions: $total_sessions (Complete: $complete_sessions, Incomplete: $((total_sessions - complete_sessions)))"
}
# Function: Validate specific backup session
validate_backup_session() {
local session_tag="$1"
log_message "Validating backup session: $session_tag"
# Validate session tag format
if [[ ! "$session_tag" =~ ^(manual|automated)-backup-[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "ERROR: Invalid backup session tag format."
echo "Expected format: manual-backup-YYYY-MM-DD_HH-MM-SS or automated-backup-YYYY-MM-DD_HH-MM-SS"
return 1
fi
local snapshots_json
snapshots_json=$(get_all_snapshots)
if [ $? -ne 0 ]; then
echo "Failed to retrieve snapshots."
return 1
fi
# Check if session exists
local session_snapshots
session_snapshots=$(echo "$snapshots_json" | jq -r ".[] | select(.tags[] | contains(\"$session_tag\"))")
if [ -z "$session_snapshots" ]; then
echo "ERROR: No snapshots found for session tag '$session_tag'."
return 1
fi
# Analyze session
local session_info
session_info=$(analyze_session_completeness "$snapshots_json" "$session_tag")
local status snapshot_count session_time missing_components
status=$(echo "$session_info" | cut -d'|' -f2)
snapshot_count=$(echo "$session_info" | cut -d'|' -f3)
session_time=$(echo "$session_info" | cut -d'|' -f4)
missing_components=$(echo "$session_info" | cut -d'|' -f5)
echo "=== BACKUP SESSION VALIDATION ==="
echo "Session Tag: $session_tag"
echo "Session Time: $session_time"
echo "Status: $status"
echo "Snapshot Count: $snapshot_count"
if [ "$status" = "COMPLETE" ]; then
echo "✓ All required components present:"
echo " ✓ Core Files (core_files)"
echo " ✓ Media Files (media_themes)"
echo " ✓ Database (wordpress_db)"
echo ""
echo "This session is ready for full restoration using:"
echo " ./restore_full_backup_session.sh $session_tag"
else
echo "✗ Session is incomplete. Missing components:"
IFS=',' read -ra MISSING <<< "$missing_components"
for component in "${MISSING[@]}"; do
echo "$component"
done
echo ""
echo "WARNING: This session cannot be used for full restoration."
fi
echo "================================="
# Show individual snapshots in session
echo ""
echo "Individual snapshots in this session:"
echo "$session_snapshots" | jq -r '" " + .short_id + " - " + .time + " - Tags: " + (.tags | join(", "))'
}
# Function: Validate environment
validate_environment() {
if [ ! -f "$password_file" ]; then
log_error "Password file not found at $password_file"
exit 1
fi
validate_repository
}
# Main script logic
main() {
local action="${1:-sessions}"
case "$action" in
"sessions")
validate_environment
display_complete_sessions
;;
"incomplete")
validate_environment
display_incomplete_sessions
;;
"all")
validate_environment
display_all_sessions
;;
"validate")
if [ -z "$2" ]; then
echo "ERROR: Session tag required for validation."
echo "Usage: $0 validate <session_tag>"
exit 1
fi
validate_environment
validate_backup_session "$2"
;;
*)
display_usage
;;
esac
}
# Run main function
main "$@"