#! /bin/sh
#
# Copyright 2006-2008 Qumranet, Inc. All Rights Reserved.
# Use is subject to license terms.
#

# 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
ksmprog=/usr/bin/ksmctl
ksmthread=kksmd
PIDFILE=/var/vdsm/vdsmd.pid
RESPAWNPIDFILE=/var/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 netconsole"
CONFLICTING_SERVICES="libvirtd"

is_coredump=`$GETCONFITEM $CONF_FILE vars core_dump_enable false | tr A-Z a-z`
[ $is_coredump != true ] && is_coredump=false
is_ksm=`$GETCONFITEM $CONF_FILE ksm ksm_enable false | tr A-Z a-z`
[ $is_ksm != true ] && is_ksm=false

if [ -r /lib/lsb/init-functions ]; then
  . /lib/lsb/init-functions
else
  . /etc/init.d/functions
  log_failure_msg() { echo -n "$@"; failure "$@"; echo; }
  log_success_msg() { echo -n "$@"; success "$@"; echo; }
fi

# circumvent RHEL 5 typo
! declare -F pidofproc>/dev/null && declare -F pidofprof >/dev/null && \
    pidofproc () { pidofprof "$@"; }

check_port_taken() {
    MANAGEMENT_PORT=`$GETCONFITEM $CONF_FILE addresses management_port ""`
    if [ -z "$MANAGEMENT_PORT" ]; then
        log_failure_msg "$prog: management_port not found in $CONF_FILE"
        return 1
    fi
    local MANAGEMENT_IP=`$GETCONFITEM $CONF_FILE addresses management_ip 0.0.0.0`
    netstat -ntl | grep -q "$MANAGEMENT_IP:$MANAGEMENT_PORT"
    RETVAL=$?
    if [ "$RETVAL" -eq 0 ]; then
        log_failure_msg "$prog: port $MANAGEMENT_PORT already bound"
        return 1
    fi
    return 0
}

mark_netconsole() {
    echo 9 > /proc/sysrq-trigger
    echo "Started logging at `date`" > /dev/kmsg
}

stop_netconsole() {
    echo "Stopped logging at `date`" > /dev/kmsg
    if ! /sbin/service netconsole stop;
    then
            echo "Unable to stop netconsole."
            return 1
    fi
    return 0
}

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

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

mk_upgrade_path() {
    if ! [ -d "/data/updates" ]; then
        /bin/mkdir -p /data/updates > /dev/null 2>&1
        /bin/chmod 755 /data/updates > /dev/null 2>&1
    fi
}

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

mk_pools_path() {
    # should simply be moved to /var/run/vdsm/pools and avoid tmpfs noise
    if ! grep -q " /var/vdsm/pools " /proc/mounts 2>&1 ; then
        mount -t tmpfs -osize=1048576 none /var/vdsm/pools
        /sbin/restorecon /var/vdsm/pools/
    fi
}

test_conflicting_srv() {
    for srv in $CONFLICTING_SERVICES
    do
        if /sbin/service $srv status > /dev/null 2>&1;
        then
             echo "Found running $srv. VDSM will not run."
             return 1
        fi
    done
    return 0
}

test_needed_srv() {
    for srv in $NEEDED_SERVICES
    do
        if ! /sbin/service $srv status > /dev/null 2>&1;
        then
            echo "Starting $srv..."
            /sbin/service $srv start
        else
            if [ "${srv}" == "netconsole" ];
            then
                echo "Restarting $srv..."
                /sbin/service $srv restart
            fi
        fi
    done
}

RETVAL=0

case "$1" in
     start)
        if ! ifconfig lo | 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
            exit 1
        fi
        test_needed_srv
        /usr/share/vdsm/vdsm-restore-net-config
        /sbin/modprobe tun
        /sbin/modprobe bonding
        # RHEV-M currently assumes that all bonding devices pre-exist
        for b in +bond{0,1,2,3,4}; do
            echo $b > /sys/class/net/bonding_masters 2>/dev/null
        done
        /sbin/modprobe 8021q
        echo 1 > /sys/module/processor/parameters/max_cstate
        mk_data_center
        mk_upgrade_path
        mk_core_path
        mk_pools_path
        mk_dom_backup
        /bin/chmod 1777 /dev/shm
        if [ $is_coredump == true ]; then
            ulimit -c unlimited
            echo $CORE_DUMP_PATH > $CORE_PATTERN
        else
            ulimit -c 0
        fi
        [ `ulimit -n` -lt 4096 ] && ulimit -n 4096
	pid=`pidofproc -p $PIDFILE $VDSM_BIN`
	RETVAL=$?
	if [ "$RETVAL" -eq 0 ]; then
            log_failure_msg "$prog: already running"
            RETVAL=1
        else
            check_port_taken && test_conflicting_srv
            if [ $? -ne 0 ]; then
                RETVAL=1
            else
                echo $"Starting up vdsm daemon: "
                mount -a # sometimes nfs is not accessible during boot
                vdsm_nice=`$GETCONFITEM $CONF_FILE vars vdsm_nice -5`
                nice -n $vdsm_nice /bin/su -s /bin/sh -c "$VDSM_BIN $CONF_FILE" vdsm
                RETVAL=$?
                [ "$RETVAL" -eq 0 ] && log_success_msg $"$prog start" || log_failure_msg $"$prog start"
                [ "$RETVAL" -eq 0 ] && touch /var/lock/subsys/vdsmd
            fi
	fi
        if [ $is_ksm == true ]; then
            ksm_nice=`$GETCONFITEM $CONF_FILE ksm ksm_nice 5`
            ksmpid=`/usr/bin/pgrep $ksmthread`
            if [ -z "$ksmpid" ]; then
                log_failure_msg $ksmthread not found
            else
                renice $ksm_nice -p $ksmpid > /dev/null
            fi
        else
            $ksmprog stop
        fi
        mark_netconsole
	;;
     stop)
	echo $"Shutting down vdsm daemon: "
	pid=`pidofproc -p $PIDFILE`
	RETVAL=$?
	pid="$pid `pidofproc $VDSM_BIN`"
	RETVAL2=$?
	if [ ! "$RETVAL" -eq 0 -a ! "$RETVAL2" -eq 0 ]; then
            log_failure_msg "$prog: not running"
            RETVAL=1
        else
            killproc -p $RESPAWNPIDFILE
	    RETVAL=$?
	    [ "$RETVAL" -eq 0 ] && log_success_msg $"$prog watchdog stop" || log_failure_msg $"$prog watchdog stop" 
            killproc -p $PIDFILE -d 2
	    RETVAL=$?
	    [ "$RETVAL" -eq 0 ] && log_success_msg $"$prog stop" || log_failure_msg $"$prog stop"
  	    [ "$RETVAL" -eq 0 ] && rm -f /var/lock/subsys/vdsmd
            sleep 2
        fi
    # TODO: check if we can remove this-
	stop_netconsole
	;;
     status)
	pid=`pidofproc -p $PIDFILE $VDSM_BIN`
	RETVAL=$?
	if [ "$RETVAL" -eq 0 ]; then
		echo "VDS daemon server is running"
	else
		echo "VDS daemon is not running"
	fi
	;;
     condrestart)
	pid=`pidofproc -p $PIDFILE $VDSM_BIN`
	RETVAL=$?
	if [ "$RETVAL" -eq 0 ]; then
	    $0 stop && $0 start;
	    RETVAL=$?;
	fi;
        ;;
     try-restart)
	$0 stop && $0 start
	;;
     restart|force-reload)
	$0 stop
	$0 start
	;;
     reload)
	;;
     *)
	echo "Usage: $0 {start|stop|status|restart|reload|force-reload|try-restart}"
	exit 1
esac

exit $RETVAL

