#!/bin/bash

# copyright 2014, Simon Oosthoek (soosthoek@nieuwland.nl)
# License: GPL v2 or later.

# violations to nagios plugin developer guidelines:
# - no checks for symlinks
# - keep checks on runtime (not too long)
# - should listen to --help (in addition to -h)
# - and in general: long option variants (--port in addition to -p)

# Check hpacucli
# check hp array controllers for failed disks in arrays
# any failure is critical

GETOPTSSTR="v:dh"
VERBOSITY=0
DEBUG=""

X_OK=0
X_WARN=1
X_CRIT=2
X_UNKNOWN=3

HPACUCLI=/usr/sbin/hpacucli
SUDO=/usr/bin/sudo

if ! [[ -f $HPACUCLI ]]; then
	echo "$HPACUCLI command not found"
	exit $X_UNKNOWN
fi

# work around permissions problems:
if [[ -x $HPACUCLI ]]; then
	CMD_HPACUCLI=$HPACUCLI
else
	CMD_HPACUCLI="$SUDO $HPACUCLI"
fi


function usage () {
	echo "Usage: $0 -d -v -h  -w <warning> -c <critical>"
	echo 
	echo " -d          = Optional debugging, saves retrieved file for vhostname in /tmp/"
	echo " -v number   = Verbosity level default=0, max=9"
	echo " -h          = This help message."
	exit   $X_UNKNOWN
}

while getopts "$GETOPTSSTR" Option
do
	case "$Option" in
	v) 	case "$OPTARG" in
			[0-9]) VERBOSITY="$OPTARG"
			;;
			*)	echo "ERROR: verbosity number outside range 0-9" 
				exit 3
			;;
		esac
	;;
	d)	DEBUG="true"
		VERBOSITY=9
	;;
	*)	usage
	esac
done
shift $(($OPTIND - 1)) 

STATUS=$X_OK

if ! cmderror=$($CMD_HPACUCLI ctrl all show) 
then
	echo "problem executing $CMD_HPACUCLI: $cmderror" 
	exit $X_UNKNOWN
fi

# find controllers
if ! hpcontrollers=$($CMD_HPACUCLI ctrl all show | sed -n '/Slot/s/^.*Slot \([0-9]\).*/\1/p')
then
	echo "no hp controllers found"
	exit $X_UNKNOWN
fi

# get disk status for all controllers

declare -a problemdisks

for ctrl in $hpcontrollers
do
	hpacucli_output=$($CMD_HPACUCLI controller slot=$ctrl pd all show)
	if [[ $VERBOSITY -gt 4 ]]; then
		echo "$hpacucli_output"
	fi

	diskstatus=$(
		awk -vverb=$VERBOSITY '
		/^#/ {
			getline
		}

		NF < 5 && $1 == "array" { 
			array=$2 
		}

		/physicaldrive/ { 
			gsub (/[(),]/, "", $0 )
			for (i=NF; i i>1; i--) {
				if ($i ~ /[oO][Kk]|[Ff]ailed|[Rr]ebuild/) {
					statusfield=i
				}
			}
			status = ""
			for (i=statusfield; i<=NF; i++) {
				status = status $i
			}
			gsub(/:/, "", status)
			pd[$2] = status
			pd_a[$2] = array # array for disk $2
		}

		END { 
			for (d in pd) { 
				if (pd[d] ~ /[fF]ailed|[Rr]ebuild/) {
					print d, pd[d], "array " pd_a[$2]
				}
			} 
		}' <<< "$hpacucli_output"
	)
	if [[ $VERBOSITY -gt 2 ]]; then
		echo "$diskstatus"
	fi

	if [[ -z $diskstatus ]]; then
		echo "OK: no failed disks"
		exit $X_OK
	fi

# in case of problems, 


	i=0
	while read pd status ignore arrayid
	do
		serialnr=$($CMD_HPACUCLI controller slot=$ctrl pd $pd show |awk '/Serial/ {print $NF}')
		problemdisks[$i]="ctrl=$ctrl,pd=$pd,status=$status,serial=$serialnr"
		((i++))
	done < <( echo "$diskstatus") #workaround subshell issue 
	# http://nion.modprobe.de/blog/archives/531-Altering-a-variable-outside-the-scope-of-a-loop-influenced-by-a-subshell.html
	
done #for


# print status and exit

cnt=${#problemdisks[*]}

if [[ $cnt -gt 0 ]]; then
	for (( i=0; i < cnt; i++ ))
	do
		outstr="${outstr} ${problemdisks[$i]}"
	done

	echo "CRITICAL: $cnt problem disks: $outstr"
	exit $X_CRIT
else
	echo "OK: no failed disks"
	exit $X_OK
fi

echo "I shouldn't be here"
exit $X_UNKNOWN
