Tuesday, December 4, 2012

Haproxy fails to reload on Fedora 17

The great load balancer Haproxy has indeed a small but annoying problem on Fedora 17 (64bit in my case). While start and stop works perfect via systemctl, the balancer reload fails without any clear message what is happened.

After few hours of digging in the starter bash script /etc/init.d/haproxy we found that the problem lies outside it, it is seems in Fedora's systemctl at all, in the /etc/init.d/functions include used in the balancer starter.

How to workaround the problem of Haproxy reload? Just remove following line from the end of functions file:
"x$1" = xreload -o \

After removal script code will look like this:
if [ "$_use_systemctl" = "1" ]; then
        if  [ "x$1" = xstart -o \
                "x$1" = xstop -o \
                "x$1" = xrestart -o \
                "x$1" = xtry-restart -o \
                "x$1" = xforce-reload -o \
                "x$1" = xcondrestart ] ; then

                systemctl_redirect $0 $1
                exit $?
        fi
fi
And Haproxy starter script finally is: 
#!/bin/sh
#
# haproxy
#
# chkconfig:   - 85 15
# description:  HAProxy is a free, very fast and reliable solution \
#               offering high availability, load balancing, and \
#               proxying for TCP and  HTTP-based applications
# processname: haproxy
# config:      /etc/haproxy/haproxy.cfg
# pidfile:     /var/run/haproxy.pid

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

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

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

exec="/usr/sbin/haproxy"
prog=$(basename $exec)

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

lockfile=/var/lock/subsys/haproxy

check() {
    $exec -c -V -f /etc/$prog/$prog.cfg
}

start() {
    $exec -c -q -f /etc/$prog/$prog.cfg
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi

    echo -n $"Starting $prog: "
    # start it up here, usually something like "daemon $exec"
    daemon $exec -D -f /etc/$prog/$prog.cfg -p /var/run/$prog.pid
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    # stop it here, often "killproc $prog"
    killproc $prog
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    $exec -c -q -f /etc/$prog/$prog.cfg
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    stop
    start
}

reload() {
    $exec -c -q -f /etc/$prog/$prog.cfg
    if [ $? -ne 0 ]; then
        echo "Errors in configuration file, check with $prog check."
        return 1
    fi
    #echo -n $"Reloading $prog by command: "
    #echo "$exec -V -D -f /etc/$prog/$prog.cfg -p /var/run/$prog.pid -sf $(cat /var/run/$prog.pid)"
    $exec -D -f /etc/$prog/$prog.cfg -p /var/run/$prog.pid -sf $(cat /var/run/$prog.pid)
    retval=$?
    return $retval
}

force_reload() {
    restart
}

fdr_status() {
    status $prog
}

case "$1" in
    start|stop|restart)
        $1
        ;;
    reload)
        reload
        ;;
    force-reload)
        force_reload
        ;;
    check)
        check
        ;;
    status)
        fdr_status
        ;;
    condrestart|try-restart)
      [ ! -f $lockfile ] || restart
    ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload}"
        exit 2
esac
But take in account, applying this workaround we are letting all output (echo ect) from the reload code to be printed out to a console where systemctl reload haproxy.service (or old-style service haproxy reload) will be invoked. The same actual for other services that used /etc/init.d/functions, in Fedora 17 case it's ipsec, network and few else.