#! /usr/local/bin/bash
# Scan pool for failed disks and light failure LED
# Should work with Supermicro SAS2 backplanes, unknown if it will work in other environments
# https://github.com/danb35/zpscan

#if [ ! "$1" ]; then
#  echo "Usage: zpscan.sh pool [email]"
#  echo "Scan a pool, send email notification and activate leds of failed drives"
#  exit
#fi
#pool="$1"
basedir="/mnt/storage1/gemensam/z.scripting/danb35"

pools=$(zpool list -H -o name)

for pool in $pools; do
  drivesfile=$basedir/drives-$pool
  locsfile=$basedir/locs-$pool
  if [ ! -d $basedir ]; then
    mkdir $basedir
  fi
  touch $drivesfile
  touch $locsfile
  if [ "$2" ]; then
    email="$2"
  else
    email="root"
  fi

#condition=$(/sbin/zpool status $pool | egrep -i '(DEGRADED|FAULTED|OFFLINE|UNAVAIL|REMOVED|FAIL|DESTROYED|corrupt|cannot|unrecover)')
condition=$(/sbin/zpool status $pool | egrep '(DEGRADED|FAULTED|OFFLINE|UNAVAIL|REMOVED|FAIL|DESTROYED|corrupt|cannot|unrecover)')
if [ "${condition}" ]; then
  glabel status | awk '{print "s|"$1"|"$3"\t\t\t      |g"}' > /tmp/glabel-lookup.sed
  emailSubject="`hostname` - ZFS pool - HEALTH fault"
  mailbody=$(zpool status $pool)
  echo "Sending email notification of degraded pool $pool"
  echo "$mailbody" | mail -s "Degraded pool $pool on `hostname`" $email
  drivelist=$(zpool status $pool | sed -f /tmp/glabel-lookup.sed | sed 's/p[0-9]//' | grep -E "(DEGRADED|FAULTED|OFFLINE|UNAVAIL|REMOVED|FAIL|DESTROYED)" | grep -vE "^\W+($pool|NAME|mirror|raidz|stripe|logs|spares|state)" | sed -E $'s/.*was \/dev\/([0-9a-z]+)/\\1/;s/^[\t  ]+([0-9a-z]+)[\t ]+.*$/\\1/')
  echo "Locating failed drives."
  for drive in $drivelist;
  do
    record=$(grep -E "^$drive" $drivesfile)
    location=$(echo $record | cut -f 3 -d " ")
    echo Locating: $record
    sas2ircu 0 locate $location ON
    if [ ! "$(egrep $location $locsfile)" ]; then
      echo $location >> $locsfile
    fi
  done
  rm /tmp/glabel-lookup.sed
else
  echo "Saving drive list."
  glabel status | awk '{print "s|"$1"|"$3"\t\t\t      |g"}' > /tmp/glabel-lookup.sed
  drivelist=$(zpool status $pool  | sed -f /tmp/glabel-lookup.sed | sed 's/p[0-9]//' | grep -E $'^\t  ' | grep -vE "^\W+($pool|NAME|mirror|raidz|stripe|logs|spares)" | sed -E $'s/^[\t ]+//;s/([a-z0-9]+).*/\\1/')
  saslist=$(sas2ircu 0 display)
  printf "" > $drivesfile
  for drive in $drivelist;
  do
    sasaddr=$(sg_vpd -i -q $drive 2>/dev/null | sed -E '2!d;s/,.*//;s/  0x//;s/([0-9a-f]{7})([0-9a-f])([0-9a-f]{4})([0-9a-f]{4})/\1-\2-\3-\4/')
    if [ "${sasaddr}" ]; then
      encaddr=$(echo "$saslist" | grep $sasaddr -B 2 | sed -E 'N;s/^.*: ([0-9]+)\n.*: ([0-9]+)/\1:\2/')
      echo $drive $sasaddr $encaddr >> $drivesfile
    else
      echo $drive "is not a connected to a sas controller" >> $drivesfile
    fi
  done

  for loc in $(cat $locsfile);
  do
    sas2ircu 0 locate $loc OFF
  done
  printf "" > $locsfile
  rm /tmp/glabel-lookup.sed
fi

done
