#! /bin/sh
#
# Copyright 2006-2010 Red Hat, Inc. and/or its affiliates.
#
# Licensed to you under the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.  See the files README and
# LICENSE_GPL_v2 which accompany this distribution.
#

# chkconfig: 2345 99 00
#
### BEGIN INIT INFO
# Provides: vdsmd
# Required-Start: $syslog $network
# Should-Start: $time
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: init script for the VDS management server
# Short-Description: init script for the VDS management server
### END INIT INFO

VDSM_BIN="/usr/share/vdsm/vdsm"
CONF_FILE="/etc/vdsm/vdsm.conf"
GETCONFITEM="/usr/share/vdsm/get-conf-item"
prog=vdsm
PIDFILE=/var/run/vdsm/vdsmd.pid
RESPAWNPIDFILE=/var/run/vdsm/respawn.pid
CORE_DUMP_PATH="/var/log/core/core.%p.%t.dump"
CORE_PATTERN="/proc/sys/kernel/core_pattern"
NEEDED_SERVICES="iscsid multipathd rpcbind ntpd wdmd sanlock network libvirtd
                 supervdsmd"
CONFLICTING_SERVICES="libvirt-guests ksmtuned"
LOCK_FILE="/var/lock/subsys/vdsmd"
VDSM_TOOL="/usr/bin/vdsm-tool"
NICE_LOWEST=-20
VDSMD_INIT_COMMON="/usr/libexec/vdsm/vdsmd_init_common.sh"
RETVAL=0

is_coredump="$("${GETCONFITEM}" "${CONF_FILE}" vars core_dump_enable false | tr A-Z a-z)"
[ "${is_coredump}" != "true" ] && is_coredump=false

SYSTEMCTL_SKIP_REDIRECT=true

[ -f /etc/sysconfig/vdsm ] && . /etc/sysconfig/vdsm
. /etc/init.d/functions

log_failure_msg() { printf "$@"; failure "$@"; echo; }
log_success_msg() { printf "$@"; success "$@"; echo; }

shutdown_conflicting_srv() {
    local srv
    local ret_val
    local conflicting_services="$1"

    for srv in ${conflicting_services}; do
        if [ "$srv" == "libvirt-guests" ]; then
           # `service libvirt-guests stop` tries to access libvirtd and
           # requires sasl authentication. Instead, removing the lockfile
           # signifies to libvirt-guests that it has stopped.
           # TODO: This condition needs to be removed when BZ 1011981 fix will
           # be available.
           "/bin/rm" -f /var/lock/subsys/libvirt-guests >/dev/null 2>&1
        else
           if initctl status "${srv}" >/dev/null 2>&1; then
               # When srv is Upstart service, status srv always returns 0
               initctl stop "${srv}" || : # stop fails when already down
               initctl status "${srv}" | grep -q stop/waiting
           elif [ -x "/etc/init.d/${srv}" ]; then
               (! service "${srv}" status >/dev/null 2>&1) ||
                   service "${srv}" stop
           else
               true
           fi
        fi
        ret_val=$?
        if [ "${ret_val}" -ne 0 ]; then
            log_failure_msg "${prog}: Stop conflicting ${srv}"
            return "${ret_val}"
        fi
    done
    return 0
}

start_needed_srv() {
    local srv
    local ret_val
    local needed_services="$1"

    for srv in ${needed_services}; do
        if initctl status "${srv}" >/dev/null 2>&1; then
            # When srv is Upstart service, status srv always returns 0
            initctl start "${srv}" || : # start fails when already running
            initctl status "${srv}" | grep -q start/running
        else
            service "${srv}" status >/dev/null 2>&1 || service "${srv}" start
        fi
        ret_val=$?
        if [ "${ret_val}" -ne 0 ]; then
            log_failure_msg "${prog}: Start dependent ${srv}"
            return "${ret_val}"
        fi
    done
}

test_already_running()
{
    if pidofproc -p "$RESPAWNPIDFILE" >/dev/null || \
       pidofproc -p "$PIDFILE" "$VDSM_BIN" >/dev/null; then
        log_success_msg "$prog: already running"
        return 0
    fi
    return 1
}

reconfigure_libvirt() {
    local force
    [ "${1}" = "force" ] && force="--force"
    "$VDSM_TOOL" libvirt-configure ${force}
}

start() {
    test_already_running && return 0

    if [ "${is_coredump}" = "true" ]; then
        export DAEMON_COREFILE_LIMIT=unlimited
        echo "${CORE_DUMP_PATH}" > "${CORE_PATTERN}"
    fi
    shutdown_conflicting_srv "${CONFLICTING_SERVICES}" || return 1
    start_needed_srv "${NEEDED_SERVICES}" || return 1
    "${VDSMD_INIT_COMMON}" --pre-start || return 1

    echo $"Starting up vdsm daemon: "
    NICELEVEL="${NICE_LOWEST}" daemon --user=vdsm "/usr/share/vdsm/daemonAdapter" \
        -0 /dev/null -1 /dev/null -2 /dev/null --syslog "/usr/share/vdsm/respawn" --minlifetime 10 \
        --daemon --masterpid "${RESPAWNPIDFILE}" "${VDSM_BIN}" --pidfile "${PIDFILE}" || return 1
    touch "${LOCK_FILE}"
    return 0
}

stop() {
    echo $"Shutting down vdsm daemon: "
    if killproc -p "$RESPAWNPIDFILE"; then
        log_success_msg $"$prog watchdog stop"
    fi
    if ! pidofproc -p "$PIDFILE" >/dev/null; then
        log_failure_msg "$prog: not running"
        RETVAL=0
    else
        killproc -p "$PIDFILE" -d 2
        RETVAL=$?
        [ "$RETVAL" = 0 ] && "/bin/rm" -f "$LOCK_FILE" > /dev/null 2>&1
    fi
    "${VDSMD_INIT_COMMON}" --post-stop
    return "$RETVAL"
}

lock_op() {
    {
        if ! flock -n 9; then
            log_failure_msg $"cannot ${1} ${prog}, operation is locked"
            false
        elif ( "${1}" 9<&- ); then
            log_success_msg $"${prog} ${1}"
        else
            log_failure_msg $"${prog} ${1}"
            false
        fi
     } 9<$0
}

case "$1" in
     start)
         lock_op start
         RETVAL=$?
    ;;
     stop)
        lock_op stop
        RETVAL=$?
    ;;
     status)
    pidofproc -p "$PIDFILE" "$VDSM_BIN" >/dev/null
    RETVAL=$?
    if [ "$RETVAL" -eq 0 ]; then
        echo "VDS daemon server is running"
    else
        printf "VDS daemon is not running"
        if pidofproc -p "$RESPAWNPIDFILE" >/dev/null; then
            echo ", and its watchdog is running"
        else
            echo
        fi
    fi
    ;;
     condrestart)
    pidofproc -p "$PIDFILE" "$VDSM_BIN" >/dev/null
    RETVAL=$?
    if [ "$RETVAL" -eq 0 ]; then
        "$0" stop && "$0" start;
        RETVAL=$?;
    fi;
        ;;
     try-restart)
    "$0" stop && "$0" start
    RETVAL=$?
    ;;
     restart|force-reload)
    "$0" stop
    "$0" start
    RETVAL=$?
    ;;
    reconfigure)
        # Jump over 'reconfigure'
        shift 1
        reconfigure_libvirt "$@"
    RETVAL=$?
    ;;
     *)
    echo "Usage: $0 {start|stop|status|restart|force-reload|try-restart}"
    RETVAL=2
esac

exit "$RETVAL"
