Files
proxmox-config/pve/scripts/backup-status-collect.sh
T

127 lines
4.8 KiB
Bash
Executable File

#!/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"
CBBV2="/opt/local/MSP360 Backup/bin/cbbV2"
SSHPW="Joker1974!!!"
OUT=/tmp/backup-status.json
NOW="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
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:-}"
}
# Fixed 2026-07-20: previously read CBB_Configuration/<planId>.cbb$/ generation
# folders on the NAS, assuming that was "more trustworthy" than the plan's own
# self-reported status. That folder turned out to only get written once, at
# initial plan setup/first test run, and never again on subsequent scheduled
# runs (even though those runs were genuinely succeeding daily and writing
# real file data elsewhere in the destination tree) - so every host showed a
# stale last_success frozen at its original setup date, making working daily
# backups look dead for weeks. The plan's own "Last run time" (from cbbV2
# plan details) reflects the actual most recent run and is accurate.
get_last_run_time() {
# $1=host $2=user $3=mode $4=plan_id
local host="$1" user="$2" mode="$3" plan_id="$4" out line
[ -z "$plan_id" ] && { echo "null"; return; }
if [ "$mode" = "local" ]; then
out="$("$CBBV2" plan details -i "$plan_id" --progress 2>&1)"
else
out="$(sshpass -p "$SSHPW" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=8 "$user@$host" "'$CBBV2' plan details -i $plan_id --progress 2>&1")"
fi
line=$(echo "$out" | grep '^Last run time:' | head -1 | sed 's/^Last run time: *//')
[ -z "$line" ] && { echo "null"; return; }
date -u -d "$line" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "null"
}
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" <<EOF
{"name": "$name", "ip": "$ip", "state": "$state", "result": "$result", "last_success": null}
EOF
else
cat >> "$OUT" <<EOF
{"name": "$name", "ip": "$ip", "state": "$state", "result": "$result", "last_success": "$last_success"}
EOF
fi
}
collect() {
local name="$1" ip="$2" user="$3" mode="$4"
local r state result id last_success
r=$(get_plan_status "$ip" "$user" "" "$mode")
state="${r%%|*}"
rest="${r#*|}"
result="${rest%%|*}"
id="${rest#*|}"
last_success=$(get_last_run_time "$ip" "$user" "$mode" "$id")
emit "$name" "$ip" "$state" "$result" "$last_success"
}
# Homebridge dropped its in-guest MSP360 agent (repeated, unresolved storage
# errors) in favor of the cluster-wide Proxmox vzdump job, which snapshots
# the whole VM disk nightly at 21:00 to the same NAS. Reads the dump
# directory directly instead of querying an in-guest agent.
collect_proxmox_vm() {
local name="$1" ip="$2" vmid="$3" dump_dir="/mnt/pve/SynologyProx/dump"
local latest_dump latest_log ts iso result state
latest_dump=$(ls "$dump_dir"/vzdump-qemu-"$vmid"-*.vma.zst 2>/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"
collect "JARVIS" "10.48.200.211" "root" "hop"
collect "NovaCPX" "10.48.200.110" "root" "hop"
collect "Jellyfin" "10.48.200.33" "root" "hop"
collect "MediaStack" "10.48.200.35" "root" "hop"
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