2 # script to manage nfs in a clustered environment
4 [ -n "$CTDB_BASE" ] || \
5 CTDB_BASE=$(d=$(dirname "$0") ; cd -P "$d" ; dirname "$PWD")
7 . "${CTDB_BASE}/functions"
11 load_system_config "nfs"
15 ctdb_setup_state_dir "service" "$service_name"
17 ######################################################################
19 service_reconfigure ()
21 # Restart lock manager, notify clients
22 if [ -x "${CTDB_BASE}/statd-callout" ] ; then
23 "${CTDB_BASE}/statd-callout" notify &
27 ######################################################################
29 ######################################################
30 # Check the health of NFS services
32 # Use .check files in $CTDB_NFS_CHECKS_DIR.
33 # Default is "${CTDB_BASE}/nfs-checks.d/"
34 ######################################################
37 _dir="${CTDB_NFS_CHECKS_DIR:-${CTDB_BASE}/nfs-checks.d}"
39 # Files must end with .check - avoids editor backups, RPM fu, ...
40 for _f in "$_dir"/[0-9][0-9].*.check ; do
41 [ -r "$_f" ] || continue
44 _progname="${_t##*/[0-9][0-9].}"
46 nfs_check_service "$_progname" <"$_f"
50 ######################################################
51 # Check the health of an NFS service
53 # $1 - progname, passed to rpcinfo (looked up in /etc/rpc)
55 # Reads variables from stdin
59 # * family - "tcp" or "udp" or space separated list
60 # default: tcp, not used with "service_check_cmd"
61 # * version - optional, RPC service version number
62 # default is to omit to check for any version,
63 # not used with "service_check_cmd"
64 # * unhealthy_after - number of check fails before unhealthy
66 # * restart_every - number of check fails before restart
67 # default: 0, meaning no restart
68 # * service_stop_cmd - command to stop service
69 # default: no default, must be provided if
71 # * service_start_cmd - command to start service
72 # default: no default, must be provided if
74 # * service_check_cmd - command to check health of service
75 # default is to check RPC service using rpcinfo
76 # * service_debug_cmd - command to debug a service after trying to stop it;
77 # for example, it can be useful to print stack
78 # traces of threads that have not exited, since
79 # they may be stuck doing I/O;
80 # no default, see also function program_stack_traces()
82 # Quoting in values is not preserved
84 ######################################################
89 # This sub-shell is created to intentionally limit the scope of
90 # variable values read from the .check files.
91 # shellcheck disable=SC2030
93 # Subshell to restrict scope variables...
105 # Eval line-by-line. Expands variable references in values.
106 # Also allows variable name checking, which seems useful.
107 while read _line ; do
109 \#*|"") : ;; # Ignore comments, blank lines
112 unhealthy_after=*|restart_every=*|\
113 service_stop_cmd=*|service_start_cmd=*|\
114 service_check_cmd=*|service_debug_cmd=*)
119 echo "ERROR: Unknown variable for ${_progname}: ${_line}"
125 if [ -n "$service_check_cmd" ] ; then
126 # Using eval means variables can contain semicolon separated commands
127 if eval "$service_check_cmd" ; then
130 _err="monitoring service \"${_progname}\" failed"
133 if nfs_check_rpcinfo \
134 "$_progname" "$version" "$family" >/dev/null ; then
137 _err="$ctdb_check_rpc_out"
142 if [ $unhealthy_after -ne 1 -o $restart_every -ne 0 ] ; then
143 ctdb_counter_init "$_progname"
148 ctdb_counter_incr "$_progname"
149 _failcount=$(ctdb_counter_get "$_progname")
152 if [ "$unhealthy_after" -gt 0 ] ; then
153 if [ "$_failcount" -ge "$unhealthy_after" ] ; then
159 if [ "$restart_every" -gt 0 ] ; then
160 if [ $((_failcount % restart_every)) -eq 0 ] ; then
161 if ! $_unhealthy ; then
162 echo "WARNING: $_err"
168 if $_unhealthy ; then
176 # Uses: service_stop_cmd, service_start_cmd, service_debug_cmd
177 # This function is called within the sub-shell that shellcheck thinks
178 # loses the above variable values.
179 # shellcheck disable=SC2031
180 nfs_restart_service ()
182 if [ -z "$service_stop_cmd" -o -z "$service_start_cmd" ] ; then
183 die "ERROR: Can not restart service \"${_progname}\" without corresponding service_start_cmd/service_stop_cmd settings"
186 echo "Trying to restart service \"${_progname}\"..."
187 # Using eval means variables can contain semicolon separated commands
188 eval "$service_stop_cmd"
189 if [ -n "$service_debug_cmd" ] ; then
190 eval "$service_debug_cmd"
192 background_with_logging eval "$service_start_cmd"
195 ######################################################
196 # Check an RPC service with rpcinfo
197 ######################################################
200 _progname="$1" # passed to rpcinfo (looked up in /etc/rpc)
201 _version="$2" # optional, not passed if empty/unset
202 _family="${3:-tcp}" # optional, default is "tcp"
206 _localhost="${CTDB_RPCINFO_LOCALHOST6:-::1}"
209 _localhost="${CTDB_RPCINFO_LOCALHOST:-127.0.0.1}"
212 # $_version is not quoted because it is optional
213 # shellcheck disable=SC2086
214 if ! ctdb_check_rpc_out=$(rpcinfo -T "$_family" "$_localhost" \
215 "$_progname" $_version 2>&1) ; then
216 ctdb_check_rpc_out="$_progname failed RPC check:
218 echo "$ctdb_check_rpc_out"
225 _progname="$1" # passed to rpcinfo (looked up in /etc/rpc)
226 _versions="$2" # optional, space separated, not passed if empty/unset
227 _families="${3:-tcp}" # optional, space separated, default is "tcp"
229 for _family in $_families ; do
230 if [ -n "$_versions" ] ; then
231 for _version in $_versions ; do
232 ctdb_check_rpc "$_progname" "$_version" "$_family" || return $?
235 ctdb_check_rpc "$_progname" "" "$_family" || return $?
240 ##################################################################
241 # use statd-callout to update NFS lock info
242 ##################################################################
243 nfs_update_lock_info ()
245 if [ -x "$CTDB_BASE/statd-callout" ] ; then
246 "$CTDB_BASE/statd-callout" update
250 ######################################################################
252 # script_state_dir set by ctdb_setup_state_dir()
253 # shellcheck disable=SC2154
254 nfs_callout_init "$script_state_dir"
256 [ "$CTDB_MANAGES_NFS" = "yes" ] || exit 0
260 nfs_callout "$@" || exit $?
264 nfs_callout "$@" || exit $?
268 nfs_callout "$@" || exit $?
269 ctdb_service_set_reconfigure
273 nfs_callout "$@" || exit $?
274 ctdb_service_set_reconfigure
278 if ctdb_service_needs_reconfigure ; then
279 ctdb_service_reconfigure
284 nfs_callout "monitor-pre" || exit $?
286 # Check that directories for shares actually exist
287 if [ "$CTDB_NFS_SKIP_SHARE_CHECK" != "yes" ] ; then
288 nfs_callout "monitor-list-shares" | ctdb_check_directories || \
297 nfs_callout "monitor-post" || exit $?