#!/bin/bash
#
# Nagios/Icinga2 plugin to check Proxmox Backup Server (PBS) backups.
#
# Checks:
#   1. Connectivité à l'API PBS              → WARNING si injoignable
#   2. Présence d'un backup du jour           → CRITICAL si absent
#   3. Statut de vérification du backup       → WARNING si non vérifié / échec

STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3

PBS_HOST=""
PBS_PORT=8007
PBS_TOKEN=""
PBS_STORE=""
BACKUP_ID=""
BACKUP_TYPE="host"
NAMESPACE=""
SKIP_SSL=0

usage() {
    cat << EOF
Usage: $0 -H <host> -T <api-token> -s <store> -n <backup-id> [-t <type>] [-P <port>] [-N <namespace>] [-k]

Options:
  -H  Hôte PBS (IP ou FQDN)
  -T  API token au format user@realm!tokenid:secret
  -s  Nom du datastore PBS
  -n  Backup ID à vérifier (backup-id : nom d'hôte, ou ID numérique pour vm/ct)
  -t  Type de backup : host (défaut), vm, ct
  -P  Port de l'API PBS (défaut : 8007)
  -N  Namespace PBS (optionnel)
  -k  Ignorer les erreurs de certificat SSL

Exemple (host) :
  $0 -H pbs.example.com -T backup@pbs!monitoring:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
     -s main -n myhost -k

Exemple (vm) :
  $0 -H pbs.example.com -T backup@pbs!monitoring:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
     -s main -n 100 -t vm -k
EOF
    exit $STATE_UNKNOWN
}

while getopts "H:T:s:n:t:P:N:k" opt; do
    case "$opt" in
        H) PBS_HOST="$OPTARG" ;;
        T) PBS_TOKEN="$OPTARG" ;;
        s) PBS_STORE="$OPTARG" ;;
        n) BACKUP_ID="$OPTARG" ;;
        t) BACKUP_TYPE="$OPTARG" ;;
        P) PBS_PORT="$OPTARG" ;;
        N) NAMESPACE="$OPTARG" ;;
        k) SKIP_SSL=1 ;;
        *) usage ;;
    esac
done

if [[ -z "$PBS_HOST" || -z "$PBS_TOKEN" || -z "$PBS_STORE" || -z "$BACKUP_ID" ]]; then
    usage
fi

if [[ "$BACKUP_TYPE" != "host" && "$BACKUP_TYPE" != "vm" && "$BACKUP_TYPE" != "ct" ]]; then
    echo "UNKNOWN: type de backup invalide '${BACKUP_TYPE}' (valeurs acceptées : host, vm, ct)"
    exit $STATE_UNKNOWN
fi

# --- Options curl ---
CURL_OPTS=(-sf --max-time 15)
[[ "$SKIP_SSL" -eq 1 ]] && CURL_OPTS+=(-k)

# --- URL de l'API ---
BASE_URL="https://${PBS_HOST}:${PBS_PORT}/api2/json"
SNAPSHOTS_URL="${BASE_URL}/admin/datastore/${PBS_STORE}/snapshots?backup-type=${BACKUP_TYPE}&backup-id=${BACKUP_ID}"
[[ -n "$NAMESPACE" ]] && SNAPSHOTS_URL+="&ns=${NAMESPACE}"

# --- Appel API ---
# PBS utilise PBSAPIToken (différent de PVEAPIToken utilisé par Proxmox VE)
RESPONSE=$(curl "${CURL_OPTS[@]}" \
    -H "Authorization: PBSAPIToken=${PBS_TOKEN}" \
    "$SNAPSHOTS_URL" 2>&1)
CURL_EXIT=$?

if [[ $CURL_EXIT -ne 0 ]]; then
    echo "WARNING: Impossible de contacter l'API PBS (${PBS_HOST}:${PBS_PORT}) - code curl : ${CURL_EXIT}"
    exit $STATE_WARNING
fi

# --- Validation JSON ---
if ! echo "$RESPONSE" | jq -e . >/dev/null 2>&1; then
    echo "WARNING: Réponse invalide de l'API PBS (réponse non-JSON)"
    exit $STATE_WARNING
fi

# Vérifier que l'API n'a pas retourné une erreur applicative
API_ERROR=$(echo "$RESPONSE" | jq -r '.errors // empty' 2>/dev/null)
if [[ -n "$API_ERROR" ]]; then
    echo "WARNING: Erreur API PBS : ${API_ERROR}"
    exit $STATE_WARNING
fi

# --- Extraction des snapshots ---
SNAPSHOTS=$(echo "$RESPONSE" | jq -r '.data // []')
TOTAL_COUNT=$(echo "$SNAPSHOTS" | jq 'length')

if [[ "$TOTAL_COUNT" -eq 0 ]]; then
    echo "CRITICAL: Aucun backup trouvé pour '${BACKUP_ID}' dans le datastore '${PBS_STORE}'"
    exit $STATE_CRITICAL
fi

# --- Filtrage des backups du jour (heure locale) ---
TODAY_START=$(date -d "today 00:00:00" +%s)
TOMORROW_START=$(date -d "tomorrow 00:00:00" +%s)

TODAY_SNAPSHOTS=$(echo "$SNAPSHOTS" | jq \
    --argjson ts "$TODAY_START" \
    --argjson te "$TOMORROW_START" \
    '[.[] | select(.["backup-time"] >= $ts and .["backup-time"] < $te)]')
TODAY_COUNT=$(echo "$TODAY_SNAPSHOTS" | jq 'length')

if [[ "$TODAY_COUNT" -eq 0 ]]; then
    LATEST_EPOCH=$(echo "$SNAPSHOTS" | jq '[.[]["backup-time"]] | max')
    LATEST_DATE=$(date -d "@${LATEST_EPOCH}" "+%Y-%m-%d %H:%M")
    echo "CRITICAL: Aucun backup aujourd'hui pour '${BACKUP_ID}' — dernier backup connu : ${LATEST_DATE}"
    exit $STATE_CRITICAL
fi

# --- Backup le plus récent du jour ---
LATEST=$(echo "$TODAY_SNAPSHOTS" | jq 'sort_by(.["backup-time"]) | last')
BACKUP_EPOCH=$(echo "$LATEST" | jq -r '.["backup-time"]')
BACKUP_TIME=$(date -d "@${BACKUP_EPOCH}" "+%Y-%m-%d %H:%M")
VERIFY_STATE=$(echo "$LATEST" | jq -r '.verification.state // "unverified"')

if [[ "$VERIFY_STATE" != "ok" ]]; then
    echo "WARNING: Backup '${BACKUP_ID}' du ${BACKUP_TIME} présent mais statut de vérification : ${VERIFY_STATE}"
    exit $STATE_WARNING
fi

echo "OK: Backup '${BACKUP_ID}' du ${BACKUP_TIME} présent et vérifié"
exit $STATE_OK
