#!/bin/sh
#
# to be managed by heartbeat.
# description: Mounts and unmounts the cluster filesystem
#	  
# Copyright (C) 1999 2000, Philipp Reisner <philipp@linuxfreak.com>.
# Initial author.
#
# Copyright (C) 2000, Fbio Oliv Leite <olive@conectiva.com.br>
# Changes to support multiple devices and different distributions.
# Changes to increase robustness and exit with proper error values.
#
# Copyright (C) 2000, Thomas Mangin <thomas.mangin@free.fr>
# Major rewrite for new sections (init,mount,umount,fsck,...)
# Added full resync from slave node option (resync)
# Better heartbeat/script integration
# Become drbdc
#
# Some ideas and inspiration from Joe Hartley <jh@brainiac.com>

INSTALL="/etc/ha.d/resource.d"
. $INSTALL/drbd_common

# Return a boolean
isMounted()
{
	[ "`mount | grep "$LOCAL_DEVICE" | cut -f1 -d\ `" = "$LOCAL_DEVICE" ] && \
		return 1 || return 0
}

# unmount the device set by setLocal
# $1 = RESOURCE
# $2 = LOCAL_DEVICE
# Return if the device is still mounted
rudeUnMount()
{
	isMounted $1
	MOUNTED=$?
		
	if [ $MOUNTED -eq 1 ]; then
		$0 $1 umount

		isMounted $1
		MOUNTED=$?

		if [ $MOUNTED -eq 1 ]; then
			fuser -km $2
			sleep 1
			$0 $1 umount
		fi
 
		isMounted $1
		MOUNTED=$?

		if [ $MOUNTED -eq 1 ]; then
			fuser -km -9 $2
			sleep 1
			$0 $1 umount
		fi

		isMounted $1
		MOUNTED=$?
	fi

	return $MOUNTED
}

# See how we were called.
case "$OPTION" in
	primary)
		if [ -z "$RESOURCE" ]; then
			runForAll primary
			exit $RETVAL
		fi
		
		setLocal $CONFIG $RESOURCE

		isMounted $RESOURCE

		if [ $? -eq 1 ]; then
			failed "$LOCAL_DEVICE is mounted"
			exit 1
		fi

		action "Becoming primary on DRBD resource $RESOURCE" \
			drbdsetup $LOCAL_DEVICE pri 2>/dev/null
		RV=$?
		[ $RETVAL -eq 0 ] && RETVAL=$RV
		;;

	secondary)
		if [ -z "$RESOURCE" ]; then
			runForAll secondary
			exit $RETVAL
		fi
		
		setLocal $CONFIG $RESOURCE
		isMounted $RESOURCE

		if [ $? -eq 1 ]; then
			failed "$LOCAL_DEVICE is mounted"
			exit 1
		fi

		action "Becoming secondary on DRBD resource $RESOURCE" \
			drbdsetup $LOCAL_DEVICE sec 2> /dev/null
		RV=$?
		[ $RETVAL -eq 0 ] && RETVAL=$RV
		;;

	master)
		if [ -z "$RESOURCE" ]; then
			runForAll master
			exit $RETVAL
		fi

		setLocal $CONFIG $RESOURCE

		isPrimary $RESOURCE
		PRIMARY=$?

		isMounted $RESOURCE
		MOUNTED=$?

		if [ $PRIMARY -eq 0 -a $MOUNTED -eq 0 ]; then
			$0 $RESOURCE primary && 
			$0 $RESOURCE fsck && 
			$0 $RESOURCE mount
			RV=$?
			[ $RETVAL -eq 0 ] && RETVAL=$RV
		fi
		if [ $PRIMARY -eq 1 -a $MOUNTED -eq 0 ]; then
			$0 $RESOURCE fsck && 
			$0 $RESOURCE mount
			RV=$? 
			[ $RETVAL -eq 0 ] && RETVAL=$RV
		fi
		if [ $MOUNTED -eq 1 ]; then
			succed "Already in master state : nothing to do" 
			RV=$? 
			[ $RETVAL -eq 0 ] && RETVAL=$RV
		fi
		if [ $RETVAL -eq 0 -a $PRIMARY -eq 1 ]; then
			setMasterBoot $RESOURCE
		fi
		if [ $RETVAL -ne 0 -a $PRIMARY -eq 0 ]; then
			$0 $RESOURCE secondary
			RV=$? 
			[ $RETVAL -eq 0 ] && RETVAL=$RV
		fi
		;;

	slave)
		if [ -z "$RESOURCE" ]; then
			runForAll slave
			exit $RETVAL
		fi

		setLocal $CONFIG $RESOURCE

		isMounted $RESOURCE
		MOUNTED=$?

		if [ $MOUNTED -eq 1 ]; then
			rudeUnMount $RESOURCE $LOCAL_DEVICE
			RETVAL=$?
		fi

		# Only become secondary if umount succed
		if [ $RETVAL -eq 0 ]; then
			$0 $RESOURCE secondary
			RETVAL=$?
			if [ "$RETVAL" -eq 0 ]; then
				setSlaveBoot $RESOURCE
			fi
		fi
		;;

	mount)
		if [ -z "$RESOURCE" ]; then
			runForAll mount
			exit $RETVAL
		fi

		setLocal $CONFIG $RESOURCE

		isPrimary $RESOURCE
		PRIMARY=$?

		if [ $PRIMARY -eq 0 ]; then
			failed "Can not mount $LOCAL_DEVICE (slave)"
			exit 1
		fi

		isMounted $RESOURCE
		MOUNTED=$?

		if [ $MOUNTED -eq 1 ]; then 
			succed "Device on $LOCAL_DEVICE already mounted"
			exit 0
		fi

		action "Mounting shared device on $LOCAL_DEVICE" \
			mount $LOCAL_DEVICE
		RV=$?
		[ $RETVAL -eq 0 ] && RETVAL=$RV
		;;

	umount)
		if [ -z "$RESOURCE" ]; then
			runForAll umount
			exit $RETVAL
		fi

		setLocal $CONFIG $RESOURCE

		#isPrimary $RESOURCE
		#PRIMARY=$?

		#if [ $PRIMARY -eq 0 ]; then
		#	failed "Can not umount $LOCAL_DEVICE (slave)"
		#	exit 1
		#fi

		isMounted $RESOURCE
		MOUNTED=$?

		if [ $MOUNTED -eq 0 ]; then
			succed "$LOCAL_DEVICE is already unmounted"
			exit 0
		fi

		action "Unmounting shared device on $LOCAL_DEVICE " \
			umount $LOCAL_DEVICE

		RV=$?
		[ $RETVAL -eq 0 ] && RETVAL=$RV
		;;

	fsck)
		if [ -z "$RESOURCE" ]; then
			runForAll fsck
			exit $RETVAL
		fi

		setLocal $CONFIG $RESOURCE

		isPrimary $RESOURCE
		PRIMARY=$?

		if [ "$PRIMARY" -ne 1 ]; then
			failed "Can not perform fsck on secondary $RESOURCE "
			exit 1
		fi

		isMounted $RESOURCE
		MOUNTED=$?

		if [ $MOUNTED -eq 1 ]; then
			$0 $RESOURCE umount
			RV=$? 
			[ $RETVAL -eq 0 ] && RETVAL=$RV
		fi

		if [ $RETVAL -eq 1 ]; then
			failed "$LOCAL_DEVICE still mounted can't check"
			exit 1
		fi

		# It seems that fsck.ext2 like to return 0 whatever happend
		# difficult know if succed of failed ..

		echo -n "performing fsck on $RESOURCE " 
		$LOCAL_FSCK $LOCAL_DEVICE > /dev/null 2>/dev/null
		RV=$?
		[ $RV -eq 0 -o $RV -eq 1 ] && RETVAL=0
		[ $RETVAL -eq 0 ] && success || failure
		echo

		if [ $MOUNTED -eq 1 ]; then 
			$0 $RESOURCE mount
			RV=$?
			[ $RV -eq 0 ] && RETVAL=$RV
		fi
		;;	

	resync)
		if [ -z "$RESOURCE" ]; then
			runForAll resync
			exit $RETVAL
		fi

		setLocal $CONFIG $RESOURCE

		isPrimary
		PRIMARY=$?

		if [ $PRIMARY -eq 1 ]; then
			failed "resync must be run from a (connected) slave"
			exit 1
		fi

		# TODO:DRDB sometimes lies about its connection status !!
		# See how to understand the proc/drbd lines

		isConnected
		CONNECTED=$?

		if [ $CONNECTED -eq 0 ]; then
			failed "node not connected to the primary"
			exit 1
		fi

		drbdsetup $LOCAL_DEVICE repl 2> /dev/null
		RETVAL=$?
		;;
		
	proc)
		if [ -r /proc/drbd ]; then
			cat /proc/drbd
		else
			failed "DRBD module not loaded."
			RETVAL=1
		fi
		;;

	status)
		if [ -z "$RESOURCE" ]; then
			runForAll status
			exit $RETVAL
		fi

		if [ -r /proc/drbd ]; then
			setLocal $CONFIG $RESOURCE

			isPrimary $RESOURCE
			PRIMARY=$?

			isMounted $RESOURCE
			MOUNTED=$?

			isConnected $RESOURCE
			CONNECTED=$?

			isSyncing $RESOURCE
			SYNC=$?

			haveRemotePrimary $RESOURCE
			RPRIMARY=$?

			haveRemoteSecondary $RESOURCE
			RSECONDARY=$?

			if [ $PRIMARY -eq 1 ]; then
				if [ $MOUNTED -eq 1 ]; then
					echo "running"
				else
					echo "stopped"
				fi
			elif [ "$SYNC" -eq 1 ]; then
				echo "not ready"
			elif [ "$CONNECTED" -eq 1 ]; then
				echo "stopped"
			else
				echo "ready"
			fi
		else
			echo "failed"
		fi
		;;
	
	running)
		if [ -z "$RESOURCE" ]; then
			runForAll running
			exit $RETVAL
		fi

		if [ -r /proc/drbd ]; then
			isPrimary $RESOURCE
			if [ $? -eq 1 ]; then
				succed "Primary"
			else
				succed "Secondary"
			fi
		else
			failed "Error drbd not loaded"
		fi
		;;
	
	boot)
		if [ -n "$RESOURCE" ]; then
			. $CONFIG/$RESOURCE
		else
			runForAll boot
			exit $RETVAL
		fi

		isMasterBoot $RESOURCE
		if [ $? -eq 1 ]; then
			echo "Master"
		else
			echo "Slave"
		fi
		;;

	help)
		echo "Usage: $0 [resource] command"
		echo
		echo "command can be :"
		echo
		echo "master : set drbd as primary,fsck the volume and mount it"
		echo "slave  : set drbd as secondary, umount the volume if needed"
		echo "mount  : mount the volume"
		echo "umount : unmount the volume"
		echo "fsck   : fsck the volume"
		echo "resync : force a full resynchronisation of the slave."
		echo "         only work on the slave"
		echo "proc   : return /proc/drbd"
		echo "status : display drdb status for heartbeat"
		echo "running: Return the string 'Primary' or 'Secondary'"
		echo "         depending on the node settings"
		echo "boot   : Return the string 'Master' or 'Slave'"
		echo "         Depending how the device is going to be bring"
		echo "         at boot time in restore mode"
		echo "help   : Contact the mailing list to learn about this option"
		echo
		echo "$* are not valid as parameter"
		RETVAL=1
		;;
	*)
		$0 help
		;;
esac

exit $RETVAL
