#!/bin/bash

# QLogic FC HBA Change LUN State Utility
# Copyright (C) 2006 QLogic Corporation (www.qlogic.com)
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of 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.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#--------------------------------------------------------------------------# 
#This script is used to change the state of LUNS.
#The state of LUNS which are disabled can be changed using this script.
#This script is useful to enable the LUNS which were marked offline and are now
#online. However changing the state from offline to online does not gurantee that
#the LUN will become online.
#---------------------------------------------------------------------------#

QL_SUCCESS=0
QL_FAIL=1
QL_CALL_AGAIN=2
QL_CALL_RETURNED=3
QL_COMMON=0
QL_INVALID=4
all_targets=()
HOST=()
QLU_VERSION=1.7
QL_FLAG=0
#*****************************************#
# echo_b()		                  #
# Prints messages in bold		  #
# Parameter: 				  #
#	$1	Message to be printed     #
# Returns: None.                          #
#*****************************************#

function echo_b() {
	echo -e "\033[1m${1}\033[0m"
	tput sgr0
}


#*****************************************#
# change_lun_state ()                     #
# checks for all LUNS which are offline   #
# and changes their status to running     #
# or online,                              #
# PARAMETERS : NONE                       #
# RETURNS : $STATUS                       #
#*****************************************#

function change_lun_state ()

{

for SEL_HOST in ${HOST[@]}
do
	STATUS=$QL_CALL_AGAIN
	ls /sys/bus/pci/drivers/qla*/*/host$SEL_HOST &> /dev/null
	if [ $? -ne 0 ]; then
		echo ""
		echo "HOST $SEL_HOST is not a QLogic HBA."
	STATUS=$QL_INVALID
	else		
	ls $SEL_HOST:0:* &> /dev/null
	if  [ $? -ne 0 ]; then 
		echo ""
		echo "No Targets connected to host $SEL_HOST"
		echo ""
		STATUS=$QL_INVALID
	fi
	fi
	if [ $STATUS -ne $QL_INVALID ]; then
	
	for DEVICE in `ls -d $SEL_HOST*`
	do
	LUN=`echo $DEVICE | cut -d : -f 4`
		cd $DEVICE/device
		if [ -e state ]; then # change state file for REDHAT
			if [ `cat state` == "offline" ]; then
				echo ""
				echo "Found LUN $LUN on HOST $SEL_HOST in offline state"
				echo "Modifying to running"
				echo running > state
				QL_FLAG=1
			fi
		elif [ -e online ]; then
			if [ `cat online` == "0" ]; then
				echo ""
				echo "Found LUN $LUN on HOST $SEL_HOST in offline state"
				echo "Modifying to running"
				echo 1 > online
				echo 1 > rescan
				QL_FLAG=1
			fi
		else
			echo "Sysfs attribute state/online not found"
		fi
		cd ../..
	done	
	fi
done
	if [ $QL_FLAG == 0 ];  then
		echo "No Offline LUNs found"
	fi
return $QL_CALL_RETURNED
}


#*****************************************#
# display_help ()                         #
# Prints the help message on screen       #
# PARAMETERS : NONE                       #
# RETURNS : NONE                          #
#*****************************************#


function display_help ()
{
	clear
        echo ""
        echo_b "QLogic Linux LUN STATE Change Utility v$QLU_VERSION"
        echo ""
        echo ""
        echo "Usage: $0 [OPTIONS]"
	echo ""
	echo "OPTIONS :"
	echo ""
	echo "  HOST NUMBER/S"
	echo "               The QLogic LUN STATE change utility"
	echo "               scans for all offline LUNs on the "
	echo "               Specified HOSTS and enables them"

	echo ""
        echo  "  -a,  --all "
        echo "               The QLogic LUN STATE change utility "
	echo "               enables all disabled LUNS "
        echo ""                        
        echo  "  -i,  --interactive"
        echo "               Use this option to use the menu driven program"
	echo ""
        echo  "  -h,  --help, ?"
	echo "               Prints this help message"
	echo ""
	exit 0

}

#*****************************************#
# qlu_hit_any_key()
# Waits for user to hit a key
# PARAMETERS : NONE
# RETURNS        : None
#*****************************************#
function qlu_hit_any_key()
{
        echo -n "Hit any key to continue......"
        read -n 1
        clear
}




#*****************************************#
# qlu_main_screen ()                      #
# Prints the interactive screen and  reads#
# input from user                         #
# PARAMETERS : NONE                       #
# RETURNS : NONE                          #
#*****************************************#


function qlu_main_screen ()
{
clear
OFF_LUNS=()
ALL_HOSTS=( `ls -d /sys/bus/pci/drivers/qla*/*/host* | sed -e "s/.*host//"` )
for O_HOST in ${ALL_HOSTS[@]}
do
ls $O_HOST:0:* &> /dev/null
if  [ $? -eq 0 ]; then 
	# if we are here then targets are connnected to host
	# Now scan targets
	for LUNS in `ls -d $O_HOST*`	
	do
		
		if [ -e "$LUNS/device/state" ] && [ "`cat $LUNS/device/state`" == "offline" ]; then
			OFF_LUNS=(${OFF_LUNS[@]} $LUNS)
		elif [ -e "$LUNS/device/online" ] && [ "`cat $LUNS/device/online`" == "0" ]; then
			OFF_LUNS=(${OFF_LUNS[@]} $LUNS)
		fi
	done
fi
done
LN=1 # line number
echo_b  "Welcome to QLogic LUN State Change Utility"
echo "============================================"
echo ""
if [ ${#OFF_LUNS[@]} -gt 0 ]; then
	echo "MAIN MENU"
fi
for O_LUNS in ${OFF_LUNS[@]}
do
	echo -n "	$LN. "
	echo $O_LUNS | sed "s/\([[:digit:]]\+\):[[:digit:]]\+:\([[:digit:]]\+\):\([[:digit:]]\+\)/HOST: \1 TGT: \2 LUN: \3/"
	LN=$((LN+1))
done
if [ $LN -eq 1 ]; then
	echo "NO OFFLINE LUNS FOUND "
	echo "Exiting $0 ..."
	exit 0
fi
echo "	$LN. MAKE ALL ONLINE "
echo "	$((LN+1)). QUIT"
echo ""
echo -n "Please select any one option : "
read SC1_CHOICE
case $SC1_CHOICE in
	q | quit | x )
	exit 0
	;;
	* )
	echo $SC1_CHOICE | grep -w "^[0-9]\+$" >& /dev/null
	if [ $? -ne 0 ]; then
	return $QL_CALL_AGAIN	
	fi

esac 
if [ $SC1_CHOICE -ge 1 ] && [ $SC1_CHOICE -lt $LN ]; then
	cd ${OFF_LUNS[((${SC1_CHOICE}-1))]}/device
		if [ -e "./state" ]; then # change state file for REDHAT/SLES10
			echo running > state
			echo -n "Modifying to running "
			echo ${OFF_LUNS[((${SC1_CHOICE}-1))]} | sed "s/\([[:digit:]]\+\):[[:digit:]]\+:\([[:digit:]]\+\):\([[:digit:]        ]\+\)/HOST: \1 TGT: \2 LUN: \3/"
		
		elif [ -e "./online" ]; then #for SLES9
				
			echo -n "Modifying online state to 1 for "
                        echo ${OFF_LUNS[((${SC1_CHOICE}-1))]} | sed "s/\([[:digit:]]\+\):[[:digit:]]\+:\([[:digit:]]\+\):\([[:digit:]        ]\+\)/HOST: \1 TGT: \2 LUN: \3/"

			echo 1 > online
			echo 1 > rescan

		else
			echo "Sysfs attribute state/online not found"
		fi
	cd ../..
	qlu_hit_any_key
	return $QL_CALL_AGAIN
elif [ $SC1_CHOICE -eq $LN ]; then
	HOST=( `ls -d /sys/bus/pci/drivers/qla*/*/host* | sed -e "s/.*host//"` )
	change_lun_state 
	return $?
elif [ $SC1_CHOICE -eq $((LN+1)) ]; then
	exit 0
else 
	return $QL_CALL_AGAIN
fi
}



# Start
cd /sys/class/scsi_device
HOST=$*
case $HOST in 

	--all | -a )
	
	HOST=( `ls -d /sys/bus/pci/drivers/qla*/*/host* | sed -e "s/.*host//"` )
	change_lun_state
	;;
	
	-i | --interactive )
	STATUS=$QL_CALL_AGAIN
	clear
	while [ $STATUS -eq $QL_CALL_AGAIN ]
	do
	qlu_main_screen
	STATUS=$?
	done
	exit 0

	;;
	--help | -h | "?" )

	display_help
	;;
	*)
	echo $1 | grep -w "^[0-9]\+$" >& /dev/null
	if [ $? -ne 0 ]; then
	echo ""
	echo "Please enter a valid argument"
	echo "		OR"
	echo "Please run $0 -h for help"
	echo ""
	exit 1
	fi
	change_lun_state
	;;
esac

