#!/bin/sh
#
# greins This is the init script that tacks up the gunicorn
#
# chkconfig: 2345 72 28
# description: Starts and stops a Gunicorn application daemon that \
#	       routes to WSGI apps installed on the filesystem.

### BEGIN INIT INFO
# Provides: greins
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Should-Start: $remote_fs
# Should-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: manages Gunicorn tack
# Description: Driving Greins for Gunicorn
### END INIT INFO

# Source function library.
. /lib/lsb/init-functions

prog=$0
exec=/usr/bin/greins
[ -x $exec ] || exit 5

if [ -d "/etc/sysconfig" ];
then
    sysconfig="/etc/sysconfig"
else
    sysconfig="/etc/default"
fi

# default values
GREINS_BIND_ADDR=unix:/var/run/greins/greins.sock
GREINS_LOG_FILE=/var/log/greins/greins.log
GREINS_CONF_D=/etc/greins/conf.d
GREINS_USER=nobody
GREINS_GROUP=nobody
GREINS_OPTIONS=

# if this script was run from a symlink, follow links until we discover a
# corresponding configuration file or get to the end of the link chain
# this allows symlinking the init script to configure multiple daemons
fullname=$0
basename=$(basename $fullname)
while [ ! -e $sysconfig/$basename -a -L $fullname ]
do
    link=$(readlink $fullname)
    if [ $(expr $link : "\.") -gt 0 ]
    then
        fullname="$(dirname $fullname)/$link"
    else
        fullname="$link"
    fi
    basename=$(basename $fullname)
done

[ -e $sysconfig/$basename ] && . $sysconfig/$basename

pidfile=/var/run/greins/$basename.pid
lockfile=/var/lock/subsys/$basename

log_daemon_msg () {
    # Some distros may replace this when we source LSB functions
    echo $@
}

start() {
    log_daemon_msg "Starting $basename: "
    status_q -p $pidfile $prog && log_warning_msg "already running" && exit 0
    $exec -D \
      -p $pidfile \
      --log-file $GREINS_LOG_FILE \
      -u $GREINS_USER -g $GREINS_GROUP \
      -b $GREINS_BIND_ADDR \
      $GREINS_OPTIONS \
      $GREINS_CONF_D >/dev/null
    if [ $? -ne 0 ]; then
        log_failure_msg "failed"
        return 1
    fi
    rh_lock
    log_success_msg "done"
    return 0
}

stop() {
    log_daemon_msg "Stopping $basename: "
    status_q -p $pidfile.oldbin $prog && cleanup
    retval=0
    status_q -p $pidfile $prog
    if [ $? -ne 0 ]; then
        log_warning_msg "already stopped"
        return 0
    fi
    killproc -p $pidfile $prog -QUIT
    retval=$?
    if [ $retval -eq 0 ]; then
        STOPTIMEOUT=60
        while [ $STOPTIMEOUT -gt 1 ]; do
            status_q -p $pidfile $prog || break
            sleep 1
            let STOPTIMEOUT=${STOPTIMEOUT}-1
        done
        if [ $STOPTIMEOUT -eq 0 ]; then
            killproc -p $pidfile $prog
            retval=$?
            log_warning_msg "timeout error occurred trying to stop gracefully. Killing."
            if [ $retval -eq 0 ]; then
                rh_unlock
                rm -rf $pidfile
                log_success_msg "killed"
            else
                log_failure_msg "failed"
            fi
        else
            rh_unlock
            rm -rf $pidfile
            log_success_msg "done"
        fi
    fi
    return $retval
}

reload() {
    log_daemon_msg "Loading a new set of workers: "
    killproc -p $pidfile $prog -HUP
    retval=$?
    if [ $retval -eq 0 ]; then
        log_success_msg "done"
    else
        log_failure_msg "problem: killproc returned error code $?"
    fi
    return $retval
}

upgrade() {
    log_daemon_msg "Starting new master: "
    status_q -p $pidfile.oldbin $prog && log_warning_msg "already running: run cleanup or rollback first" && exit 0
    killproc -p $pidfile $prog -USR2
    TIMEOUT=60
    while [ $TIMEOUT -gt 1 ]; do
        status_q -p $pidfile.oldbin $prog && status_q -p $pidfile $prog && break
        sleep 1
        let TIMEOUT=${TIMEOUT}-1
    done
    if [ $TIMEOUT -eq 0 ]; then
        log_failure_msg "failed"
        return 1
    else
        log_daemon_msg "started"
    fi

    log_daemon_msg "Shutting down old workers: "
    killproc -p $pidfile.oldbin $prog -WINCH
    TIMEOUT=60
    while [ $TIMEOUT -gt 1 ]; do
        ps axo ppid | grep -q -f $pidfile.oldbin - && break
        sleep 1
        let TIMEOUT=${TIMEOUT}-1
    done
    if [ $TIMEOUT -eq 0 ]; then
        log_failure_msg "failed"
        return 1
    fi
    log_success_msg "done"
    return 0
}

rollback() {
    log_daemon_msg "Rolling back to old master: "
    status_q -p $pidfile.oldbin $prog
    if [ $? -ne 0 ]; then
        log_warning_msg "no old master found"
        return 0
    fi

    if [ -f $pidfile ]; then
        mv $pidfile $pidfile.tmp
    fi

    killproc -p $pidfile.oldbin $prog -HUP
    killproc -p $pidfile.tmp $prog
    log_success_msg "done"
    status_q -p $pidfile $prog
}

cleanup() {
    log_daemon_msg "Killing off old master: "
    status_q -p $pidfile.oldbin $prog
    if [ $? -ne 0 ]; then
        log_warning_msg "no old master found"
        return 0
    fi
    killproc -p $pidfile.oldbin $prog -QUIT
    TIMEOUT=60
    while [ $TIMEOUT -gt 1 ]; do
        status_q -p $pidfile.oldbin $prog && break
        sleep 1
        let TIMEOUT=${TIMEOUT}-1
    done
    if [ $TIMEOUT -eq 0 ]; then
        killproc -p $pidfile.oldbin $prog
    fi
    rm -f $pidfile.oldbin
    log_success_msg $"killed"
}

status_of_proc() {
    # Distros may override this but with RHEL5 we can use status
    . /etc/init.d/functions
    status $@
}

status_q() {
    status_of_proc $@ >/dev/null 2>&1
}

rh_lock() {
    [ -d $(basename $lockfile) ] && mkdir -p $(basename $lockfile)
    touch $lockfile
    return
}

rh_unlock() {
    [ -e $lockfile ] && rm -rf $lockfile
    return
}


case "$1" in
    start)
        $1
        ;;
    stop)
        $1
        ;;
    restart)
        stop
        start
        ;;
    reload)
        $1
        ;;
    upgrade)
        $1
        ;;
    rollback)
        $1
        ;;
    cleanup)
        $1
        ;;
    status)
        status_of_proc -p $pidfile $prog
        ;;
    condrestart|try-restart)
        status_q -p $pidfile $prog|| exit 0
        stop
        start
        ;;
    *)
        echo "Usage: $0 {start|stop|status|restart|upgrade|cleanup|rollback|condrestart|try-restart|reload}"
        log_failure_msg $"Unknown command"
        exit 2
esac
exit $?
