diff --git a/rgmanager/src/resources/netfs.sh b/rgmanager/src/resources/netfs.sh index 5dad99373..dc64cd722 100755 --- a/rgmanager/src/resources/netfs.sh +++ b/rgmanager/src/resources/netfs.sh @@ -1,493 +1,488 @@ #!/bin/bash # # 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" required="0"> + <parameter name="fstype"> <longdesc lang="en"> File System type (nfs, nfs4 or cifs) </longdesc> <shortdesc lang="en"> File System Type </shortdesc> - <content type="string"/> + <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() { - if [ -z "$OCF_RESKEY_fstype" ]; then - export OCF_RESKEY_fstype=nfs - fi - - 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 $*