Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3687428
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
index 5b375b006..fe409b0f9 100755
--- a/heartbeat/nfsserver
+++ b/heartbeat/nfsserver
@@ -1,661 +1,665 @@
#!/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=""
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_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_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="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="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="nfs_shared_infodir" unique="0" required="1">
+<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_log err "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_log error "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_nfsd_args()
{
local args
if [ -z "$OCF_RESKEY_nfsd_args" ]; then
return
fi
# If we don't move this file. It will override our environment variables.
mv -f /etc/sysconfig/nfs /etc/sysconfig/nfs.bu
echo "RPCNFSDARGS=$OCF_RESKEY_nfsd_args" > /etc/sysconfig/nfs
export RPCNFSDARGS=$OCF_RESKEY_nfsd_args
}
cleanup_nfsd_args()
{
if [ -z "$OCF_RESKEY_nfsd_args" ]; then
return
fi
rm -f /etc/sysconfig/nfs
mv -f /etc/sysconfig/nfs.bu /etc/sysconfig/nfs
}
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`" -a "`id -g rpcuser`" ] && 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"
[ $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."
if [ -n "$OCF_RESKEY_nfs_ip" ]; then
rm -rf $STATD_PATH/sm.ha.save > /dev/null 2>&1
cp -rpf $STATD_PATH/sm.ha $STATD_PATH/sm.ha.save > /dev/null 2>&1
for ip in `echo ${OCF_RESKEY_nfs_ip} | sed 's/,/ /g'`; do
rpc.statd -n $ip -P $STATD_PATH/sm.ha
ret=$?
if [ $ret -eq 0 ]; then
break
fi
rm -rf $STATD_PATH/sm.ha > /dev/null 2>&1
cp -rpf $STATD_PATH/sm.ha.save $STATD_PATH/sm.ha > /dev/null 2>&1
done
else
rpc.statd -d
fi
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()
{
declare pids
declare i=0
while : ; do
pids=$(binary_status $1)
[ -z "$pids" ] && return 0
kill $pids
sleep 1
((i++))
[ $i -gt 3 ] && return 1
done
}
killkill()
{
declare pids
declare i=0
while : ; do
pids=$(binary_status $1)
[ -z "$pids" ] && return 0
kill -9 $pids
sleep 1
((i++))
[ $i -gt 3 ] && return 1
done
}
stop_process()
{
declare 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
}
renotify_locks()
{
# 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
# 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
rm -rf $STATD_PATH/sm.ha.save > /dev/null 2>&1
cp -rpf $STATD_PATH/sm.ha $STATD_PATH/sm.ha.save > /dev/null 2>&1
for ip in `echo ${OCF_RESKEY_nfs_ip} | sed 's/,/ /g'`; do
sm-notify $opts -v $ip -P $STATD_PATH/sm.ha
rm -rf $STATD_PATH/sm.ha > /dev/null 2>&1
cp -rpf $STATD_PATH/sm.ha.save $STATD_PATH/sm.ha > /dev/null 2>&1
done
else
sm-notify $opts
fi
}
nfsserver_start ()
{
local notifies_sent=0;
local rc;
if nfsserver_monitor; then
ocf_log debug "NFS server is already started"
return $OCF_SUCCESS
fi
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
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 ..."
# 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_log error "Failed to start NFS server locking daemons"
return $rc
fi
# rpc.statd sends notifies automatically
notifies_sent=1
else
ocf_log info "rpc.statd already up"
fi
set_nfsd_args
fn=`mktemp`
nfs_exec start > $fn 2>&1
rc=$?
ocf_log debug "$(cat $fn)"
rm -f $fn
cleanup_nfsd_args
if [ $rc -ne 0 ]; then
ocf_log err "Failed to start NFS server"
return $rc
fi
# notify peers using sm-notify if rpc.statd was already initialized.
# Otherwise the initalization of rpc.statd started sm-notify for us.
if [ $notifies_sent -eq 0 ]; then
renotify_locks
fi
ocf_log info "NFS server started"
return $OCF_SUCCESS
}
nfsserver_stop ()
{
ocf_log info "Stopping NFS server ..."
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_log err "Failed to stop NFS locking daemons"
rc=$OCF_ERR_GENERIC
fi
if [ $rc -eq 0 ]; then
unbind_tree
ocf_log info "NFS server stopped"
return $OCF_SUCCESS
fi
ocf_log err "Failed to stop NFS server"
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 [ x = "x$OCF_RESKEY_nfs_shared_infodir" ]; then
- ocf_log err "nfs_shared_infodir not set"
+
+ if [ -n "$OCF_RESKEY_CRM_meta_clone" ] && [ -n "$OCF_RESKEY_nfs_shared_infodir" ]; then
+ ocf_log err "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_log err "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_log err "Invalid nfs_notify_cmd [$OCF_RESKEY_nfs_notify_cmd]"
exit $OCF_ERR_CONFIGURED
;;
esac
return $OCF_SUCCESS
}
-if [ -n "$OCF_RESKEY_CRM_meta_clone" ]; then
- ocf_log err "THIS RA DOES NOT SUPPORT CLONE MODE!"
- exit $OCF_ERR_CONFIGURED
-fi
-
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
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Apr 21, 7:24 PM (4 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1665526
Default Alt Text
(16 KB)
Attached To
Mode
rR Resource Agents
Attached
Detach File
Event Timeline
Log In to Comment