summaryrefslogtreecommitdiffstats
path: root/ctdb/doc/examples
diff options
context:
space:
mode:
Diffstat (limited to 'ctdb/doc/examples')
-rw-r--r--ctdb/doc/examples/11.natgw.options25
-rw-r--r--ctdb/doc/examples/20.nfs_ganesha.check8
-rw-r--r--ctdb/doc/examples/91.lvs.options12
-rw-r--r--ctdb/doc/examples/README15
-rwxr-xr-xctdb/doc/examples/config_migrate.sh741
-rw-r--r--ctdb/doc/examples/config_migrate.test_input50
-rw-r--r--ctdb/doc/examples/ctdb.conf73
-rw-r--r--ctdb/doc/examples/ctdb.spec.in291
-rwxr-xr-xctdb/doc/examples/nfs-ganesha-callout352
9 files changed, 1567 insertions, 0 deletions
diff --git a/ctdb/doc/examples/11.natgw.options b/ctdb/doc/examples/11.natgw.options
new file mode 100644
index 0000000..e2460cb
--- /dev/null
+++ b/ctdb/doc/examples/11.natgw.options
@@ -0,0 +1,25 @@
+# NAT gateway configuration
+#
+# See ctdb.conf for main cluster configuration details
+#
+# Cluster provides file services on following IP addresses
+#
+# 10.1.1.101 - 10.1.1.106
+#
+# When a node is not hosting any IPs, it cannot connect to network
+# infrastructure (e.g. DNS, Active Directory, ...).
+#
+# Using NAT gateway feature of CTDB allows a node not hosting IPs to connect
+# to network infrastructure using the additional CTDB_NATGW_PUBLIC_IP.
+
+# ---------- /etc/ctdb/natgw_nodes ----------
+# 192.168.1.1
+# 192.168.1.2
+# 192.168.1.3
+# ---------- /etc/ctdb/natgw_nodes ----------
+#
+CTDB_NATGW_PUBLIC_IP=10.1.1.121/24
+CTDB_NATGW_PUBLIC_IFACE=eth1
+CTDB_NATGW_DEFAULT_GATEWAY=10.1.1.254
+CTDB_NATGW_PRIVATE_NETWORK=192.168.1.0/24
+CTDB_NATGW_NODES=/etc/ctdb/natgw_nodes
diff --git a/ctdb/doc/examples/20.nfs_ganesha.check b/ctdb/doc/examples/20.nfs_ganesha.check
new file mode 100644
index 0000000..3288f16
--- /dev/null
+++ b/ctdb/doc/examples/20.nfs_ganesha.check
@@ -0,0 +1,8 @@
+# nfs_ganesha
+restart_every=2
+unhealthy_after=6
+service_stop_cmd="$CTDB_NFS_CALLOUT stop nfs"
+service_start_cmd="$CTDB_NFS_CALLOUT start nfs"
+service_check_cmd="$CTDB_NFS_CALLOUT check nfs"
+# Ganesha initscript restarts rpc.statd and stack trace is desirable!
+service_debug_cmd="program_stack_traces status 5"
diff --git a/ctdb/doc/examples/91.lvs.options b/ctdb/doc/examples/91.lvs.options
new file mode 100644
index 0000000..adb3660
--- /dev/null
+++ b/ctdb/doc/examples/91.lvs.options
@@ -0,0 +1,12 @@
+# LVS configuration
+#
+# ---------- /etc/ctdb/lvs_nodes ----------
+# 192.168.1.1
+# 192.168.1.2
+# 192.168.1.3
+# ---------- /etc/ctdb/lvs_nodes ----------
+#
+CTDB_LVS_NODES=/etc/ctdb/lvs_nodes
+
+CTDB_LVS_PUBLIC_IP=10.1.1.101
+CTDB_LVS_PUBLIC_IFACE=eth1
diff --git a/ctdb/doc/examples/README b/ctdb/doc/examples/README
new file mode 100644
index 0000000..a4ea222
--- /dev/null
+++ b/ctdb/doc/examples/README
@@ -0,0 +1,15 @@
+This directory includes...
+
+Sample CTDB configuration files:
+
+ o ctdb.conf - Main configuration file
+ o 11.natgw.options - Options for the 11.natgw event script
+ o 91.lvs.options - Options for the 91.lvs event script
+
+Sample 60.nfs configuration for NFS ganesha - callout script and
+.check file
+
+ o nfs-ganesha-callout
+ o 20.nfs_ganesha.check
+
+See the comment at the top of nfs-ganesha-callout for instructions.
diff --git a/ctdb/doc/examples/config_migrate.sh b/ctdb/doc/examples/config_migrate.sh
new file mode 100755
index 0000000..874e96c
--- /dev/null
+++ b/ctdb/doc/examples/config_migrate.sh
@@ -0,0 +1,741 @@
+#!/bin/sh
+
+# config_migrate.sh - migrate old ctdbd.conf file to new configuration files
+#
+# Input files are old-style CTDB configuration files, including:
+#
+# /etc/ctdb/ctdbd.conf
+# /usr/local/etc/ctdb/ctdbd.conf
+# /etc/sysconfig/ctdb
+# /etc/defaults/ctdb
+#
+# These files are sourced by this script. They used to be sourced by
+# ctdbd_wrapper, so this should not be too surprising.
+#
+# By default, the output directory is the given configuration
+# directory. An alternate output directory can be specified if this
+# isn't desired.
+#
+# The output directory will contain the following if non-empty:
+#
+# * ctdb.conf (may be empty)
+# * script.options
+# * ctdb.tunables
+# * ctdb.sysconfig - consider installing as /etc/sysconfig/ctdb,
+# /etc/default/ctdb, or similar
+# * commands.sh - consider running commands in this files
+# * README.warn - warnings about removed/invalid configuration options
+
+usage ()
+{
+ cat <<EOF
+usage: config_migrate.sh [-f] [-d <ctdb-config-dir>] [-o <out-dir>] <file> ...
+EOF
+ exit 1
+}
+
+config_dir=""
+out_dir=""
+force=false
+
+while getopts "d:fho:?" opt ; do
+ case "$opt" in
+ d) config_dir="$OPTARG" ;;
+ f) force=true ;;
+ o) out_dir="$OPTARG" ;;
+ \?|h) usage ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+if [ $# -lt 1 ] ; then
+ usage
+fi
+
+if [ -z "$config_dir" ] ; then
+ echo "Assuming \"/etc/ctdb\" as ctdb configuration directory"
+ echo "If that's not correct, please specify config dir with -d"
+ echo
+ config_dir="/etc/ctdb"
+else
+ echo "Using \"$config_dir\" as ctdb configuration directory"
+ echo
+fi
+
+if [ -z "$out_dir" ] ; then
+ echo "No output directory specified, using \"$config_dir\""
+ echo
+ out_dir="$config_dir"
+fi
+
+############################################################
+
+#
+# Output file handling
+#
+
+out_file_check_and_create ()
+{
+ _out_file="$1"
+
+ if [ -f "$_out_file" ] ; then
+ if ! $force ; then
+ echo "Not overwriting existing file: ${_out_file}" >&2
+ return 1
+ fi
+ mv -v "$_out_file" "${_out_file}.convertsave"
+ fi
+
+ touch "$_out_file"
+
+ return 0
+}
+
+out_file_remove_if_empty ()
+{
+ _out_file="$1"
+
+ if [ ! -s "$_out_file" ] ; then
+ rm "$_out_file"
+ fi
+}
+
+############################################################
+
+#
+# Option/tunable/service conversion and validity checking
+#
+# This is basically the data that drives most of the rest of the
+# script
+#
+
+# Convert a ctdbd.conf opt+val into a ctdb.conf section+opt+val
+#
+# If opt is matched and val is empty then output is printed, allowing
+# this function to be reused to check if opt is valid.
+#
+# Note that for boolean options, the expected value and the new value
+# form part of the data.
+get_ctdb_conf_option ()
+{
+ _opt="$1"
+ _val="$2"
+
+ awk -v opt="${_opt}" -v val="${_val}" \
+ '$3 == opt {
+ if (!$4 || !val || val == $4) {
+ if ($5) {
+ print $1, $2, $5
+ } else {
+ print $1, $2, val
+ }
+ }
+ }' <<EOF
+cluster node-address CTDB_NODE_ADDRESS
+cluster cluster-lock CTDB_RECOVERY_LOCK
+cluster transport CTDB_TRANSPORT
+cluster leader-capability CTDB_CAPABILITY_RECMASTER no false
+database lock-debug-script CTDB_DEBUG_LOCKS
+database persistent-database-directory CTDB_DBDIR_PERSISTENT
+database state-database-directory CTDB_DBDIR_STATE
+database volatile-database-directory CTDB_DBDIR
+event debug-script CTDB_DEBUG_HUNG_SCRIPT
+legacy lmaster-capability CTDB_CAPABILITY_LMASTER no false
+legacy realtime-scheduling CTDB_NOSETSCHED yes false
+legacy script-log-level CTDB_SCRIPT_LOG_LEVEL
+legacy start-as-disabled CTDB_START_AS_DISABLED yes true
+legacy start-as-stopped CTDB_START_AS_STOPPED yes true
+logging location CTDB_LOGGING
+logging log-level CTDB_DEBUGLEVEL
+EOF
+
+}
+
+# Check if an option will convert to a ctdb.conf option
+check_ctdb_conf_option ()
+{
+ _opt="$1"
+
+ _out=$(get_ctdb_conf_option "$_opt" "")
+ [ -n "$_out" ]
+}
+
+# Convert a ctdbd.conf tunable option into a ctdb.conf section+opt
+#
+# The difference between this and get_ctdb_conf_option() is that only
+# the tunable part of the option is passed as opt and it is matched
+# case-insensitively.
+get_ctdb_conf_tunable_option ()
+{
+ _opt="$1"
+ _val="$2"
+
+ awk -v opt="${_opt}" -v val="${_val}" \
+ 'tolower($3) == tolower(opt) {
+ if (!$4 || !val || (val == 0 ? 0 : 1) == $4) {
+ if ($5) {
+ print $1, $2, $5
+ } else {
+ print $1, $2, val
+ }
+ }
+ }' <<EOF
+database tdb-mutexes TDBMutexEnabled 0 false
+failover disabled DisableIPFailover 1 true
+EOF
+
+}
+
+# Check if a tunable will convert to a ctdb.conf option
+check_ctdb_conf_tunable_option ()
+{
+ _opt="$1"
+
+ _out=$(get_ctdb_conf_tunable_option "$_opt" "")
+ [ -n "$_out" ]
+}
+
+# Check if an option has been removed
+check_removed_option ()
+{
+ _option="$1"
+
+ grep -Fqx "$_option" <<EOF
+CTDB_BASE
+CTDB_PIDFILE
+CTDB_SOCKET
+CTDB_EVENT_SCRIPT_DIR
+CTDB_NOTIFY_SCRIPT
+CTDB_PUBLIC_INTERFACE
+CTDB_MAX_PERSISTENT_CHECK_ERRORS
+CTDB_SHUTDOWN_TIMEOUT
+CTDB_MONITOR_SWAP_USAGE
+EOF
+}
+
+# Check if an option is a valid script option
+check_valid_script_option ()
+{
+ _option="$1"
+
+ grep -Fqx "$_option" <<EOF
+# 10.interface
+CTDB_PARTIALLY_ONLINE_INTERFACES
+# 11.natgw
+CTDB_NATGW_DEFAULT_GATEWAY
+CTDB_NATGW_NODES
+CTDB_NATGW_PRIVATE_NETWORK
+CTDB_NATGW_PUBLIC_IFACE
+CTDB_NATGW_PUBLIC_IP
+CTDB_NATGW_STATIC_ROUTES
+# 13.per_ip_routing
+CTDB_PER_IP_ROUTING_CONF
+CTDB_PER_IP_ROUTING_RULE_PREF
+CTDB_PER_IP_ROUTING_TABLE_ID_LOW
+CTDB_PER_IP_ROUTING_TABLE_ID_HIGH
+# 90.lvs
+CTDB_LVS_NODES
+CTDB_LVS_PUBLIC_IFACE
+CTDB_LVS_PUBLIC_IP
+# 20.multipathd
+CTDB_MONITOR_MPDEVICES
+# 31.clamd
+CTDB_CLAMD_SOCKET
+# 48.netbios
+CTDB_SERVICE_NMB
+# 49.winbind
+CTDB_SERVICE_WINBIND
+# 50.samba
+CTDB_SAMBA_CHECK_PORTS
+CTDB_SAMBA_SKIP_SHARE_CHECK
+CTDB_SERVICE_SMB
+# 60.nfs
+CTDB_NFS_CALLOUT
+CTDB_NFS_CHECKS_DIR
+CTDB_NFS_SKIP_SHARE_CHECK
+CTDB_RPCINFO_LOCALHOST
+CTDB_RPCINFO_LOCALHOST6
+CTDB_NFS_STATE_FS_TYPE
+CTDB_NFS_STATE_MNT
+# 70.iscsi
+CTDB_START_ISCSI_SCRIPTS
+# 00.ctdb
+CTDB_MAX_CORRUPT_DB_BACKUPS
+# 05.system
+CTDB_MONITOR_FILESYSTEM_USAGE
+CTDB_MONITOR_MEMORY_USAGE
+# debug_hung_scripts.sh
+CTDB_DEBUG_HUNG_SCRIPT_STACKPAT
+EOF
+}
+
+# Check if a tunable is valid
+check_valid_tunable ()
+{
+ _tunable="$1"
+
+ grep -Fiqx "$_tunable" <<EOF
+AllowClientDBAttach
+AllowMixedVersions
+AllowUnhealthyDBRead
+ControlTimeout
+DBRecordCountWarn
+DBRecordSizeWarn
+DBSizeWarn
+DatabaseHashSize
+DatabaseMaxDead
+DeferredAttachTO
+DisableIPFailover
+ElectionTimeout
+EnableBans
+EventScriptTimeout
+FetchCollapse
+HopcountMakeSticky
+IPAllocAlgorithm
+KeepaliveInterval
+KeepaliveLimit
+LockProcessesPerDB
+LogLatencyMs
+MaxQueueDropMsg
+MonitorInterval
+MonitorTimeoutCount
+NoIPFailback
+NoIPTakeover
+PullDBPreallocation
+QueueBufferSize
+RecBufferSizeLimit
+RecLockLatencyMs
+RecdFailCount
+RecdPingTimeout
+RecoverInterval
+RecoverTimeout
+RecoveryBanPeriod
+RecoveryDropAllIPs
+RecoveryGracePeriod
+RepackLimit
+RerecoveryTimeout
+SeqnumInterval
+StatHistoryInterval
+StickyDuration
+StickyPindown
+TDBMutexEnabled
+TakeoverTimeout
+TickleUpdateInterval
+TraverseTimeout
+VacuumFastPathCount
+VacuumInterval
+VacuumMaxRunTime
+VerboseMemoryNames
+EOF
+}
+
+# Check if a tunable has been removed
+check_removed_tunable ()
+{
+ _tunable="$1"
+
+ grep -Fiqx "$_tunable" <<EOF
+NoIPHostOnAllDisabled
+VacuumLimit
+EOF
+}
+
+# Print a command to enable an event script for the given service
+print_event_script_enable_command ()
+{
+ _service="$1"
+
+ _component=""
+ _script=""
+ case "$_service" in
+ samba) _component="legacy" ; _script="50.samba" ;;
+ winbind) _component="legacy" ; _script="49.winbind" ;;
+ apache2|httpd) _component="legacy" ; _script="41.httpd" ;;
+ clamd) _component="legacy" ; _script="31.clamd" ;;
+ iscsi) _component="legacy" ; _script="70.iscsi" ;;
+ nfs) _component="legacy" ; _script="60.nfs" ;;
+ vsftpd) _component="legacy" ; _script="40.vsftpd" ;;
+ esac
+
+ if [ -z "$_script" ] ; then
+ return 1
+ fi
+
+ cat <<EOF
+# Enable the ${_service} service
+ctdb event script enable ${_component} ${_script}
+
+EOF
+}
+
+# Check if the given service is valid
+check_valid_service ()
+{
+ _service="$1"
+
+ print_event_script_enable_command "$_service" >/dev/null
+}
+
+############################################################
+
+#
+# Utilities
+#
+
+# List all options starting with "CTDB_" set in given configuration files
+list_options ()
+{
+ set |
+ sed -n 's|^\(CTDB_[^=]*\)=\(.*\)|\1 \2|p' |
+ while read -r _var _val ; do
+ # Strip quotes from value
+ _val=$(echo "$_val" | sed -e "s|^'||" -e "s|'\$||")
+
+ echo "${_var} ${_val}"
+ done
+}
+
+# List all tunables set in the given configuration files
+list_tunables ()
+{
+ list_options |
+ while read -r _opt _val ; do
+ case "$_opt" in
+ CTDB_SET_*) echo "${_opt#CTDB_SET_} ${_val}" ;;
+ esac
+ done
+}
+
+# List all managed services according to the given configuration files
+list_managed_services ()
+{
+ #
+ # CTDB_MANAGES_<service>="yes"
+ #
+ list_options |
+ while read -r _opt _val ; do
+ case "$_opt" in
+ CTDB_MANAGES_*) : ;;
+ *) continue ;;
+ esac
+
+ if [ "$_val" != "yes" ] ; then
+ continue
+ fi
+
+ # Trim and downcase
+ echo "${_opt#CTDB_MANAGES_}" | tr '[:upper:]' '[:lower:]'
+ done
+
+ #
+ # CTDB_MANAGED_SERVICES
+ #
+ for _service in $CTDB_MANAGED_SERVICES ; do
+ echo "$_service"
+ done
+}
+
+############################################################
+
+#
+# Print warnings for removed and unknown options
+#
+
+
+# Print a warning as a bullet list item
+#
+# Arguments after the 1st are printed as a subsequent paragraph.
+warn ()
+{
+ bullet="$1" ; shift
+
+ printf '* %s\n\n' "$bullet"
+
+ if [ $# -gt 0 ] ; then
+ printf ' %s\n\n' "$*"
+ fi
+}
+
+warn_about_CTDB_DBDIR_tmpfs_yes ()
+{
+ if $ctdb_dbdir_tmpfs_magic ; then
+ warn "Option \"CTDB_DBDIR=tmpfs\" is no longer available:" \
+ "Permanently mount a tmpfs filesystem on the volatile" \
+ "database directory"
+ fi
+}
+
+warn_about_unknown_managed_services ()
+{
+ list_managed_services |
+ while read -r _s ; do
+ if check_valid_service "$_s" ; then
+ continue
+ fi
+ warn "Unknown service \"${_s}\" marked as managed" \
+ "If this is a 3rd party service, please enable it manually"
+ done
+}
+
+warn_about_removed_and_unknown_options ()
+{
+ list_options |
+ while read -r _opt _val ; do
+ if check_ctdb_conf_option "$_opt" ; then
+ continue
+ fi
+
+ if check_valid_script_option "$_opt" ; then
+ continue
+ fi
+
+ case "$_opt" in
+ CTDB_MANAGED_SERVICES|\
+ CTDB_MANAGES_*|\
+ CTDB_SET_*|\
+ CTDB_NODES|\
+ CTDB_PUBLIC_ADDRESSES|\
+ CTDB_MAX_OPEN_FILES|\
+ CTDB_SUPPRESS_COREFILE)
+ # Handled elsewhere
+ continue
+ ;;
+ esac
+
+ if check_removed_option "$_opt" ; then
+ warn "Option \"${_opt}\" is no longer available" \
+ "Please see the WHATSNEW.txt"
+ continue
+ fi
+
+ warn "Option \"${_opt}\" is unknown"
+ done
+}
+
+warn_about_removed_and_unknown_tunables ()
+{
+ list_tunables |
+ while read -r _var _val ; do
+ if check_valid_tunable "$_var" ; then
+ continue
+ fi
+
+ if check_removed_tunable "$_var" ; then
+ warn "Tunable \"${_var}\" is no longer available" \
+ "Please see the WHATSNEW.txt"
+ continue
+ fi
+
+ warn "Tunable \"${_var}\" is unknown"
+ done
+}
+
+############################################################
+
+#
+# Top-level file builders
+#
+
+build_ctdb_conf ()
+{
+ _out_file="$1"
+
+ out_file_check_and_create "$_out_file" || return
+
+ list_options |
+ while read -r _opt _val ; do
+ case "$_opt" in
+ CTDB_SET_*)
+ _opt="${_opt#CTDB_SET_}"
+ _out=$(get_ctdb_conf_tunable_option "$_opt" "$_val")
+ ;;
+ *)
+ _out=$(get_ctdb_conf_option "$_opt" "$_val")
+ esac
+ if [ -z "$_out" ] ; then
+ continue
+ fi
+
+ # $_out is section and key, replace dashes with spaces
+ # Intentional word splitting
+ # shellcheck disable=SC2086
+ set -- $_out
+ _section=$(echo "$1" | sed -e 's|-| |g')
+ _key=$(echo "$2" | sed -e 's|-| |g')
+ _newval="$3"
+
+ if ! grep -Fqx "[${_section}]" "$_out_file" ; then
+ # Add blank line if file is not empty
+ if [ -s "$_out_file" ] ; then
+ echo >>"$_out_file"
+ fi
+ # Create section at end of file
+ echo "[${_section}]" >>"$_out_file"
+ fi
+
+ # Must escape leading TAB or sed eats it
+ sed -i -e "/\\[${_section}\\]/a\
+\\ ${_key} = ${_newval}
+" "$_out_file"
+
+ done
+
+}
+
+build_script_options ()
+{
+ _out_file="$1"
+
+ out_file_check_and_create "$_out_file" || return
+
+ list_options |
+ while read -r _var _val ; do
+ if check_valid_script_option "$_var" ; then
+ echo "${_var}=${_val}"
+ fi
+ done >>"$_out_file"
+
+ out_file_remove_if_empty "$_out_file"
+}
+
+build_ctdb_tunables ()
+{
+ _out_file="$1"
+
+ out_file_check_and_create "$_out_file" || return
+
+ list_tunables |
+ while read -r _var _val ; do
+ if check_ctdb_conf_tunable_option "$_var" ; then
+ continue
+ fi
+ if ! check_valid_tunable "$_var" ; then
+ continue
+ fi
+ echo "${_var}=${_val}"
+ done >>"$_out_file"
+
+ out_file_remove_if_empty "$_out_file"
+}
+
+build_ctdb_sysconfig ()
+{
+ _out_file="$1"
+
+ out_file_check_and_create "$_out_file" || return
+
+ if [ -n "$CTDB_SUPPRESS_COREFILE" ] ; then
+ if [ "$CTDB_SUPPRESS_COREFILE" = "yes" ] ; then
+ echo "ulimit -c 0"
+ else
+ echo "ulimit -c unlimited"
+ fi >>"$_out_file"
+ fi
+
+ if [ -n "$CTDB_MAX_OPEN_FILES" ] ; then
+ echo "ulimit -n ${CTDB_MAX_OPEN_FILES}" >>"$_out_file"
+ fi
+
+ out_file_remove_if_empty "$_out_file"
+}
+
+build_commands_sh ()
+{
+ _out_file="$1"
+
+ out_file_check_and_create "$_out_file" || return
+
+ #
+ # Enable script for managed services
+ #
+ list_managed_services |
+ while read -r _service ; do
+ print_event_script_enable_command "$_service"
+ done >>"$_out_file"
+
+ #
+ # CTDB_NODES no longer available
+ #
+ if [ -n "$CTDB_NODES" ] ; then
+ if [ "$CTDB_NODES" = "${config_dir}/nodes" ] ; then
+ cat <<EOF
+# CTDB_NODES=${CTDB_NODES}
+# Looks like the standard location. Nothing to do.
+
+EOF
+ else
+ cat <<EOF
+# CTDB_NODES=${CTDB_NODES}
+# Looks like a non-standard location. Use the default location
+# in the configuration directory or create a symlink.
+ln -s "$CTDB_NODES" "${config_dir}/nodes"
+
+EOF
+ fi >>"$_out_file"
+ fi
+
+ #
+ # CTDB_PUBLIC_ADDRESSES no longer available
+ #
+ if [ -n "$CTDB_PUBLIC_ADDRESSES" ] ; then
+ _pa="public_addresses"
+ if [ "$CTDB_PUBLIC_ADDRESSES" = "${config_dir}/${_pa}" ] ; then
+ cat <<EOF
+# CTDB_PUBLIC_ADDRESSES=${CTDB_PUBLIC_ADDRESSES}
+# Looks like the standard location. Nothing to do.
+
+EOF
+ else
+ cat <<EOF
+# CTDB_PUBLIC_ADDRESSES=${CTDB_PUBLIC_ADDRESSES}
+# Looks like a non-standard location. Use the default location
+# in the configuration directory or create a symlink.
+ln -s "$CTDB_PUBLIC_ADDRESSES" "${config_dir}/${_pa}"
+
+EOF
+ fi >>"$_out_file"
+ fi
+
+ out_file_remove_if_empty "$_out_file"
+}
+
+build_README_warn ()
+{
+ _out_file="$1"
+
+ out_file_check_and_create "$_out_file" || return
+
+ {
+ warn_about_CTDB_DBDIR_tmpfs_yes
+ warn_about_unknown_managed_services
+ warn_about_removed_and_unknown_options
+ warn_about_removed_and_unknown_tunables
+ } >>"$_out_file"
+
+ out_file_remove_if_empty "$_out_file"
+}
+
+############################################################
+
+mkdir -p "$out_dir" || exit 1
+
+# Source the input files
+for i ; do
+ # Unknown non-constant source
+ # shellcheck disable=SC1090
+ . "$i"
+done
+
+# Special case
+ctdb_dbdir_tmpfs_magic=false
+if [ "$CTDB_DBDIR" = "tmpfs" ] ; then
+ ctdb_dbdir_tmpfs_magic=true
+ unset CTDB_DBDIR
+fi
+
+build_ctdb_conf "${out_dir}/ctdb.conf"
+build_script_options "${out_dir}/script.options"
+build_ctdb_tunables "${out_dir}/ctdb.tunables"
+build_ctdb_sysconfig "${out_dir}/ctdb.sysconfig"
+build_commands_sh "${out_dir}/commands.sh"
+build_README_warn "${out_dir}/README.warn"
diff --git a/ctdb/doc/examples/config_migrate.test_input b/ctdb/doc/examples/config_migrate.test_input
new file mode 100644
index 0000000..e823fd4
--- /dev/null
+++ b/ctdb/doc/examples/config_migrate.test_input
@@ -0,0 +1,50 @@
+CTDB_BASE="/etc/ctdb"
+
+CTDB_RECOVERY_LOCK="/some/place/on/shared/storage"
+
+CTDB_NODES="/etc/ctdb/nodes"
+
+CTDB_PUBLIC_ADDRESSES="/clusterfs/.ctdb/public_addresses"
+
+CTDB_SOCKET="/var/run/ctdb.sock"
+
+CTDB_MANAGES_SAMBA="yes"
+CTDB_MANAGES_WINBIND="yes"
+CTDB_MANAGES_NFS="yes"
+CTDB_MANAGED_SERVICES="vsftpd"
+CTDB_MANAGES_FOOBAR="yes"
+
+CTDB_MAX_OPEN_FILES=10000
+
+CTDB_LOGGING="syslog"
+CTDB_DEBUGLEVEL="ERROR"
+
+CTDB_SAMBA_CHECK_PORTS="445"
+CTDB_SAMBA_SKIP_SHARE_CHECK="yes"
+
+CTDB_START_AS_STOPPED="yes"
+CTDB_CAPABILITY_RECMASTER="no"
+CTDB_CAPABILITY_LMASTER="yes"
+
+CTDB_NOSETSCHED="yes"
+
+CTDB_FOO="bar"
+
+CTDB_NATGW_PUBLIC_IP=10.1.1.121/24
+CTDB_NATGW_PUBLIC_IFACE=eth1
+CTDB_NATGW_DEFAULT_GATEWAY=10.1.1.254
+CTDB_NATGW_PRIVATE_NETWORK=192.168.1.0/24
+CTDB_NATGW_NODES=/etc/ctdb/natgw_nodes
+
+CTDB_SET_TDBMutexEnabled=0
+CTDB_SET_IPALLOCALGORITHM=0
+CTDB_SET_noiphostonalldisabled=0
+CTDB_SET_DisableIpFailover=1
+CTDB_SET_foobar=0
+
+CTDB_SUPPRESS_COREFILE="yes"
+CTDB_MAX_OPEN_FILES="1048576"
+
+CTDB_NOTIFY_SCRIPT=/etc/ctdb/notify-custom.sh
+
+CTDB_DBDIR=tmpfs
diff --git a/ctdb/doc/examples/ctdb.conf b/ctdb/doc/examples/ctdb.conf
new file mode 100644
index 0000000..3a8ccc6
--- /dev/null
+++ b/ctdb/doc/examples/ctdb.conf
@@ -0,0 +1,73 @@
+#
+# CTDB configuration for simple cluster
+#
+# This is the sample configuration for a 3-node CTDB cluster providing file
+# services via Samba and NFS.
+#
+# Cluster details:
+#
+# internal network (192.168.1.0/24)
+# -------+----------------------+-----------------------+----------
+# | | |
+# | | |
+# eth0 | 192.168.1.1 eth0 | 192.168.1.2 eth0 | 192.168.1.3
+# +-----+-----+ +-----+-----+ +-----+-----+
+# | | | | | |
+# | Node 1 | | Node 2 | | Node 3 |
+# | | | | | |
+# +-----+-----+ +-----+-----+ +-----+-----+
+# eth1 | 10.1.1.1 eth1 | 10.1.1.2 eth1 | 10.1.1.3
+# | | |
+# | | |
+# -------+----------------------+-----------------------+----------
+# public network (10.1.1.0/24)
+#
+#
+# Storage details:
+#
+# Each node has a shared storage - /shared
+#
+#
+# Service details:
+#
+# Cluster provides file services on following IP addresses
+#
+# 10.1.1.101 - 10.1.1.106
+#
+# Each node also has a fixed IP address on public network. This is used to
+# communicate to network infrastructure (e.g. DNS, Active Directory, ...).
+# Make sure that file services are not available on these fixed IP addresses
+# (e.g. network filtering, using cluster hostname instead of IPs)
+
+[logging]
+ # Enable logging to syslog
+ location = syslog
+
+ # Default log level
+ log level = NOTICE
+
+[cluster]
+ cluster lock = /shared/cluster.lock
+
+#
+# Nodes configuration
+#
+# ---------- /etc/ctdb/nodes ----------
+# 192.168.1.1
+# 192.168.1.2
+# 192.168.1.3
+# ---------- /etc/ctdb/nodes ----------
+#
+#
+# Public addresses configuration
+#
+# ---------- /etc/ctdb/public_addresses ----------
+# 10.1.1.101/24 eth1
+# 10.1.1.102/24 eth1
+# 10.1.1.103/24 eth1
+# 10.1.1.104/24 eth1
+# 10.1.1.105/24 eth1
+# 10.1.1.106/24 eth1
+# ---------- /etc/ctdb/public_addresses ----------
+#
+# Event script configuration - see *.options examples
diff --git a/ctdb/doc/examples/ctdb.spec.in b/ctdb/doc/examples/ctdb.spec.in
new file mode 100644
index 0000000..addb7e1
--- /dev/null
+++ b/ctdb/doc/examples/ctdb.spec.in
@@ -0,0 +1,291 @@
+%define with_systemd %{?_with_systemd: 1} %{?!_with_systemd: 0}
+%define initdir %{_sysconfdir}/init.d
+Name: ctdb
+Summary: Clustered TDB
+Vendor: Samba Team
+Packager: Samba Team <samba@samba.org>
+Version: @VERSION@
+Release: @RELEASE@
+Epoch: 0
+License: GNU GPL version 3
+Group: System Environment/Daemons
+URL: http://ctdb.samba.org/
+
+Source: ctdb-%{version}.tar.gz
+
+# Packages
+Requires: coreutils, sed, gawk, iptables, iproute, procps, ethtool, sudo
+# Commands - package name might vary
+Requires: /usr/bin/killall, /bin/kill, /bin/ss
+
+Provides: ctdb = %{version}
+
+Prefix: /usr
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+# Allow build with system libraries
+# To enable, run rpmbuild with,
+# "--with system_talloc"
+# "--with system_tdb"
+# "--with system_tevent"
+#%define with_included_talloc %{?_with_system_talloc: 0} %{?!_with_system_talloc: 1}
+#%define with_included_tdb %{?_with_system_tdb: 0} %{?!_with_system_tdb: 1}
+#%define with_included_tevent %{?_with_system_tevent: 0} %{?!_with_system_tevent: 1}
+
+%define with_included_talloc 0
+%define with_included_tevent 0
+%define with_included_tdb 0
+
+# Required minimum library versions when building with system libraries
+%define libtalloc_version 2.0.8
+%define libtdb_version 1.3.11
+%define libtevent_version 0.9.16
+
+%if ! %with_included_talloc
+BuildRequires: libtalloc-devel >= %{libtalloc_version}
+Requires: libtalloc >= %{libtalloc_version}
+%endif
+%if ! %with_included_tdb
+BuildRequires: libtdb-devel >= %{libtdb_version}
+Requires: libtdb >= %{libtdb_version}
+%endif
+%if ! %with_included_tevent
+BuildRequires: libtevent-devel >= %{libtevent_version}
+Requires: libtevent >= %{libtevent_version}
+%endif
+
+# To build the ctdb-pcp-pmda package, run rpmbuild with "--with pmda"
+%define with_pcp_pmda %{?_with_pmda: 1} %{?!_with_pmda: 0}
+%if %with_pcp_pmda
+BuildRequires: pcp-libs-devel
+%endif
+
+%if %{with_systemd}
+BuildRequires: systemd-units
+%endif
+
+%description
+ctdb is the clustered database used by samba
+
+#######################################################################
+
+
+
+%prep
+%setup -q
+# setup the init script and sysconfig file
+%setup -T -D -n ctdb-%{version} -q
+
+%build
+
+## check for ccache
+if ccache -h >/dev/null 2>&1 ; then
+ CC="ccache gcc"
+else
+ CC="gcc"
+fi
+
+export CC
+
+CFLAGS="$RPM_OPT_FLAGS $EXTRA -D_GNU_SOURCE" \
+./configure \
+ --builtin-libraries=replace,popt \
+ --bundled-libraries=!talloc,!tevent,!tdb \
+ --minimum-library-version=talloc:%libtalloc_version,tdb:%libtdb_version,tevent:%libtevent_version \
+%if %with_pcp_pmda
+ --enable-pmda \
+%endif
+ --prefix=%{_prefix} \
+ --includedir=%{_includedir}/ctdb \
+ --libdir=%{_libdir} \
+ --libexecdir=%{_libexecdir} \
+ --sysconfdir=%{_sysconfdir} \
+ --mandir=%{_mandir} \
+ --localstatedir=%{_localstatedir}
+
+make -j
+
+%install
+# Clean up in case there is trash left from a previous build
+rm -rf $RPM_BUILD_ROOT
+
+# Create the target build directory hierarchy
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sudoers.d
+
+DESTDIR=$RPM_BUILD_ROOT make -j install
+
+install -m644 config/ctdb.conf $RPM_BUILD_ROOT%{_sysconfdir}/ctdb
+install -m644 config/ctdb.tunables $RPM_BUILD_ROOT%{_sysconfdir}/ctdb
+install -m644 config/script.options $RPM_BUILD_ROOT%{_sysconfdir}/ctdb
+
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
+install -m644 config/ctdb.sysconfig $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ctdb
+
+%if %{with_systemd}
+mkdir -p $RPM_BUILD_ROOT%{_unitdir}
+install -m 755 config/ctdb.service $RPM_BUILD_ROOT%{_unitdir}
+%else
+mkdir -p $RPM_BUILD_ROOT%{initdir}
+install -m755 config/ctdb.init $RPM_BUILD_ROOT%{initdir}/ctdb
+%endif
+
+# This is a hack. All documents should be installed in /usr/share/doc.
+cp config/events/README README.eventscripts
+rm -f $RPM_BUILD_ROOT%{_sysconfdir}/ctdb/nfs-checks.d/README
+cp config/nfs-checks.d/README README.nfs-checks.d
+cp config/notification.README README.notification
+
+# Remove "*.old" files
+find $RPM_BUILD_ROOT -name "*.old" -exec rm -f {} \;
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+
+# If mandatory 00.ctdb event script is not enabled then enable it and
+# some other scripts. The assumption here is that this is a
+# first-time install or an upgrade to a version that requires event
+# scripts to be enabled via symlinks.
+required_script="00.ctdb"
+required_path="%{_sysconfdir}/ctdb/events/legacy/${required_script}.script"
+if [ ! -L "$required_path" ] && [ ! -e "$required_path" ] ; then
+ default_scripts="${required_script}
+ 01.reclock
+ 05.system
+ 10.interface
+ "
+ for t in $default_scripts ; do
+ tgt="%{_datadir}/ctdb/events/legacy/${t}.script"
+ name="%{_sysconfdir}/ctdb/events/legacy/${t}.script"
+ # Directory is created via install and files
+ ln -s "$tgt" "$name"
+ done
+fi
+
+%preun
+
+# Uninstall, not upgrade. Clean up by removing any remaining links.
+if [ "$1" = "0" ] ; then
+ for i in "%{_sysconfdir}/ctdb/events/legacy/"*.script ; do
+ if [ -L "$i" ] ; then
+ rm -f "$i"
+ fi
+ done
+fi
+
+%files
+%defattr(-,root,root)
+
+%config(noreplace) %{_sysconfdir}/ctdb/ctdb.conf
+%config(noreplace) %{_sysconfdir}/ctdb/ctdb.tunables
+%config(noreplace) %{_sysconfdir}/ctdb/script.options
+%{_sysconfdir}/ctdb/notify.sh
+%config(noreplace) %{_sysconfdir}/ctdb/debug-hung-script.sh
+%config(noreplace) %{_sysconfdir}/ctdb/ctdb-crash-cleanup.sh
+%config(noreplace) %{_sysconfdir}/ctdb/debug_locks.sh
+
+%config(noreplace, missingok) %{_sysconfdir}/sysconfig/ctdb
+
+%if %{with_systemd}
+%{_unitdir}/ctdb.service
+%else
+%attr(755,root,root) %{initdir}/ctdb
+%endif
+
+%doc README COPYING
+%doc README.eventscripts README.notification
+%doc doc/recovery-process.txt
+%doc doc/cluster_mutex_helper.txt
+%doc doc/*.html
+%doc doc/examples
+%{_sysconfdir}/sudoers.d/ctdb
+%dir %{_sysconfdir}/ctdb
+%{_sysconfdir}/ctdb/functions
+%dir %{_sysconfdir}/ctdb/events
+%{_sysconfdir}/ctdb/events/*
+%dir %{_sysconfdir}/ctdb/nfs-checks.d
+%config(noreplace) %{_sysconfdir}/ctdb/nfs-checks.d/00.portmapper.check
+%config(noreplace) %{_sysconfdir}/ctdb/nfs-checks.d/10.status.check
+%config(noreplace) %{_sysconfdir}/ctdb/nfs-checks.d/20.nfs.check
+%config(noreplace) %{_sysconfdir}/ctdb/nfs-checks.d/30.nlockmgr.check
+%config(noreplace) %{_sysconfdir}/ctdb/nfs-checks.d/40.mountd.check
+%config(noreplace) %{_sysconfdir}/ctdb/nfs-checks.d/50.rquotad.check
+%{_sysconfdir}/ctdb/statd-callout
+%{_sysconfdir}/ctdb/nfs-linux-kernel-callout
+%{_sbindir}/ctdbd
+%{_bindir}/ctdb
+%{_bindir}/ping_pong
+%{_bindir}/ltdbtool
+%{_bindir}/ctdb_diagnostics
+%{_bindir}/onnode
+%dir %{_libexecdir}/ctdb
+%{_libexecdir}/ctdb/*
+%dir %{_libdir}/ctdb
+%{_libexecdir}/tdb_mutex_check
+%{_libdir}/ctdb/lib*
+%dir %{_datadir}/ctdb/events
+%{_datadir}/ctdb/events/*
+%{_mandir}/man1/ctdb.1.gz
+%{_mandir}/man1/ctdb_diagnostics.1.gz
+%{_mandir}/man1/ctdbd.1.gz
+%{_mandir}/man1/onnode.1.gz
+%{_mandir}/man1/ltdbtool.1.gz
+%{_mandir}/man1/ping_pong.1.gz
+%{_mandir}/man5/ctdb.conf.5.gz
+%{_mandir}/man5/ctdb-script.options.5.gz
+%{_mandir}/man5/ctdb.sysconfig.5.gz
+%{_mandir}/man7/ctdb.7.gz
+%{_mandir}/man7/ctdb-statistics.7.gz
+%{_mandir}/man7/ctdb-tunables.7.gz
+%attr(0700,root,root) %dir %{_localstatedir}/lib/ctdb
+%attr(0700,root,root) %dir %{_localstatedir}/lib/ctdb/*
+%attr(0700,root,root) %dir %{_localstatedir}/run/ctdb
+
+
+%package devel
+Summary: CTDB development libraries
+Group: Development/Libraries
+
+%description devel
+development libraries for ctdb
+
+%files devel
+%defattr(-,root,root)
+
+%package tests
+Summary: CTDB test suite
+Group: Development/Tools
+Requires: ctdb = %{version}
+Requires: nc, tcpdump
+
+%description tests
+test suite for ctdb
+
+%files tests
+%defattr(-,root,root)
+%dir %{_datadir}/%{name}/tests
+%{_datadir}/%{name}/tests/*
+%dir %{_libexecdir}/%{name}/tests
+%{_libexecdir}/%{name}/tests/*
+%{_bindir}/ctdb_run_tests
+%{_bindir}/ctdb_run_cluster_tests
+%{_bindir}/ctdb_local_daemons
+%doc tests/README
+
+%if %with_pcp_pmda
+
+%package pcp-pmda
+Summary: CTDB PCP pmda support
+Group: Development/Tools
+Requires: ctdb = %{version}
+Requires: pcp-libs
+
+%description pcp-pmda
+Performance Co-Pilot (PCP) support for CTDB
+
+%files pcp-pmda
+%dir %{_localstatedir}/lib/pcp/pmdas/ctdb
+%{_localstatedir}/lib/pcp/pmdas/ctdb/*
+
+%endif
diff --git a/ctdb/doc/examples/nfs-ganesha-callout b/ctdb/doc/examples/nfs-ganesha-callout
new file mode 100755
index 0000000..7c7b074
--- /dev/null
+++ b/ctdb/doc/examples/nfs-ganesha-callout
@@ -0,0 +1,352 @@
+#!/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 (a
+# copy of) this script, making sure it is executable.
+#
+# * Create a new directory alongside the nfs-checks.d directory, for
+# example nfs-checks-ganesha.d. Install 20.nfs-ganesha.check in
+# this directory. Symlink to any other check files from
+# nfs-checks.d that should still be used, such as
+# 00.portmapper.check. Set CTDB_NFS_CHECKS_DIR to point to this new
+# directory of check files.
+#
+# * 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 _dir in "${GANSTATEDIR}/"* ; do
+ # Handle no directories case
+ if [ ! -d "$_dir" ] ; then
+ break
+ fi
+
+ _node="${_dir##*/}" # basename
+ 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 "$_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