3 # This is an example CTDB NFS callout script for Ganesha. It is based
4 # on the last version of 60.ganesha shipped with CTDB. As such, it
5 # does not try to monitor RPC services that were not monitored by
6 # 60.ganesha - this might be a useful improvement. It has also not
7 # been properly tested.
9 # You should check your version of NFS Ganesha to see if it ships with
14 # * Set CTDB_NFS_CALLOUT in your CTDB configuration to point to (a
15 # copy of) this script, making sure it is executable.
17 # * Create a new directory alongside the nfs-checks.d directory, for
18 # example nfs-checks-ganesha.d. Install 20.nfs-ganesha.check in
19 # this directory. Symlink to any other check files from
20 # nfs-checks.d that should still be used, such as
21 # 00.portmapper.check. Set CTDB_NFS_CHECKS_DIR to point to this new
22 # directory of check files.
24 # * It is recommended, but not required, to install the grace_period
25 # script (usually shipped in a utils package for NFS-Ganesha) to
26 # /usr/bin/grace_period
28 # I (Martin Schwenke) hereby relicense all of my contributions to this
29 # callout (and, previously, to 60.ganesha) to a license compatible
30 # with NFS Ganesha (right now this is LGPLv3, but I'm flexible).
31 # There may be other contributions to be considered for relicensing,
32 # particularly those in commit 28cbe527d47822f870e8252495ab2a1c8fddd12f.
34 ######################################################################
39 # Filesystem type and mount point for the (typically clustered)
40 # volume that will contain the NFS-Ganesha state.
41 state_fs="${CTDB_NFS_STATE_FS_TYPE:-gpfs}"
42 state_dir="${CTDB_NFS_STATE_MNT}" # No sane default.
44 # To change the following, edit the default values below. Do not set
45 # these - they aren't configuration variables, just hooks for testing.
46 nfs_exports_file="${CTDB_NFS_EXPORTS_FILE:-/etc/ganesha/ganesha.conf}"
47 nfs_service="${CTDB_NFS_SERVICE:-nfs-ganesha}"
48 ganesha_rec_subdir=${CTDB_GANESHA_REC_SUBDIR:-.ganesha}
49 procfs=${PROCFS_PATH:-/proc}
53 GANRECDIR="/var/lib/nfs/ganesha"
56 if [ -z "${state_dir}" ]; then
57 echo "CTDB_NFS_STATE_MNT not defined for GlusterFS"
61 NODESTATEDIR="$state_dir/nfs-ganesha/$host"
62 GANSTATEDIR="$state_dir/nfs-ganesha/.noderefs"
63 NODESTATELN="$GANSTATEDIR/$host"
68 ##################################################
74 usage: $_c { shutdown | startup }
75 $_c { stop | start | check } nfs
76 $_c { releaseip | takeip }
77 $_c { monitor-list-shares }
83 ##################################################
84 # Basic service stop and start
90 service "$nfs_service" stop
101 service "$nfs_service" start
108 ##################################################
109 # "stop" and "start" options for restarting
118 # Do nothing - used by statd-callout
133 # Do nothing - used by statd-callout
141 ##################################################
142 # Nitty gritty - monitoring and IP handling
144 # Check that a symlink exists, create it otherwise.
145 # Usage: check_ln <TARGET> <LINK>
148 if [ ! -L "${2}" ] ; then
151 _t=$(readlink "${2}")
152 if [ "$_t" != "${1}" ] ; then
156 # This is not an "else". It also re-creates the link if it was
158 if [ ! -e "${2}" ]; then
159 ln -sfv "${1}" "${2}"
163 # Return 'active' if the shared filesystem is accessible.
164 get_cluster_fs_state ()
168 /usr/lpp/mmfs/bin/mmgetstate | awk 'NR == 4 { print $3 }'
171 # Since we're past create_ganesha_recdirs(), we're active.
175 echo "File system $state_fs not supported"
181 create_ganesha_recdirs ()
183 if ! _mounts=$(mount | grep "$state_fs"); then
184 echo "Failed to find mounts of type $state_fs"
187 if [ -z "$_mounts" ]; then
188 echo "startup $state_fs not ready"
194 _mntpt=$(echo "$_mounts" | sort | awk 'NR == 1 {print $3}')
195 _link_dst="${_mntpt}/${ganesha_rec_subdir}"
196 mkdir -vp "$_link_dst"
197 check_ln "$_link_dst" "$GANRECDIR"
200 [ -d /var/lib/nfs.backup ] || \
201 mv /var/lib/nfs /var/lib/nfs.backup
202 check_ln "$NODESTATEDIR" /var/lib/nfs
204 mkdir -p "${NODESTATEDIR}/ganesha/v4recov"
205 mkdir -p "${NODESTATEDIR}/ganesha/v4old"
206 mkdir -p "${NODESTATEDIR}/statd/sm"
207 mkdir -p "${NODESTATEDIR}/statd/sm.bak"
208 touch "${NODESTATEDIR}/state"
209 touch "${NODESTATEDIR}/statd/state"
211 mkdir -p "$GANSTATEDIR"
212 check_ln "$NODESTATEDIR" "$NODESTATELN"
213 for _dir in "${GANSTATEDIR}/"* ; do
214 # Handle no directories case
215 if [ ! -d "$_dir" ] ; then
219 _node="${_dir##*/}" # basename
220 if [ "${_node}" != "${host}" ]; then
221 check_ln "${GANSTATEDIR}/${_node}/ganesha" \
222 "${NODESTATEDIR}/ganesha/${_node}"
223 check_ln "${GANSTATEDIR}/${_node}/statd" \
224 "${NODESTATEDIR}/statd/${_node}"
233 create_ganesha_recdirs
235 # Always succeed if cluster filesystem is not active
236 _cluster_fs_state=$(get_cluster_fs_state)
237 if [ "$_cluster_fs_state" != "active" ] ; then
241 # Check that NFS Ganesha is running, according to PID file
242 _pidfile="/var/run/ganesha.pid"
243 _ganesha="/usr/bin/ganesha.nfsd"
244 if ! { read -r _pid < "$_pidfile" && \
245 grep "$_ganesha" "${procfs}/${_pid}/cmdline" ; } >/dev/null 2>&1
248 echo "ERROR: NFS Ganesha not running according to PID file"
255 #-------------------------------------------------
261 if [ -x "/usr/bin/grace_period" ]; then
262 /usr/bin/grace_period "$_arg"
264 dbus-send --print-reply --system --dest=org.ganesha.nfsd \
265 /org/ganesha/nfsd/admin org.ganesha.nfsd.admin.grace \
274 # NFS-Ganesha recovery code only processes items matching $_ip
275 grace_period "2:${_ip}"
284 check_ln "$NODESTATEDIR" "${GANSTATEDIR}/${_ip}"
288 grace_period "5:${_ip}"
291 ##################################################
292 # service init startup and final shutdown
301 basic_stop "nfs" || true
303 create_ganesha_recdirs
306 _f="${procfs}/sys/net/ipv4/tcp_tw_recycle"
307 if [ -f "$_f" ] ; then
312 ##################################################
313 # list share directories
315 nfs_monitor_list_shares ()
317 grep Path "$nfs_exports_file" |
322 ##################################################
338 ##################################################
344 shutdown) nfs_shutdown ;;
345 startup) nfs_startup ;;
346 stop) service_stop "$1" ;;
347 start) service_start "$1" ;;
348 check) service_check "$1" ;;
349 releaseip) nfs_releaseip "$@" ;;
350 takeip) nfs_takeip "$@" ;;
351 monitor-list-shares) nfs_monitor_list_shares ;;
352 register) nfs_register ;;
353 monitor-pre|monitor-post|releaseip-pre|takeip-pre|startipreallocate)
354 # Not required/implemented