#!/bin/sh
# nfsserver
#
# Description: Manages nfs server as OCF resource
# by hxinwei@gmail.com
# License: GNU General Public License v2 (GPLv2) and later

if [ -n "$OCF_DEBUG_LIBRARY" ]; then
    . $OCF_DEBUG_LIBRARY
else
    : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
fi

DEFAULT_INIT_SCRIPT="/etc/init.d/nfsserver"
if ! [ -f $DEFAULT_INIT_SCRIPT ]; then
	# On some systems, the script is just called nfs
	DEFAULT_INIT_SCRIPT="/etc/init.d/nfs"
fi

DEFAULT_NOTIFY_CMD=`which sm-notify`
DEFAULT_NOTIFY_CMD=${DEFAULT_NOTIFY_CMD:-"/sbin/sm-notify"}
DEFAULT_NOTIFY_FOREGROUND="false"
DEFAULT_RPCPIPEFS_DIR="/var/lib/nfs/rpc_pipefs"
EXEC_MODE=0
SELINUX_ENABLED=-1
STATD_PATH="/var/lib/nfs"
STATD_DIR=""
NFS_SYSCONFIG="/etc/sysconfig/nfs"
NFS_SYSCONFIG_LOCAL_BACKUP="/etc/sysconfig/nfs.ha.bu"
NFS_SYSCONFIG_AUTOGEN_TAG="AUTOGENERATED by $0 high availability resource-agent"

nfsserver_meta_data() {
	cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="nfsserver">
<version>1.0</version>

<longdesc lang="en">
Nfsserver helps to manage the Linux nfs server as a failover-able resource in Linux-HA.
It depends on Linux specific NFS implementation details, so is considered not portable to other platforms yet.
</longdesc>

<shortdesc lang="en">Manages an NFS server</shortdesc>

<parameters>

<parameter name="nfs_init_script" unique="0" required="0">
<longdesc lang="en">
The default init script shipped with the Linux distro.
The nfsserver resource agent offloads the start/stop/monitor 
work to the init script because the procedure to start/stop/monitor 
nfsserver varies on different Linux distro. In the event that this
option is not set, this agent will attempt to use an init script at 
this location, ${DEFAULT_INIT_SCRIPT}, or detect a systemd unit-file 
to use in the event that no init script is detected.
</longdesc>
<shortdesc lang="en">
Init script for nfsserver
</shortdesc>
<content type="string" default="auto detected" />
</parameter>

<parameter name="nfs_no_notify" unique="0" required="0">
<longdesc lang="en">
Do not send reboot notifications to NFSv3 clients during server startup.
</longdesc>
<shortdesc lang="en">
Disable NFSv3 server reboot notifications
</shortdesc>
<content type="boolean" default="false" />
</parameter>

<parameter name="nfs_notify_foreground" unique="0" required="0">
<longdesc lang="en">
Keeps the sm-notify attached to its controlling terminal and running in the foreground.
</longdesc>
<shortdesc lang="en">
Keeps the notify tool running in the foreground.
</shortdesc>
<content type="boolean" default="$DEFAULT_NOTIFY_FOREGROUND" />
</parameter>

<parameter name="nfs_smnotify_retry_time" unique="0" required="0">
<longdesc lang="en">
Specifies the length of sm-notify retry time, in minutes, to continue retrying notifications to unresponsive hosts.  
If this option is not specified, sm-notify attempts to send notifications for 15 minutes. Specifying a value of 0 
causes sm-notify to continue sending notifications to unresponsive peers until it is manually killed.
</longdesc>
<shortdesc lang="en">
Specifies the length of sm-notify retry time (minutes).
</shortdesc>
<content type="integer" default="" />
</parameter>

<parameter name="nfs_ip" unique="0" required="0">
<longdesc lang="en">
Comma separated list of floating IP addresses used to access the nfs service
</longdesc>
<shortdesc lang="en">
IP addresses.
</shortdesc>
<content type="string"/>
</parameter>

<parameter name="nfsd_args" unique="0" required="0">
<longdesc lang="en">
Specifies what arguments to pass to the nfs daemon on startup. View the rpc.nfsd man page for information on what arguments are available.
Note that setting this value will override all settings placed in the local /etc/sysconfig/nfs file.
</longdesc>
<shortdesc lang="en">
rpc.nfsd options
</shortdesc>
<content type="string" />
</parameter>

<parameter name="lockd_udp_port" unique="0" required="0">
<longdesc lang="en">
The udp port lockd should listen on.
Note that setting this value will override all settings placed in the local /etc/sysconfig/nfs file.
</longdesc>
<shortdesc lang="en">
lockd udp port
</shortdesc>
<content type="integer" />
</parameter>

<parameter name="lockd_tcp_port" unique="0" required="0">
<longdesc lang="en">
The tcp port lockd should listen on.
Note that setting this value will override all settings placed in the local /etc/sysconfig/nfs file.
</longdesc>
<shortdesc lang="en">
lockd tcp port
</shortdesc>
<content type="integer" />
</parameter>

<parameter name="statd_outgoing_port" unique="0" required="0">
<longdesc lang="en">
The source port number sm-notify uses when sending reboot notifications.
Note that setting this value will override all settings placed in the local /etc/sysconfig/nfs file.
</longdesc>
<shortdesc lang="en">
sm-notify source port
</shortdesc>
<content type="integer" />
</parameter>

<parameter name="statd_port" unique="0" required="0">
<longdesc lang="en">
The port number used for RPC listener sockets.
Note that setting this value will override all settings placed in the local /etc/sysconfig/nfs file.
</longdesc>
<shortdesc lang="en">
rpc.statd listener port
</shortdesc>
<content type="integer" />
</parameter>

<parameter name="mountd_port" unique="0" required="0">
<longdesc lang="en">
The port number used for rpc.mountd listener sockets.
Note that setting this value will override all settings placed in the local /etc/sysconfig/nfs file.
</longdesc>
<shortdesc lang="en">
rpc.mountd listener port
</shortdesc>
<content type="integer" />
</parameter>

<parameter name="rquotad_port" unique="0" required="0">
<longdesc lang="en">
The port number used for rpc.rquotad.
Note that setting this value will override all settings placed in the local /etc/sysconfig/nfs file.
</longdesc>
<shortdesc lang="en">
rpc.rquotad port
</shortdesc>
<content type="integer" />
</parameter>

<parameter name="nfs_shared_infodir" unique="0" required="0">
<longdesc lang="en">
The nfsserver resource agent will save nfs related information in this specific directory.
And this directory must be able to fail-over before nfsserver itself.
</longdesc>
<shortdesc lang="en">
Directory to store nfs server related information.
</shortdesc>
<content type="string" default="" />
</parameter>

<parameter name="rpcpipefs_dir" unique="0" required="0">
<longdesc lang="en">
The mount point for the sunrpc file system. Default is $DEFAULT_RPCPIPEFS_DIR. 
This script will mount (bind) nfs_shared_infodir on /var/lib/nfs/ (cannot be changed),
and this script will mount the sunrpc file system on $DEFAULT_RPCPIPEFS_DIR (default, can be changed by this parameter).
If you want to move only rpc_pipefs/ (e.g. to keep rpc_pipefs/ local) from default, please set this value.
</longdesc>
<shortdesc lang="en">
The mount point for the sunrpc file system.
</shortdesc>
<content type="string" default="$DEFAULT_RPCPIPEFS_DIR" />
</parameter>

</parameters>

<actions>
<action name="start"   timeout="40" />
<action name="stop"    timeout="20s" />
<action name="monitor" depth="0"  timeout="20s" interval="10" />
<action name="meta-data"  timeout="5" />
<action name="validate-all"  timeout="30" />
</actions>
</resource-agent>
END

return $OCF_SUCCESS
}

nfsserver_usage() {
	cat <<END
		usage: $0 {start|stop|monitor|status|validate-all|meta-data}
END
}

if [ $# -ne 1 ]; then
	nfsserver_usage
	exit $OCF_ERR_ARGS
fi

case $__OCF_ACTION in
	meta-data)  nfsserver_meta_data
		exit $OCF_SUCCESS
		;;
	usage|help) nfsserver_usage
		exit $OCF_SUCCESS
		;;
	*)
		;;	
esac

fp="$OCF_RESKEY_nfs_shared_infodir"
: ${OCF_RESKEY_nfs_notify_cmd="$DEFAULT_NOTIFY_CMD"}
: ${OCF_RESKEY_nfs_notify_foreground="$DEFAULT_NOTIFY_FOREGROUND"}

if [ -z ${OCF_RESKEY_rpcpipefs_dir} ]; then
	rpcpipefs_make_dir=$fp/rpc_pipefs
	rpcpipefs_umount_dir=${DEFAULT_RPCPIPEFS_DIR}
else
	rpcpipefs_make_dir=${OCF_RESKEY_rpcpipefs_dir}
	rpcpipefs_umount_dir=${OCF_RESKEY_rpcpipefs_dir}
fi

# Use statd folder if it exists
if [ -d "/var/lib/nfs/statd" ]; then
	STATD_DIR="statd"
	STATD_PATH="/var/lib/nfs/statd"
fi

# SELinux information. We are taking the permissions from
# the current statd dir and applying it to the HA one that is
# being mounted in its place.
which restorecon > /dev/null 2>&1 && selinuxenabled
SELINUX_ENABLED=$?
if [ $SELINUX_ENABLED -eq 0 ]; then
	export SELINUX_LABEL="$(ls -ldZ $STATD_PATH | cut -f4 -d' ')"
fi

##
# EXEC_MODE values
# 1  user init script or default init script
# 2  systemd
#
# On error, this function will terminate the process
# with error code $OCF_ERR_INSTALLED
##
set_exec_mode()
{

	##
	# If EXEC_MODE is already set, we don't need to run this function again.
	## 
	if [ $EXEC_MODE -ne 0 ]; then
		return 0;
	fi

	##
	# If the user defined an init script, It must exist for us to continue
	##
	if [ -n "$OCF_RESKEY_nfs_init_script" ]; then
		# check_binary will exit the process if init script does not exist
		check_binary ${OCF_RESKEY_nfs_init_script}
		EXEC_MODE=1
		return 0
	fi

	##
	# Check to see if the default init script exists, if so we'll use that.
	##
	if which $DEFAULT_INIT_SCRIPT > /dev/null 2>&1; then
		OCF_RESKEY_nfs_init_script=$DEFAULT_INIT_SCRIPT
		EXEC_MODE=1
		return 0
	fi

	##
	# Last of all, attempt systemd.
	##
	if which systemctl > /dev/null 2>&1; then
		if systemctl list-unit-files | grep nfs-server > /dev/null && systemctl list-unit-files | grep nfs-lock > /dev/null; then
			EXEC_MODE=2
			# when using systemd, the nfs-lock service file handles nfsv3 locking daemons for us.
			return 0
		fi
	fi

	ocf_exit_reason "No init script or systemd unit file detected for nfs server"
	exit $OCF_ERR_INSTALLED
}

##
# wrapper for init script and systemd calls.
##
nfs_exec()
{
	local cmd=$1
	set_exec_mode

	case $EXEC_MODE in 
		1) ${OCF_RESKEY_nfs_init_script} $cmd;;
		2) systemctl $cmd nfs-server.service ;;
	esac
}

v3locking_exec()
{
	local cmd=$1
	set_exec_mode

	if [ $EXEC_MODE -eq 2 ]; then
		systemctl $cmd nfs-lock.service
	else 
		case $cmd in
			start) locking_start;;
			stop) locking_stop;;
			status) locking_status;;
		esac
	fi
}

nfsserver_monitor ()
{
	fn=`mktemp`
	nfs_exec status > $fn 2>&1 
	rc=$?
	ocf_log debug "$(cat $fn)"
	rm -f $fn

	#Adapte LSB status code to OCF return code
	if [ $rc -eq 0 ]; then
		# don't report success if nfs servers are up
		# without locking daemons.
		v3locking_exec "status"
		rc=$?
		if [ $rc -ne 0 ]; then
			ocf_exit_reason "NFS server is up, but the locking daemons are down"
			rc=$OCF_ERR_GENERIC
		fi
		return $rc
	elif [ $rc -eq 3 ]; then
		return $OCF_NOT_RUNNING
	else
		return $OCF_ERR_GENERIC
	fi
}

set_arg()
{
	local key="$1"
	local value="$2"
	local file="$3"
	local requires_sysconfig="$4"

	if [ -z "$value" ]; then
		return
	fi

	# only write to the tmp /etc/sysconfig/nfs if sysconfig exists.
	# otherwise this distro does not support setting these options.
	if [ -d "/etc/sysconfig" ]; then
		echo "${key}=\"${value}\"" >> $file
	elif [ "$requires_sysconfig" = "true" ]; then
		ocf_log warn "/etc/sysconfig/nfs not found, unable to set port and nfsd args."
	fi

	export ${key}="${value}"
}

set_env_args()
{
	local tmpconfig=$(mktemp ${HA_RSCTMP}/nfsserver-tmp-XXXXX)
	local statd_args

	# nfsd args
	set_arg "RPCNFSDARGS" "$OCF_RESKEY_nfsd_args" "$tmpconfig" "true"

	# mountd args
	if [ -n "$OCF_RESKEY_mountd_port" ]; then
		set_arg "RPCMOUNTDOPTS" "-p $OCF_RESKEY_mountd_port" "$tmpconfig" "true"
	fi

	# statd args. we always want to perform the notify using sm-notify after
	# both rpc.statd and the nfsd daemons are initialized
	statd_args="--no-notify"
	if [ -n "$OCF_RESKEY_statd_outgoing_port" ]; then
		statd_args="$statd_args -o $OCF_RESKEY_statd_outgoing_port"
	fi
	if [ -n "$OCF_RESKEY_statd_port" ]; then
		statd_args="$statd_args -p $OCF_RESKEY_statd_port"
	fi
	set_arg "STATDARG" "$statd_args" "$tmpconfig" "false"

	# lockd ports
	set_arg "LOCKD_UDPPORT" "$OCF_RESKEY_lockd_udp_port" "$tmpconfig" "true"
	set_arg "LOCKD_TCPPORT" "$OCF_RESKEY_lockd_tcp_port" "$tmpconfig" "true"

	# rquotad_port
	if [ -n "$OCF_RESKEY_rquotad_port" ]; then
		set_arg "RPCRQUOTADOPTS" "-p $OCF_RESKEY_rquotad_port" "$tmpconfig" "true"
	fi

	# override local nfs config. preserve previous local config though.
	if [ -s $tmpconfig ]; then
		cat $NFS_SYSCONFIG | grep -e "$NFS_SYSCONFIG_AUTOGEN_TAG"
		if [ $? -ne 0 ]; then
			# backup local nfs config if it doesn't have our HA autogen tag in it.
			mv -f $NFS_SYSCONFIG $NFS_SYSCONFIG_LOCAL_BACKUP
		fi
		echo "# $NFS_SYSCONFIG_AUTOGEN_TAG" > $NFS_SYSCONFIG
		echo "# local config backup stored here, '$NFS_SYSCONFIG_LOCAL_BACKUP'" >> $NFS_SYSCONFIG
		cat $tmpconfig >> $NFS_SYSCONFIG
	fi
	rm -f $tmpconfig
}

prepare_directory ()
{
	if [ -z "$fp" ]; then
		return
	fi

	[ -d "$fp" ] || mkdir -p $fp
	[ -d "$rpcpipefs_make_dir" ] || mkdir -p $rpcpipefs_make_dir
	[ -d "$fp/v4recovery" ] || mkdir -p $fp/v4recovery

	[ -d "$fp/$STATD_DIR" ] || mkdir -p "$fp/$STATD_DIR"
	[ -d "$fp/$STATD_DIR/sm" ] || mkdir -p "$fp/$STATD_DIR/sm"
	[ -d "$fp/$STATD_DIR/sm.ha" ] || mkdir -p "$fp/$STATD_DIR/sm.ha"
	[ -d "$fp/$STATD_DIR/sm.bak" ] || mkdir -p "$fp/$STATD_DIR/sm.bak"
	[ -n "`id -u rpcuser 2>/dev/null`" -a "`id -g rpcuser 2>/dev/null`" ] &&
		chown -R rpcuser.rpcuser "$fp/$STATD_DIR"

	[ -f "$fp/etab" ] || touch "$fp/etab"
	[ -f "$fp/xtab" ] || touch "$fp/xtab"
	[ -f "$fp/rmtab" ] || touch "$fp/rmtab"

	dd if=/dev/urandom of=$fp/$STATD_DIR/state bs=1 count=4 >/dev/null 2>&1
	[ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown rpcuser.rpcuser "$fp/$STATD_DIR/state"
	[ $SELINUX_ENABLED -eq 0 ] && chcon -R "$SELINUX_LABEL" "$fp"
}

is_bound ()
{
	if mount | grep -q "on $1 type"; then
		return 0
	fi

	return 1
}

bind_tree ()
{
	if [ -z "$fp" ]; then
		return
	fi

	if is_bound /var/lib/nfs; then
		ocf_log debug "$fp is already bound to /var/lib/nfs"
		return 0
	fi
	mount --bind $fp /var/lib/nfs
	[ $SELINUX_ENABLED -eq 0 ] && restorecon /var/lib/nfs
}

unbind_tree ()
{
	if `mount | grep -q " on $rpcpipefs_umount_dir"`; then
		umount -t rpc_pipefs $rpcpipefs_umount_dir
	fi
	if is_bound /var/lib/nfs; then
		umount /var/lib/nfs
	fi
}

binary_status()
{
	local binary=$1
	local pid

	pid=$(pgrep ${binary})
	case $? in
		0)
			echo "$pid"
			return $OCF_SUCCESS;;
		1)
			return $OCF_NOT_RUNNING;;
		*)
			return $OCF_ERR_GENERIC;;
	esac
}

locking_status()
{
	binary_status "rpc.statd" > /dev/null 2>&1
}

locking_start()
{
	local ret=$OCF_SUCCESS

	ocf_log info "Starting rpc.statd."

	rpc.statd $STATDARG

	ret=$?
	if [ $ret -ne 0 ]; then
		ocf_log err "Failed to start rpc.statd"
		return $ret
	fi
	touch /var/lock/subsys/nfslock

	return $ret
}

terminate()
{
	local pids
	local i=0

	while : ; do
		pids=$(binary_status $1)
		[ -z "$pids" ] && return 0
	 	kill $pids
		sleep 1
		i=$((i + 1))
		[ $i -gt 3 ] && return 1
	done
}


killkill()
{
	local pids
	local i=0

	while : ; do
		pids=$(binary_status $1)
		[ -z "$pids" ] && return 0
	 	kill -9 $pids
		sleep 1
		i=$((i + 1))
		[ $i -gt 3 ] && return 1
	done
}

stop_process()
{
	local process=$1

	ocf_log info "Stopping $process"
	if terminate $process; then
		ocf_log debug "$process is stopped"
	else
		if killkill $process; then
			ocf_log debug "$process is stopped"
		else
			ocf_log debug "Failed to stop $process"
			return 1
		fi
	fi
	return 0
}

locking_stop()
{
	ret=0

	# sm-notify can prevent umount of /var/lib/nfs/statd if
	# it is still trying to notify unresponsive clients.
	stop_process sm-notify
	if [ $? -ne 0 ]; then
		ret=$OCF_ERR_GENERIC
	fi

	stop_process rpc.statd
	if [ $? -ne 0 ]; then
		ret=$OCF_ERR_GENERIC
	fi

	return $ret
}

notify_locks()
{
	if ocf_is_true "$OCF_RESKEY_nfs_no_notify"; then
		# we've been asked not to notify clients
		return;
	fi

	# run in foreground, if requested
	if ocf_is_true "$OCF_RESKEY_nfs_notify_foreground"; then
		opts="-d"
	fi

	if [ -n "$OCF_RESKEY_nfs_smnotify_retry_time" ]; then
		opts="$opts -m $OCF_RESKEY_nfs_smnotify_retry_time"
	fi

	if [ -n "$OCF_RESKEY_statd_outgoing_port" ]; then
		opts="$opts -p $OCF_RESKEY_statd_outgoing_port"
	fi

	# forces re-notificaiton regardless if notifies have already gone out
	opts="$opts -f"

	ocf_log info "executing sm-notify"
	if [ -n "$OCF_RESKEY_nfs_ip" ]; then
		for ip in `echo ${OCF_RESKEY_nfs_ip} | sed 's/,/ /g'`; do
			cp -rpfn $STATD_PATH/sm.ha/* $STATD_PATH/  > /dev/null 2>&1
			sm-notify $opts -v $ip
		done
	else
		sm-notify $opts
	fi
}

nfsserver_start ()
{
	local rc;

	if nfsserver_monitor; then
		ocf_log debug "NFS server is already started"
		return $OCF_SUCCESS
	fi

	set_env_args
	prepare_directory
	bind_tree

	# remove the sm-notify pid so sm-notify will be allowed to run again without requiring a reboot.
	rm -f /var/run/sm-notify.pid
	#
	# Synchronize these before starting statd
	#
	cp -rpfn $STATD_PATH/sm.ha/* $STATD_PATH/ > /dev/null 2>&1
	rm -rf $STATD_PATH/sm.ha/* > /dev/null 2>&1
	cp -rpf $STATD_PATH/sm $STATD_PATH/sm.bak /var/lib/nfs/state $STATD_PATH/sm.ha > /dev/null 2>&1

	ocf_log info "Starting NFS server ..."

	# mounts /proc/fs/nfsd for us
	lsmod | grep -q nfsd
	if [ $? -ne 0 ]; then
		modprobe nfsd
	fi

	# check to see if we need to start rpc.statd
	v3locking_exec "status"
	if [ $? -ne $OCF_SUCCESS ]; then
		v3locking_exec "start"
		rc=$?
		if [ $rc -ne 0 ]; then
			ocf_exit_reason "Failed to start NFS server locking daemons"
			return $rc
		fi
	else
		ocf_log info "rpc.statd already up"
	fi

	fn=`mktemp`
	nfs_exec start > $fn 2>&1
	rc=$?
	ocf_log debug "$(cat $fn)"
	rm -f $fn

	if [ $rc -ne 0 ]; then
		ocf_exit_reason "Failed to start NFS server"
		return $rc
	fi	

	notify_locks

	ocf_log info "NFS server started"
	return $OCF_SUCCESS
}

nfsserver_stop ()
{
	ocf_log info "Stopping NFS server ..."

	# backup the current sm state information to the ha folder before stopping.
	# the ha folder will be synced after startup, restoring the statd client state
	rm -rf $STATD_PATH/sm.ha/* > /dev/null 2>&1
	cp -rpf $STATD_PATH/sm $STATD_PATH/sm.bak /var/lib/nfs/state $STATD_PATH/sm.ha > /dev/null 2>&1

	fn=`mktemp`
	nfs_exec stop > $fn 2>&1
	rc=$?
	ocf_log debug "$(cat $fn)"
	rm -f $fn

	v3locking_exec "stop"
	if [ $? -ne 0 ]; then
		ocf_exit_reason "Failed to stop NFS locking daemons"
		rc=$OCF_ERR_GENERIC
	fi

	if [ $rc -eq 0 ]; then
		unbind_tree 
		ocf_log info "NFS server stopped"
	else 
		ocf_exit_reason "Failed to stop NFS server"
	fi
	return $rc
}

nfsserver_validate ()
{
	##
	# set_exec_mode will exit if nfs server is not installed
	##
	set_exec_mode
	check_binary ${OCF_RESKEY_nfs_notify_cmd}


	if [ -n "$OCF_RESKEY_CRM_meta_clone" ] && [ -n "$OCF_RESKEY_nfs_shared_infodir" ]; then
		ocf_exit_reason "This RA does not support clone mode when a shared info directory is in use."
		exit $OCF_ERR_CONFIGURED
	fi

	if [ -n "$OCF_RESKEY_nfs_smnotify_retry_time" ]; then
		if ! ocf_is_decimal "$OCF_RESKEY_nfs_smnotify_retry_time"; then
			ocf_exit_reason "Invalid nfs_smnotify_retry_time [$OCF_RESKEY_nfs_smnotify_retry_time]"
			exit $OCF_ERR_CONFIGURED
		fi
	fi

	case ${OCF_RESKEY_nfs_notify_cmd##*/} in
	sm-notify|rpc.statd) ;;
	*)
		ocf_exit_reason "Invalid nfs_notify_cmd [$OCF_RESKEY_nfs_notify_cmd]"
		exit $OCF_ERR_CONFIGURED
		;;
	esac

	return $OCF_SUCCESS
}

nfsserver_validate

case $__OCF_ACTION in
	start)      nfsserver_start
		;;
	stop)       nfsserver_stop
		;;
	monitor)    nfsserver_monitor
		;;
	validate-all)   exit $OCF_SUCCESS
		;;
	*)      nfsserver_usage
	exit $OCF_ERR_UNIMPLEMENTED
	;;
esac

