#! /bin/bash
# chkconfig: 2345 16 84
# description: Start/Stop script for QLogic VNIC
#
### BEGIN INIT INFO
# Provides:       qlgc_vnic
# Required-Start: openibd
# Required-Stop:
# Default-Start:  2 3 5
# Default-Stop: 0 1 2 6
# Description:  Start/Stop for QLogic VNIC
### END INIT INFO
#
# Start, Stop, Restart the QLogic VNIC service
#
# Handles loading, unloading of the VNIC driver and triggers creation
# of the VNIC interfaces by invoking ib_qlgc_vnic_parser.pl, which parses the
# VNIC configuration file and creates the VNIC interfaces.
#
# Copyright (c) 2007 QLogic, Inc.  All rights reserved.
#
# This software is available to you under a choice of one of two
# licenses.  You may choose to be licensed under the terms of the GNU
# General Public License (GPL) Version 2, available from the file
# COPYING in the main directory of this source tree, or the
# OpenIB.org BSD license below:
#
#     Redistribution and use in source and binary forms, with or
#     without modification, are permitted provided that the following
#     conditions are met:
#
#      - Redistributions of source code must retain the above
#        copyright notice, this list of conditions and the following
#        disclaimer.
#
#      - Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials
#        provided with the distribution.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#
# config: /etc/infiniband/qlgc_vnic.cfg  (or /etc/sysconfig/qlogic_vnic.cfg or /etc/sysconfig/ics_inic.cfg)
# pidfile: /var/lock/subsys/qlgc_vnic

USE_DAEMON=1

DAEMON_USE_OPTIMIZATION=1

DAEMON_VERBOSITY=6
DAEMON_INTERVAL=60
DAEMON_FACTOR=5

QLGC_VNIC_PATH=$PATH:/sbin:/usr/bin
if [ -e /etc/profile.d/ofed.sh ]; then
        . /etc/profile.d/ofed.sh
fi

MODULE_IB=qlgc_vnic
CONFIG_FILE=/etc/infiniband/qlgc_vnic.cfg
CONFIG_FILE_OLD=/etc/infiniband/qlogic_vnic.cfg
ICS_INIC_CFG=/etc/sysconfig/ics_inic.cfg
SCRIPT="ib_qlgc_vnic_parser.pl -v -f"
IB_ENV=""
IB_SERVICE=""
ENV_INFINIPATH="InfiniPath"
ENV_OFED="OFED"
CHECK_MODULE=""
CONFIG_FILE_COPY=/tmp/qlgc_config
ACTIVE_INTERFACES=/tmp/qlgc_chk_interfaces

DAEMON_OPTIMIZE_OPTION="-o"


if [ -f /etc/init.d/functions ]; then
    . /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
    . /etc/rc.d/init.d/functions
elif [[ -e /sbin/start_daemon && -e /sbin/killproc ]]; then
#This case is for SLES systems where we implement the functions
#available in RHEL systems using the commands available on SLES.
	daemon()
    {
       path=`which $1`;
       dir=`dirname $path`;
	   dir=$dir"/";
	   cmd=$dir${1+"$@"};
       /sbin/start_daemon $cmd
	   ret=$?
	   if [ $ret -eq 0 ]; then
			echo_success
       else
			echo_failure
	   fi
	   return $ret
	}

	killproc()
	{
	   path=`which $1`;
	   dir=`dirname $path`;
	   dir=$dir"/";
	   cmd=$dir${1+"$@"};
	   /sbin/killproc $cmd 
	   ret=$?
	   if [ $ret -eq 0 ]; then
			echo_success
       else
			echo_failure
	   fi
	   return $ret
	}

#Implementing the subsys file part of RHEL status function
	status()
	{
		echo $1
		if [ -f /var/lock/subsys/$1 ]; then
	        return 2
    	fi
	}
else
	echo "Supporting tools for starting daemon not present. QLogic Dynamic update daemon will not be started"
	USE_DAEMON=0
fi

# /etc/init.d/functions which has been sourced in previous step modifies the
# shell's PATH variable, which is why QLogic VNIC binaries placed at location
# other than /sbin:/usr/sbin/ are not found.  Hence, VNIC retains the PATH
# variable set by openibd script.  We cannot do away with /etc/init.d/functions
# because "daemon" and "killproc" are obtained from that file.

PATH=$QLGC_VNIC_PATH

if [ -z "${BOOTUP:-}" ]; then
  if [ -f /etc/sysconfig/init ]; then
      . /etc/sysconfig/init
  else
    # This all seem confusing? Look in /etc/sysconfig/init,
    # or in /usr/doc/initscripts-*/sysconfig.txt
    BOOTUP=color
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \\033[0;39m"
    LOGLEVEL=1
  fi
  if [ "$CONSOLETYPE" = "serial" ]; then
      BOOTUP=serial
      MOVE_TO_COL=
      SETCOLOR_SUCCESS=
      SETCOLOR_FAILURE=
      SETCOLOR_WARNING=
      SETCOLOR_NORMAL=
  fi
fi

if [ "${BOOTUP:-}" != "verbose" ]; then
   INITLOG_ARGS="-q"
else
   INITLOG_ARGS=
fi


test -f  || exit 0

echo_success() {
  echo -n $@
  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
  echo -n "[  "
  [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
  echo -n $"OK"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo -n "  ]"
  echo -e "\r"
  return 0
}

echo_failure() {
  echo -n $@
  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
  echo -n "["
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo -n $"FAILED"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo -n "]"
  echo -e "\r"
  return 1
}

echo_log() {
	logger "$@" -p user.err
	echo "Please refer to /var/log/messages"	
}

print_status()
{
	if [ $1 -eq 0 ]
	then
		echo_log "Success"
	else
		echo_log "Failure"
	fi
	echo_log ""
}

load_module()
{
	
	if lsmod | grep "^$*" >/dev/null 2>&1 ; then
		return 0;
	fi		
	# try to silently load
	modprobe $* >/dev/null 2>&1
	res=$?
	
	if [ $res != 0 ]
	then
		# if fails, try again and log failures
		modprobe $* 2>&1|logger -s -p kern.err
		res=$?
	fi
	return $res
}

function set_environment()
{
    if [ -f /etc/init.d/infinipath  ]
    then
        IB_ENV="$ENV_INFINIPATH"
		IB_SERVICE=infinipath
		CHECK_MODULE=ipath
    else
        if [  -f /etc/init.d/openibd  ]
        then
            IB_ENV="$ENV_OFED"
			IB_SERVICE=openibd
			CHECK_MODULE=umad
        else
            echo "Your InfiniBand Stack has not properly been installed"
            return 1
        fi
    fi

	return 0
}

function load_modules()
{
	# Check whether $IB_SERVICE is running

	# We check for modules we depend on - first up - ib_core
	IB_SERVICE_STARTED=`lsmod | grep ib_core`
	if [ "x$IB_SERVICE_STARTED" != "x" ]
	then
		IB_SERVICE_STARTED=`lsmod | grep ib_cm`
	fi

	# If service has not been started, start it

	if [ "x$IB_SERVICE_STARTED" == "x" ]
	then
		service $IB_SERVICE start
		if [ $? -ne 0 ]
		then
			echo "service start $IB_SERVICE returned errors" >&2
			IB_SERVICE_STARTED=`lsmod | grep ib_core`
			if [ "x$IB_SERVICE_STARTED" == "x" ]
			then
				echo "Cannot start qlgc_vnic service" >&2
				exit 1
			fi
			echo "may be ok to continue....." >&2
		fi
	fi

	load_module $MODULE_IB
	res=$?
	if [ $res != 0 ] ; then
		modprobe -r $MODULE_IB > /dev/null 2>&1
		return 1
	fi
	return 0
}

function unload_config()
{
	ifconfig  >$ACTIVE_INTERFACES
	if [ -f $CONFIG_FILE_COPY ] ; then
		grep -v "^#" $CONFIG_FILE_COPY | grep 'NAME' | sed "s/.*NAME[ ]*\=[ ]*\"\([ a-zA-Z0-9]*\)\"\;.*/\1/" |
		while read i
		do
			if grep -q $i $ACTIVE_INTERFACES; then
				ifdown $i >& /dev/null	
			fi
		done
	fi
	rm -rf $ACTIVE_INTERFACES
}


function remove_modules()
{
	modprobe -r $MODULE_IB

	echo_success		
}

function start_hotswap_daemon()
{
        echo -n "Starting QLogic VNIC Dynamic Update Daemon "
	if [ $DAEMON_USE_OPTIMIZATION -eq 1 ] 
	then
	        daemon ib_qlgc_vnic_update -d -v $DAEMON_VERBOSITY -t $DAEMON_INTERVAL -f $DAEMON_FACTOR $DAEMON_OPTIMIZE_OPTION 
	else
	        daemon ib_qlgc_vnic_update -d -v $DAEMON_VERBOSITY -t $DAEMON_INTERVAL -f $DAEMON_FACTOR 
	fi

        res=$?

        if [ $res != 0 ]; then
                echo "Could not start dynamic update daemon for qlgc_vnic"
                echo_log "Try starting daemon manually by running command"
        else
                touch /var/lock/subsys/ib_qlgc_vnic_update
        fi

        return $res
}

function stop_hotswap_daemon()
{
        echo -n "Stopping QLogic VNIC Dynamic Update Daemon "
        killproc ib_qlgc_vnic_update
        res=$?
        status ib_qlgc_vnic_update >/dev/null 2>&1 || rm -f /var/lock/subsys/ib_qlgc_vnic_update
        return $res 
}

function start()
{
# load modules
    echo -n "Starting QLogic Virtual NIC"
    if load_modules ; then
 	echo_success
	echo -n "Parsing Configuration file"
        # load the configuration
	$SCRIPT > /dev/null 2>&1
	res=$?	
	    	 
	if [ $res = 127 ]; then
		echo_failure	
		echo_log "Cannot execute $SCRIPT"
		return
	fi
	if [ $res != 0 ]; then
		echo_failure
		echo_log "$0: Error in configuring QLogic VNIC"
	else
		echo_success
		if [ -f $CONFIG_FILE ]; then
			cat $CONFIG_FILE > $CONFIG_FILE_COPY
		elif [ -f $CONFIG_FILE_OLD ]; then
			cat $CONFIG_FILE_OLD > $CONFIG_FILE_COPY
		else 
			if [ -f $ICS_INIC_CFG ]; then
				cat $ICS_INIC_CFG > $CONFIG_FILE_COPY
			fi
		fi
   	fi  			
	touch /var/lock/subsys/qlgc_vnic
	if [ $USE_DAEMON -eq 1 ]; then
		start_hotswap_daemon
	fi
     else
		echo_failure
		echo_error "$0: Loading kernel modules failed"
	
    fi
}

function stop()
{
	if [ $USE_DAEMON -eq 1 ]; then
		stop_hotswap_daemon
	fi
	echo -n "Stopping QLogic Virtual NIC" 
	unload_config
	remove_modules	
	rm -f /var/lock/subsys/qlgc_vnic
	rm -f $CONFIG_FILE_COPY		
}

function restart()
{
	stop
	start
}

set_environment
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    *)
       echo_log $"Usage: $0 {start|stop|restart}"
       exit 1
esac

exit 0
