Gitweb: http://git.fedorahosted.org/git/resource-agents.git?p=resource-agents.git;a=... Commit: 07d213ce05841db8ee82b2daf55c62bbc9539229 Parent: 53c9f50ebe210a63c74f11184d3023992ed88f31 Author: Lon Hohberger lhh@redhat.com AuthorDate: Wed Apr 28 12:50:24 2010 -0400 Committer: Fabio M. Di Nitto fdinitto@redhat.com CommitterDate: Tue Jul 6 05:42:42 2010 +0200
resource-agents: Clean up file system agents
- Make mountpoints with spaces work universally - Use fuser -kvm in all agents to make force_unmount work - Eliminate duplicate code
Resolves: rhbz#581533 rhbz#582753 rhbz#582754
Signed-off-by: Lon Hohberger lhh@redhat.com --- rgmanager/src/resources/clusterfs.sh | 608 +------------------ rgmanager/src/resources/fs.sh.in | 797 +----------------------- rgmanager/src/resources/netfs.sh | 368 ++---------- rgmanager/src/resources/utils/Makefile.am | 3 +- rgmanager/src/resources/utils/fs-lib.sh | 942 +++++++++++++++++++++++++++++ 5 files changed, 1039 insertions(+), 1679 deletions(-)
diff --git a/rgmanager/src/resources/clusterfs.sh b/rgmanager/src/resources/clusterfs.sh index f90f865..06214d5 100644 --- a/rgmanager/src/resources/clusterfs.sh +++ b/rgmanager/src/resources/clusterfs.sh @@ -1,37 +1,12 @@ #!/bin/bash
# -# File system (normal) mount/umount/fsck/etc. agent +# Cluster File System mount/umount/fsck/etc. agent #
-LC_ALL=C -LANG=C -PATH=/bin:/sbin:/usr/bin:/usr/sbin -export LC_ALL LANG PATH +. $(dirname $0)/utils/fs-lib.sh
-# -# XXX todo - search and replace on these -# -SUCCESS=0 -FAIL=2 -YES=0 -NO=1 -YES_STR="yes" - -# Grab nfs lock tricks if available -export NFS_TRICKS=1 -if [ -f "$(dirname $0)/svclib_nfslock" ]; then - . $(dirname $0)/svclib_nfslock - NFS_TRICKS=0 -else - unset OCF_RESKEY_nfslock -fi - - -. $(dirname $0)/ocf-shellfuncs - - -meta_data() +do_metadata() { cat <<EOT <?xml version="1.0" ?> @@ -182,86 +157,6 @@ EOT }
-verify_name() -{ - [ -n "$OCF_RESKEY_name" ] || exit $OCF_ERR_ARGS -} - - -verify_mountpoint() -{ - if [ -z "$OCF_RESKEY_mountpoint" ]; then - ocf_log err "No mount point specified." - return $OCF_ERR_ARGS - fi - - if ! [ -e "$OCF_RESKEY_mountpoint" ]; then - ocf_log info "Mount point $OCF_RESKEY_mountpoint will be " - "created at mount time." - return 0 - fi - - [ -d "$OCF_RESKEY_mountpoint" ] && return 0 - - ocf_log err "$OCF_RESKEY_mountpoint is not a directory" - return $OCF_ERR_ARGS -} - - -real_device() -{ - declare dev=$1 - declare realdev - - [ -z "$dev" ] && return 1 - - if [ -h "$dev" ]; then - realdev=$(readlink -f $dev) - if [ $? -ne 0 ]; then - return 1 - fi - echo $realdev - return 0 - fi - - if [ -b "$dev" ]; then - echo $dev - return 0 - fi - - realdev=$(findfs $dev 2> /dev/null) - if [ -n "$realdev" ] && [ -b "$realdev" ]; then - echo $realdev - return 0 - fi - - return 1 -} - - -verify_device() -{ - declare realdev - - if [ -z "$OCF_RESKEY_device" ]; then - ocf_log err "No device or label specified." - return $OCF_ERR_ARGS - fi - - realdev=$(real_device $OCF_RESKEY_device) - if [ -n "$realdev" ]; then - if [ "$realdev" != "$OCF_RESKEY_device" ]; then - echo "Specified $OCF_RESKEY_device maps to $realdev" - fi - return $OCF_SUCCESS - fi - - ocf_log "Device or label "$OCF_RESKEY_device" not valid" - - return $OCF_ERR_ARGS -} - - verify_fstype() { # Auto detect? @@ -328,7 +223,7 @@ verify_options() }
-verify_all() +do_verify() { verify_name || return $OCF_ERR_ARGS verify_fstype || return $OCF_ERR_ARGS @@ -338,361 +233,7 @@ verify_all() }
-# -# mountInUse device mount_point -# -# Check to see if either the device or mount point are in use anywhere on -# the system. It is not required that the device be mounted on the named -# moint point, just if either are in use. -# -mountInUse () { - typeset mp tmp_mp - typeset dev tmp_dev - typeset junk - - if [ $# -ne 2 ]; then - ocf_log err "Usage: mountInUse device mount_point". - return $FAIL - fi - - dev=$1 - mp=$2 - - while read tmp_dev tmp_mp junk; do - if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then - return $YES - fi - - if [ -n "$tmp_mp" -a "$tmp_mp" = "$mp" ]; then - return $YES - fi - done < <(mount | awk '{print $1,$3}') - - return $NO -} - - -# -# isMounted device mount_point -# -# Check to see if the device is mounted. Print a warning if its not -# mounted on the directory we expect it to be mounted on. -# -isMounted () { - - typeset mp tmp_mp - typeset dev tmp_dev - - if [ $# -ne 2 ]; then - ocf_log err "Usage: isMounted device mount_point" - return $FAIL - fi - - dev=$(real_device $1) - if [ -z "$dev" ]; then - ocf_log err "isMounted: Could not match $1 with a real device" - return $FAIL - fi - mp=$(readlink -f $2) - - while read tmp_dev tmp_mp - do - #echo "spec=$1 dev=$dev tmp_dev=$tmp_dev" - tmp_dev=$(real_device $tmp_dev) - - if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then - # - # Check to see if its mounted in the right - # place - # - if [ -n "$tmp_mp" -a "$tmp_mp" != "$mp" ]; then - ocf_log warn "\ -Device $dev is mounted on $tmp_mp instead of $mp" - fi - return $YES - fi - done < <(mount | awk '{print $1,$3}') - - return $NO -} - - -# -# isAlive mount_point -# -# Check to see if mount_point is alive (testing read/write) -# -isAlive() -{ - declare errcode - declare mount_point - declare file=".writable_test.$(hostname)" - declare rw - - if [ $# -ne 1 ]; then - ocf_log err "Usage: isAlive mount_point" - return $FAIL - fi - mount_point=$1 - - test -d $mount_point - if [ $? -ne 0 ]; then - ocf_log err "$mount_point is not a directory" - return $FAIL - fi - - [ $OCF_CHECK_LEVEL -lt 10 ] && return $YES - - # depth 10 test (read test) - ls $mount_point > /dev/null 2> /dev/null - errcode=$? - if [ $errcode -ne 0 ]; then - ocf_log err "clusterfs:${OCF_RESKEY_name}: isAlive failed read test on [$mount_point]. Return code: $errcode" - return $NO - fi - - [ $OCF_CHECK_LEVEL -lt 20 ] && return $YES - - # depth 20 check (write test) - rw=$YES - for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do - if [ "$o" = "ro" ]; then - rw=$NO - fi - done - if [ $rw -eq $YES ]; then - file=$mount_point/$file - while true; do - if [ -e "$file" ]; then - file=${file}_tmp - continue - else - break - fi - done - touch $file > /dev/null 2> /dev/null - errcode=$? - if [ $errcode -ne 0 ]; then - ocf_log err "clusterfs:${OCF_RESKEY_name}: isAlive failed write test on [$mount_point]. Return code: $errcode" - return $NO - fi - rm -f $file > /dev/null 2> /dev/null - fi - - return $YES -} - - -# -# startFilesystem -# -startFilesystem() { - typeset -i ret_val=$SUCCESS - typeset mp="" # mount point - typeset dev="" # device - typeset fstype="" - typeset opts="" - typeset device_in_use="" - typeset mount_options="" - - # - # Get the mount point, if it exists. If not, no need to continue. - # - mp=${OCF_RESKEY_mountpoint} - case "$mp" in - ""|"[ ]*") # nothing to mount - return $SUCCESS - ;; - /*) # found it - ;; - *) # invalid format - ocf_log err \ -"startFilesystem: Invalid mount point format (must begin with a '/'): '$mp'" - return $FAIL - ;; - esac - - # - # Get the device - # - dev=$(real_device $OCF_RESKEY_device) - if [ -z "$dev" ]; then - ocf_log err "\ -startFilesystem: Could not match $OCF_RESKEY_device with a real device" - return $FAIL - fi - - # - # Ensure we've got a valid directory - # - if [ -e "$mp" ]; then - if ! [ -d "$mp" ]; then - ocf_log err "\ -startFilesystem: Mount point $mp exists but is not a directory" - return $FAIL - fi - else - ocf_log info "\ -startFilesystem: Creating mount point $mp for device $dev" - mkdir -p "$mp" - ret_val=$? - if [ $ret_val -ne 0 ]; then - ocf_log err "\ -startFilesystem: Unable to create $mp. Error code: $ret_val" - return $OCF_ERR_GENERIC - fi - fi - - # - # Get the filesystem type, if specified. - # - fstype_option="" - fstype=${OCF_RESKEY_fstype} - case "$fstype" in - ""|"[ ]*") - fstype="" - ;; - *) # found it - fstype_option="-t $fstype" - ;; - esac - - # - # See if the device is already mounted. - # - isMounted $dev $mp - case $? in - $YES) # already mounted - ocf_log debug "$dev already mounted" - return $SUCCESS - ;; - $NO) # not mounted, continue - ;; - $FAIL) - return $FAIL - ;; - esac - - - # - # Make sure that neither the device nor the mount point are mounted - # (i.e. they may be mounted in a different location). The'mountInUse' - # function checks to see if either the device or mount point are in - # use somewhere else on the system. - # - mountInUse $dev $mp - case $? in - $YES) # uh oh, someone is using the device or mount point - ocf_log err "\ -Cannot mount $dev on $mp, the device or mount point is already in use!" - return $FAIL - ;; - $NO) # good, no one else is using it - ;; - $FAIL) - return $FAIL - ;; - *) - ocf_log err "Unknown return from mountInUse" - return $FAIL - ;; - 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 - - # - # Mount the device - # - ocf_log debug "mount $fstype_option $mount_options $dev $mp" - mount $fstype_option $mount_options $dev $mp - ret_val=$? - if [ $ret_val -ne 0 ]; then - ocf_log err "\ -'mount $fstype_option $mount_options $dev $mp' failed, error=$ret_val" - return $FAIL - fi - - return $SUCCESS -} - - -# -# stopFilesystem serviceID deviceID -# -# Run the stop actions -# -stopFilesystem() { - typeset -i ret_val=0 - typeset -i try=1 - typeset -i max_tries=3 # how many times to try umount - typeset -i sleep_time=2 # time between each umount failure - typeset -i refs=0 - typeset done="" - typeset umount_failed="" - typeset force_umount="" - typeset self_fence="" - typeset fstype="" - - - # - # Get the mount point, if it exists. If not, no need to continue. - # - mp=${OCF_RESKEY_mountpoint} - case "$mp" in - ""|"[ ]*") # nothing to mount - return $SUCCESS - ;; - /*) # found it - ;; - *) # invalid format - ocf_log err \ -"stopFilesystem: Invalid mount point format (must begin with a '/'): '$mp'" - return $FAIL - ;; - esac - - # - # Get the device - # - dev=$(real_device $OCF_RESKEY_device) - if [ -z "$dev" ]; then - ocf_log err "\ -stop: Could not match $OCF_RESKEY_device with a real device" - return $FAIL - fi - - - # - # Get the force unmount setting if there is a mount point. - # - if [ -n "$mp" ]; then - case ${OCF_RESKEY_force_unmount} in - $YES_STR) force_umount=$YES ;; - 1) force_umount=$YES ;; - *) force_umount="" ;; - esac - fi - - if [ -n "$mp" ]; then - case ${OCF_RESKEY_self_fence} in - $YES_STR) self_fence=$YES ;; - 1) self_fence=$YES ;; - *) self_fence="" ;; - esac - fi - +do_pre_unmount() { # # Check the rgmanager-supplied reference count if one exists. # If the reference count is <= 1, we can safely proceed @@ -701,10 +242,15 @@ stop: Could not match $OCF_RESKEY_device with a real device" refs=$OCF_RESKEY_RGMANAGER_meta_refcnt if [ $refs -gt 0 ]; then ocf_log debug "Not unmounting $OCF_RESOURCE_INSTANCE - still in use by $refs other service(s)" - return $OCF_SUCCESS + return 2 fi fi
+ if [ -z "$force_umount" ]; then + ocf_log debug "Not umounting $dev (clustered file system)" + return 2 + fi + # # Always do this hackery on clustered file systems. # @@ -723,135 +269,7 @@ stop: Could not match $OCF_RESKEY_device with a real device" # Always invalidate buffers on clusterfs resources clubufflush -f $dev
- if [ -z "$force_umount" ]; then - ocf_log debug "Not umounting $dev (clustered file system)" - return $SUCCESS - fi - - # - # Unmount the device. - # - while [ ! "$done" ]; do - isMounted $dev $mp - case $? in - $NO) - ocf_log info "$dev is not mounted" - umount_failed= - done=$YES - ;; - $FAIL) - return $FAIL - ;; - $YES) - sync; sync; sync - ocf_log info "unmounting $dev ($mp)" - - umount $mp - if [ $? -eq 0 ]; then - umount_failed= - done=$YES - continue - fi - - umount_failed=yes - - if [ "$force_umount" ]; then - if [ $try -eq 1 ]; then - fuser -TERM -kvm "$mp" - else - fuser -kvm "$mp" - fi - fi - - if [ $try -ge $max_tries ]; then - done=$YES - else - sleep $sleep_time - let try=try+1 - fi - ;; - *) - return $FAIL - ;; - esac - - if [ $try -ge $max_tries ]; then - done=$YES - else - sleep $sleep_time - let try=try+1 - fi - done # while - - if [ -n "$umount_failed" ]; then - ocf_log err "'umount $mp' failed, error=$ret_val" - - if [ "$self_fence" ]; then - ocf_log alert "umount failed - REBOOTING" - sync - reboot -fn - fi - return $FAIL - fi - - return $SUCCESS + return 0 }
- -case $1 in -start) - declare tries=0 - declare rv - - while [ $tries -lt 3 ]; do - startFilesystem - rv=$? - if [ $rv -eq 0 ]; then - exit 0 - fi - - ((tries++)) - sleep 3 - done - exit $rv - ;; -stop) - stopFilesystem - exit $? - ;; -status|monitor) - isMounted ${OCF_RESKEY_device} ${OCF_RESKEY_mountpoint} - [ $? -ne $YES ] && exit $OCF_ERR_GENERIC - - isAlive ${OCF_RESKEY_mountpoint} - [ $? -ne $YES ] && exit $OCF_ERR_GENERIC - - exit 0 - ;; -restart) - stopFilesystem - if [ $? -ne 0 ]; then - exit $OCF_ERR_GENERIC - fi - - startFilesystem - if [ $? -ne 0 ]; then - exit $OCF_ERR_GENERIC - fi - - exit 0 - ;; -meta-data) - meta_data - exit 0 - ;; -validate-all) - verify_all - ;; -*) - echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" - exit $OCF_ERR_UNIMPLEMENTED - ;; -esac - -exit 0 +main $* diff --git a/rgmanager/src/resources/fs.sh.in b/rgmanager/src/resources/fs.sh.in index ffa721f..b63d53b 100644 --- a/rgmanager/src/resources/fs.sh.in +++ b/rgmanager/src/resources/fs.sh.in @@ -4,75 +4,9 @@ # File system (normal) mount/umount/fsck/etc. agent #
-LC_ALL=C -LANG=C -PATH=/bin:/sbin:/usr/bin:/usr/sbin -export LC_ALL LANG PATH +. $(dirname $0)/utils/fs-lib.sh
-# -# XXX todo - search and replace on these -# -SUCCESS=0 -FAIL=2 -YES=0 -NO=1 -YES_STR="yes" -INVALIDATEBUFFERS="/bin/true" - -# -# Using a global to contain the return value saves -# clone() operations. This is important to reduce -# resource consumption during status checks. -# -# There is no way to return a string from a function -# in bash without cloning the process, which is exactly -# what we are trying to avoid. So, we have to resort -# to using a dedicated global variable. This one is -# for the real_device() function below. -# -declare REAL_DEVICE - -# -# Stub ocf_log function for when we are using -# quick_status, since ocf_log generally forks (and -# sourcing ocf-shellfuncs forks -a lot-). -# -ocf_log() -{ - echo $* -} - -# -# Assume NFS_TRICKS are not available until we are -# proved otherwise. -# -export NFS_TRICKS=1 - -# -# Quick status doesn't fork() or clone() when using -# device files directly. (i.e. not symlinks, LABEL= or -# UUID= -# -if [ "$1" = "status" -o "$1" = "monitor" ] && - [ "$OCF_RESKEY_quick_status" = "1" ]; then - echo Using Quick Status - - # XXX maybe we can make ocf-shellfuncs have a 'quick' mode too? - export OCF_SUCCESS=0 - export OCF_ERR_GENERIC=1 -else - # - # Grab nfs lock tricks if available - # - if [ -f "$(dirname $0)/svclib_nfslock" ]; then - . $(dirname $0)/svclib_nfslock - NFS_TRICKS=0 - fi - - . $(dirname $0)/ocf-shellfuncs -fi - -meta_data() +do_metadata() { cat <<EOT <?xml version="1.0" encoding="ISO-8859-1" ?> @@ -254,109 +188,6 @@ meta_data() EOT }
-verify_name() -{ - if [ -z "$OCF_RESKEY_name" ]; then - ocf_log err "No file system name specified." - return $OCF_ERR_ARGS - fi - return $OCF_SUCCESS -} - - -verify_mountpoint() -{ - if [ -z "$OCF_RESKEY_mountpoint" ]; then - ocf_log err "No mount point specified." - return $OCF_ERR_ARGS - fi - - if ! [ -e "$OCF_RESKEY_mountpoint" ]; then - ocf_log info "Mount point $OCF_RESKEY_mountpoint will be "\ - "created at mount time." - return $OCF_SUCCESS - fi - - [ -d "$OCF_RESKEY_mountpoint" ] && return $OCF_SUCCESS - - ocf_log err "$OCF_RESKEY_mountpoint exists but is not a directory." - - return $OCF_ERR_ARGS -} - - -# -# This used to be called using $(...), but doing this causes bash -# to set up a pipe and clone(). So, the output of this function is -# stored in the global variable REAL_DEVICE, declared previously. -# -real_device() -{ - declare dev=$1 - declare realdev - - REAL_DEVICE="" - - [ -z "$dev" ] && return $OCF_ERR_ARGS - - # If our provided blockdev is a device, we are done - if [ -b "$dev" ]; then - REAL_DEVICE="$dev" - return $OCF_SUCCESS - fi - - # Oops, we have a link. Sorry, this is going to fork. - if [ -h "$dev" ]; then - realdev=$(readlink -f $dev) - if [ $? -ne 0 ]; then - return $OCF_ERR_ARGS - fi - REAL_DEVICE="$realdev" - return $OCF_SUCCESS - fi - - # It's not a link, it's not a block device. If it also - # does not match UUID= or LABEL=, then findfs is not - # going to find anything useful, so we should quit now. - if [ "${dev/UUID=/}" = "$dev" ] && - [ "${dev/LABEL=/}" = "$dev" ]; then - return $OCF_ERR_GENERIC - fi - - # When using LABEL= or UUID=, we can't save a fork. - realdev=$(findfs $dev 2> /dev/null) - if [ -n "$realdev" ] && [ -b "$realdev" ]; then - REAL_DEVICE="$realdev" - return $OCF_SUCCESS - fi - - return $OCF_ERR_GENERIC -} - - -verify_device() -{ - declare realdev - - if [ -z "$OCF_RESKEY_device" ]; then - ocf_log err "No device or label specified." - return $OCF_ERR_ARGS - fi - - real_device $OCF_RESKEY_device - realdev=$REAL_DEVICE - if [ -n "$realdev" ]; then - if [ "$realdev" != "$OCF_RESKEY_device" ]; then - ocf_log info "Specified $OCF_RESKEY_device maps to $realdev" - fi - return $OCF_SUCCESS - fi - - ocf_log err "Device or label "$OCF_RESKEY_device" not valid" - - return $OCF_ERR_ARGS -} -
verify_fstype() { @@ -396,6 +227,8 @@ verify_options() ;; esac
+ do_verify_option $OCF_RESKEY_fstype "$o" + case $OCF_RESKEY_fstype in ext2|ext3|ext4) case $o in @@ -500,7 +333,7 @@ verify_options() }
-verify_all() +do_validate() { verify_name || return $OCF_ERR_ARGS verify_fstype || return $OCF_ERR_ARGS @@ -510,389 +343,9 @@ verify_all() }
-# -# mountInUse device mount_point -# -# Check to see if either the device or mount point are in use anywhere on -# the system. It is not required that the device be mounted on the named -# moint point, just if either are in use. -# -mountInUse () { - typeset mp tmp_mp - typeset dev tmp_dev - typeset junka junkb junkc junkd - - if [ $# -ne 2 ]; then - ocf_log err "Usage: mountInUse device mount_point". - return $FAIL - fi - - dev=$1 - mp=$2 - - while read tmp_dev tmp_mp junka junkb junkc junkd; do - if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then - return $YES - fi - - if [ -n "$tmp_mp" -a "$tmp_mp" = "$mp" ]; then - return $YES - fi - done < /proc/mounts - - return $NO -} - - -# -# isMounted device mount_point -# -# Check to see if the device is mounted. Print a warning if its not -# mounted on the directory we expect it to be mounted on. -# -isMounted () { - - typeset mp tmp_mp - typeset dev tmp_dev - typeset ret=$FAIL - typeset found=1 - typeset poss_mp - - if [ $# -ne 2 ]; then - ocf_log err "Usage: isMounted device mount_point" - return $FAIL - fi - - real_device $1 - dev=$REAL_DEVICE - if [ -z "$dev" ]; then - ocf_log err \ - "fs (isMounted): Could not match $1 with a real device" - return $OCF_ERR_ARGS - fi - - if [ -h "$2" ]; then - mp=$(readlink -f $2) - else - mp=$2 - fi - - ret=$NO - - while read tmp_dev tmp_mp junk_a junk_b junk_c junk_d - do - real_device $tmp_dev - tmp_dev=$REAL_DEVICE - - # This bash glyph simply removes a trailing slash - # if one exists. /a/b/ -> /a/b; /a/b -> /a/b. - tmp_mp=${tmp_mp%/} - mp=${mp%/} - - if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then - # - # Check to see if its mounted in the right - # place - # - if [ -n "$tmp_mp" ]; then - if [ "$tmp_mp" != "$mp" ]; then - poss_mp=$tmp_mp - else - found=0 - fi - fi - ret=$YES - fi - done < /proc/mounts - - if [ $ret -eq $YES ] && [ $found -ne 0 ]; then - ocf_log warn "Device $dev is mounted on $poss_mp instead of $mp" - fi - - return $ret -} - - -# -# isAlive mount_point -# -# Check to see if mount_point is alive (testing read/write) -# -isAlive() +do_pre_mount() { - declare errcode - declare mount_point - declare file=".writable_test" - declare rw - - if [ $# -ne 1 ]; then - ocf_log err "Usage: isAlive mount_point" - return $FAIL - fi - mount_point=$1 - - test -d $mount_point - if [ $? -ne 0 ]; then - ocf_log err "fs (isAlive): $mount_point is not a directory" - return $FAIL - fi - - [ $OCF_CHECK_LEVEL -lt 10 ] && return $YES - - # depth 10 test (read test) - ls $mount_point > /dev/null 2> /dev/null - errcode=$? - if [ $errcode -ne 0 ]; then - ocf_log err "fs:${OCF_RESKEY_name}: isAlive failed read test on [$mount_point]. Return code: $errcode" - return $NO - fi - - [ $OCF_CHECK_LEVEL -lt 20 ] && return $YES - - # depth 20 check (write test) - rw=$YES - for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do - if [ "$o" = "ro" ]; then - rw=$NO - fi - done - if [ $rw -eq $YES ]; then - file=$mount_point/$file - while true; do - if [ -e "$file" ]; then - file=${file}_tmp - continue - else - break - fi - done - touch $file > /dev/null 2> /dev/null - errcode=$? - if [ $errcode -ne 0 ]; then - ocf_log err "fs:${OCF_RESKEY_name}: isAlive failed write test on [$mount_point]. Return code: $errcode" - return $NO - fi - rm -f $file > /dev/null 2> /dev/null - fi - - return $YES -} - - -# -# Decide which quota options are enabled and return a string -# which we can pass to quotaon -# -quota_opts() -{ - declare quotaopts="" - declare opts=$1 - declare mopt - - for mopt in `echo $opts | sed -e s/,/\ /g`; do - case $mopt in - usrquota) - quotaopts="u$quotaopts" - continue - ;; - grpquota) - quotaopts="g$quotaopts" - continue - ;; - noquota) - quotaopts="" - return 0 - ;; - esac - done - - echo $quotaopts - return 0 -} - - - -# -# Enable quotas on the mount point if the user requested them -# -enable_fs_quotas() -{ - declare -i need_check=0 - declare -i rv - declare quotaopts="" - declare mopt - declare opts=$1 - declare mp=$2 - - if [ -z "`which quotaon`" ]; then - ocf_log err "quotaon not found in $PATH" - return $OCF_ERR_GENERIC - fi - - quotaopts=$(quota_opts $opts) - - ocf_log info "quotaopts = $quotaopts" - - [ -z "$quotaopts" ] && return 0 - - # Ok, create quota files if they don't exist - for f in quota.user aquota.user quota.group aquota.group; do - if ! [ -f "$mp/$f" ]; then - ocf_log info "$mp/$f was missing - creating" - touch "$mp/$f" - chmod 600 "$mp/$f" - need_check=1 - fi - done - - if [ $need_check -eq 1 ]; then - ocf_log info "Checking quota info in $mp" - quotacheck -$quotaopts "$mp" - fi - - ocf_log info "Enabling Quotas on $mp" - ocf_log debug "quotaon -$quotaopts "$mp"" - quotaon -$quotaopts "$mp" - rv=$? - if [ $rv -ne 0 ]; then - # Just a warning - ocf_log warn "Unable to turn on quotas for $mp; return = $rv" - fi - - return $rv -} - - -# -# startFilesystem -# -startFilesystem() { - typeset -i ret_val=$SUCCESS - typeset mp="" # mount point - typeset dev="" # device - typeset fstype="" - typeset opts="" - typeset device_in_use="" - typeset mount_options="" - - # - # Get the mount point, if it exists. If not, no need to continue. - # - mp=${OCF_RESKEY_mountpoint} - case "$mp" in - ""|"[ ]*") # nothing to mount - return $OCF_SUCCESS - ;; - /*) # found it - ;; - *) # invalid format - ocf_log err \ -"startFilesystem: Invalid mount point format (must begin with a '/'): '$mp'" - return $OCF_ERR_ARGS - ;; - esac - - # - # Get the device - # - real_device $OCF_RESKEY_device - dev=$REAL_DEVICE - if [ -z "$dev" ]; then - ocf_log err "\ -startFilesystem: Could not match $OCF_RESKEY_device with a real device" - return $OCF_ERR_ARGS - fi - - # - # Ensure we've got a valid directory - # - if [ -e "$mp" ]; then - if ! [ -d "$mp" ]; then - ocf_log err"\ -startFilesystem: Mount point $mp exists but is not a directory" - return $OCF_ERR_ARGS - fi - else - ocf_log err "\ -startFilesystem: Creating mount point $mp for device $dev" - mkdir -p "$mp" - ret_val=$? - if [ $ret_val -ne 0 ]; then - ocf_log err "\ -startFilesystem: Unable to create $mp. Error code: $ret_val" - return $OCF_ERR_GENERIC - fi - fi - - # - # Get the filesystem type, if specified. - # - fstype_option="" - fstype=${OCF_RESKEY_fstype} - case "$fstype" in - ""|"[ ]*") - fstype="" - ;; - *) # found it - fstype_option="-t $fstype" - ;; - esac - - # - # See if the device is already mounted. - # - isMounted $dev "$mp" - case $? in - $YES) # already mounted - ocf_log debug "$dev already mounted" - return $OCF_SUCCESS - ;; - $NO) # not mounted, continue - ;; - *) - return $FAIL - ;; - esac - - - # - # Make sure that neither the device nor the mount point are mounted - # (i.e. they may be mounted in a different location). The'mountInUse' - # function checks to see if either the device or mount point are in - # use somewhere else on the system. - # - mountInUse $dev "$mp" - case $? in - $YES) # uh oh, someone is using the device or mount point - ocf_log err "\ -Cannot mount $dev on $mp, the device or mount point is already in use!" - return $FAIL - ;; - $NO) # good, no one else is using it - ;; - $FAIL) - return $FAIL - ;; - *) - ocf_log err "Unknown return from mountInUse" - return $FAIL - ;; - 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 - + declare fstype="$OCF_RESKEY_fstype"
# # Check to determine if we need to fsck the filesystem. @@ -936,24 +389,15 @@ Unknown file system type '$fstype' for device $dev. Assuming fsck is required." 'fsck -p $dev' failed, error=$ret_val; check $fsck_log for errors" ocf_log debug "Invalidating buffers for $dev" $INVALIDATEBUFFERS -f $dev - return $FAIL + return $OCF_ERR_GENERIC fi rm -f $fsck_log fi
- # - # Mount the device - # - ocf_log info "mounting $dev on $mp" - ocf_log debug "mount $fstype_option $mount_options $dev $mp" - mount $fstype_option $mount_options $dev "$mp" - ret_val=$? - if [ $ret_val -ne 0 ]; then - ocf_log err "\ -'mount $fstype_option $mount_options $dev $mp' failed, error=$ret_val" - return $FAIL - fi + return 0 +}
+do_post_mount() { # # Create this for the NFS NLM broadcast bit # @@ -965,218 +409,35 @@ Unknown file system type '$fstype' for device $dev. Assuming fsck is required." fi fi
- enable_fs_quotas $opts "$mp" - - return $SUCCESS + return 0 }
-# -# stopFilesystem serviceID deviceID -# -# Run the stop actions -# -stopFilesystem() { - typeset -i ret_val=0 - typeset -i try=1 - typeset -i max_tries=3 # how many times to try umount - typeset -i sleep_time=5 # time between each umount failure - typeset -i nfslock_reclaim=0 - typeset done="" - typeset umount_failed="" - typeset force_umount="" - typeset self_fence="" - typeset fstype="" - typeset quotaopts="" - +do_force_unmount() { + if [ "$OCF_RESKEY_nfslock" = "yes" ] || \ + [ "$OCF_RESKEY_nfslock" = "1" ]; then + ocf_log warning "Dropping node-wide NFS locks" + pkill -KILL -x lockd + mkdir -p "$mp"/.clumanager/statd + # Copy out the notify list; our + # IPs are already torn down + notify_list_store "$mp"/.clumanager/statd
- # - # Get the mount point, if it exists. If not, no need to continue. - # - mp=${OCF_RESKEY_mountpoint} - case "$mp" in - ""|"[ ]*") # nothing to mount - return $SUCCESS - ;; - /*) # found it - ;; - *) # invalid format - ocf_log err \ -"stopFilesystem: Invalid mount point format (must begin with a '/'): '$mp'" - return $FAIL - ;; - esac - - - # - # Get the device - # - real_device $OCF_RESKEY_device - dev=$REAL_DEVICE - if [ -z "$dev" ]; then - ocf_log err "\ -stop: Could not match $OCF_RESKEY_device with a real device" - return $FAIL - fi - - # - # Get the force unmount setting if there is a mount point. - # - if [ -n "$mp" ]; then - case ${OCF_RESKEY_force_unmount} in - $YES_STR) force_umount=$YES ;; - 1) force_umount=$YES ;; - *) force_umount="" ;; - esac - fi - - if [ -n "$mp" ]; then - case ${OCF_RESKEY_self_fence} in - $YES_STR) self_fence=$YES ;; - 1) self_fence=$YES ;; - *) self_fence="" ;; - esac + # Save for post-umount phase + export nfslock_reclaim=1 fi
- # - # Unmount the device. - # - while [ ! "$done" ]; do - isMounted $dev "$mp" - case $? in - $NO) - ocf_log info "$dev is not mounted" - umount_failed= - done=$YES - ;; - $FAIL) - return $FAIL - ;; - $YES) - sync; sync; sync - quotaopts=$(quota_opts $OCF_RESKEY_options) - if [ -n "$quotaopts" ]; then - ocf_log debug "Turning off quotas for $mp" - quotaoff -$quotaopts "$mp" &> /dev/null - fi - - - ocf_log info "unmounting $mp" - umount "$mp" - if [ $? -eq 0 ]; then - umount_failed= - done=$YES - continue - fi - - umount_failed=yes - - if [ "$force_umount" ]; then - if [ $try -eq 1 ]; then - fuser -TERM -kvm "$mp" - - if [ "$OCF_RESKEY_nfslock" = "yes" ] || \ - [ "$OCF_RESKEY_nfslock" = "1" ]; then - ocf_log warning \ - "Dropping node-wide NFS locks" - pkill -KILL -x lockd - mkdir -p "$mp"/.clumanager/statd - # Copy out the notify list; our - # IPs are already torn down - notify_list_store "$mp"/.clumanager/statd - nfslock_reclaim=1 - fi - else - fuser -kvm "$mp" - fi - fi - - ;; - *) - return $FAIL - ;; - esac + return 0 +}
- if [ $try -ge $max_tries ]; then - done=$YES - elif [ "$done" != "$YES" ]; then - sleep $sleep_time - let try=try+1 - fi - done # while
- if [ $nfslock_reclaim -eq 1 ]; then +do_post_unmount() { + if [ "$nfslock_reclaim" = "1" ]; then # If we have this flag set, do a full reclaim broadcast notify_list_broadcast "$mp"/.clumanager/statd fi
- if [ -n "$umount_failed" ]; then - ocf_log err "'umount $mp' failed, error=$ret_val" - - if [ "$self_fence" ]; then - ocf_log alert "umount failed - REBOOTING" - sync - reboot -fn - fi - return $FAIL - else - return $SUCCESS - fi + return 0 }
- -case $1 in -start) - startFilesystem - exit $? - ;; -stop) - stopFilesystem - exit $? - ;; -status|monitor) - isMounted ${OCF_RESKEY_device} ${OCF_RESKEY_mountpoint} - - if [ $? -ne $YES ]; then - ocf_log err "fs:${OCF_RESKEY_name}: ${OCF_RESKEY_device} is not mounted on ${OCF_RESKEY_mountpoint}" - exit $OCF_ERR_GENERIC - fi - - if [ "$OCF_RESKEY_quick_status" = "1" ]; then - exit 0 - fi - - isAlive ${OCF_RESKEY_mountpoint} - [ $? -eq $YES ] && exit 0 - - ocf_log err "fs:${OCF_RESKEY_name}: Mount point is not accessible!" - exit $OCF_ERR_GENERIC - ;; -restart) - stopFilesystem - if [ $? -ne 0 ]; then - exit $OCF_ERR_GENERIC - fi - - startFilesystem - if [ $? -ne 0 ]; then - exit $OCF_ERR_GENERIC - fi - - exit 0 - ;; -meta-data) - meta_data - exit 0 - ;; -validate-all) - verify_all - exit $? - ;; -*) - echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" - exit $OCF_ERR_UNIMPLEMENTED - ;; -esac - -exit 0 +main $* diff --git a/rgmanager/src/resources/netfs.sh b/rgmanager/src/resources/netfs.sh index bb749f7..53eab98 100644 --- a/rgmanager/src/resources/netfs.sh +++ b/rgmanager/src/resources/netfs.sh @@ -4,25 +4,9 @@ # NFS/CIFS file system mount/umount/etc. agent #
-LC_ALL=C -LANG=C -PATH=/bin:/sbin:/usr/bin:/usr/sbin -export LC_ALL LANG PATH +. $(dirname $0)/utils/fs-lib.sh
-# -# XXX todo - search and replace on these -# -SUCCESS=0 -FAIL=2 -YES=0 -NO=1 -YES_STR="yes" - - -. $(dirname $0)/ocf-shellfuncs - - -meta_data() +do_metadata() { cat <<EOT <?xml version="1.0" ?> @@ -154,33 +138,6 @@ EOT }
-verify_name() -{ - [ -n "$OCF_RESKEY_name" ] || exit $OCF_ERR_ARGS -} - - -verify_mountpoint() -{ - if [ -z "$OCF_RESKEY_mountpoint" ]; then - ocf_log err "No mount point specified." - return $OCF_ERR_ARGS - fi - - if ! [ -e "$OCF_RESKEY_mountpoint" ]; then - ocf_log info "Mount point $OCF_RESKEY_mountpoint will be created "\ - "at mount time." - return 0 - fi - - [ -d "$OCF_RESKEY_mountpoint" ] && return 0 - - ocf_log err "$OCF_RESKEY_mountpoint is not a directory" - - return 1 -} - - verify_host() { if [ -z "$OCF_RESKEY_host" ]; then @@ -298,116 +255,45 @@ verify_options() }
-verify_all() +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 }
- # -# isMounted fullpath mount_point +# Override real_device to use fs-lib's functions for start/stop_filesystem # -# Check to see if the full path is mounted where we need it. -# -isMounted () { - - typeset mp tmp_mp - typeset fullpath tmp_fullpath - - if [ $# -ne 2 ]; then - ocf_log err "Usage: isMounted host:/export mount_point" - return $FAIL - fi - - fullpath=$1 - mp=$(readlink -f $2) - - while read tmp_fullpath tmp_mp - do - if [ "$tmp_fullpath" = "$fullpath" -a \ - "$tmp_mp" = "$mp" ]; then - return $YES - fi - done < <(mount | awk '{print $1,$3}') - - return $NO +real_device() { + export REAL_DEVICE="$1" }
+ # -# startNFSFilesystem +# do_mount - nfs / cifs are mounted differently than blockdevs # -startNFSFilesystem() { - typeset -i ret_val=$SUCCESS - typeset mp="" # mount point - typeset host="" - typeset fullpath="" - typeset exp="" - typeset opts="" - typeset mount_options="" - - # - # Get the mount point, if it exists. If not, no need to continue. - # - mp=${OCF_RESKEY_mountpoint} - case "$mp" in - ""|"[ ]*") # nothing to mount - return $SUCCESS - ;; - /*) # found it - ;; - *) # invalid format - ocf_log err \ -"startFilesystem: Invalid mount point format (must begin with a '/'): '$mp'" - return $FAIL - ;; - esac - # - # Get the device - # - host=${OCF_RESKEY_host} - exp=${OCF_RESKEY_export} - - fullpath=$host:$exp +do_mount() { + declare opts="" + declare mount_options="" + declare ret_val + declare mp="$OCF_RESKEY_mountpoint"
# - # Ensure we've got a valid directory + # Get the filesystem type, if specified. # - if [ -e "$mp" ]; then - if ! [ -d "$mp" ]; then - ocf_log err "\ -startFilesystem: Mount point $mp exists but is not a directory" - return $FAIL - fi - else - ocf_log info "\ -startFilesystem: Creating mount point $mp for $fullpath" - mkdir -p "$mp" - ret_val=$? - if [ $ret_val -ne 0 ]; then - ocf_log err "\ -startFilesystem: Unable to create $mp. Error code: $ret_val" - return $OCF_ERR_GENERIC - fi - fi - - # - # See if the mount path is already mounted. - # - isMounted $fullpath $mp - case $? in - $YES) # already mounted - ocf_log debug "$fullpath already mounted on $mp" - return $SUCCESS - ;; - $NO) # not mounted, continue + fstype_option="" + fstype=${OCF_RESKEY_fstype} + case "$fstype" in + ""|"[ ]*") + fstype="" ;; - $FAIL) - return $FAIL + *) # found it + fstype_option="-t $fstype" ;; esac
@@ -425,154 +311,37 @@ startFilesystem: Unable to create $mp. Error code: $ret_val" ;; esac
- # - # Mount the NFS export - # - ocf_log debug "mount $fstype_option $mount_options $fullpath $mp" - case $OCF_RESKEY_fstype in - nfs|nfs4) - mount -t $OCF_RESKEY_fstype $mount_options $host:$exp $mp - ;; - cifs) - mount -t $OCF_RESKEY_fstype $mount_options //$host/$exp $mp - ;; + 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 $fullpath $mp' failed, error=$ret_val" - return $FAIL +'mount $fstype_option $mount_options $OCF_RESKEY_host:$OCF_RESKEY_export $mp' failed, error=$ret_val" + return 1 fi - return $SUCCESS + return 0 }
-# -# stopFilesystem serviceID deviceID -# -# Run the stop actions -# -stopNFSFilesystem() { - typeset -i ret_val=0 - typeset -i try=1 - typeset -i max_tries=3 # how many times to try umount - typeset -i sleep_time=2 # time between each umount failure - typeset done="" - typeset umount_failed="" - typeset no_umount="" - typeset force_umount="" - typeset fstype="" - - - # - # Get the mount point, if it exists. If not, no need to continue. - # - mp=${OCF_RESKEY_mountpoint} - case "$mp" in - ""|"[ ]*") # nothing to mount - return $SUCCESS - ;; - /*) # found it - ;; - *) # invalid format - ocf_log err \ -"stopNFSFilesystem: Invalid mount point format (must begin with a '/'): '$mp'" - return $FAIL - ;; - esac - - # - # Get the host/path - # - fullpath="${OCF_RESKEY_host}:${OCF_RESKEY_export}" - - # - # Get the force unmount setting if there is a mount point. - # - if [ -n "$mp" ]; then - case ${OCF_RESKEY_force_unmount} in - $YES_STR) force_umount="$YES" ;; - 1) force_umount="$YES" ;; - *) force_umount="" ;; - esac - fi - - # - # Unmount - # - while [ ! "$done" ]; do - isMounted $fullpath $mp - case $? in - $NO) - ocf_log debug "$fullpath is not mounted" - umount_failed= - done=$YES - ;; - $FAIL) - return $FAIL - ;; - $YES) - case ${OCF_RESKEY_no_unmount} in - $YES_STR) no_umount="$YES" ;; - 1) no_umount="$YES" ;; - *) no_umount="" ;; - esac - - if [ "$no_umount" ]; then - ocf_log info "skipping unmount operation of $mp" - return $SUCCESS - fi - - sync; sync; sync - ocf_log info "unmounting $mp" - - umount $mp - if [ $? -eq 0 ]; then - umount_failed= - done=$YES - continue - fi - - umount_failed=yes - - if [ "$force_umount" ]; then - if [ $try -eq 1 ]; then - fuser -TERM -kvm "$mp" - else - fuser -kvm "$mp" - fi - fi - - - if [ $try -ge $max_tries ]; then - done=$YES - else - sleep $sleep_time - let try=try+1 - fi +do_force_unmount() { + case $OCF_RESKEY_fstype in + nfs|nfs4) + ocf_log warning "Calling 'umount -f $mp'" + umount -f "$OCF_RESKEY_mountpoint" ;; *) - return $FAIL ;; esac
- if [ $try -ge $max_tries ]; then - done=$YES - else - sleep $sleep_time - let try=try+1 - fi - done # while - if [ -n "$umount_failed" ]; then - ocf_log err "'umount $fullpath' failed ($mp), error=$ret_val" - - return $FAIL - fi - - return $SUCCESS + return 0 # Returning 0 lets stop_filesystem do add'l checks }
@@ -582,57 +351,26 @@ populate_defaults() export OCF_RESKEY_fstype=nfs fi
- if [ -z "$OCF_RESKEY_options" ]; then - export OCF_RESKEY_options=sync,soft,noac - 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 - -case $1 in -start) - startNFSFilesystem - exit $? - ;; -stop) - stopNFSFilesystem - exit $? - ;; -status|monitor) - isMounted ${OCF_RESKEY_host}:${OCF_RESKEY_export} \ - ${OCF_RESKEY_mountpoint} - exit $? - ;; -restart) - stopNFSFilesystem - if [ $? -ne 0 ]; then - exit $OCF_ERR_GENERIC - fi - - startNFSFilesystem - if [ $? -ne 0 ]; then - exit $OCF_ERR_GENERIC - fi - - exit 0 - ;; -meta-data) - meta_data - exit 0 - ;; -validate-all) - verify_all - exit $? - ;; -*) - echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" - exit $OCF_ERR_UNIMPLEMENTED - ;; -esac - -exit 0 +main $* diff --git a/rgmanager/src/resources/utils/Makefile.am b/rgmanager/src/resources/utils/Makefile.am index b5010d4..fca3e6e 100644 --- a/rgmanager/src/resources/utils/Makefile.am +++ b/rgmanager/src/resources/utils/Makefile.am @@ -2,7 +2,8 @@ MAINTAINERCLEANFILES = Makefile.in
TARGET = config-utils.sh
-commonscripts = httpd-parse-config.pl \ +commonscripts = fs-lib.sh \ + httpd-parse-config.pl \ member_util.sh \ messages.sh \ named-parse-config.pl \ diff --git a/rgmanager/src/resources/utils/fs-lib.sh b/rgmanager/src/resources/utils/fs-lib.sh new file mode 100644 index 0000000..bc3877e --- /dev/null +++ b/rgmanager/src/resources/utils/fs-lib.sh @@ -0,0 +1,942 @@ +#!/bin/bash + +# +# File system common functions +# + +LC_ALL=C +LANG=C +PATH=/bin:/sbin:/usr/bin:/usr/sbin +export LC_ALL LANG PATH + +# Private return codes +FAIL=2 +NO=1 +YES=0 +YES_STR="yes" + +[ -z "$OCF_RESOURCE_INSTANCE" ] && export OCF_RESOURCE_INSTANCE="filesystem:$OCF_RESKEY_name" + +# +# Using a global to contain the return value saves +# clone() operations. This is important to reduce +# resource consumption during status checks. +# +# There is no way to return a string from a function +# in bash without cloning the process, which is exactly +# what we are trying to avoid. So, we have to resort +# to using a dedicated global variable. This one is +# for the real_device() function below. +# +declare REAL_DEVICE + +# +# Stub ocf_log function for when we are using +# quick_status, since ocf_log generally forks (and +# sourcing ocf-shellfuncs forks -a lot-). +# +ocf_log() +{ + echo $* +} + +# +# Assume NFS_TRICKS are not available until we are +# proved otherwise. +# +export NFS_TRICKS=1 + +# +# Quick status doesn't fork() or clone() when using +# device files directly. (i.e. not symlinks, LABEL= or +# UUID= +# +if [ "$1" = "status" -o "$1" = "monitor" ] && + [ "$OCF_RESKEY_quick_status" = "1" ]; then + echo Using Quick Status + + # XXX maybe we can make ocf-shellfuncs have a 'quick' mode too? + export OCF_SUCCESS=0 + export OCF_ERR_GENERIC=1 +else + # + # Grab nfs lock tricks if available + # + if [ -f "$(dirname $0)/svclib_nfslock" ]; then + . $(dirname $0)/svclib_nfslock + NFS_TRICKS=0 + fi + + . $(dirname $0)/ocf-shellfuncs +fi + + +verify_name() +{ + if [ -z "$OCF_RESKEY_name" ]; then + ocf_log err "No file system name specified." + return $OCF_ERR_ARGS + fi + return $OCF_SUCCESS +} + + +verify_mountpoint() +{ + if [ -z "$OCF_RESKEY_mountpoint" ]; then + ocf_log err "No mount point specified." + return $OCF_ERR_ARGS + fi + + if ! [ -e "$OCF_RESKEY_mountpoint" ]; then + ocf_log info "Mount point $OCF_RESKEY_mountpoint will be "\ + "created at mount time." + return $OCF_SUCCESS + fi + + [ -d "$OCF_RESKEY_mountpoint" ] && return $OCF_SUCCESS + + ocf_log err "$OCF_RESKEY_mountpoint exists but is not a directory." + + return $OCF_ERR_ARGS +} + + +# +# This used to be called using $(...), but doing this causes bash +# to set up a pipe and clone(). So, the output of this function is +# stored in the global variable REAL_DEVICE, declared previously. +# +real_device() +{ + declare dev="$1" + declare realdev + + REAL_DEVICE="" + + [ -z "$dev" ] && return $OCF_ERR_ARGS + + # If our provided blockdev is a device, we are done + if [ -b "$dev" ]; then + REAL_DEVICE="$dev" + return $OCF_SUCCESS + fi + + # Oops, we have a link. Sorry, this is going to fork. + if [ -h "$dev" ]; then + realdev=$(readlink -f $dev) + if [ $? -ne 0 ]; then + return $OCF_ERR_ARGS + fi + REAL_DEVICE="$realdev" + return $OCF_SUCCESS + fi + + # It's not a link, it's not a block device. If it also + # does not match UUID= or LABEL=, then findfs is not + # going to find anything useful, so we should quit now. + if [ "${dev/UUID=/}" = "$dev" ] && + [ "${dev/LABEL=/}" = "$dev" ]; then + return $OCF_ERR_GENERIC + fi + + # When using LABEL= or UUID=, we can't save a fork. + realdev=$(findfs "$dev" 2> /dev/null) + if [ -n "$realdev" ] && [ -b "$realdev" ]; then + REAL_DEVICE="$realdev" + return $OCF_SUCCESS + fi + + return $OCF_ERR_GENERIC +} + + +verify_device() +{ + declare realdev + + if [ -z "$OCF_RESKEY_device" ]; then + ocf_log err "No device or label specified." + return $OCF_ERR_ARGS + fi + + real_device "$OCF_RESKEY_device" + realdev="$REAL_DEVICE" + if [ -n "$realdev" ]; then + if [ "$realdev" != "$OCF_RESKEY_device" ]; then + ocf_log info "Specified $OCF_RESKEY_device maps to $realdev" + fi + return $OCF_SUCCESS + fi + + ocf_log err "Device or label "$OCF_RESKEY_device" not valid" + + return $OCF_ERR_ARGS +} + + +# +# mount_in_use device mount_point +# +# Check to see if either the device or mount point are in use anywhere on +# the system. It is not required that the device be mounted on the named +# moint point, just if either are in use. +# +mount_in_use () { + declare mp tmp_mp + declare dev tmp_dev + declare junka junkb junkc junkd + + if [ $# -ne 2 ]; then + ocf_log err "Usage: mount_in_use device mount_point". + return $FAIL + fi + + dev="$1" + mp="$2" + + while read -r tmp_dev tmp_mp junka junkb junkc junkd; do + # XXX fork/clone warning XXX + if [ "${tmp_dev:0:1}" != "-" ]; then + tmp_dev="$(printf "$tmp_dev")" + fi + + if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then + return $YES + fi + + # Mountpoint from /proc/mounts containing spaces will + # have spaces represented in octal. printf takes care + # of this for us. + tmp_mp="$(printf "$tmp_mp")" + + if [ -n "$tmp_mp" -a "$tmp_mp" = "$mp" ]; then + return $YES + fi + done < /proc/mounts + + return $NO +} + + +# +# is_mounted device mount_point +# +# Check to see if the device is mounted. Print a warning if its not +# mounted on the directory we expect it to be mounted on. +# +is_mounted () { + + declare mp tmp_mp + declare dev tmp_dev + declare ret=$FAIL + declare found=1 + declare poss_mp + + if [ $# -ne 2 ]; then + ocf_log err "Usage: is_mounted device mount_point" + return $FAIL + fi + + real_device "$1" + dev="$REAL_DEVICE" + if [ -z "$dev" ]; then + ocf_log err "$OCF_RESOURCE_INSTANCE: is_mounted: Could not match $1 with a real device" + return $OCF_ERR_ARGS + fi + + if [ -h "$2" ]; then + mp="$(readlink -f $2)" + else + mp="$2" + fi + + ret=$NO + + # This bash glyph simply removes a trailing slash + # if one exists. /a/b/ -> /a/b; /a/b -> /a/b. + mp="${mp%/}" + + while read -r tmp_dev tmp_mp junk_a junk_b junk_c junk_d + do + # XXX fork/clone warning XXX + if [ "${tmp_dev:0:1}" != "-" ]; then + tmp_dev="$(printf "$tmp_dev")" + fi + + real_device "$tmp_dev" + tmp_dev="$REAL_DEVICE" + + # XXX fork/clone warning XXX + # Mountpoint from /proc/mounts containing spaces will + # have spaces represented in octal. printf takes care + # of this for us. + tmp_mp="$(printf "$tmp_mp")" + + if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then + # + # Check to see if its mounted in the right + # place + # + if [ -n "$tmp_mp" ]; then + if [ "$tmp_mp" != "$mp" ]; then + poss_mp=$tmp_mp + else + found=0 + fi + fi + ret=$YES + fi + done < /proc/mounts + + if [ $ret -eq $YES ] && [ $found -ne 0 ]; then + ocf_log warn "Device $dev is mounted on $poss_mp instead of $mp" + fi + + return $ret +} + + +# +# is_alive mount_point +# +# Check to see if mount_point is alive (testing read/write) +# +is_alive() +{ + declare errcode + declare mount_point="$1" + declare file=".writable_test.$(hostname)" + declare rw + + if [ $# -ne 1 ]; then + ocf_log err "Usage: is_alive mount_point" + return $FAIL + fi + + [ -z "$OCF_CHECK_LEVEL" ] && export OCF_CHECK_LEVEL=0 + + test -d "$mount_point" + if [ $? -ne 0 ]; then + ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: $mount_point is not a directory" + return $FAIL + fi + + [ $OCF_CHECK_LEVEL -lt 10 ] && return $YES + + # depth 10 test (read test) + ls "$mount_point" > /dev/null 2> /dev/null + errcode=$? + if [ $errcode -ne 0 ]; then + ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: failed read test on [$mount_point]. Return code: $errcode" + return $NO + fi + + [ $OCF_CHECK_LEVEL -lt 20 ] && return $YES + + # depth 20 check (write test) + rw=$YES + for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do + if [ "$o" = "ro" ]; then + rw=$NO + fi + done + if [ $rw -eq $YES ]; then + file="$mount_point"/$file + while true; do + if [ -e "$file" ]; then + file=${file}_tmp + continue + else + break + fi + done + touch $file > /dev/null 2> /dev/null + errcode=$? + if [ $errcode -ne 0 ]; then + ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: failed write test on [$mount_point]. Return code: $errcode" + return $NO + fi + rm -f $file > /dev/null 2> /dev/null + fi + + return $YES +} + + +# +# Decide which quota options are enabled and return a string +# which we can pass to quotaon +# +quota_opts() +{ + declare quotaopts="" + declare opts="$1" + declare mopt + + for mopt in `echo $opts | sed -e s/,/\ /g`; do + case $mopt in + quota) + quotaopts="gu" + break + ;; + usrquota) + quotaopts="u$quotaopts" + continue + ;; + grpquota) + quotaopts="g$quotaopts" + continue + ;; + noquota) + quotaopts="" + return 0 + ;; + esac + done + + echo $quotaopts + return 0 +} + + + +# +# Enable quotas on the mount point if the user requested them +# +enable_fs_quotas() +{ + declare -i need_check=0 + declare -i rv + declare quotaopts="" + declare mopt + declare opts="$1" + declare mp="$2" + + if ! type quotaon &> /dev/null; then + ocf_log err "quotaon not found in $PATH" + return $OCF_ERR_GENERIC + fi + + quotaopts=$(quota_opts $opts) + [ -z "$quotaopts" ] && return 0 + + ocf_log debug "quotaopts = $quotaopts" + + # Ok, create quota files if they don't exist + for f in quota.user aquota.user quota.group aquota.group; do + if ! [ -f "$mp/$f" ]; then + ocf_log info "$mp/$f was missing - creating" + touch "$mp/$f" + chmod 600 "$mp/$f" + need_check=1 + fi + done + + if [ $need_check -eq 1 ]; then + ocf_log info "Checking quota info in $mp" + quotacheck -$quotaopts "$mp" + fi + + ocf_log info "Enabling Quotas on $mp" + ocf_log debug "quotaon -$quotaopts "$mp"" + quotaon -$quotaopts "$mp" + rv=$? + if [ $rv -ne 0 ]; then + # Just a warning + ocf_log warn "Unable to turn on quotas for $mp; return = $rv" + fi + + return $rv +} + + +# Agent-specific actions to take before mounting +# (if required). Typically things like fsck. +do_pre_mount() { + return 0 +} + +# Default mount handler - for block devices +# +do_mount() { + declare dev="$1" + declare mp="$2" + declare mount_options="" + declare fstype_option="" + declare fstype + + # + # 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 + + # + # Mount the device + # + ocf_log info "mounting $dev on $mp" + ocf_log err "mount $fstype_option $mount_options $dev $mp" + mount $fstype_option $mount_options "$dev" "$mp" +} + + +# Agent-specific actions to take after mounting +# (if required). +do_post_mount() { + return 0 +} + + +# Agent-specific actions to take before unmounting +# (if required) +do_pre_unmount() { + return 0 +} + + +# Agent-specific actions to take after umount succeeds +# (if required) +do_post_unmount() { + return 0 +} + + +# Agent-specific force-unmount logic, if required +do_force_unmount() { + return 0 +} + + +# +# start_filesystem +# +start_filesystem() { + declare -i ret_val=$OCF_SUCCESS + declare mp="${OCF_RESKEY_mountpoint}" + declare dev="" # device + declare fstype="" + declare opts="" + declare mount_options="" + + # + # Check if mount point was specified. If not, no need to continue. + # + case "$mp" in + ""|"[ ]*") # nothing to mount + return $OCF_SUCCESS + ;; + /*) # found it + ;; + *) # invalid format + ocf_log err \ +"start_filesystem: Invalid mount point format (must begin with a '/'): '$mp'" + return $OCF_ERR_ARGS + ;; + esac + + # + # Get the device + # + real_device "$OCF_RESKEY_device" + dev="$REAL_DEVICE" + if [ -z "$dev" ]; then + ocf_log err "\ +start_filesystem: Could not match $OCF_RESKEY_device with a real device" + return $OCF_ERR_ARGS + fi + + # + # Ensure we've got a valid directory + # + if [ -e "$mp" ]; then + if ! [ -d "$mp" ]; then + ocf_log err"\ +start_filesystem: Mount point $mp exists but is not a directory" + return $OCF_ERR_ARGS + fi + else + ocf_log err "\ +start_filesystem: Creating mount point $mp for device $dev" + mkdir -p "$mp" + ret_val=$? + if [ $ret_val -ne 0 ]; then + ocf_log err "\ +start_filesystem: Unable to create $mp. Error code: $ret_val" + return $OCF_ERR_GENERIC + fi + fi + + # + # See if the device is already mounted. + # + is_mounted "$dev" "$mp" + case $? in + $YES) # already mounted + ocf_log debug "$dev already mounted" + return $OCF_SUCCESS + ;; + $NO) # not mounted, continue + ;; + *) + return $FAIL + ;; + esac + + + # + # Make sure that neither the device nor the mount point are mounted + # (i.e. they may be mounted in a different location). The'mount_in_use' + # function checks to see if either the device or mount point are in + # use somewhere else on the system. + # + mount_in_use "$dev" "$mp" + case $? in + $YES) # uh oh, someone is using the device or mount point + ocf_log err "\ +Cannot mount $dev on $mp, the device or mount point is already in use!" + return $FAIL + ;; + $NO) # good, no one else is using it + ;; + $FAIL) + return $FAIL + ;; + *) + ocf_log err "Unknown return from mount_in_use" + return $FAIL + ;; + esac + + do_pre_mount + case $? in + 0) + ;; + 1) + return $OCF_ERR_GENERIC + ;; + 2) + return $OCF_SUCCESS + ;; + esac + + do_mount "$dev" "$mp" + case $? in + 0) + ;; + 1) + return $OCF_ERR_GENERIC + ;; + 2) + return $OCF_SUCCESS + ;; + esac + + do_post_mount + case $? in + 0) + ;; + 1) + return $OCF_ERR_GENERIC + ;; + 2) + return $OCF_SUCCESS + ;; + esac + + enable_fs_quotas "$opts" "$mp" + + return $OCF_SUCCESS +} + + +# +# stop_filesystem - unmount a file system; calls out to +# +stop_filesystem() { + declare -i ret_val=0 + declare -i try + declare -i sleep_time=5 # time between each umount failure + declare umount_failed="" + declare force_umount="" + declare self_fence="" + declare quotaopts="" + + # + # Get the mount point, if it exists. If not, no need to continue. + # + mp=${OCF_RESKEY_mountpoint} + case "$mp" in + ""|"[ ]*") # nothing to mount + return $OCF_SUCCESS + ;; + /*) # found it + ;; + *) # invalid format + ocf_log err \ +"stop_filesystem: Invalid mount point format (must begin with a '/'): '$mp'" + return $FAIL + ;; + esac + + # + # Get the device + # + real_device "$OCF_RESKEY_device" + dev="$REAL_DEVICE" + if [ -z "$dev" ]; then + ocf_log err "\ +stop: Could not match $OCF_RESKEY_device with a real device" + return $FAIL + fi + + # + # Get the force unmount setting if there is a mount point. + # + case ${OCF_RESKEY_force_unmount} in + $YES_STR) force_umount=$YES ;; + 1) force_umount=$YES ;; + *) force_umount="" ;; + esac + + case ${OCF_RESKEY_self_fence} in + $YES_STR) self_fence=$YES ;; + 1) self_fence=$YES ;; + *) self_fence="" ;; + esac + + do_pre_unmount + case $? in + 0) + ;; + 1) + return $OCF_ERR_GENERIC + ;; + 2) + return $OCF_SUCCESS + ;; + esac + + # + # Preparations: sync, turn off quotas + # + sync + + quotaopts=$(quota_opts $OCF_RESKEY_options) + if [ -n "$quotaopts" ]; then + ocf_log debug "Turning off quotas for $mp" + quotaoff -$quotaopts "$mp" &> /dev/null + fi + + # + # Unmount the device. + # + for try in 1 2 3; do + if [ $try -ne 1 ]; then + sleep $sleep_time + fi + + is_mounted "$dev" "$mp" + case $? in + $NO) + ocf_log info "$dev is not mounted" + umount_failed= + break + ;; + $YES) # fallthrough + ;; + *) + return $FAIL + ;; + esac + + ocf_log info "unmounting $mp" + umount "$mp" + ret_val=$? + if [ $ret_val -eq 0 ]; then + umount_failed= + break + fi + + ocf_log debug "umount failed: $ret_val" + umount_failed=yes + + if [ -z "$force_umount" ]; then + continue + fi + + # Force unmount: try #1: send SIGTERM + if [ $try -eq 1 ]; then + ocf_log warning "Sending SIGTERM to processes on $mp" + fuser -TERM -kvm "$mp" + continue + else + ocf_log warning "Sending SIGKILL to processes on $mp" + fuser -kvm "$mp" + + do_force_unmount + case $? in + 0) + ;; + 1) + return $OCF_ERR_GENERIC + ;; + 2) + break + ;; + esac + fi + done # for + + do_post_unmount + case $? in + 0) + ;; + 1) + return $OCF_ERR_GENERIC + ;; + 2) + return $OCF_SUCCESS + ;; + esac + + if [ -n "$umount_failed" ]; then + ocf_log err "'umount $mp' failed, error=$ret_val" + + if [ "$self_fence" ]; then + ocf_log alert "umount failed - REBOOTING" + sync + reboot -fn + fi + return $OCF_ERR_GENERIC + fi + + return $OCF_SUCCESS +} + + +do_start() { + declare tries=0 + declare rv + + while [ $tries -lt 3 ]; do + start_filesystem + rv=$? + if [ $rv -eq 0 ]; then + return 0 + fi + + ((tries++)) + sleep 3 + done + return $rv +} + + +do_stop() { + stop_filesystem + return $? +} + + +do_monitor() { + is_mounted "${OCF_RESKEY_device}" "${OCF_RESKEY_mountpoint}" + + if [ $? -ne $YES ]; then + ocf_log err "${OCF_RESOURCE_INSTANCE}: ${OCF_RESKEY_device} is not mounted on ${OCF_RESKEY_mountpoint}" + return $OCF_NOT_RUNNING + fi + + if [ "$OCF_RESKEY_quick_status" = "1" ]; then + return 0 + fi + + is_alive "${OCF_RESKEY_mountpoint}" + [ $? -eq $YES ] && return 0 + + ocf_log err "fs:${OCF_RESKEY_name}: Mount point is not accessible!" + return $OCF_ERR_GENERIC +} + + +do_restart() { + stop_filesystem + if [ $? -ne 0 ]; then + return $OCF_ERR_GENERIC + fi + + start_filesystem + if [ $? -ne 0 ]; then + return $OCF_ERR_GENERIC + fi + + return 0 +} + + +# MUST BE OVERRIDDEN +do_metadata() { + return 1 +} + + +do_validate() { + return 1 +} + + +main() { + case $1 in + start) + do_start + exit $? + ;; + stop) + do_stop + exit $? + ;; + status|monitor) + do_monitor + exit $? + ;; + restart) + do_restart + exit $? + ;; + meta-data) + do_metadata + exit $? + ;; + validate-all) + do_validate + ;; + *) + echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" + exit $OCF_ERR_UNIMPLEMENTED + ;; + esac + exit 0 +} +
cluster-commits@lists.fedorahosted.org