#!/bin/sh

. /opt/etc/globals

CONFIG=/opt/etc/hddmon.conf


TEMP_WARN=40
TEMP_SHUTDOWN=45
HDD_DATABASE=/opt/var/smart.hdd

HDD_NEW_DATABASE=/tmp/smart.hdd
WARNINGS=0
CRITICAL=0
MAILFILE=/tmp/hddcheck.mailfile
MAILCOMMAND="/usr/local/bin/php -f /opt/etc/send-file-utf8.php $0-$(hostname)"
LOCKFILE=/tmp/hddmon.lock
TMP=/tmp/hdtemp.tmphaha

if [ -f $LOCKFILE ]; then
	exit 1;
fi

if [ -f $CONFIG ]; then
	.	$CONFIG
fi

$touch $LOCKFILE

# Get current state of HDDs

NUMHDD=`ls /dev/pass*|wc -l`
# Counts from zero
NUMHDD=$(($NUMHDD - 1))

if [ -f $MAILFILE ]; then
	$rm -f $MAILFILE
fi

if [ -f $HDD_NEW_DATABASE ]; then
	$rm -f $HDD_NEW_DATABASE
fi

for HDDNO in `seq 0 $NUMHDD`; do
	HDD=/dev/pass$HDDNO
	$rm -f $TMP > /dev/null 2>&1
	/usr/local/sbin/smartctl -a $HDD > $TMP
	if [ `$cat $TMP | $wc -l` -le 10 ]; then
#	USB memstick? SES device? Just ignore it.
#		echo "Unable to get SMART for $HDD" >> $MAILFILE
#		WARNINGS=$(($WARNINGS + 1))
		continue
	fi
	if ($grep '^ATA' $TMP > /dev/null 2>&1); then
		MODEL=`$grep 'Device Model:' $TMP | $awk '{print $3;}'`
		SERIAL=`$grep 'Serial Number:' $TMP | $awk '{print $3;}'`
		TEMPERATURE=`$grep ^194 $TMP | $awk '{print $10;}'`
		REALLOCATED=`$grep Reallocated_Sector $TMP | $awk '{print $10;}'`
		PENDING=`$grep ^197 $TMP | $awk '{print $10;}'`
		DEFECTS=$(($REALLOCATED + $PENDING))
		echo "SATA $MODEL $SERIAL $TEMPERATURE $DEFECTS" >> ${HDD_NEW_DATABASE}
		continue;
	fi
	if ($grep 'SAS' $TMP > /dev/null 2>&1); then
		VENDOR=`$grep 'Vendor:' $TMP | $awk '{print $2;}'`
		PRODUCT=`$grep 'Product:' $TMP | $awk '{print $2;}'`
		MODEL=${VENDOR}"-"${PRODUCT}
		SERIAL=`$grep 'Serial number:' $TMP | $awk '{print $3;}'`
		TEMPERATURE=`$grep 'Current Drive Temperature:' $TMP | $awk '{print $4;}'`
		DEFECTS=`$grep 'Elements in grown defect list:' $TMP | $awk '{print $6;}'`
		echo "SAS $MODEL $SERIAL $TEMPERATURE $DEFECTS" >> ${HDD_NEW_DATABASE}
		continue;
	fi
done

$rm -f $TMP

if ! [ -f $HDD_DATABASE ]; then
	# First call
	$cat $HDD_NEW_DATABASE > $HDD_DATABASE
fi

# Search for added/removed devices

NUMHDD=`cat $HDD_NEW_DATABASE|wc -l`
OLDNUMHDD=`cat $HDD_DATABASE|wc -l`

if [ $OLDNUMHDD -ne $NUMHDD ]; then
	echo "$0: number of HDD changed, old $OLDNUMHDD, new $NUMHDD" >> $MAILFILE
	WARNINGS=$(($WARNINGS + 1))
fi

# Compare new state with prevous one, line by line reading of new database

for HDDNO in `seq 1 $NUMHDD`; do
	HDD_NEW_STATE=`cat $HDD_NEW_DATABASE | $head -n $HDDNO | $tail -n 1`
	SERIAL=`echo $HDD_NEW_STATE|awk '{print $3}'`
	TEMPERATURE=`echo $HDD_NEW_STATE|awk '{print $4}'`
	DEFECTS=`echo $HDD_NEW_STATE|awk '{print $5}'`
	if !(grep $SERIAL $HDD_DATABASE > /dev/null 2>&1); then
		# New device
		OLD_DEFECTS=$DEFECTS
	else
		HDD_STATE=`grep $SERIAL $HDD_DATABASE`
		OLD_DEFECTS=`echo $HDD_STATE|awk '{print $5}'`
	fi
	if test $DEFECTS -gt $OLD_DEFECTS; then
		echo "$SERIAL: number of defects increased from $OLD_DEFECTS to $DEFECTS." | tee -a $MAILFILE
		WARNINGS=$(($WARNINGS + 1))
	fi
	if test $TEMPERATURE -ge $TEMP_WARN; then
		if test $TEMPERATURE -ge $TEMP_SHUTDOWN; then
			echo "$SERIAL: HDD(s) OVERHEATED, $TEMPERATURE, powering server off!" | tee -a $MAILFILE
			CRITICAL=$(($CRITICAL + 1))
		else
			echo "$SERIAL: overheating, $TEMPERATURE." >> $MAILFILE
		fi
		WARNINGS=$(($WARNINGS + 1))
	fi
done

$cat $HDD_NEW_DATABASE > $HDD_DATABASE
$rm $HDD_NEW_DATABASE

if test $WARNINGS -gt 0; then
	cat $MAILFILE
	$MAILCOMMAND $MAILFILE
fi

if test $CRITICAL -gt 0; then
	if [ -d /opt/etc/vmmon ]; then
		# HACK
		$touch /tmp/checkvms.lock
		/opt/etc/vmmon/stopvms
		$sleep 10
	fi
	/sbin/shutdown -p +1 HDD_Overheat_$CRITICAL
fi

if ! [ -z $REPORT_FILE ]; then
	cat $HDD_DATABASE > $REPORT_FILE
fi
	
$rm -f $MAILFILE
$rm -f $LOCKFILE
