#!/bin/sh
###############################################
#
# Nagios script to check I/O statistics
#
# NOTE: Requires kernel 2.4 or higher 
# 
# See usage for command line switches
# 
# Created: 2007-06-27 (i.yates@uea.ac.uk)
# Updated: 2007-07-27 (i.yates@uea.ac.uk)
# Updated: 2007-10-29 (i.yates@uea.ac.uk) - Fixed typos in usage!
# Updated: 2008-03-26 (i.yates@uea.ac.uk) - Fixed bug in critical/warning level checking which could result in erroneous results.  Thanks to Drew Sudell for pointing this out!
# Updated: 2008-11-21 (kseever@in-kc.com) - Rewrote entire script to meet our needs
#
###############################################

. /usr/lib/nagios/plugins/utils.sh


VERSION="1.2"

IOSTAT=/usr/bin/iostat
GREP=/bin/grep
AWK=/usr/bin/awk

TPS_LEVEL_WARN=""
TPS_LEVEL_CRIT=""
READS_LEVEL_WARN=""
READS_LEVEL_CRIT=""
WRITES_LEVEL_CRIT=""
WRITES_LEVEL_CRIT=""
RESULT=""
RESULT_STATUS=""
RESULT_TPS=""
RESULT_READS=""
RESULT_WRITES=""
PERF=""
PERF_TPS=""
PERF_READS=""
PERF_WRITES=""
EXIT_STATUS=$STATE_OK
EXIT_STATUS_TPS=$STATE_OK
EXIT_STATUS_READS=$STATE_OK
EXIT_STATUS_WRITES=$STATE_OK
READSS_HISTORY=0
WRITESS_HISTORY=0

###############################################
#
## FUNCTIONS 
#

## Print usage
usage() {
	echo " check_iostat $VERSION - Nagios I/O statistics check script"
	echo ""
	echo " Usage: check_iostat -w <warning value> -c <critical value> -d <device> ] [ -h ]"
	echo ""
	echo "		-w  Warning trigger levels READS/WRITES"
	echo "		-c  Critical trigger levels READS/WRITES"
	echo "		-d  Device"
	echo "		-h  Show this page"
	echo ""
}
 
## Process command line options
doopts() {
	if ( `test 0 -lt $#` )
	then
		while getopts ":w:c:d:h:" myarg "$@"
		do
			case $myarg in
				h|\?)
					usage
					exit;;
				w)
					LEVEL_WARN="$OPTARG";;
				c)
					LEVEL_CRIT="$OPTARG";;
				d)	
					DEVICE="$OPTARG";;
				*)	# Default
					usage
					exit;;
			esac
		done
		shift `expr $OPTIND - 1`
	else
		usage
		exit
	fi
}


# Write output and return result
theend() {
	echo "$RESULT_STATUS: $RESULT |$PERF"
	exit $EXIT_STATUS
}


#
## END FUNCTIONS 
#

#############################################
#
## MAIN 
#


# Handle command line options
doopts $@

# Do the do
FIRST_RUN=$(if test -f "/tmp/$DEVICE.readsio" && test -f "/tmp/$DEVICE.readsio"; then echo "false"; else echo "true"; fi)
OUTPUT=`$IOSTAT -k -d $DEVICE | $GREP $DEVICE`
TIMESTAMP=`date +%s`

if test -z "$OUTPUT" ; then
	RESULT="IOSTAT UNKNOWN - query returned no output!"
	EXIT_STATUS=$STATE_UNKNOWN
else
	## Handle Transactions per second
#	TPS=`echo $OUTPUT | $AWK '{print $2}'`
#	TPS_ABS=`echo $TPS | $AWK '{printf "%d",$1}'`

#	TPS_LEVEL_WARN=`echo $LEVEL_WARN | $AWK -F/ '{print $1}'`
#	TPS_LEVEL_CRIT=`echo $LEVEL_CRIT | $AWK -F/ '{print $1}'`	

#	RESULT_TPS="Transactions = $TPS"
#	PERF_TPS="TPS=$TPS;$TPS_LEVEL_WARN;$TPS_LEVEL_CRIT"
#	if test "$TPS_ABS" -lt "$TPS_LEVEL_WARN" ; then
#		EXIT_STATUS_TPS=$STATE_OK
#	else
#		if test "$TPS_ABS" -ge "$TPS_LEVEL_CRIT" ; then 
#			EXIT_STATUS_TPS=$STATE_CRITICAL
#		else
#			if test "$TPS_ABS" -ge "$TPS_LEVEL_WARN" ; then 
#				EXIT_STATUS_TPS=$STATE_WARNING
#			fi
#		fi
#	fi
#	
	READSS_CURRENT=`echo $OUTPUT | $AWK '{print $6}'`
	WRITESS_CURRENT=`echo $OUTPUT | $AWK '{print $7}'`
	if [ $FIRST_RUN = "false" ]; then
		## Handle Reads per second
		READSS_HISTORY=`cat /tmp/$DEVICE.readsio | $AWK -F"::" '{print $1}'`
		READSS_TIMESTAMP=`cat /tmp/$DEVICE.readsio | $AWK -F"::" '{print $2}'`
	
		if test "$READSS_CURRENT" -ge "$READSS_HISTORY" ; then
			TIMEVARIANCE=`expr $TIMESTAMP - $READSS_TIMESTAMP`
			READSSVARIANCE=`expr $READSS_CURRENT - $READSS_HISTORY`
		fi
	
		READSS=`expr $READSSVARIANCE / $TIMEVARIANCE`
		READSS_ABS=`echo $READSS | $AWK '{printf "%d",$1}'`
		
		READS_LEVEL_WARN=`echo $LEVEL_WARN | $AWK -F/ '{print $1}'`
		READS_LEVEL_CRIT=`echo $LEVEL_CRIT | $AWK -F/ '{print $1}'`	
	
		RESULT_READS="Reads = $READSS"
		PERF_READS="READS=$READSS;$READS_LEVEL_WARN;$READS_LEVEL_CRIT"
		if test "$READSS_ABS" -lt "$READS_LEVEL_WARN" ; then
			EXIT_STATUS_READS=$STATE_OK
		else
			if test "$READSS_ABS" -ge "$READS_LEVEL_CRIT" ; then 
				EXIT_STATUS_READS=$STATE_CRITICAL
			else
				if test "$READSS_ABS" -ge "$READS_LEVEL_WARN" ; then 
					EXIT_STATUS_READS=$STATE_WARNING
				fi
			fi
		fi
	
		## Handle Writes per second
		WRITESS_HISTORY=`cat /tmp/$DEVICE.writesio | $AWK -F"::" '{print $1}'`
		WRITESS_TIMESTAMP=`cat /tmp/$DEVICE.writesio | $AWK -F"::" '{print $2}'`
	
		if test "$WRITESS_CURRENT" -ge "$WRITESS_HISTORY" ; then
			TIMEVARIANCE=`expr $TIMESTAMP - $WRITESS_TIMESTAMP`
			WRITESSVARIANCE=`expr $WRITESS_CURRENT - $WRITESS_HISTORY`
		fi
	
		WRITESS=`expr $WRITESSVARIANCE / $TIMEVARIANCE` 
		WRITESS_ABS=`echo $WRITESS | $AWK '{printf "%d",$1}'`
		
	
	
		WRITES_LEVEL_WARN=`echo $LEVEL_WARN | $AWK -F/ '{print $2}'`
		WRITES_LEVEL_CRIT=`echo $LEVEL_CRIT | $AWK -F/ '{print $2}'`	
	
		RESULT_WRITES="Writes = $WRITESS"
		PERF_WRITES="WRITES=$WRITESS;$WRITES_LEVEL_WARN;$WRITES_LEVEL_CRIT"
		if test "$WRITESS_ABS" -lt "$WRITES_LEVEL_WARN" ; then
			EXIT_STATUS_WRITES=$STATE_OK
		else
			if test "$WRITESS_ABS" -ge "$WRITES_LEVEL_CRIT" ; then 
				EXIT_STATUS_WRITES=$STATE_CRITICAL
			else
				if test "$WRITESS_ABS" -ge "$WRITES_LEVEL_WARN" ; then 
					EXIT_STATUS_WRITES=$STATE_WARNING
				fi
			fi
		fi
	fi
	echo "$READSS_CURRENT::$TIMESTAMP" > "/tmp/$DEVICE.readsio"
	echo "$WRITESS_CURRENT::$TIMESTAMP" > "/tmp/$DEVICE.writesio"
#	RESULT="$RESULT_TPS ; $RESULT_READS ; $RESULT_WRITES"
#	PERF="$PERF_TPS $PERF_READS $PERF_WRITES"
if [ $FIRST_RUN = "false" ]; then
	RESULT="$RESULT_READS ; $RESULT_WRITES"
	PERF="$PERF_READS $PERF_WRITES"
		
#	if test $EXIT_STATUS_TPS -eq $STATE_CRITICAL ; then
#		EXIT_STATUS=$STATE_CRITICAL
#		RESULT_STATUS="CRITICAL"
#	else
		if test $EXIT_STATUS_READS -eq $STATE_CRITICAL ; then
			EXIT_STATUS=$STATE_CRITICAL
			RESULT_STATUS="CRITICAL"
		else		
			if test $EXIT_STATUS_WRITES -eq $STATE_CRITICAL ; then
				EXIT_STATUS=$STATE_CRITICAL
				RESULT_STATUS="CRITICAL"
			else
#				if test $EXIT_STATUS_TPS -eq $STATE_WARNING ; then
#					EXIT_STATUS=$STATE_WARNING
#					RESULT_STATUS="WARNING"
#				else		
					if test $EXIT_STATUS_READS -eq $STATE_WARNING ; then
						EXIT_STATUS=$STATE_WARNING
						RESULT_STATUS="WARNING"
					else
						if test $EXIT_STATUS_WRITES -eq $STATE_WARNING ; then
							EXIT_STATUS=$STATE_WARNING
							RESULT_STATUS="WARNING"
						else		
							EXIT_STATUS=$STATE_OK
							RESULT_STATUS="OK"
						fi
					fi
#				fi	
			fi
#		fi
	fi
else
	RESULT_STATUS="CRITICAL"
	RESULT="Tracker file IO error. Verify /tmp/$DEVICE.* files."
fi
fi

# Quit and return information and exit status
theend
