#!/bin/bash # Collects MSP360 backup plan status from all known hosts and writes a JSON # status file, then pushes it to web.orbishosting.com (VM110). set -u CBB="/opt/local/MSP360 Backup/bin/cbb" SSHPW="Joker1974!!!" OUT=/tmp/backup-status.json NOW="$(date -u +%Y-%m-%dT%H:%M:%SZ)" BACKUP_ROOT=/mnt/nas-backups/MSPBackups get_plan_status() { # $1=host $2=user $3=planname $4=mode(local|hop) local host="$1" user="$2" plan="$3" mode="$4" out if [ "$mode" = "local" ]; then out="$("$CBB" plan -l 2>&1)" elif [ "$mode" = "hop" ]; then out="$(sshpass -p "$SSHPW" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=8 "$user@$host" "'$CBB' plan -l 2>&1")" fi local state result id state=$(echo "$out" | grep 'State:' | head -1 | sed 's/.*State: *//') result=$(echo "$out" | grep 'Last result:' | head -1 | sed 's/.*Last result: *//') id=$(echo "$out" | grep 'Id:' | head -1 | sed 's/.*Id: *//') echo "${state:-unreachable}|${result:-unreachable}|${id:-}" } # Reads the destination generation folders on the NAS (mounted locally on # PVE1) to find the last backup that actually completed and wrote data. # More trustworthy than the plan's self-reported "Last result", since a # plan can report Warning/Fail on a run after previously succeeding, and # we want to know how stale the actual backed-up data is. get_last_success() { local nas_folder="$1" plan_id="$2" latest [ -z "$plan_id" ] && { echo "null"; return; } latest=$(ls "$BACKUP_ROOT/$nas_folder/CBB_Configuration/${plan_id}.cbb\$/" 2>/dev/null | sort | tail -1) if [ -z "$latest" ]; then echo "null" else date -u -d "${latest:0:4}-${latest:4:2}-${latest:6:2} ${latest:8:2}:${latest:10:2}:${latest:12:2}" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "null" fi } echo "[" > "$OUT" first=1 emit() { local name="$1" ip="$2" state="$3" result="$4" last_success="$5" [ "$first" -eq 1 ] && first=0 || echo "," >> "$OUT" if [ "$last_success" = "null" ]; then cat >> "$OUT" <> "$OUT" </dev/null | sort | tail -1) if [ -z "$latest_dump" ]; then emit "$name" "$ip" "Unknown" "unreachable" "null" return fi ts=$(basename "$latest_dump" | sed -E 's/vzdump-qemu-[0-9]+-([0-9_]+-[0-9_]+)\.vma\.zst/\1/') iso=$(date -u -d "$(echo "$ts" | sed -E 's/(....)_(..)_(..)-(..)_(..)_(..)/\1-\2-\3 \4:\5:\6/')" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "") latest_log="$dump_dir/vzdump-qemu-$vmid-$ts.log" if [ -f "$latest_log" ] && grep -q "Finished Backup" "$latest_log"; then result="Success" else result="Warning" fi state="Proxmox nightly" if [ -n "$iso" ]; then emit "$name" "$ip" "$state" "$result" "$iso" else emit "$name" "$ip" "$state" "$result" "null" fi } collect "PVE1" "10.48.200.90" "" "local" "CBB_pve" collect "JARVIS" "10.48.200.211" "root" "hop" "CBB_JARVIS-211" collect "NovaCPX" "10.48.200.110" "root" "hop" "CBB_NovaCPX-110" collect "Jellyfin" "10.48.200.33" "root" "hop" "CBB_Jellyfin-33" collect "MediaStack" "10.48.200.35" "root" "hop" "CBB_MediaStack-35" collect_proxmox_vm "Homebridge" "10.48.200.18" "118" echo "]" >> "$OUT" python3 -c " import json data = json.load(open('$OUT')) data = {'updated': '$NOW', 'hosts': data} json.dump(data, open('$OUT', 'w'), indent=2) " sshpass -p "$SSHPW" scp -o StrictHostKeyChecking=no "$OUT" root@10.48.200.110:/home/webacct/public_html/downloads/backup-status.json