#! /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
DOM_METADATA_BACKUP_DIR=/var/log/vdsm/backup
CORE_PATTERN=/proc/sys/kernel/core_pattern
NEEDED_SERVICES="iscsid multipathd rpcbind ntpd wdmd sanlock network libvirtd
                 supervdsmd"
CONFLICTING_SERVICES="libvirt-guests ksmtuned"
VDSM_TOOL="/usr/bin/vdsm-tool"
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; }

mk_data_center() {
    local dc
    dc="$("${GETCONFITEM}" "${CONF_FILE}" irs repository /rhev/)"
    /usr/bin/mkdir -p "$dc"
    "/usr/bin/chown" vdsm.kvm "$dc"
}

mk_dom_backup() {
    /usr/bin/mkdir -p "${DOM_METADATA_BACKUP_DIR}" > /dev/null 2>&1
    "/usr/bin/chown" vdsm.kvm "$(dirname "${DOM_METADATA_BACKUP_DIR}")" > /dev/null 2>&1
    "/usr/bin/chown" vdsm.kvm "${DOM_METADATA_BACKUP_DIR}" > /dev/null 2>&1
}

mk_core_path() {
    core_path=/var/log/core
    if ! [ -d "$core_path" ]; then
        /usr/bin/mkdir -p "$core_path" > /dev/null 2>&1
    fi
    "/usr/bin/chmod" a+tw "$core_path" > /dev/null 2>&1
}

mk_run_path() {
    local run_path

    for run_path in "/var/run/vdsm" "/var/run/vdsm/pools"; do
        /usr/bin/mkdir -p "$run_path"
        "/usr/bin/chmod" 755 "$run_path"
        "/usr/bin/chown" vdsm:kvm "$run_path"
        "/sbin/restorecon" "$run_path"
    done
}

shutdown_conflicting_srv() {
    local srv

    for srv in ${CONFLICTING_SERVICES}; do
        "$VDSM_TOOL" service-disable "$srv"
        if "$VDSM_TOOL" service-status "$srv" > /dev/null 2>&1; then
            if [ "$srv" = "libvirt-guests" ]; then
                "/usr/bin/rm" -f /var/lock/subsys/libvirt-guests
            else
                "$VDSM_TOOL" service-stop "$srv"
            fi
        fi
    done
    return 0
}

syslog_available() {
    if ! [ -S "/dev/log" ]; then
        log_failure_msg "Cannot communicate with syslog deamon for reports. " \
                        "Check rsyslog.conf"
        return 1
    fi
    return 0
}

start_needed_srv() {
    local srv
    local ret_val

    for srv in ${NEEDED_SERVICES}; do
        if ! "$VDSM_TOOL" service-status "$srv" > /dev/null 2>&1; then
            echo "Starting $srv..."
            "$VDSM_TOOL" service-start "$srv"
            ret_val=$?
            if [ "$ret_val" -ne 0 ]; then
                log_failure_msg "$prog: Dependent $srv failed to start"
                return "$ret_val"
            fi
        fi
    done
}

test_lo() {
    if ! LC_ALL=C "/usr/sbin/ip" link show lo | "/usr/bin/grep" -q UP; then
        log_failure_msg "VDSMD: lo interface is down, can't run !"
        echo "VDSMD: lo interface is down, can't run !" > /dev/kmsg
        return 1
    fi
    return 0
}

free_space() {
    local path="$1"
    df -P "$path" | awk '{print $4}'| tail -1
}

test_space() {
    local MIN_SPACE_KB=10000

    if [ "$(free_space /var/log/vdsm)" -lt "$MIN_SPACE_KB" ]; then
        log_failure_msg "$prog: low log space"
        return 1
    fi
    return 0
}


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() {
    if [ "$1" = "force" ]; then
        "$VDSM_TOOL" libvirt-configure --force
    else
        "$VDSM_TOOL" libvirt-configure
    fi
}

reconfigure_sanlock() {
    # If sanlock was started before the *first* installation of vdsm
    # then it is probably missing the supplementary groups.
    # Here we attempt to restart the service (when needed) to refresh
    # the groups.
    "$VDSM_TOOL" sanlock-check-service
    if [ $? != 0 ]; then
        echo -n "Attempting to restart sanlock service:"
        "$VDSM_TOOL" service-restart sanlock && success || failure
        echo
    fi
}

has_systemd() {
    "/usr/bin/mountpoint" -q /cgroup/systemd ||
        "/usr/bin/mountpoint" -q /sys/fs/cgroup/systemd
}

start() {
    local ret_val
    "/usr/bin/python" "/usr/share/vdsm/hooks.pyc" before_vdsm_start

    shutdown_conflicting_srv

    if ! "/usr/libexec/vdsm/vdsm-gencerts.sh" --check; then
        printf $"Configuring a self-signed VDSM host certificate: "
        "/usr/libexec/vdsm/vdsm-gencerts.sh" && success || failure ; echo
    fi

    reconfigure_sanlock

    reconfigure_libvirt noforce
    ret_val=$?
    if [ "$ret_val" -ne 0 ]; then
        log_failure_msg "$prog: failed to reconfigure libvirt"
        return "$ret_val"
    fi

    start_needed_srv && syslog_available

    ret_val=$?
    if [ "$ret_val" -ne 0 ]; then
       log_failure_msg "$prog: one of the dependent services did not start, error code $ret_val"
       return "$ret_val"
    fi

    "$VDSM_TOOL" nwfilter
    ret_val=$?
    if [ "$ret_val" -ne 0 ]; then
        log_failure_msg "$prog: Failed to define network filters on libvirt"
        return "$ret_val"
    fi

    "$VDSM_TOOL" dummybr
    ret_val=$?
    if [ "$ret_val" -ne 0 ]; then
        log_failure_msg "$prog: Failed to create ephemeral dummy bridge."
        return "$ret_val"
    fi

    if ! has_systemd; then
        "$VDSM_TOOL" load-needed-modules
    fi

    "/usr/sbin/sysctl" -q -p /etc/sysctl.d/vdsm
    mk_data_center
    mk_core_path
    mk_dom_backup
    mk_run_path
    "/usr/bin/chmod" 1777 /dev/shm
    if [ "${is_coredump}" = "true" ]; then
        export DAEMON_COREFILE_LIMIT=unlimited
        echo "${CORE_DUMP_PATH}" > "${CORE_PATTERN}"
    fi

    test_already_running && return 0

    if ! (test_space && test_lo && \
          "$VDSM_TOOL" libvirt-test-conflicts); then
        return 1
    fi

    echo $"Starting up vdsm daemon: "
    local vdsm_nice="$("${GETCONFITEM}" "${CONF_FILE}" vars vdsm_nice -5)"

    LIBVIRT_LOG_FILTERS="$("${GETCONFITEM}" "${CONF_FILE}" vars libvirt_env_variable_log_filters "")" \
    LIBVIRT_LOG_OUTPUTS="$("${GETCONFITEM}" "${CONF_FILE}" vars libvirt_env_variable_log_outputs "")" \
    LC_ALL=C NICELEVEL="$vdsm_nice" daemon --user=vdsm "/usr/share/vdsm/respawn" --minlifetime 10 --daemon --masterpid "$RESPAWNPIDFILE" "$VDSM_BIN"
    RETVAL=$?
    [ "$RETVAL" -eq 0 ] && log_success_msg $"$prog start" || log_failure_msg $"$prog start"
    [ "$RETVAL" -eq 0 ] && touch /var/lock/subsys/vdsmd
}

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" -eq 0 ] && log_success_msg $"$prog stop" || log_failure_msg $"$prog stop"
        [ "$RETVAL" -eq 0 ] && "/usr/bin/rm" -f /var/lock/subsys/vdsmd
    fi
    "/usr/bin/python" "/usr/share/vdsm/hooks.pyc" after_vdsm_stop
    return "$RETVAL"
}

case "$1" in
     start)
        start
    RETVAL=$?
    ;;
     stop)
        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 ", but its watchdog is"
            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_sanlock
        reconfigure_libvirt "$@"
    RETVAL=$?
    ;;
     *)
    echo "Usage: $0 {start|stop|status|restart|force-reload|try-restart}"
    RETVAL=2
esac

exit "$RETVAL"
