#!/bin/bash
#
# Bring up/down opensm
#
# chkconfig: - 15 85
# description: Activates/Deactivates InfiniBand Subnet Manager
#
### BEGIN INIT INFO
# Provides:       opensm
### END INIT INFO
#
# Copyright (c) 2006 Mellanox Technologies. All rights reserved.
#
# This Software is licensed under one of the following licenses:
#
# 1) under the terms of the "Common Public License 1.0" a copy of which is
#    available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/cpl.php.
#
# 2) under the terms of the "The BSD License" a copy of which is
#    available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/bsd-license.php.
#
# 3) under the terms of the "GNU General Public License (GPL) Version 2" a
#    copy of which is available from the Open Source Initiative, see
#    http://www.opensource.org/licenses/gpl-license.php.
#
# Licensee has the right to choose one of the above licenses.
#
# Redistributions of source code must retain the above copyright
# notice and one of the license notices.
#
# Redistributions in binary form must reproduce both the above copyright
# notice, one of the license notices in the documentation
# and/or other materials provided with the distribution.
#
#
#  $Id: opensm.initd,v 1.2 2008/04/11 17:23:53 dledford Exp $
#
# processname: /usr/sbin/opensm
# config: /etc/ofed/opensm.conf
# pidfile: /var/run/opensm.pid
. /etc/rc.d/init.d/functions

CONFIG=/etc/ofed/opensm.conf

prog=/usr/sbin/opensm
bin=${prog##*/}

# Handover daemon for updating guid2lid cache file
sldd_prog=/usr/sbin/sldd.sh
sldd_bin=${sldd_prog##*/}
sldd_pid_file=/var/run/sldd.pid

ACTION=$1

# Setting OpenSM start parameters
PID_FILE=/var/run/${bin}.pid



#########################################################################
   
start_sldd()
{
    if [ -f $sldd_pid_file ]; then
            local line p
            read line < $sldd_pid_file
            for p in $line ; do
                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p"
            done
    fi

    if [ -z "$sldd_pid" ]; then
        sldd_pid=`pidof -x $sldd_bin`
    fi

    if [ -n "${sldd_pid:-}" ] ; then
	kill -9 ${sldd_pid} > /dev/null 2>&1
    fi

    $sldd_prog > /dev/null 2>&1 &
    sldd_pid=$!

    echo ${sldd_pid} > $sldd_pid_file
    # Sleep is needed in order to update local gid2lid cache file before running opensm
    sleep 3
}

stop_sldd()
{
    if [ -f $sldd_pid_file ]; then
            local line p
            read line < $sldd_pid_file
            for p in $line ; do
                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p"
            done
    fi

    if [ -z "$sldd_pid" ]; then
        sldd_pid=`pidof -x $sldd_bin`
    fi

    if [ -n "${sldd_pid:-}" ] ; then
        kill -15 ${sldd_pid} > /dev/null 2>&1
    fi

}

start()
{
    local OSM_PID=
    if [ ! -f $CONFIG ]; then
        echo -n "Starting IB Subnet Manager: $CONFIG missing" 
        echo_failure
        return 6
    fi
    . $CONFIG
if [[ -z $DEBUG || "$DEBUG" == "none" ]]; then
    DEBUG_FLAG=""
else
    DEBUG_FLAG="-d ${DEBUG}"
fi

if [[ -z $LMC || "$LMC" == "0" ]]; then
    LMC_FLAG=""
else
    LMC_FLAG="-l ${LMC}"
fi

if [[ -z $MAXSMPS ]]; then
    MAXSMPS_FLAG=""
else
    MAXSMPS_FLAG="-maxsmps ${MAXSMPS}"
fi

if [[ -z $REASSIGN_LIDS || "$REASSIGN_LIDS" == "no" ]]; then
    REASSIGN_LIDS_FLAG=""
else
    REASSIGN_LIDS_FLAG="-r"
fi

if [[ -z $SWEEP || "$SWEEP" == "10" ]]; then
    SWEEP_FLAG=""
else
    SWEEP_FLAG="-s ${SWEEP}"
fi

if [[ -z $TIMEOUT || "$TIMEOUT" == "100" ]]; then
    TIMEOUT_FLAG=""
else
    TIMEOUT_FLAG="-t ${TIMEOUT}"
fi

if [[ -z $OSM_LOG || "$OSM_LOG" == "/tmp/osm.log" ]]; then
    OSM_LOG_FLAG=""
else
    OSM_LOG_FLAG="-f ${OSM_LOG}"
fi

if [[ -z $VERBOSE || "$VERBOSE" == "none" ]]; then
    VERBOSE_FLAG=""
else
    VERBOSE_FLAG="${VERBOSE}"
fi

if [[ -z $UPDN || "$UPDN" == "off" ]]; then
    UPDN_FLAG=""
else
    UPDN_FLAG="-u"
fi

if [[ -z $GUID_FILE || "$GUID_FILE" == "none" ]]; then
    GUID_FILE_FLAG=""
else
    GUID_FILE_FLAG="-a ${GUID_FILE}"
fi

if [[ -z $GUID || "$GUID" == "none" ]]; then
    GUID_FLAG=""
else
    GUID_FLAG="-g ${GUID}"
fi

if [[ -z $HONORE_GUID2LID || "$HONORE_GUID2LID" == "none" ]]; then
    HONORE_GUID2LID_FLAG=""
else
    HONORE_GUID2LID_FLAG="--honor_guid2lid"
fi

if [[ -n "${OSM_HOSTS}" && $(echo -n ${OSM_HOSTS} | wc -w | tr -d '[:space:]') -gt 1  ]]; then
    HONORE_GUID2LID_FLAG="--honor_guid2lid"
fi


if [[ -z $CACHE_OPTIONS || "$CACHE_OPTIONS" == "none" ]]; then
    CACHE_OPTIONS_FLAG=""
else
    CACHE_OPTIONS_FLAG="--cache-options"
fi


if [ -z $PORT_NUM ]; then
    PORT_FLAG=1
else
    PORT_FLAG="${PORT_NUM}"
fi

    
    echo -n "Starting IB Subnet Manager" 
    if [ -f $PID_FILE ]; then
            local line p
            read line < $PID_FILE
            for p in $line ; do
                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p"
            done
    fi
    
    if [ -z "$pid" ]; then
        pid=`pidof -o $$ -o $PPID -o %PPID -x $bin`
    fi
    
    if [ -n "${pid:-}" ] ; then
        echo_success
	echo
	return 0
    else    

	if [ -n "${HONORE_GUID2LID_FLAG}" ]; then
		# Run sldd daemod
		start_sldd
	fi

        # Start opensm
        local START_FLAGS=""
        for flag in "$DEBUG_FLAG" "$LMC_FLAG" "$MAXSMPS_FLAG" "$REASSIGN_LIDS_FLAG" "$SWEEP_FLAG" "$TIMEOUT_FLAG" "$OSM_LOG_FLAG" "$VERBOSE_FLAG" "$UPDN_FLAG" "$GUID_FILE_FLAG" "$GUID_FLAG" "$HONORE_GUID2LID_FLAG" "$CACHE_OPTIONS_FLAG"
        do
            [ ! -z "$flag" ] && START_FLAGS="$START_FLAGS $flag"
        done
       
        echo $PORT_FLAG | $prog $START_FLAGS > /dev/null 2>&1 &
        OSM_PID=$!
        echo $OSM_PID > $PID_FILE
	sleep 1        
        checkpid $OSM_PID
        RC=$?
        [ $RC -eq 0 ] && echo_success || echo_failure
        [ $RC -eq 0 ] && touch /var/lock/subsys/opensmd
	echo
    fi
    return $RC    
}

stop()
{
    local pid=
    local pid1=
    local pid2=

    echo -n "Stopping IB Subnet Manager."
    # Stop sldd daemon
    stop_sldd

    if [ -f $PID_FILE ]; then
            local line p
            read line < $PID_FILE
            for p in $line ; do
                    [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid1="$pid1 $p"
            done
    fi
    
    pid2=`pidof -o $$ -o $PPID -o %PPID -x $bin`
    
    pid=`echo "$pid1 $pid2" | sed -e 's/\ /\n/g' | sort -n | uniq | sed -e 's/\n/\ /g'`              
    
    if [ -n "${pid:-}" ] ; then
        # Kill opensm
        kill -15 $pid > /dev/null 2>&1
	cnt=0
        while [ $cnt -lt 6 ]; do echo -n "."; sleep 1; let cnt++;done

        for p in $pid
        do
            while checkpid $p ; do
                kill -KILL $p > /dev/null 2>&1
                echo -n "+"
                sleep 1
            done
        done
        checkpid $pid
        DEAD=$?
        if [ $DEAD -eq 0 ]; then
	    echo_failure
	    echo
	    return 1
	fi
	echo_success 
	echo
    else
	echo_success 
	echo
    fi
 
    # Remove pid file if any.
    rm -f $PID_FILE
    rm -f /var/lock/subsys/opensmd
    return 0    
}

restart ()
{
	stop
	start
}

condrestart ()
{
	[ -f /var/lock/subsys/opensmd ] && restart || return 0
}

usage ()
{
	echo
	echo "Usage: `basename $0` {start|stop|restart|condrestart|try-restart|force-reload|status}"
	echo
	return 2
}

case $ACTION in
	start) start; RC=$? ;;
	stop) stop; RC=$? ;;
	restart) restart; RC=$? ;;
	reload) action $"Rescanning IB Subnet:" killall -HUP $prog; RC=$? ;;
	condrestart) condrestart; RC=$? ;;
	try-restart) condrestart; RC=$? ;;
	force-reload) condrestart; RC=$? ;;
	status) status $prog; RC=$? ;;
	*) usage; RC=$? ;;
esac

exit $RC
