#! /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: - 99 00
#
### BEGIN INIT INFO
# Provides: vdsmd
# Required-Start: $syslog $network
# Should-Start: $time
# Required-Stop: $syslog
# 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"
prog=vdsm
PIDFILE=/var/run/vdsm/vdsmd.pid
RESPAWNPIDFILE=/var/run/vdsm/respawn.pid
NEEDED_SERVICES="multipathd rpcbind ntpd wdmd sanlock 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

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 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
            if service "${srv}" status >/dev/null 2>&1; then
                service "${srv}" stop
            fi
        else
            true
        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
}

start_network() {
    # Check if there are unactivated VDSM devices
    local interfaces dev static_devs activated_devs

    pushd /etc/sysconfig/network-scripts/ > /dev/null

    # copied from /etc/init.d/network
    interfaces=$(ls ifcfg-* | \
            LC_ALL=C sed -e "$__sed_discard_ignored_files" \
                   -e '/\(ifcfg-lo$\|:\|ifcfg-.*-range\)/d' \
                   -e '{ s/^ifcfg-//g;s/[0-9]/ &/}' | \
            LC_ALL=C sort -k 1,1 -k 2n | \
            LC_ALL=C sed 's/ //')

    for dev in $interfaces; do
        ifcfg="ifcfg-$dev"
        grep -q '# Generated by VDSM version' "$ifcfg" || continue
        grep -q 'ONBOOT=yes' "$ifcfg" || continue
        static_devs="$static_devs $dev"
    done
    popd > /dev/null

    activated_devs="`service network status | tail -1`"

    for static_dev in $static_devs; do
        if [[ $activated_devs != *"$static_dev"* ]]; then
            service network restart
            ret_val=$?
            if [ "${ret_val}" -ne 0 ]; then
                log_failure_msg "${prog}: Start dependent network"
                return "${ret_val}"
            fi
            break
        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() {
    if [ "${1}" = "force" ] || ! "$VDSM_TOOL" is-configured; then
        "$VDSM_TOOL" configure "--force"
    fi
}

restore_nets(){
    "$VDSM_TOOL" restore-nets
    return 0
}

unified_network_persistence_upgrade(){
    echo 'Upgrading to unified persistence if needed'
    "$VDSM_TOOL" ${UPGRADE_LOGGING_PARAMS} upgrade-unified-persistence
}

upgrade_300_nets(){
    echo 'Upgrading to v3.x networking if needed'
    "$VDSM_TOOL" ${UPGRADE_LOGGING_PARAMS} upgrade-3.0.0-networks
}

start() {
    test_already_running && return 0

    start_network || return 1
    shutdown_conflicting_srv "${CONFLICTING_SERVICES}" || return 1
    start_needed_srv "${NEEDED_SERVICES}" || return 1

    # "service iscsid start" may not start becasue we configure node.startup to
    # manual. See /etc/init.d/iscsid.
    service iscsid status >/dev/null 2>&1 || service iscsid force-start \
        || return 1

    "${VDSMD_INIT_COMMON}" --pre-start || return 1

    unified_network_persistence_upgrade || return 1
    restore_nets || return 1
    upgrade_300_nets || return 1

    echo $"Starting up vdsm daemon: "
    DAEMON_COREFILE_LIMIT=unlimited 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 10
        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 "$@"
    RETVAL=$?
    ;;
     *)
    echo "Usage: $0 {start|stop|status|restart|force-reload|try-restart|condrestart}"
    RETVAL=2
esac

exit "$RETVAL"
