#!/bin/sh

##############################
#   MD superblock checker    #
#   Version 1.4              #
#   Daniel Orme 25-03-2016   #
#   Qnap Systems, Inc.       #
##############################

red='\033[0;91m'
redB='\033[1;91m'
green='\033[0;32m'
orange='\033[0;33m'
blue='\033[0;34m'
NC='\033[0m' # No Color

echo
echo "Welcome to MD superblock checker (v1.4) - have a nice day~"
echo

mkdir -p /mnt/HDA_ROOT  ## if /mnt/HDA_ROOT not existing, will cause md_checker fail
rm /tmp/noSuperblock 2>/dev/null
rm /tmp/md_uuid 2>/dev/null
LOG=/mnt/HDA_ROOT/md_backup_`date +%F_%H.%M.%S`
echo Superblock information recorded by md_checker at `date` > $LOG

echo Scanning system...
echo

## Record active data md device name and Online Disk ([UU_U]) status
/bin/cat /proc/mdstat | /bin/sed '/md/i \break' | /bin/tr '\n' ' ' | /bin/awk -v RS=break '/sd[a-z][a-z]*3/' | /bin/awk 'match ($0,/\[[U_]*\]|raid0|linear/) {print $1, substr($0,RSTART,RLENGTH)}' > /tmp/md_stat 2>/dev/null

## Record active data md device UUID
for q in `/bin/awk '{print $1}' /tmp/md_stat`; do 
	mdadm -D /dev/$q 2>/dev/null | /bin/awk -v p=$q '/UUID/ {print p,$3}' >> /tmp/md_uuid
done

## Concatenate information into /tmp/md_online
## Format: md1 3e01bd32:31ce8a78:7e379936:6b216de2 [UUUUUU]
/bin/awk 'FNR==NR{a[$1]=$1 FS $2;next}{print a[$1],$2}' /tmp/md_uuid /tmp/md_stat > /tmp/md_online 2>/dev/null

## Checking all disk superblocks
HDDs=24

if [ -e /etc/enclosure_0.conf ]; then ## HAL detected
  echo HAL firmware detected!
  for((k=0;k<16;k++));do  ## enumerate over all enclosures
    [ "$HDDs" == "" ] && HDDs=24
    
    echo "" > /tmp/RaidUUID
    echo "" > /tmp/mdinfo
    echo "" > /tmp/mdinfo_u

    if [ -e /etc/enclosure_$k.conf ]; then ## RAID report per enclosure
	echo Scanning Enclosure ${k}...
        for((i=1;i<=$HDDs;i++));do ## enumerate over all HDDs
            PORTID=$(/bin/echo $(/bin/cat /etc/enclosure_$k.conf | /bin/grep port_id | /bin/sed -n "$i"p | /bin/cut -d "=" -f2))
            HDT=$(/bin/echo $(/bin/cat /etc/enclosure_$k.conf | /bin/grep pd_sys_name | /bin/sed -n "$i"p | /bin/cut -d "=" -f2))
            if [ -e $HDT ] && [ "$HDT" != "" ]; then
		mdadm -E ${HDT}3 >> $LOG 2> /dev/null
		if [ $? = 1 ]; then
			echo ${HDT}3 >> /tmp/noSuperblock
		else 
			#kRaidUUID=`mdadm -E "$HDT"3 | /bin/awk '/Array UUID/ {print $4}'`
			kRaidUUID=`mdadm -E "$HDT"3 | /bin/grep 'UUID' | /bin/grep -v 'Device' | /bin/cut -d ':' -f '2-5' | /bin/tr -d ' '`
			kRaidLevel=`mdadm -E "$HDT"3 | /bin/awk '/Raid Level/ {print $4}'`
			kRaidDevices=`mdadm -E "$HDT"3 | /bin/awk '/Raid Devices/ {print $4}'`
			kRaidName=`mdadm -E "$HDT"3 | /bin/awk '/Name/ {print $3}'`
			if [ -z `echo $kRaidName` ]; then
				kRaidName=`mdadm -E "$HDT"3 | /bin/awk '/Preferred Minor/ {print $4}'`
			fi
			kRaidChunk=`mdadm -E "$HDT"3 | /bin/awk '/Chunk/ {print $4}'`
			if [ -z `echo $kRaidChunk` ]; then
				kRaidChunk="-"
			fi
			kRaidVersion=`mdadm -E "$HDT"3 | /bin/awk '/Version/ {print $3}'`
			kRaidCreation=`mdadm -E "$HDT"3 | /bin/awk '/Creation/ {print $5, $6, $7, $8}'`
			kDevName=$HDT"3"
			kDevNum=`mdadm -E "$HDT"3 | /bin/awk '/Role/ {print $6}'`
			if [ -z `echo $kDevNum` ]; then ## Handle 0.9 superblock
				kDevNum=`mdadm -E "$HDT"3 | /bin/awk '/this/ {print $5}'`
				if [ -z `echo $kDevNum` ]; then ## Handle 32-bit mdadm output
					kDevNum=`mdadm -E "$HDT"3 | /bin/awk '/Slot/ {print $4}'`
				fi
			fi
			kRole=`mdadm -E "$HDT"3 | /bin/awk '/Role/ {print $4}'`
			if [ -z `echo $kRole` ]; then ## Handle 0.9 superblock
				kRole=`mdadm -E "$HDT"3 | /bin/awk '/this/ {print $6}'`
				if [ -z `echo $kRole` ]; then ## Handle 32-bit mdadm ouput 
					kRole="Active"
				fi
			fi
			mdadm -E "$HDT"3 | /bin/grep -q Recovery
			if [ $? = 0 ]; then
				kRole="Rebuild"
			fi

			#####									 #####
			# Reminder: Still need to handle the rebuild/spare case for md version 0.90! #
			#####									 #####

			kUpdateTime=`mdadm -E "$HDT"3 | /bin/awk '/Update/ {print $5, $6, $7, $8}'`
			kEvents=`mdadm -E "$HDT"3 | /bin/awk '/Events/ {print $3}'`
			kArrayState=`mdadm -E "$HDT"3 | /bin/awk '/Array State/ {print $4}'`
			if [ -z `echo $kArrayState` ]; then
				kArrayState=`mdadm -E "$HDT"3 | grep '^[ ]*[0-9]' | awk '{print $6}' | cut -c 1 | awk -v ORS= '{print}'`
			fi
			/bin/grep -q $kRaidUUID /tmp/RaidUUID
			if [ $? = 1 ]; then
				echo $kRaidUUID $kRaidLevel $kRaidDevices $kRaidName $kRaidChunk $kRaidVersion $kRaidCreation >> /tmp/RaidUUID
			fi
			echo $PORTID$'\t'$kRaidUUID$'\t'$kRaidLevel$'\t'$kRaidDevices$'\t'$kRaidName$'\t'$kRaidVersion$'\t'$kDevName$'\t'$kDevNum$'\t'$kRole$'\t'$'\t'$kUpdateTime$'\t'$kEvents$'\t'$kArrayState >> /tmp/mdinfo
		fi
            fi

        done ## enumerate over all HDDs
	#cat /tmp/mdinfo
	for RaidUUID in `/bin/cat /tmp/RaidUUID | /bin/awk '{print $1}'`;do
		echo
		echo RAID metadata found!
		echo UUID:$'\t'$'\t'$RaidUUID
		echo Level:$'\t'$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $2}'`
		echo Devices:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $3}'`
		echo Name:$'\t'$'\t'md`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $4}'`
		echo Chunk Size:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $5}'`
		echo md Version:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $6}'`
		echo Creation Time:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $7, $8, $9, $10}'`
		/bin/grep -q $RaidUUID /tmp/md_online 2>/dev/null
		if [ $? = 0 ]; then
			/bin/grep $RaidUUID /tmp/md_online | /bin/awk '{print "Status:         \033[1;32mONLINE\033[1;0m (" $1 ")", $3}'
		else
			echo -e "Status:\t\t${redB}OFFLINE${NC}"
		fi
		echo ===============================================================================
		echo " Disk | Device | # | Status |   Last Update Time   | Events | Array State"
		echo ===============================================================================
		grep $RaidUUID /tmp/mdinfo | grep -v spare | awk '{print $8, $1,$7,$8,$9,$10,$11,$12,$13,$14,$15}' | sort -n | cut -d ' ' -f 2-11 > /tmp/mdinfo_u

		n=`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $3}'`  ## total RAID devices
                m=0  ## RAID device index
                dup_array=() ## duplicate device record
                while [ $m -lt $n ]; do
                        cat /tmp/mdinfo_u | awk '{print $3}' | grep -q "^$m$"
                        if [ $? = 0 ]; then
                                /bin/awk -v m=$m '$3==m' /tmp/mdinfo_u | /bin/awk \
                                '{ \
                                        if ($4=="Rebuild") printf "  %2s %10s %2s %8s %5s %2s %s %s %8s   %-24s \n", $1, $2, $3, " \033[0;93m" $4 "\033[0m", $5, $6, $7, $8, $9, $10; \
                                        else if ($4~"[Aa]ctive") printf "  %2s %10s %2s %7s %5s %2s %s %s %8s   %-24s \n", $1, $2, $3, "  \033[0;94m" $4 "\033[0m", $5, $6, $7, $8, $9, $10; \
                                        else printf "  %2s %10s %2s %8s %5s %2s %s %s %8s   %-24s \n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10; \
                                }'
				if [ `awk -v m=$m '$3==m' /tmp/mdinfo_u | wc -l` -gt 1 ]; then ## Record duplicate device
                                        dup_array+=($m)
                                fi
                                (( m+=1 ))
                        else
                                printf " -------------- %2i  "${red}"Missing"${NC}"   -------------------------------------------\n" $m
                                (( m+=1 ))
                        fi
                done
                echo ===============================================================================
                if [[ -n ${dup_array[*]} ]]; then
                        echo -e ${redB} WARNING${NC}: Duplicate device detected for \#\(${dup_array[*]}\)!
                fi
                echo
	done ## for RaidUUID
    fi ## RAID report per enclosure
  done ## enumerate over all enclosures

else ## not HAL detected then must be Legacy

	echo Legacy Firmware Detected!

        echo "" > /tmp/RaidUUID
        echo "" > /tmp/mdinfo
        echo "" > /tmp/mdinfo_u

	echo Scanning disks...
        for((i=1;i<=$HDDs;i++));do ## enumerate over all HDDs
                HDT=sd$(/bin/echo abcdefghijklmnop | /bin/cut -c $i)
                if [ -e /sys/block/$HDT ]; then
			HDT=/dev/${HDT}
                	mdadm -E ${HDT}3 >> $LOG 2> /dev/null
                	if [ $? = 1 ]; then
                        	echo ${HDT}3 >> /tmp/noSuperblock
                	else
			#kRaidUUID=`mdadm -E "$HDT"3 | /bin/awk '/Array UUID/ {print $4}'`
			kRaidUUID=`mdadm -E "$HDT"3 | /bin/grep 'UUID' | /bin/grep -v 'Device' | /bin/cut -d ':' -f '2-5' | /bin/tr -d ' '`
			kRaidLevel=`mdadm -E "$HDT"3 | /bin/awk '/Raid Level/ {print $4}'`
			kRaidDevices=`mdadm -E "$HDT"3 | /bin/awk '/Raid Devices/ {print $4}'`
			kRaidName=`mdadm -E "$HDT"3 | /bin/awk '/Name/ {print $3}'`
			if [ -z `echo $kRaidName` ]; then
				kRaidName=`mdadm -E "$HDT"3 | /bin/awk '/Preferred Minor/ {print $4}'`
			fi
			kRaidChunk=`mdadm -E "$HDT"3 | /bin/awk '/Chunk/ {print $4}'`
			if [ -z `echo $kRaidChunk` ]; then
				kRaidChunk="-"
			fi
			kRaidVersion=`mdadm -E "$HDT"3 | /bin/awk '/Version/ {print $3}'`
			kRaidCreation=`mdadm -E "$HDT"3 | /bin/awk '/Creation/ {print $5, $6, $7, $8}'`
			kDevName=$HDT"3"
			kDevNum=`mdadm -E "$HDT"3 | /bin/awk '/Role/ {print $6}'`
			if [ -z `echo $kDevNum` ]; then ## Handle 0.9 superblock
				kDevNum=`mdadm -E "$HDT"3 | /bin/awk '/this/ {print $5}'`
				if [ -z `echo $kDevNum` ]; then ## Handle 32-bit mdadm output
					# kDevNum=`mdadm -E "$HDT"3 | /bin/awk '/Slot/ {print $4}'`
					slot=`mdadm -E "$HDT"3 | awk '/Array Slot/ {print $4}'`
					if [ $slot ]; then
						slot_pos=$(( $slot + 1 ))
        					kDevNum=`mdadm -E "$HDT"3 | awk '/Array Slot/' | sed 's/.*(\(.*[0-9]\).*)/\1/' | cut -d ',' -f $slot_pos | tr -d ' '`
					fi
				fi
			fi
			kRole=`mdadm -E "$HDT"3 | /bin/awk '/Role/ {print $4}'`
			if [ -z `echo $kRole` ]; then ## Handle 0.9 superblock
				kRole=`mdadm -E "$HDT"3 | /bin/awk '/this/ {print $6}'`
				if [ -z `echo $kRole` ]; then ## Handle 32-bit mdadm output
					kRole="Active"
				fi
			fi
			mdadm -E "$HDT"3 | /bin/grep -q Recovery
			if [ $? = 0 ]; then
				kRole="Rebuild"
			fi

			#####									 #####
			# Reminder: Still need to handle the rebuild/spare case for md version 0.90! #
			#####									 #####

			kUpdateTime=`mdadm -E "$HDT"3 | /bin/awk '/Update/ {print $5, $6, $7, $8}'`
			kEvents=`mdadm -E "$HDT"3 | /bin/awk '/Events/ {print $3}'`
			kArrayState=`mdadm -E "$HDT"3 | /bin/awk '/Array State/ {print $4}'`
			if [ -z `echo $kArrayState` ]; then
				kArrayState=`mdadm -E "$HDT"3 | grep '^[ ]*[0-9]' | awk '{print $6}' | cut -c 1 | awk -v ORS= '{print}'`
			fi
			/bin/grep -q $kRaidUUID /tmp/RaidUUID
			if [ $? = 1 ]; then
				echo $kRaidUUID $kRaidLevel $kRaidDevices $kRaidName $kRaidChunk $kRaidVersion $kRaidCreation >> /tmp/RaidUUID
			fi
			echo $i$'\t'$kRaidUUID$'\t'$kRaidLevel$'\t'$kRaidDevices$'\t'$kRaidName$'\t'$kRaidVersion$'\t'$kDevName$'\t'$kDevNum$'\t'$kRole$'\t'$'\t'$kUpdateTime$'\t'$kEvents$'\t'$kArrayState >> /tmp/mdinfo
		fi
            fi

        done ## enumerate over all HDDs
	#cat /tmp/mdinfo
	for RaidUUID in `/bin/cat /tmp/RaidUUID | /bin/awk '{print $1}'`;do
		echo
		echo RAID metadata found!
		echo UUID:$'\t'$'\t'$RaidUUID
		echo Level:$'\t'$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $2}'`
		echo Devices:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $3}'`
		echo Name:$'\t'$'\t'md`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $4}'`
		echo Chunk Size:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $5}'`
		echo md Version:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $6}'`
		echo Creation Time:$'\t'`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $7, $8, $9, $10}'`
		/bin/grep -q $RaidUUID /tmp/md_online 2>/dev/null
		if [ $? = 0 ]; then
			/bin/grep $RaidUUID /tmp/md_online | /bin/awk '{print "Status:         \033[1;32mONLINE\033[1;0m (" $1 ")", $3}'
		else
			echo -e "Status:\t\t${redB}OFFLINE${NC}"
		fi
		echo ===============================================================================
		echo " Disk | Device | # | Status |   Last Update Time   | Events | Array State"
		echo ===============================================================================
		grep $RaidUUID /tmp/mdinfo | grep -v spare | awk '{print $8, $1,$7,$8,$9,$10,$11,$12,$13,$14,$15}' | sort -n | cut -d ' ' -f 2-11 > /tmp/mdinfo_u

		n=`/bin/grep $RaidUUID /tmp/RaidUUID | /bin/awk '{print $3}'`  ## total RAID devices
		m=0  ## RAID device index
		dup_array=() ## duplicate device record
		while [ $m -lt $n ]; do
			cat /tmp/mdinfo_u | awk '{print $3}' | grep -q "^$m$"
			if [ $? = 0 ]; then
				awk -v m=$m '$3==m' /tmp/mdinfo_u | awk \
				'{ \
					if ($4=="Rebuild") printf "  %2s %10s %2s %8s %5s %2s %s %s %8s   %-24s \n", $1, $2, $3, " \033[0;93m" $4 "\033[0m", $5, $6, $7, $8, $9, $10; \
					else if ($4~"[Aa]ctive") printf "  %2s %10s %2s %7s %5s %2s %s %s %8s   %-24s \n", $1, $2, $3, "  \033[0;94m" $4 "\033[0m", $5, $6, $7, $8, $9, $10; \
					else printf "  %2s %10s %2s %8s %5s %2s %s %s %8s   %-24s \n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10; \
				}'
				if [ `awk -v m=$m '$3==m' /tmp/mdinfo_u | wc -l` -gt 1 ]; then ## Record duplicate device
					dup_array+=($m)
				fi
				(( m+=1 ))
			else
				printf " -------------- %2i  "${red}"Missing"${NC}"   -------------------------------------------\n" $m
				(( m+=1 ))
			fi
		done
		echo ===============================================================================
		if [[ -n ${dup_array[*]} ]]; then
			echo -e ${redB} WARNING${NC}: Duplicate device detected for \#\(${dup_array[*]}\)!
		fi
		echo
	done ## for RaidUUID

fi
