#!/bin/sh
# Bereitschaft von keepalived, so weit ein Paket sie ohne Instanzwissen messen kann.
#
# Zwei Stufen, und die zweite ist die eigentliche:
#
# 1. Der VRRP-KINDPROZESS laeuft. keepalived liest erst die Konfiguration und
#    forkt dann den VRRP-Prozess; ist er da, ist die Konfiguration gelesen und
#    die Instanz initialisiert. "Der Elternprozess existiert" beweist das nicht
#    -- er existiert auch, waehrend er die Konfiguration noch verwirft.
#
# 2. Der VRRP-ZUSTAND ist erreicht (MASTER oder BACKUP). Den kann keepalived nur
#    selbst sagen, und zwar ueber ein notify-Skript oder notify_fifo -- also
#    ueber KONFIGURATION, die hier Puppet verwaltet. Das Paket kann sie nicht
#    setzen, ohne dem Katalog ins Handwerk zu pfuschen. Deshalb der Vertrag:
#    schreibt jemand den Zustand nach $KEEPALIVED_STATE_FILE
#    (Vorgabe /run/keepalived/state, ein Wort: MASTER, BACKUP oder FAULT), dann
#    zaehlt diese Datei. Fehlt sie, gilt Stufe 1 -- und der Unterschied wird
#    genannt, nicht verschwiegen.
#
# Warum das ueberhaupt gebraucht wird: bis 0.1.3 hatte die Unit kein
# notification-fd, also meldete s6 "up", sobald der Prozess lief. Auf einem
# Router ist das zu frueh: Puppet sieht einen fertigen Dienst, waehrend die
# VRRP-Wahl noch laeuft, und die Router-Abnahme stuetzt sich auf den Zustand.

set -u

STATE_FILE=${KEEPALIVED_STATE_FILE:-/run/keepalived/state}

if [ -r "$STATE_FILE" ]; then
    read -r _s < "$STATE_FILE" || _s=''
    case ${_s:-} in
    MASTER|BACKUP) exit 0 ;;
    FAULT) exit 1 ;;   # Zustand erreicht, aber gestoert -- nicht bereit
    *) exit 1 ;;
    esac
fi

# Stufe 1: hat der Elternprozess ein Kind?
_pid=$(cat /run/keepalived.pid 2>/dev/null || true)
case ${_pid:-} in
'' | *[!0-9]*)
    # Ohne pid-Datei den eigenen Prozessbaum nicht raten: nicht bereit melden,
    # damit s6-notifyoncheck weiter fragt, statt Bereitschaft zu behaupten.
    exit 1
    ;;
esac
[ -d "/proc/$_pid" ] || exit 1

for _c in /proc/[0-9]*/stat; do
    # Feld 4 ist die PPID. Ein Kind des keepalived-Elternprozesses genuegt.
    set -- $(cat "$_c" 2>/dev/null) || continue
    [ "${4:-}" = "$_pid" ] && exit 0
done
exit 1
