#!/bin/bash

# Manfred.Kehr@siemens-enterprise.com
# Version
# V 1.0 released;
# V 1.1 released;
# V 1.2 released;
# V 1.3 corection for OSFOURK-8322
# V 1.3 corection for OSFOURK-19126

VER='1.4'

MDADM=/sbin/mdadm
BASENAME=`basename $0`
LOGGER="/bin/logger -t $BASENAME"
GREP=/usr/bin/grep
SED=/usr/bin/sed
AWK=/usr/bin/awk
SORT=/usr/bin/sort
STAT=/usr/bin/stat
HEAD=/usr/bin/head
UDEVADM=/sbin/udevadm
TOUCH=/usr/bin/touch
CUT=/usr/bin/cut
ECHO=/bin/echo
BIN_DATE="/bin/date"
FDISK=/sbin/fdisk
WC=/usr/bin/wc
RAIDSTAT=/var/run/raidstat
STATUS_FILE=/proc/mdstat
RESCAN=/usr/bin/rescan-scsi-bus.sh
SLEEP=2
HEADER=Softraid:
AUTOADD=
HOTADD=
RAIDAID=
LOGHIST="/var/log/softraid/raid.history"
LOGFILEDIR=/var/log/softraid
SLEEPWATCH=10
RETURNFILE=$LOGFILEDIR/return.ini


get_all_drives()
{
  unset ALLOTHERSDX
  declare -i n=0
  #dummy initialization with value which can not be a block device name
  local oldmemb=" . . "
  for member in `ls -l /dev/disk/by-*/* | $AWK '{print $NF}' | $SED -e "sS../../SS" | $SORT`
  do
    #ignore dupli$CATes: because the list is already $SORTed the dupli$CATes will be consecutive
    [ "$oldmemb" = "$member" ] && continue
    oldmemb=$member
    #ignore device mapper(253), raid(9), cdrom(11) and loop(7) devices (for the moment we only consider these not to be HDDs)
    major=`$STAT --format %t /dev/$member`
    [ "$major" = "fd" -o "$major" = "9" -o "$major" = "b" -o "$major" = "7" ] && continue
    local dev_sys_path=`$UDEVADM info --query=path -n /dev/$member`
    if [ ! -e /sys/$dev_sys_path/partition ]; then
      ALLOTHERSDX[$n]=$member
      n=n+1
    fi
  done
  return $n
}

clear_files()
{
# touch raidstat to trigger portal
$TOUCH -a $RAIDSTAT
# remove old bad disk sector file
hdbad=`echo $1 | cut -d/ -f3-`
rm -f $LOGFILEDIR/$hdbad.bad
rm -f /tmp/$hdbad.txt
#restore return when last action was repair
if [  -f $RETURNFILE ]; then
	. $RETURNFILE
	if [ "$last_action" == "repairHD" ] && [ "$exit_code" == "1" ]; then
		cp $RETURNFILE.save $RETURNFILE
	fi
fi
}

if [ -n "$AUTOADD" ]; then
  exit 0
elif [ -n "$HOTADD" ]; then
  if [ "$2" == "delayedadd" ]; then
    sleep $SLEEP
    mdline=`$MDADM --examine --scan $1 | $SED -e "s/.*\(UUID.*\)\s\+name.*/\1/" | $HEAD -n 1`
  #  $LOGGER "mdline = $mdline"
    if [ -n $mdline ]; then
      mddev=$($GREP `$MDADM --examine --scan $1 | $SED -e "s/.*\(UUID.*\)\s\+name.*/\1/" | $HEAD -n 1` /etc/mdadm.conf | $SED -e "s/.*\(\/dev\/md.\).*/\1/")
      if [ -n $mddev ]; then
				$LOGGER "$HEADER Adding device $1 into RAID device $mddev"
				log=`$MDADM -a $mddev $1 2>&1`
				$LOGGER "$HEADER $log"
      else
				$LOGGER "$HEADER Device $1 was inserted but it does not belong to any raid"
      fi
    else
      $LOGGER "$HEADER Device $1 is a linux raid partition but could not be examined with mdadm"
    fi
    exit 0
  fi
  # touch raidstat to trigger portal
  $TOUCH -a $RAIDSTAT

  #check fs type if it is linux raid member
  if ! $UDEVADM info --query=all --name=$1 2>/dev/null | $GREP -q "ID_FS_TYPE=linux_raid_member"; then
    exit 0
  fi
  if [[ "$1" != d* ]]; then
	  $LOGGER "$HEADER Will add device $1 into corresponding RAID device within next $SLEEP seconds"
	  $0 $1 delayedadd &
  fi
elif [ -n "$RAIDAID" ]; then
   if [ "$2" == "delayedadd" ]; then
      sleep $SLEEP
      device=`udevadm info -a -n $1 | grep -i partition`
      if [ -z "$device" ]; then
#	  mdline=$($GREP -s md0 $STATUS_FILE | $GREP  "(F)") #mdline contains something like "md0 : active raid1 sda1[0] sdb1[1]"
#	  mddev=${mdline% :*}            #delete everything from " :" till the end of line and return the result as mddev
				$LOGGER "$HEADER Trying to clean md0"
				log0=`$MDADM /dev/md0 --fail detached --remove detached 2>&1`
				$LOGGER "$HEADER $log0"
#	  mdline=$($GREP -s md1 $STATUS_FILE | $GREP  "(F)") #mdline contains something like "md0 : active raid1 sda1[0] sdb1[1]"
#	  mddev=${mdline% :*}            #delete everything from " :" till the end of line and return the result as mddev
				$LOGGER "$HEADER Trying to clean md1"
				log1=`$MDADM /dev/md1 --fail detached --remove detached 2>&1`
				$LOGGER "$HEADER $log1"
				if [ -z "$log0" ] && [ -z "$log1" ];then
					device=$1
					drive=${device##*/}
					$LOGGER "$HEADER delete drive /dev/$drive"
					$ECHO 1 > /sys/block/$drive/device/delete
					$LOGGER "$HEADER rescan bus"
					$RESCAN
					# touch raidstat to trigger portal
					$TOUCH -a $RAIDSTAT
				fi
      fi
    else
	  if [[ "$1" != d* ]]; then
		  $LOGGER "$HEADER Called to clean raid. Will be delayed for $SLEEP seconds ($1)"
		  $0 $1 delayedadd &
	  fi
    fi
else

    #OSFOURK-19126 - remove strange/unexpected RAID devices
    [[ "x$1" =~ x/dev/md ]] && {
        while [ 1 ]; do
            #we allow only /dev/md0 or /dev/md1 which we know ; anything else should be stopped as it is not a active 4K softraid device
            [ $1 = "/dev/md0" ] && break
            [ $1 = "/dev/md1" ] && break
            $LOGGER "$HEADER Hot add of $1 (SN:n.a.) called but we must not use this device => will stop it now"
            LOGLINE="`date`: Hot add of $1 (SN:n.a.) called but we must not use this device => will stop it now"
            echo $LOGLINE >> $LOGHIST
            echo $LOGLINE | logger
            (
                . /etc/profile
                mdadm --stop $1
            )
            exit 0
            break
        done
    }

	if [ "$2" == "delayedadd" ]; then
		sleep $SLEEP
		get_all_drives
		LDATE=$($BIN_DATE)
		SERNUM=`$UDEVADM info --query=all --name=$1 |$GREP ID_SERIAL_SHORT | $CUT -d "=" -f2`
		#check fs type if it is linux raid member
		if ! $UDEVADM info --query=all --name=$1 2>/dev/null | $GREP -q "ID_FS_TYPE=linux_raid_member"; then
			for i in ${ALLOTHERSDX[@]}; do if [[ /dev/$i == $1 ]] ; then
				LOGLINE="$LDATE: info: Hot add of $1 (SN:$SERNUM)"
				echo $LOGLINE >> $LOGHIST
				$LOGGER "$HEADER Hot add of $1 (SN:$SERNUM)"
					#OSFOURK-8322 NA16349679: Simplex dscxl Portal > Hard Disk Status shows "no smart DATA available"
					#We enable the smart
					LOGLINE="$LDATE: info: enable the smart for $1 disk"
					echo $LOGLINE >> $LOGHIST
					echo $LOGLINE | logger
					/usr/sbin/smartctl.orig -s on $1 | logger
					rm /dev/shm/smartctl/sd*
					#OSFOURK-8322
				clear_files
				exit 0
			fi; done
			$LOGGER "$HEADER Hot add of $1 (SN:$SERNUM)"
			#OSFOURK-8322 NA16349679: Simplex dscxl Portal > Hard Disk Status shows "no smart DATA available"
			#We enable the smart 
			LOGLINE="$LDATE: info: enable the smart for $1 disk"
			echo $LOGLINE >> $LOGHIST
			echo $LOGLINE | logger
			/usr/sbin/smartctl.orig -s on $1 | logger
			rm /dev/shm/smartctl/sd*
			#OSFOURK-8322
			clear_files 
			exit 0
		fi
		clear_files
		$LOGGER "$HEADER Hot plugging of raid device $1 (SN:$SERNUM)"
	else
		if [[ "$1" != d* ]]; then
			$LOGGER "$HEADER Called to add $1. Will be delayed for $SLEEP seconds."
			$0 $1 delayedadd &
		fi
	fi
fi

exit 0

