#!/bin/bash

# chkconfig: 345 99 01
# description: Icinga2 network monitoring daemon

### BEGIN INIT INFO
# Provides:       icinga2
# Required-Start:
# Required-Stop:
# Default-Start:  2 3 5
# Default-Stop:
# Description:    Icinga2 network monitoring daemon
### END INIT INFO

cd /omd/sites/monitor
. .profile
. lib/omd/init_profile
. etc/omd/site.conf
[ "$CONFIG_CORE" = "icinga2" ] || exit 5

BIN=$OMD_ROOT/bin/icinga2
CFG_FILE=$OMD_ROOT/etc/icinga2/icinga2.conf
CMD_FILE=$OMD_ROOT/tmp/run/icinga.cmd
PID_FILE=$OMD_ROOT/tmp/run/icinga2.pid
ERROR_LOG=$OMD_ROOT/var/icinga2/log/icinga2/error.log
USR=$OMD_SITE
GRP=$OMD_SITE

OPTIONS="-c $CFG_FILE"

# Fetches the pid of the currently running icinga2 process of the given
# user.
# It returns 1 when no process can be found and echos the PID while
# returning 0 when a process can be found.
icinga2_proc() {
    PROC=$(ps -f -p"$(pgrep -d, -u $USER -P 1)" 2>/dev/null)
    PID=$(echo "$PROC" | grep -v grep | grep "bin/icinga2" | grep daemon | awk '{print $2}' | tr '\n' ' ')
    if [ "$PID" != "" ]; then
        echo "$PID"
        return 0
    else
        return 1
    fi
}

# First try to use the process list to gather a icinga2 process,
# when no process is found via ps take a look at the lock file
#
# It returns 1 when no process can be found and echos the PID while
# returning 0 when a process can be found.
pidof_icinga2() {
    icinga2_proc
    return $?
}

verify_config() {
    if [ "$1" != "quiet" ]; then
        echo -n "Running configuration check... "
    fi
    RESULT=$($BIN daemon $OPTIONS -C 2>&1)
    if [ $? -eq 0 ]; then
        if [ "$1" != "quiet" ]; then
            echo "done."
            echo "$RESULT" >&2
        fi
        return 0
    else
        if [ "$1" != "quiet" ]; then
            echo "CONFIG ERROR! Aborted. Check your Icinga configuration."
        fi
        echo "$RESULT" >&2
        return 1
    fi
}

prep_start() {
    if [ -f $CMD_FILE ]; then
        rm -f $CMD_FILE
    fi
    touch $PID_FILE
    chown $USR:$GRP $PID_FILE
    ln -sfn $OMD_ROOT/tmp/icinga2 $OMD_ROOT/tmp/core
}

icinga2_wait_stop() {
    pid=$(pidof_icinga2) || true
    if ! kill -0 ${pid:-} >/dev/null 2>&1; then
        echo -n 'Not running. '
        return 0
    fi

    # wait until really stopped.
    # it might happen that icinga2 has a subprocess which
    # is left running and becomes ppid 1 after killing the
    # main icinga2 process. So fetch the process id again
    # multiple times to fetch new processes until all are gone.
    if [ -n "${pid:-}" ]; then
        I=0
        while kill -0 ${pid:-} >/dev/null 2>&1; do
            # Send single kill per process
            kill $pid
            while kill -0 ${pid:-} >/dev/null 2>&1;  do
                if [ $I = '60' ]; then
                    return 1
                else
                    echo -n "."
                    I=$(($I+1))
                    sleep 1
                fi
            done
            # Is there another proc with ppid 1?
            pid=$(pidof_icinga2) || true
        done
    fi

    [ -f "$PID_FILE" ] && rm -f "$PID_FILE"
    return 0
}

icinga2_wait_start() {
    prep_start
    $BIN daemon $OPTIONS -d >>$ERROR_LOG 2>&1

    I=0
    while ! pidof_icinga2 >/dev/null 2>&1;  do
        if [ $I = '10' ]; then
            return 1
        else
            echo -n "."
            I=$(($I+1))
            sleep 1
        fi
    done

    return 0
}

if [ ! -f $BIN ]; then
    echo "Icinga binary $BIN not found. Terminating..."
    exit 1
fi

case "$1" in start|restart|reload|checkconfig)
    if [ ! -f $CFG_FILE ]; then
        echo "Icinga configuration file $CFG_FILE not found. Terminating..."
        exit 1
    fi
esac

__init_hook $0 $1 pre
case "$1" in
    start)
         echo -n "Starting icinga2..."
         if pidof_icinga2 >/dev/null 2>&1; then
             echo 'Already running.'
             exit 1
         fi

         if ! verify_config quiet; then
             exit 1
         fi

         if icinga2_wait_start; then
             echo 'OK'
             __init_hook $0 $1 post 0
             exit 0
         else
             echo 'ERROR'
             __init_hook $0 $1 post 1
             exit 1
         fi
    ;;
    stop)
        echo -n "Stopping icinga2..."
        if icinga2_wait_stop; then
            echo 'OK'
             __init_hook $0 $1 post 0
            exit 0
        else
            echo 'ERROR'
             __init_hook $0 $1 post 1
            exit 1
        fi
    ;;
    check|checkconfig)
        if ! verify_config; then
            exit 1
        fi
        exit 0
    ;;
    status)
        PID=$(cat $PID_FILE 2>&1) || true
        if kill -0 ${PID:-} >/dev/null 2>&1; then
            echo "Running ($PID)."
            exit 0
        else
            echo 'Not running. '
            exit 1
        fi
    ;;
    restart)
        if ! verify_config quiet; then
            exit 1
        fi

        $0 stop || (echo "Unable to stop icinga2. Terminating..." && exit 1)
        echo -n "Starting icinga2..."
        if icinga2_wait_start; then
            echo 'OK'
            exit 0
        else
            echo 'ERROR'
            exit 1
        fi
    ;;

    reload|force-reload)
        if ! verify_config quiet; then
            exit 1
        fi

        # Execute a start when icinga2 is not running
        if ! pidof_icinga2 >/dev/null 2>&1; then
            $0 start
            exit $?
        fi

        echo -n "Reloading icinga2 configuration (PID: $PID)... "
        if kill -HUP ${PID:-} >/dev/null 2>&1; then
            echo 'OK'
            exit 0
        else
            $0 restart
            exit $?
        fi
    ;;
  check)
    ;;
    *)
        echo "Usage: icinga2 {start|stop|restart|reload|status|checkconfig}"
        exit 2
    ;;
esac

# EOF
