summaryrefslogtreecommitdiffstats
path: root/rgmanager/src/resources/netfs.sh.in
diff options
context:
space:
mode:
Diffstat (limited to 'rgmanager/src/resources/netfs.sh.in')
-rw-r--r--rgmanager/src/resources/netfs.sh.in488
1 files changed, 488 insertions, 0 deletions
diff --git a/rgmanager/src/resources/netfs.sh.in b/rgmanager/src/resources/netfs.sh.in
new file mode 100644
index 0000000..5b75f9d
--- /dev/null
+++ b/rgmanager/src/resources/netfs.sh.in
@@ -0,0 +1,488 @@
+#!@BASH_SHELL@
+
+#
+# NFS/CIFS file system mount/umount/etc. agent
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+. $(dirname $0)/utils/fs-lib.sh
+
+do_metadata()
+{
+ cat <<EOT
+<?xml version="1.0" ?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent name="netfs" version="rgmanager 2.0">
+ <version>1.0</version>
+
+ <longdesc lang="en">
+ This defines an NFS/CIFS mount for use by cluster services.
+ </longdesc>
+ <shortdesc lang="en">
+ Defines an NFS/CIFS file system mount.
+ </shortdesc>
+
+ <parameters>
+ <parameter name="name" primary="1">
+ <longdesc lang="en">
+ Symbolic name for this file system.
+ </longdesc>
+ <shortdesc lang="en">
+ File System Name
+ </shortdesc>
+ <content type="string"/>
+ </parameter>
+
+ <parameter name="mountpoint" unique="1" required="1">
+ <longdesc lang="en">
+ Path in file system heirarchy to mount this file system.
+ </longdesc>
+ <shortdesc lang="en">
+ Mount Point
+ </shortdesc>
+ <content type="string"/>
+ </parameter>
+
+ <parameter name="host" required="1">
+ <longdesc lang="en">
+ Server IP address or hostname
+ </longdesc>
+ <shortdesc lang="en">
+ IP or Host
+ </shortdesc>
+ <content type="string"/>
+ </parameter>
+
+ <parameter name="export" required="1">
+ <longdesc lang="en">
+ NFS Export directory name or CIFS share
+ </longdesc>
+ <shortdesc lang="en">
+ Export
+ </shortdesc>
+ <content type="string"/>
+ </parameter>
+
+ <parameter name="fstype">
+ <longdesc lang="en">
+ File System type (nfs, nfs4 or cifs)
+ </longdesc>
+ <shortdesc lang="en">
+ File System Type
+ </shortdesc>
+ <content type="string" default="nfs"/>
+ </parameter>
+
+ <parameter name="no_unmount" required="0">
+ <longdesc lang="en">
+ Do not unmount the filesystem during a stop or relocation operation
+ </longdesc>
+ <shortdesc lang="en">
+ Skip unmount opration
+ </shortdesc>
+ <content type="boolean"/>
+ </parameter>
+
+ <parameter name="force_unmount">
+ <longdesc lang="en">
+ If set, the cluster will kill all processes using
+ this file system when the resource group is
+ stopped. Otherwise, the unmount will fail, and
+ the resource group will be restarted.
+ </longdesc>
+ <shortdesc lang="en">
+ Force Unmount
+ </shortdesc>
+ <content type="boolean"/>
+ </parameter>
+
+ <parameter name="self_fence">
+ <longdesc lang="en">
+ If set and unmounting the file system fails, the node will
+ immediately reboot. Generally, this is used in conjunction
+ with force_unmount support, but it is not required.
+ </longdesc>
+ <shortdesc lang="en">
+ Seppuku Unmount
+ </shortdesc>
+ <content type="boolean"/>
+ </parameter>
+
+ <parameter name="options">
+ <longdesc lang="en">
+ Provides a list of mount options. If none are specified,
+ the NFS file system is mounted -o sync.
+ </longdesc>
+ <shortdesc lang="en">
+ Mount Options
+ </shortdesc>
+ <content type="string"/>
+ </parameter>
+
+ <parameter name="use_findmnt">
+ <longdesc lang="en">
+ Use findmnt to determine if and where a filesystem is mounted.
+ Disabling this uses the failback method (should be used if autofs
+ maps are located on network storage (ie. nfs, iscsi, etc).
+ </longdesc>
+ <shortdesc lang="en">
+ Utilize findmnt to detect if and where filesystems are mounted
+ </shortdesc>
+ <content type="boolean"/>
+ </parameter>
+
+ </parameters>
+
+ <actions>
+ <action name="start" timeout="900"/>
+ <action name="stop" timeout="30"/>
+ <!-- Recovery isn't possible; we don't know if resources are using
+ the file system. -->
+
+ <!-- Checks to see if it's mounted in the right place -->
+ <action name="status" interval="1m" timeout="10"/>
+ <action name="monitor" interval="1m" timeout="10"/>
+
+ <!-- Checks to see if we can read from the mountpoint -->
+ <action name="status" depth="10" timeout="30" interval="5m"/>
+ <action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+ <!-- Checks to see if we can write to the mountpoint (if !ROFS) -->
+ <action name="status" depth="20" timeout="30" interval="10m"/>
+ <action name="monitor" depth="20" timeout="30" interval="10m"/>
+
+ <action name="meta-data" timeout="5"/>
+ <action name="validate-all" timeout="5"/>
+ </actions>
+
+ <special tag="rgmanager">
+ <child type="nfsexport" forbid="1"/>
+ <child type="nfsclient" forbid="1"/>
+ </special>
+</resource-agent>
+EOT
+}
+
+
+verify_host()
+{
+ if [ -z "$OCF_RESKEY_host" ]; then
+ ocf_log err "No server hostname or IP address specified."
+ return 1
+ fi
+
+ host $OCF_RESKEY_host 2>&1 | grep -vq "not found"
+ if [ $? -eq 0 ]; then
+ return 0
+ fi
+
+ ocf_log err "Hostname or IP address \"$OCF_RESKEY_host\" not valid"
+
+ return $OCF_ERR_ARGS
+}
+
+
+verify_fstype()
+{
+ # Auto detect?
+ [ -z "$OCF_RESKEY_fstype" ] && return 0
+
+ case $OCF_RESKEY_fstype in
+ nfs|nfs4|cifs)
+ return 0
+ ;;
+ *)
+ ocf_log err "File system type $OCF_RESKEY_fstype not supported"
+ return $OCF_ERR_ARGS
+ ;;
+ esac
+}
+
+
+verify_options()
+{
+ declare -i ret=0
+
+ #
+ # From mount(1)
+ #
+ for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
+ case $o in
+ async|atime|auto|defaults|dev|exec|_netdev|noatime)
+ continue
+ ;;
+ noauto|nodev|noexec|nosuid|nouser|ro|rw|suid|sync)
+ continue
+ ;;
+ dirsync|user|users)
+ continue
+ ;;
+ esac
+
+ case $OCF_RESKEY_fstype in
+ cifs)
+ continue
+ ;;
+ nfs|nfs4)
+ case $o in
+ #
+ # NFS / NFS4 common
+ #
+ rsize=*|wsize=*|timeo=*|retrans=*|acregmin=*)
+ continue
+ ;;
+ acregmax=*|acdirmin=*|acdirmax=*|actimeo=*)
+ continue
+ ;;
+ retry=*|port=*|bg|fg|soft|hard|intr|cto|ac|noac)
+ continue
+ ;;
+ esac
+
+ #
+ # NFS v2/v3 only
+ #
+ if [ "$OCF_RESKEY_fstype" = "nfs" ]; then
+ case $o in
+ mountport=*|mounthost=*)
+ continue
+ ;;
+ mountprog=*|mountvers=*|nfsprog=*|nfsvers=*)
+ continue
+ ;;
+ namelen=*)
+ continue
+ ;;
+ tcp|udp|lock|nolock)
+ continue
+ ;;
+ esac
+ fi
+
+ #
+ # NFS4 only
+ #
+ if [ "$OCF_RESKEY_fstype" = "nfs4" ]; then
+ case $o in
+ proto=*|clientaddr=*|sec=*)
+ continue
+ ;;
+ esac
+ fi
+
+ ;;
+ esac
+
+ ocf_log err "Option $o not supported for $OCF_RESKEY_fstype"
+ ret=$OCF_ERR_ARGS
+ done
+
+ return $ret
+}
+
+
+do_validate()
+{
+ verify_name || return $OCF_ERR_ARGS
+ verify_fstype|| return $OCF_ERR_ARGS
+ verify_host || return $OCF_ERR_ARGS
+ verify_mountpoint || return $OCF_ERR_ARGS
+ verify_options || return $OCF_ERR_ARGS
+ # verify_target || return $OCF_ERR_ARGS
+}
+
+
+#
+# Override real_device to use fs-lib's functions for start/stop_filesystem
+#
+real_device() {
+ export REAL_DEVICE="$1"
+}
+
+
+#
+# do_mount - nfs / cifs are mounted differently than blockdevs
+#
+do_mount() {
+ declare opts=""
+ declare mount_options=""
+ declare ret_val
+ declare mp="$OCF_RESKEY_mountpoint"
+
+ #
+ # Get the filesystem type, if specified.
+ #
+ fstype_option=""
+ fstype=${OCF_RESKEY_fstype}
+ case "$fstype" in
+ ""|"[ ]*")
+ fstype=""
+ ;;
+ *) # found it
+ fstype_option="-t $fstype"
+ ;;
+ esac
+
+ #
+ # Get the mount options, if they exist.
+ #
+ mount_options=""
+ opts=${OCF_RESKEY_options}
+ case "$opts" in
+ ""|"[ ]*")
+ opts=""
+ ;;
+ *) # found it
+ mount_options="-o $opts"
+ ;;
+ esac
+
+ case $OCF_RESKEY_fstype in
+ nfs|nfs4)
+ mount -t $OCF_RESKEY_fstype $mount_options $OCF_RESKEY_host:"$OCF_RESKEY_export" "$mp"
+ ;;
+ cifs)
+ mount -t $OCF_RESKEY_fstype $mount_options //$OCF_RESKEY_host/"$OCF_RESKEY_export" "$mp"
+ ;;
+ esac
+
+ ret_val=$?
+ if [ $ret_val -ne 0 ]; then
+ ocf_log err "\
+'mount $fstype_option $mount_options $OCF_RESKEY_host:$OCF_RESKEY_export $mp' failed, error=$ret_val"
+ return 1
+ fi
+
+ return 0
+}
+
+do_nfs_rpc_check() {
+ # see man nfs TRANSPORT PROTOCOL section for defaults
+ local nfsproto=tcp
+ local nfsmountproto=udp
+
+ # follow the same logic as mount.nfs option parser.
+ # the rightmost option wins over previous ones, so don't break when
+ # we find something.
+
+ for o in $(echo ${OCF_RESKEY_options} | sed -e s/,/\ /g); do
+ if echo $o | grep -q "^proto=" ; then
+ nfsproto="$(echo $o | cut -d "=" -f 2)"
+ fi
+ if echo $o | grep -q "^mountproto=" ; then
+ nfsmountproto="$(echo $o | cut -d "=" -f 2)"
+ fi
+ case $o in
+ tcp) nfsproto=tcp;;
+ udp) nfsproto=udp;;
+ rdma) nfsproto=rdma;;
+ esac
+ done
+
+ ocf_log debug "Testing generic rpc access on server ${OCF_RESKEY_host} with protocol $nfsproto"
+ if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} > /dev/null 2>&1; then
+ ocf_log alert "RPC server on ${OCF_RESKEY_host} with $nfsproto is not responding"
+ return 1
+ fi
+
+ ocf_log debug "Testing nfs rcp access on server ${OCF_RESKEY_host} with protocol $nfsproto"
+ if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} nfs > /dev/null 2>&1; then
+ ocf_log alert "NFS server on ${OCF_RESKEY_host} with $nfsproto is not responding"
+ return 1
+ fi
+
+ if [ "$OCF_RESKEY_fstype" = nfs ]; then
+ ocf_log debug "Testing mountd rpc access on server ${OCF_RESKEY_host} with protocol $nfsmountproto"
+ if ! rpcinfo -T $nfsmountproto ${OCF_RESKEY_host} mountd; then
+ ocf_log alert "MOUNTD server on ${OCF_RESKEY_host} with $nfsmountproto is not responding"
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+do_pre_unmount() {
+ case $OCF_RESKEY_fstype in
+ nfs|nfs4)
+ if [ "$self_fence" != $YES ]; then
+ ocf_log debug "Skipping pre unmount checks: self_fence is disabled"
+ return 0
+ fi
+
+ is_mounted "$dev" "$mp"
+ case $? in
+ $NO)
+ ocf_log debug "Skipping pre unmount checks: device is not mounted"
+ return 0
+ ;;
+ esac
+
+ ocf_log info "pre unmount: checking if nfs server ${OCF_RESKEY_host} is alive"
+ if ! do_nfs_rpc_check; then
+ ocf_log alert "NFS server not responding - REBOOTING"
+ sleep 2
+ reboot -fn
+ fi
+ ;;
+ esac
+
+ return 0
+}
+
+do_force_unmount() {
+ case $OCF_RESKEY_fstype in
+ nfs|nfs4)
+ ocf_log warning "Calling 'umount -f $mp'"
+ umount -f "$OCF_RESKEY_mountpoint"
+ return $?
+ ;;
+ *)
+ ;;
+ esac
+
+ return 1 # Returning 1 lets stop_filesystem do add'l checks
+}
+
+
+populate_defaults()
+{
+ case $OCF_RESKEY_fstype in
+ nfs|nfs4)
+ export OCF_RESKEY_device="$OCF_RESKEY_host:$OCF_RESKEY_export"
+ if [ -z "$OCF_RESKEY_options" ]; then
+ export OCF_RESKEY_options=sync,soft,noac
+ fi
+ ;;
+ cifs)
+ export OCF_RESKEY_device="//$OCF_RESKEY_host/$OCF_RESKEY_export"
+ if [ -z "$OCF_RESKEY_options" ]; then
+ export OCF_RESKEY_options=guest
+ fi
+ ;;
+ esac
+}
+
+
+#
+# Main...
+#
+populate_defaults
+main $*