#!/bin/sh
# $Id$
# Script:       S20ext3
#
# Description:  ext3 filesystem failover script
#               Reads <RSFDIR>/etc/fs/fstab.<service> for filesystems to (un)mount
#
# Platform:    
#
# Author:       High-Availability.Com Ltd
#

#
# standard variables and functions
#
. /opt/HAC/bin/rsf.sh

service=${RSF_SERVICE:-"servicename"}
fstab="${PRODUCT_DIR}/etc/fs/fstab.${service}"    # filesystem table
#dfstab="${PRODUCT_DIR}/etc/fs/dfstab.${service}"    # NFS exports table

# functions

#
# checkfs
# - Check Linux filesystems with fsck
# args: filesystem type, device to check (raw)
# ret: standard RSF-1 exit codes
#
checkfs()
{
        _fstype=$1
        _checkdev=$2

        # sanity check
        fsck -t ${_fstype} -a ${_checkdev} >/dev/null 2>&1
        fsckret1=$?

        case ${fsckret1} in
	#
	# 0 is all OK, 1 is file systems errors corrected. jfs seems to give 1 every time!
        0|1)
                # OK
                echo "done."
                ;;
        4|8)
                # corruption, check deeper
                echo "checking deeper ... \c"
                fsckout=`fsck -t ${_fstype} -a ${_checkdev} 2>&1`
                fsckret2=$?

                case ${fsckret2} in

                0 | 1 | 8)
                        # OK
                        echo "done."
                        ;;
                2 | 4 | 16 | 128)
                        # failed
                        echo "failed!"
                        dated_echo "*** ERROR - Unable to repair ${_checkdev} ***"
                        dated_echo ${fsckout}
                        dated_echo "Run fsck manually (fsck -t ${_fstype} ${_checkdev})"
                        dated_echo "Aborting ${state}"
                        return ${RSF_ABORT}
                        ;;
                *)
                        # misc errors
                        echo "failed!"
                        dated_echo "*** ERROR - second fsck returned ${fsckret2} ***"
                        dated_echo ${fsckout}
                        dated_echo "Fix the problem manually before proceeding"
                        dated_echo "Aborting ${state}"
                        return ${RSF_ABORT}
                        ;;
                esac
                ;;
        *)
                # unknown error
                echo "failed!"
                dated_echo "*** ERROR - initial fsck returned ${fsckret1} ***"
                dated_echo "Fix the problem manually before proceeding"
                dated_echo "Aborting ${state}"
                return ${RSF_ABORT}
                ;;
        esac
}

#
# mountfs
# - Mount a filesystem
# args: filesystem, mount point, mount options
# ret: standard RSF-1 exit codes
#
mountfs()
{
        _fstype=$1
        _dev=$2
        _mntpt=$3
        _mntopts=$4

        case "${_mntpt}" in
        "-")
                # do nothing
                :
                ;;
        *)
                if [ ! -d "${_mntpt}" ]; then
			dated_echo "creating mount point ... \c"
                        mkdir -p "${_mntpt}"
                        if [ $? -ne 0 ]; then
                                echo "failed!"
                                dated_echo "Failed to create mount point for ${_mntpt}, aborting"
                                return ${RSF_ABORT}
                        fi
                fi


                if [ "${_mntopts}" = "-" ]; then
                  mountout=`mount -t ${_fstype} ${_dev} ${_mntpt} 2>&1`
                else
                  mountout=`mount -t ${_fstype} -o ${_mntopts} ${_dev} ${_mntpt} 2>&1`
                fi

                case $? in
                0)
                        echo "done"
                        ;;
                36)     # 16 - vxfs
                        echo "already mounted, proceeding"
                        ;;
                32 | 33)
		        mountedout=`mount | egrep ${_mntpt} 2>&1`
		        if [ $? = 0 ]; then
			    echo "mount point is busy, assuming already mounted and proceeding"
			    dated_echo "Message from ${mountout}"
			    dated_echo "result from mount | egrep ${_mntpt} : ${mountedout}"
			else
			    echo "Failed to mount ${_mntpt}:"
			    dated_echo ${mountout}
			    dated_echo "Aborting ${state}"
			    return ${RSF_ABORT}
                        fi
                        ;;
                *)
                        echo "failed!"
                        dated_echo "Failed to mount ${_mntpt}:"
                        dated_echo ${mountout}
                        dated_echo "Aborting ${state}"
                        return ${RSF_ABORT}
                        ;;
                esac
                ;;
        esac
}

#
# Main
#

script="`basename $0`"
state=$1
attempts=${2:-'1'}      # no of attempts at this action

# abort after three attempts
if [ ${attempts} -gt 3 ]; then
        # fail after three goes
        dated_echo "Too many retries on ${state}, aborting"
        exit ${RSF_ABORT}       # abort code
fi

# check filesys table is present
if [ ! -f "${fstab}" ]; then
        dated_echo "No ${fstab} file present, aborting"
        exit ${RSF_ABORT}
fi

#
# decide action based on first argument
#
case "${state}" in

'start')
        dated_echo "Checking and mounting filesystems in ${fstab}"
        # read fstab file, line by line
        exec < ${fstab}
        while read dev mount fstype opts pass dump; do
                case ${dev} in
                '#'* | '' | '-')
                        continue
                        ;;
                esac

                if [ "${checkdev}" != "-" ]; then
                        dated_echo "Checking ${dev} ... \c"
                        checkfs ${fstype} ${dev}
                        checkret=$?
                        if [ ${checkret} -gt 1 ]; then
                                exit ${checkret}
                        fi
                fi

                dated_echo "Mounting ${mount} ... \c"
                mountfs ${fstype} ${dev} ${mount} ${opts}
                mntret=$?
                if [ ${mntret} -gt 1 ]; then
                        exit ${mntret}
                fi
        done


        ;;

'stop')
        dated_echo "Unmounting filesystems in ${fstab}"
        abort=0 # flag
        for mount in `awk '!/^#/ { print $2 }' ${fstab}`; do
                case ${mount} in
                '-')
                        continue
                        ;;
                esac

                exportfs -u ${mount} >/dev/null 2>&1
                dated_echo "Unmounting ${mount} ... \c"
                mount -l | egrep -s " ${mount} " > /dev/null
                if [ $? -ne 0 ]; then
                        echo "not mounted, skipping"
                        continue
                fi

                umount ${mount} >/dev/null 2>&1
                if [ $? -eq 0 ]; then
                        echo "done"
                else
                        echo " failed, looking for active processes.............."
			fuser -vm ${mount} 2>&1
			if [ $? -eq 0 ]; then
				echo " trying to kill above listed processes............."
				fuser -km ${mount} 2>&1
			fi
                        echo " Trying to unmount one more time..................."
			sleep 3
			umntout=`umount -f ${mount} 2>&1`
                        if [ $? -eq 0 ]; then
                                echo "done"
                        else
                                echo "failed!"
                                dated_echo "*** WARNING - cannot unmount ${mount} ***"
                                dated_echo "Error was:"
                                dated_echo ${umntout}
                                dated_echo "*** Please check! ***"
                                abort=1 # abort after all unmounts
                        fi
                fi
        done

        # signal abort if we partially failed
        if [ ${abort} -eq 1 ]; then
                dated_echo " *** Aborting ${state} because one or more filesystems could not be unmounted"
                exit ${RSF_ABORT}
        fi

        ;;

*)
        echo "Usage: $0 <start|stop>"
        exit ${RSF_WARN}        # warning code
        ;;

esac

exit ${RSF_OK}  # OK code (default)
