#!/bin/bash
# $Id$
#
# chkconfig: - 91 09
# description: Starts and stops the common address redundancy protocol daemon

### BEGIN INIT INFO
# Provides: lsb-ucarp
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start:
# Default-Stop: 0 1 6
# Short-Description: start and stop ucarp
# Description: Common Address Redundancy Protocol (CARP) for Unix
### END INIT INFO

# Source function library.
. /etc/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 0

get_files() {
    local FILE
    cd ${CONFDIR}
    for FILE in *.conf
       do [ "${FILE}" != "vip-common.conf" ] && echo -n "${FILE} "
    done
}

prog=$"common address redundancy protocol daemon"
LOGGER="/usr/bin/logger -p daemon.notice -t ucarp"
CONFDIR=/etc/ucarp
UPSCRIPT=/usr/libexec/ucarp/vip-up
DOWNSCRIPT=/usr/libexec/ucarp/vip-down

start() {
    RETVAL=-1
    VIP_RETVAL=0

    echo -n $"Starting ${prog}: "

    FILES=`get_files`

    if [ -z "${FILES}" ]; then
        ${LOGGER} "no virtual addresses are configured in ${CONFDIR}"
        failure
        RETVAL=1
    else
        for FILE in ${FILES}; do

            unset ID PASSWORD BIND_INTERFACE SOURCE_ADDRESS VIP_ADDRESS OPTIONS

           . ${CONFDIR}/vip-common.conf
           . ${CONFDIR}/${FILE}

           # If the SOURCE_ADDRESS is not defined in the config, guess it from the ifcfg file
           [ ${SOURCE_ADDRESS} ] || SOURCE_ADDRESS=$( . /etc/sysconfig/network-scripts/ifcfg-${BIND_INTERFACE} ; echo $IPADDR )

           # If a value for MASTER is set in the file, use it to set advskew value
	   # The default advskew is 0, so if we are not the master, add advskew=1 to the options
	   # If the skew is already set in the options, then ignore the MASTER parameter
	   if ! [[ "${OPTIONS}" =~ "-k" || "${OPTIONS}" =~ "-advskew" ]]; then
               [ "${MASTER:-NULL}" == "${SOURCE_ADDRESS}" ] || OPTIONS="${OPTIONS} --advskew=1"
	   fi

           # Set the ID from the config file if it's defined, otherwise guess from the filename
           if [[ -z "$ID" ]]; then
               ID="${FILE#vip-}"; ID="${ID%.conf}"
               IDnozero="${ID#0}"; IDnozero="${IDnozero#0}"
               if [[ "$ID" != "$IDnozero" ]]; then
                   if [[ "${ID}" != "${ID/8}" || "${ID}" != "${ID/9}" ]]; then
                      # Has leading zeroes, is not a valid octal number.
                      # Remove leading zeroes, interpret it as decimal.
                      ID="$IDnozero"
                  else
                      # Has leading zeroes, will be interpreted as octal.
                      ${LOGGER} "$FILE uses VIP ID" $(($ID)) "(octal $ID). To use $ID, add the line 'ID=$IDnozero' to $FILE or rename it to vip-$IDnozero.conf"
                  fi
              fi
          fi

            if [ ${ID} -lt 1 -o ${ID} -gt 255 ]; then
                ${LOGGER} "ID out of range (1-255) for ${FILE}, skipped VIP ID ${ID}"
                continue
            fi

            TMP_RETVAL=0

            if [ -z "${PASSWORD}" ]; then
                ${LOGGER} "no PASSWORD found for ${FILE}, skipped VIP ID ${ID}"
                TMP_RETVAL=1
            fi
            if [ -z "${BIND_INTERFACE}" ]; then
                ${LOGGER} "no BIND_INTERFACE found for ${FILE}, skipped VIP ID ${ID}"
                TMP_RETVAL=1
            fi
            if [ -z "${SOURCE_ADDRESS}" ]; then
                ${LOGGER} "no SOURCE_ADDRESS found for ${FILE}, skipped VIP ID ${ID}"
                TMP_RETVAL=1
            fi
            if [ -z "${VIP_ADDRESS}" ]; then
                ${LOGGER} "no VIP_ADDRESS found for ${FILE}, skipped VIP ID ${ID}"
                TMP_RETVAL=1
            fi

            # If one of more of the above failed, skip the daemon launch
            if [ ${TMP_RETVAL} -ne 0 ]; then
                VIP_RETVAL=1
                continue
            fi

            [ ${RETVAL} -eq -1 ] && RETVAL=0
            daemon /usr/sbin/ucarp --daemonize --interface=${BIND_INTERFACE} --pass=${PASSWORD} --srcip=${SOURCE_ADDRESS} --vhid=${ID} --addr=${VIP_ADDRESS} ${OPTIONS} --upscript=$UPSCRIPT --downscript=$DOWNSCRIPT >/dev/null
            LAUNCH_RETVAL=$?
            [ ${LAUNCH_RETVAL} -ne 0 ] && RETVAL=1
        done

        # failure/success or warning if launch worked with some vip errors
        if [ ${RETVAL} -eq 0 -a ${VIP_RETVAL} -eq 0 ]; then
            ${LOGGER} "all ucarp configurations were applied successfully"
            success
            touch /var/lock/subsys/ucarp
        elif [ ${RETVAL} -eq 0 -a ${VIP_RETVAL} -eq 1 ]; then
            ${LOGGER} "error in one or more of the ucarp configurations"
            warning
        else
           ${LOGGER} "error running one or more of the ucarp daemon instances"
            failure
        fi
    fi
    echo
}

stop() {
    echo -n $"Stopping $prog: "
    killproc /usr/sbin/ucarp >/dev/null
    RETVAL=$?

    # With "--shutdown" in the default OPTIONS, the down script is called
    # when ucarp is stopped, so IP addresses are released, no "leftovers".

    # failure/success (no warning, too complicated to handle properly)
    if [ ${RETVAL} -eq 1 ]; then
        ${LOGGER} "it seems like no ucarp daemon were running"
        failure
    else
        ${LOGGER} "all ucarp daemons stopped and IP addresses unassigned"
        success
        rm -f /var/lock/subsys/ucarp
    fi
    echo
}

# See how we were called.
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    condrestart)
        if [ -f /var/lock/subsys/ucarp ]; then
            stop
            start
        fi
        ;;
    status)
        status /usr/sbin/ucarp
        ;;
    *)
        echo $"Usage: $0 {start|stop|restart|condrestart|status}"
        exit 1
esac

exit $RETVAL

