mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
8c21aac77f
This call-out is referred to in the wiki as an example, so make it as clean as possible. All the changes here are trivial. There is still one failure, which is slightly non-trivial, so it can be fixed in a separate commit. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
350 lines
7.4 KiB
Bash
Executable File
350 lines
7.4 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# This is an example CTDB NFS callout script for Ganesha. It is based
|
|
# on the last version of 60.ganesha shipped with CTDB. As such, it
|
|
# does not try to monitor RPC services that were not monitored by
|
|
# 60.ganesha - this might be a useful improvement. It has also not
|
|
# been properly tested.
|
|
|
|
# You should check your version of NFS Ganesha to see if it ships with
|
|
# a newer callout.
|
|
|
|
# To use this:
|
|
#
|
|
# * Set CTDB_NFS_CALLOUT in your CTDB configuration to point to this
|
|
# script
|
|
#
|
|
# * Rename the following files in nfs-checks.d so that they no longer
|
|
# have the ".check" suffix:
|
|
# * 10.status.check
|
|
# * 20.nfs.check
|
|
# * 30.nlockmgr.check
|
|
# * 40.mountd.check
|
|
# * 50.rquotad.check
|
|
#
|
|
# * Install 20.nfs-ganesha.check to nfs-checks.d/20.nfs.check
|
|
#
|
|
# * It is recommended, but not required, to install the grace_period
|
|
# script (usually shipped in a utils package for NFS-Ganesha) to
|
|
# /usr/bin/grace_period
|
|
|
|
# I (Martin Schwenke) hereby relicense all of my contributions to this
|
|
# callout (and, previously, to 60.ganesha) to a license compatible
|
|
# with NFS Ganesha (right now this is LGPLv3, but I'm flexible).
|
|
# There may be other contributions to be considered for relicensing,
|
|
# particularly those in commit 28cbe527d47822f870e8252495ab2a1c8fddd12f.
|
|
|
|
######################################################################
|
|
|
|
# Exit on 1st error
|
|
set -e
|
|
|
|
# Filesystem type and mount point for the (typically clustered)
|
|
# volume that will contain the NFS-Ganesha state.
|
|
state_fs="${CTDB_NFS_STATE_FS_TYPE:-gpfs}"
|
|
state_dir="${CTDB_NFS_STATE_MNT}" # No sane default.
|
|
|
|
# To change the following, edit the default values below. Do not set
|
|
# these - they aren't configuration variables, just hooks for testing.
|
|
nfs_exports_file="${CTDB_NFS_EXPORTS_FILE:-/etc/ganesha/ganesha.conf}"
|
|
nfs_service="${CTDB_NFS_SERVICE:-nfs-ganesha}"
|
|
ganesha_rec_subdir=${CTDB_GANESHA_REC_SUBDIR:-.ganesha}
|
|
procfs=${PROCFS_PATH:-/proc}
|
|
|
|
case "$state_fs" in
|
|
gpfs)
|
|
GANRECDIR="/var/lib/nfs/ganesha"
|
|
;;
|
|
glusterfs)
|
|
if [ -z "${state_dir}" ]; then
|
|
echo "CTDB_NFS_STATE_MNT not defined for GlusterFS"
|
|
exit 1
|
|
fi
|
|
host=$(hostname)
|
|
NODESTATEDIR="$state_dir/nfs-ganesha/$host"
|
|
GANSTATEDIR="$state_dir/nfs-ganesha/.noderefs"
|
|
NODESTATELN="$GANSTATEDIR/$host"
|
|
;;
|
|
esac
|
|
|
|
|
|
##################################################
|
|
|
|
usage ()
|
|
{
|
|
_c=$(basename "$0")
|
|
cat <<EOF
|
|
usage: $_c { shutdown | startup }
|
|
$_c { stop | start | check } nfs
|
|
$_c { releaseip | takeip }
|
|
$_c { monitor-list-shares }
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
|
|
##################################################
|
|
# Basic service stop and start
|
|
|
|
basic_stop ()
|
|
{
|
|
case "$1" in
|
|
nfs)
|
|
service "$nfs_service" stop
|
|
;;
|
|
*)
|
|
usage
|
|
esac
|
|
}
|
|
|
|
basic_start ()
|
|
{
|
|
case "$1" in
|
|
nfs)
|
|
service "$nfs_service" start
|
|
;;
|
|
*)
|
|
usage
|
|
esac
|
|
}
|
|
|
|
##################################################
|
|
# "stop" and "start" options for restarting
|
|
|
|
service_stop ()
|
|
{
|
|
case "$1" in
|
|
nfs)
|
|
basic_stop "nfs"
|
|
;;
|
|
nlockmgr)
|
|
# Do nothing - used by statd-callout
|
|
:
|
|
;;
|
|
*)
|
|
usage
|
|
esac
|
|
}
|
|
|
|
service_start ()
|
|
{
|
|
case "$1" in
|
|
nfs)
|
|
basic_start "nfs"
|
|
;;
|
|
nlockmgr)
|
|
# Do nothing - used by statd-callout
|
|
:
|
|
;;
|
|
*)
|
|
usage
|
|
esac
|
|
}
|
|
|
|
##################################################
|
|
# Nitty gritty - monitoring and IP handling
|
|
|
|
# Check that a symlink exists, create it otherwise.
|
|
# Usage: check_ln <TARGET> <LINK>
|
|
check_ln ()
|
|
{
|
|
if [ ! -L "${2}" ] ; then
|
|
rm -vrf "${2}"
|
|
else
|
|
_t=$(readlink "${2}")
|
|
if [ "$_t" != "${1}" ] ; then
|
|
rm -v "${2}"
|
|
fi
|
|
fi
|
|
# This is not an "else". It also re-creates the link if it was
|
|
# removed above!
|
|
if [ ! -e "${2}" ]; then
|
|
ln -sfv "${1}" "${2}"
|
|
fi
|
|
}
|
|
|
|
# Return 'active' if the shared filesystem is accessible.
|
|
get_cluster_fs_state ()
|
|
{
|
|
case $state_fs in
|
|
gpfs)
|
|
/usr/lpp/mmfs/bin/mmgetstate | awk 'NR == 4 { print $3 }'
|
|
;;
|
|
glusterfs)
|
|
# Since we're past create_ganesha_recdirs(), we're active.
|
|
echo "active"
|
|
;;
|
|
*)
|
|
echo "File system $state_fs not supported"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
create_ganesha_recdirs ()
|
|
{
|
|
if ! _mounts=$(mount | grep "$state_fs"); then
|
|
echo "Failed to find mounts of type $state_fs"
|
|
exit 1
|
|
fi
|
|
if [ -z "$_mounts" ]; then
|
|
echo "startup $state_fs not ready"
|
|
exit 0
|
|
fi
|
|
|
|
case $state_fs in
|
|
gpfs)
|
|
_mntpt=$(echo "$_mounts" | sort | awk 'NR == 1 {print $3}')
|
|
_link_dst="${_mntpt}/${ganesha_rec_subdir}"
|
|
mkdir -vp "$_link_dst"
|
|
check_ln "$_link_dst" "$GANRECDIR"
|
|
;;
|
|
glusterfs)
|
|
[ -d /var/lib/nfs.backup ] || \
|
|
mv /var/lib/nfs /var/lib/nfs.backup
|
|
check_ln "$NODESTATEDIR" /var/lib/nfs
|
|
|
|
mkdir -p "${NODESTATEDIR}/ganesha/v4recov"
|
|
mkdir -p "${NODESTATEDIR}/ganesha/v4old"
|
|
mkdir -p "${NODESTATEDIR}/statd/sm"
|
|
mkdir -p "${NODESTATEDIR}/statd/sm.bak"
|
|
touch "${NODESTATEDIR}/state"
|
|
touch "${NODESTATEDIR}/statd/state"
|
|
|
|
mkdir -p "$GANSTATEDIR"
|
|
check_ln "$NODESTATEDIR" "$NODESTATELN"
|
|
for node in `ls ${GANSTATEDIR}`; do
|
|
if [ "${node}" != "${host}" ]; then
|
|
check_ln "${GANSTATEDIR}/${node}/ganesha" \
|
|
"${NODESTATEDIR}/ganesha/${node}"
|
|
check_ln "${GANSTATEDIR}/${node}/statd" \
|
|
"${NODESTATEDIR}/statd/${node}"
|
|
fi
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
service_check ()
|
|
{
|
|
create_ganesha_recdirs
|
|
|
|
# Always succeed if cluster filesystem is not active
|
|
_cluster_fs_state=$(get_cluster_fs_state)
|
|
if [ "$_cluster_fs_state" != "active" ] ; then
|
|
return 0
|
|
fi
|
|
|
|
# Check that NFS Ganesha is running, according to PID file
|
|
_pidfile="/var/run/ganesha.pid"
|
|
_ganesha="/usr/bin/ganesha.nfsd"
|
|
if ! { read -r _pid < "$_pidfile" && \
|
|
grep "$_ganesha" "${procfs}/${_pid}/cmdline" ; } >/dev/null 2>&1
|
|
then
|
|
|
|
echo "ERROR: NFS Ganesha not running according to PID file"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
#-------------------------------------------------
|
|
|
|
nfs_releaseip ()
|
|
{
|
|
if [ -x "/usr/bin/grace_period" ]; then
|
|
/usr/bin/grace_period "2:${2}"
|
|
else
|
|
dbus-send --print-reply --system --dest=org.ganesha.nfsd \
|
|
/org/ganesha/nfsd/admin org.ganesha.nfsd.admin.grace \
|
|
string:"2:${2}"
|
|
fi
|
|
}
|
|
|
|
nfs_takeip ()
|
|
{
|
|
case $state_fs in
|
|
glusterfs)
|
|
check_ln "$NODESTATEDIR" "${GANSTATEDIR}/${2}"
|
|
;;
|
|
esac
|
|
if [ -x "/usr/bin/grace_period" ]; then
|
|
/usr/bin/grace_period "5:${2}"
|
|
else
|
|
dbus-send --print-reply --system --dest=org.ganesha.nfsd \
|
|
/org/ganesha/nfsd/admin org.ganesha.nfsd.admin.grace \
|
|
string:"5:${2}"
|
|
fi
|
|
}
|
|
|
|
##################################################
|
|
# service init startup and final shutdown
|
|
|
|
nfs_shutdown ()
|
|
{
|
|
basic_stop "nfs"
|
|
}
|
|
|
|
nfs_startup ()
|
|
{
|
|
basic_stop "nfs" || true
|
|
|
|
create_ganesha_recdirs
|
|
|
|
basic_start "nfs"
|
|
_f="${procfs}/sys/net/ipv4/tcp_tw_recycle"
|
|
if [ "$_f" ] ; then
|
|
echo 1 >"$_f"
|
|
fi
|
|
}
|
|
|
|
##################################################
|
|
# list share directories
|
|
|
|
nfs_monitor_list_shares ()
|
|
{
|
|
grep Path "$nfs_exports_file" |
|
|
cut -f2 -d\" |
|
|
sort -u
|
|
}
|
|
|
|
##################################################
|
|
|
|
nfs_register ()
|
|
{
|
|
cat <<EOF
|
|
shutdown
|
|
startup
|
|
stop
|
|
start
|
|
check
|
|
releaseip
|
|
takeip
|
|
monitor-list-shares
|
|
EOF
|
|
}
|
|
|
|
##################################################
|
|
|
|
action="$1"
|
|
shift
|
|
|
|
case "$action" in
|
|
shutdown) nfs_shutdown ;;
|
|
startup) nfs_startup ;;
|
|
stop) service_stop "$1" ;;
|
|
start) service_start "$1" ;;
|
|
check) service_check "$1" ;;
|
|
releaseip) nfs_releaseip "$@" ;;
|
|
takeip) nfs_takeip "$@" ;;
|
|
monitor-list-shares) nfs_monitor_list_shares ;;
|
|
register) nfs_register ;;
|
|
monitor-pre|monitor-post|releaseip-pre|takeip-pre)
|
|
# Not required/implemented
|
|
:
|
|
;;
|
|
*)
|
|
usage
|
|
esac
|