#!/bin/bash
# init script for Xsigo services.  
#

# legacy chkconfig for older systems
# chkconfig: 345 09 90
# description: Load and unload Xsigo host modules

# full chkconfig info for newer systems
### BEGIN INIT INFO
# Provides:          xsigo
# Should-Start:
# Required-Start:
# Required-Stop:
# Should-Stop:
# Default-Start:     3 4 5
# Default-Stop:      0 1 2 4 6
# Short-Description: Loads and unloads the Xsigo modules
# Description:       Loads and unloads the Xsigo modules which are required for Xsigo virtual services
### END INIT INFO

redhat=0
BONDING_MODULE=bonding

# Source function library for Redhat
if [ -f /etc/rc.d/init.d/functions ]
then
	. /etc/rc.d/init.d/functions
	redhat=1
fi

# Source any Xsigo definitions
if [ -f /etc/sysconfig/xsigo ]
then
    . /etc/sysconfig/xsigo
fi

MODPROBE=/sbin/modprobe
RMMOD=/sbin/rmmod
UNAME_R=`uname -r`

XEN=false

if echo ${UNAME_R}|grep -q xen; then
   XEN=true
else
   XEN=false
fi

# this is the rhel5 'action' function.  The one in rhel4 doesn't allow the
# passing of functions as its arg
action_redhat() {
  local STRING cmd rc

  cmd=$1
  shift 1
  STRING="$@"
  echo -n "$STRING "
  if [ "${RHGB_STARTED:-}" != "" -a -w /etc/rhgb/temp/rhgb-console ]; then
      echo -n "$STRING " > /etc/rhgb/temp/rhgb-console
  fi
  "$cmd" && success $"$STRING" || failure $"$STRING"
  rc=$?
  echo
  if [ "${RHGB_STARTED:-}" != "" -a -w /etc/rhgb/temp/rhgb-console ]; then
      if [ "$rc" = "0" ]; then
        echo_success > /etc/rhgb/temp/rhgb-console
      else
        echo_failure > /etc/rhgb/temp/rhgb-console
    [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=yes
      fi
      echo > /etc/rhgb/temp/rhgb-console
  fi
  return $rc
}

action_generic() {
	local STRING cmd rc

	cmd=$1
	shift 1
	STRING="$@"
	echo -n "$STRING "
	"$cmd"
	rc=$?

	if [ $rc -eq 0 ]
	then
		echo -e "done"
	else
		echo -e "failed [$rc]"
	fi
	return $rc
}

action() {
	if [ $redhat -eq 1 ]
	then
		action_redhat $*
        	return $?
	else
		action_generic $*
		return $?
	fi
}
	
load_modules() {
	# Check to see if we need to regenerate the uuid
	SYSTEM_UUID=$(dmidecode -t system 2>/dev/null|grep UUID:|cut -f2 -d:|sed -e 's/-//g')
	if echo $SYSTEM_UUID | grep -i Settable  > /dev/null
	then
		SYSTEM_UUID=`hostid`
	else
		SYSTEM_UUID=$(echo $SYSTEM_UUID | tr [:upper:] [:lower:] 2>/dev/null)
	fi
	if [ "${XSIGO_ENABLE_VNIC}" != "no" ] || \
	   [ "${XSIGO_ENABLE_VHBA}" != "no" ]; then
		$MODPROBE mlx4_ib
		$MODPROBE ib_cm && $MODPROBE ib_sa
		if [ ! -z "${SYSTEM_UUID}" ]; then
			MODOPT="system_id=${SYSTEM_UUID}"
		fi
		$MODPROBE xscore boot_flag=0 $MODOPT
	fi
	if [ "${XSIGO_ENABLE_VNIC}" != "no" ]; then
		is_module_loaded $BONDING_MODULE
		if [ $? -gt 0 ]; then
			modprobe $BONDING_MODULE
		fi
		$MODPROBE xsvnic
	fi

	if [ "${XSIGO_ENABLE_XVE}" != "no" ]; then
		$MODPROBE xve
	fi

	vhba_options=""
	if [ "${XSIGO_ENABLE_FMR}" == "no" ]; then
		vhba_options="vhba_use_fmr=0"
	fi
	if [ "${XSIGO_ENABLE_VHBA}" != "no" ]; then
		$MODPROBE xsvhba ${vhba_options}
	fi
}

start() {
	action load_modules $"Loading Xsigo modules: "
	if [ "${XSIGO_ENABLE_USERSPACE}" != "no" ]; 
	then
		action load_xsigod $"Starting Xsigo services: "
		#
		# Sleep here for VNICS to show up and settle down
		#
		sleep 10
	else
		/opt/xsigo/bin/xsmaster.sh systemid
		/opt/xsigo/bin/xsmaster.sh hostname
	fi
}

try_and_unload() {
	module=$1
	if [ ! -z "`lsmod | grep $module`" ]
	then
		$RMMOD $module 2> /dev/null
		return $?
	fi
	return 0
}
	
unload_modules() {
	try_and_unload xsvhba
	if [ $? -gt 0 ]
	then
		echo "Could not unload xsvhba"
		return 1
	fi

	try_and_unload xsvnic
	if [ $? -gt 0 ]
	then
		echo "Could not unload xsvnic"
		return 1
	fi

	try_and_unload xve
	if [ $? -gt 0 ]
	then
		echo "Could not unload xve"
		return 1
	fi

	try_and_unload xscore 
	if [ $? -gt 0 ]
	then
		echo "Could not unload xscore"
		return 1
	fi
}

stop() {
	action unload_xsigod $"Stopping Xsigo services: "
	action unload_modules $"Unloading Xsigo modules: "
}

load_vnic() {
	$MODPROBE xsvnic
}

unload_vnic() {
	$RMMOD xsvnic 2> /dev/null
}

load_xve() {
	$MODPROBE xve
}

unload_xve() {
	$RMMOD xve 2> /dev/null
}

load_vhba() {
	$MODPROBE xsvhba
}

unload_vhba() {
	$RMMOD xsvhba 2> /dev/null
}

start_xsigod() {
	# Make sure xend starts first, if it does exist
	if [ "$XEN" == "true" ]; then
    		time_spent=0
    		xend_status=1
    		while [ $xend_status -gt 0 -a $time_spent -lt 10 ]
    		do
        		/bin/sleep 1
        		x=`ps aux | grep xend | grep -v grep | wc -l`
        		if [ $x != 0 ] ; then
            			xend_status=0
        		fi
        		time_spent=`/usr/bin/expr $time_spent + 1`
    		done
	fi

	y=`ps aux | grep "/opt/xsigo/sbin/xsigod" | grep -v grep | wc -l`
	if [ $y == 0 ] ; then
		if [ ! -e "/dev/kxsigod" ]; then
			/sbin/udevstart > /dev/null 2>&1
		fi
		/bin/sleep 5
		if [ "$XEN" == "true" ]; then
			/opt/xsigo/sbin/xsigod.xen >/dev/null
		else
			/opt/xsigo/sbin/xsigod >/dev/null
		fi
	fi
}

load_xsigod() {
	time_spent=0
	while [ ! -e /dev/kxsigod -a $time_spent -lt 10 ]
	do
    		/bin/sleep 1
    		time_spent=`/usr/bin/expr $time_spent + 1`
	done

	start_xsigod

	# Save the max pid for reference
	ps aux | grep xsigod | awk '{ print $2 }' | head -1 > /var/run/xsigod.maxpid
}

unload_xsigod() {
	killall xsigod 2> /dev/null

	for vnic in `ls /proc/driver/xsvnic/devices/ 2> /dev/null`
	do
		if [ -e /var/run/dhclient-$vnic.pid ] ; then
			pid=`cat /var/run/dhclient-$vnic.pid`
			kill -9 $pid
		fi
		if [ -e /var/run/dhcpcd-$vnic.pid ] ; then
			pid=`cat /var/run/dhcpcd-$vnic.pid`
			kill -9 $pid
		fi
	done

	touch /var/run/xsigod.maxpid
	maxpid=`cat /var/run/xsigod.maxpid`
	if [ -z $maxpid ]
	then
		return 0
	fi

	for pid in `ps aux | egrep "dhclient|dhcpcd" | awk '{ print $2 }'`
	do
		if [ $pid -gt $maxpid ]
		then
			kill -9 $pid 2> /dev/null
		fi
	done

	return 0
}

unloadall() {
	stop
	
	# Don't go any further if our drivers could not be unloaded
	if [ $? -gt 0 ]
	then
		echo -n "Could not unload all Xsigo drivers, "
		echo "'unloadall' could not complete"
		return 1
	fi

	$RMMOD ib_ipoib 2> /dev/null
	$RMMOD ib_ucm 2> /dev/null
	$RMMOD ib_iser 2> /dev/null
	$RMMOD ib_ucm 2> /dev/null
	$RMMOD rdma_ucm 2> /dev/null
	$RMMOD rdma_cm 2> /dev/null
	$RMMOD ib_local_sa 2> /dev/null
	$RMMOD ib_addr 2> /dev/null
	$RMMOD ib_uverbs 2> /dev/null
	$RMMOD ib_ping 2> /dev/null
	$RMMOD ib_uverbs 2> /dev/null
	$RMMOD ib_umad 2> /dev/null
	$RMMOD ib_cm 2> /dev/null
	$RMMOD ib_sa 2> /dev/null
	$RMMOD mlx4_ib 2> /dev/null
	$RMMOD mlx4_core 2> /dev/null
	$RMMOD ib_mad 2> /dev/null
	$RMMOD ib_core 2> /dev/null
}

is_module_loaded() {
    modname=$1
    if grep $modname /proc/modules 2<&1 >/dev/null ; then
        return 0
    else
        return 1
    fi
}

status() {
    xsigod_pid=`pidof xsigod`
    if [ "$?" -eq 0 ] ; then
        echo "xsigod is running"
    else
        echo "xsigod is not running"
    fi

    for mod in xsvnic xve xsvhba mlx4_ib mlx4_core xscore; do
        if is_module_loaded $mod ; then
            echo "Module $mod is loaded"
        else
            echo "Module $mod is not loaded"
        fi
    done
}

case "$1" in
    start)
	start
	;;
    stop)
	stop
	;;
    restart)
	stop
	start
	;;
    reload)
	stop
	start
        ;;
    load_modules)
	action load_modules $"Loading Xsigo modules: "
	;;
    load_vnic)
	load_vnic
	;;
    unload_vnic)
	unload_vnic
	;;
    load_vhba)
	load_vhba
	;;
    unload_vhba)
	unload_vhba
	;;
    load_xsigod)
	load_xsigod
	;;
    unload_xsigod)
	unload_xsigod
	;;
    unloadall)
	unloadall
	;;
    reloadall)
	unloadall
	start
        ;;
    status)
        status
        ;;
    *)
	echo $"Usage: $0 {start|stop|restart|reload|load_vnic|unload_vnic|load_vhba|unload_vhba|load_xsigod|unload_xsigod|unloadall|reloadall|status}"
	;;
esac
exit $RETVAL
