diff --git a/rgmanager/src/resources/apache.metadata b/rgmanager/src/resources/apache.metadata index 727d138de..93d5fd834 100644 --- a/rgmanager/src/resources/apache.metadata +++ b/rgmanager/src/resources/apache.metadata @@ -1,95 +1,96 @@ + 1.0 This defines an instance of Apache web server Defines an Apache web server Define a name for use in <IfDefine name> directive. Name Define an alternate initial ServerRoot Initial ServerRoot Define an alternate ServerConfigFile Initial ServerConfigFile Other command-line options for httpd Other command-line options for httpd Wait X seconds for correct end of service shutdown Wait X seconds for correct end of service shutdown Inherit the service name. We need to know the service name in order to determine file systems and IPs for this service. Inherit the service name. diff --git a/rgmanager/src/resources/apache.sh b/rgmanager/src/resources/apache.sh old mode 100644 new mode 100755 index 2ec0d4d01..f0da4b0d2 --- a/rgmanager/src/resources/apache.sh +++ b/rgmanager/src/resources/apache.sh @@ -1,274 +1,286 @@ #!/bin/bash # # 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. # export LC_ALL=C export LANG=C export PATH=/bin:/sbin:/usr/bin:/usr/sbin . $(dirname $0)/ocf-shellfuncs . $(dirname $0)/utils/config-utils.sh . $(dirname $0)/utils/messages.sh . $(dirname $0)/utils/ra-skelet.sh if [ -x /usr/sbin/httpd ]; then declare APACHE_HTTPD=/usr/sbin/httpd elif [ -x /usr/sbin/apache2 ]; then declare APACHE_HTTPD=/usr/sbin/apache2 fi declare APACHE_serverConfigFile declare APACHE_pid_file="`generate_name_for_pid_file`" declare APACHE_conf_dir="`generate_name_for_conf_dir`" declare APACHE_genConfig="$APACHE_conf_dir/httpd.conf" declare APACHE_parseConfig=$(dirname $0)/utils/httpd-parse-config.pl apache_serverConfigFile() { if $(echo $OCF_RESKEY_config_file | grep -q "^/"); then APACHE_serverConfigFile="$OCF_RESKEY_config_file" else APACHE_serverConfigFile="$OCF_RESKEY_server_root/$OCF_RESKEY_config_file" fi return; } verify_all() { clog_service_verify $CLOG_INIT if [ -z "$OCF_RESKEY_name" ]; then clog_service_verify $CLOG_FAILED "Invalid Name Of Service" return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_service_name" ]; then clog_service_verify $CLOG_FAILED_NOT_CHILD return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_server_root" ]; then clog_service_verify $CLOG_FAILED "Invalid ServerRoot" return $OCF_ERR_ARGS fi if [ ! -d "$OCF_RESKEY_server_root" ]; then clog_service_verify $CLOG_FAILED "ServerRoot Directory Is Missing" return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_config_file" ]; then clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file" return $OCF_ERR_ARGS fi if [ ! -r "$APACHE_serverConfigFile" ]; then clog_check_file_exist $CLOG_FAILED_NOT_READABLE "$APACHE_serverConfigFile" return $OCF_ERR_ARGS fi if [ -z "$APACHE_pid_file" ]; then clog_service_verify $CLOG_FAILED "Invalid name of PID file" return $OCF_ERR_ARGS fi clog_check_syntax $CLOG_INIT "$APACHE_serverConfigFile" "$APACHE_HTTPD" -t \ -D"$OCF_RESKEY_name" \ -d "$OCF_RESKEY_server_root" \ -f "$APACHE_serverConfigFile" \ $OCF_RESKEY_httpd_options &> /dev/null if [ $? -ne 0 ]; then clog_check_syntax $CLOG_FAILED "$APACHE_serverConfigFile" return $OCF_ERR_GENERIC fi clog_check_syntax $CLOG_SUCCEED "$APACHE_serverConfigFile" return 0 } generate_configFile() { declare originalConfigFile=$1; declare generatedConfigFile=$2; declare ip_addresses=$3; if [ -f "$generatedConfigFile" ]; then sha1_verify "$generatedConfigFile" if [ $? -ne 0 ]; then clog_check_sha1 $CLOG_FAILED return 0 fi fi clog_generate_config $CLOG_INIT "$originalConfigFile" "$generatedConfigFile" generate_configTemplate "$generatedConfigFile" "$1" cat >> "$generatedConfigFile" << EOT # From a cluster perspective, the key fields are: # Listen - must be set to service floating IP address. # ServerRoot - path to the ServerRoot (initial value is set in service conf) # EOT IFS_old="$IFS" IFS=$'\n' for i in `"$APACHE_parseConfig" -D"$OCF_RESKEY_name" < "$originalConfigFile" | grep -P '(^Listen)|(^Port)' `; do port=`echo $i | sed 's/^Listen \(.*\)/\1/;s/^Port \(.*\)/\1/'`; testcond=`echo $port|grep :` if [ $testcond ]; then port=`echo $port|awk -F : '{print $2}'` fi IFS=$' '; for z in $ip_addresses; do echo "Listen $z:$port" >> "$generatedConfigFile"; done IFS=$'\n'; done; IFS="$IFS_old" echo "PidFile \"$APACHE_pid_file\"" >> "$generatedConfigFile"; echo >> "$generatedConfigFile" cat "$originalConfigFile" | sed 's/^Listen/### Listen/;s/^Port/### Port/;s/^PidFile/### PidFile/' | \ "$APACHE_parseConfig" -D"$OCF_RESKEY_name" >> "$generatedConfigFile" sha1_addToFile "$generatedConfigFile" clog_generate_config $CLOG_SUCCEED "$originalConfigFile" "$generatedConfigFile" } start() { + if status; then + ocf_log info "Starting Service $OCF_RESOURCE_INSTANCE > Already running" + return $OCF_SUCCESS + fi + declare ip_addresses clog_service_start $CLOG_INIT create_pid_directory create_conf_directory "$APACHE_conf_dir" check_pid_file "$APACHE_pid_file" if [ $? -ne 0 ]; then clog_check_pid $CLOG_FAILED "$APACHE_pid_file" clog_service_start $CLOG_FAILED return $OCF_ERR_GENERIC fi clog_looking_for $CLOG_INIT "IP Addresses" get_service_ip_keys "$OCF_RESKEY_service_name" ip_addresses=`build_ip_list` if [ -z "$ip_addresses" ]; then clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses" return $OCF_ERR_GENERIC fi clog_looking_for $CLOG_SUCCEED "IP Addresses" generate_configFile "$APACHE_serverConfigFile" "$APACHE_genConfig" "$ip_addresses" "$APACHE_HTTPD" \ "-D$OCF_RESKEY_name" \ -d "$OCF_RESKEY_server_root" \ -f "$APACHE_genConfig" \ $OCF_RESKEY_httpd_options \ -k start if [ $? -ne 0 ]; then clog_service_start $CLOG_FAILED return $OCF_ERR_GENERIC else clog_service_start $CLOG_SUCCEED fi return 0; } stop() { clog_service_stop $CLOG_INIT stop_generic "$APACHE_pid_file" "$OCF_RESKEY_shutdown_wait" if [ $? -ne 0 ]; then clog_service_stop $CLOG_FAILED return $OCF_ERR_GENERIC fi clog_service_stop $CLOG_SUCCEED return 0; } status() { clog_service_status $CLOG_INIT status_check_pid "$APACHE_pid_file" - if [ $? -ne 0 ]; then - clog_service_status $CLOG_FAILED "$APACHE_pid_file" - return $OCF_ERR_GENERIC - fi - - clog_service_status $CLOG_SUCCEED - return 0 + case $? in + $OCF_NOT_RUNNING) + clog_service_status $CLOG_FAILED "$APAHCE_pid_file" + return $OCF_NOT_RUNNING + ;; + 0) + clog_service_status $CLOG_SUCCEED + exit 0 + ;; + *) + clog_service_status $CLOG_FAILED "$APACHE_pid_file" + return $OCF_ERR_GENERIC + ;; + esac } if [ "$1" != "meta-data" ]; then apache_serverConfigFile fi; case $1 in meta-data) cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'` exit 0 ;; validate-all|verify-all) verify_all exit $? ;; start) verify_all && start exit $? ;; stop) verify_all && stop exit $? ;; status|monitor) verify_all status exit $? ;; restart) verify_all stop start exit $? ;; *) echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" exit $OCF_ERR_UNIMPLEMENTED ;; esac diff --git a/rgmanager/src/resources/clusterfs.sh b/rgmanager/src/resources/clusterfs.sh old mode 100644 new mode 100755 index af40f08cd..d052ffeef --- a/rgmanager/src/resources/clusterfs.sh +++ b/rgmanager/src/resources/clusterfs.sh @@ -1,292 +1,293 @@ #!/bin/bash # # Cluster File System mount/umount/fsck/etc. agent # # Copyright (C) 2000 Mission Critical Linux # Copyright (C) 2002-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 < + 1.0 This defines a cluster file system mount (i.e. GFS) Defines a cluster file system mount. Symbolic name for this file system. File System Name Path in file system heirarchy to mount this file system. Mount Point Block device, file system label, or UUID of file system. Device or Label File system type. If not specified, mount(8) will attempt to determine the file system type. File system type 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. Force Unmount If set, the file system will be checked (even if it is a journalled file system). This option is ignored for non-journalled file systems such as ext2. Mount Options 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. Seppuku Unmount File system ID for NFS exports. This can be overridden in individual nfsclient entries. NFS File system ID If set, the node will try to kill lockd and issue reclaims across all remaining network interface cards. This happens always, regardless of unmounting failed. Enable NFS lock workarounds EOT } verify_fstype() { # Auto detect? [ -z "$OCF_RESKEY_fstype" ] && return $OCF_SUCCESS case $OCF_RESKEY_fstype in gfs|gfs2) return $OCF_SUCCESS ;; *) ocf_log err "File system type $OCF_RESKEY_fstype not supported" return $OCF_ERR_ARGS ;; esac } verify_options() { declare -i ret=$OCF_SUCCESS # # From mount(8) # 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 gfs) case $o in lockproto=*|locktable=*|hostdata=*) continue; ;; localcaching|localflocks|ignore_local_fs) continue; ;; num_glockd|acl|suiddir) continue ;; esac ;; gfs2) # XXX continue ;; esac ocf_log err "Option $o not supported for $OCF_RESKEY_fstype" ret=$OCF_ERR_ARGS done return $ret } do_verify() { verify_name || return $OCF_ERR_ARGS verify_fstype || return $OCF_ERR_ARGS verify_device || return $OCF_ERR_ARGS verify_mountpoint || return $OCF_ERR_ARGS verify_options || return $OCF_ERR_ARGS } do_pre_unmount() { # # Check the rgmanager-supplied reference count if one exists. # If the reference count is <= 1, we can safely proceed # if [ -n "$OCF_RESKEY_RGMANAGER_meta_refcnt" ]; then 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 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. # if [ "$OCF_RESKEY_nfslock" = "yes" ] || \ [ "$OCF_RESKEY_nfslock" = "1" ]; then ocf_log warning "Dropping node-wide NFS locks" mkdir -p $mp/.clumanager/statd pkill -KILL -x lockd # Copy out the notify list; our # IPs are already torn down if notify_list_store $mp/.clumanager/statd; then notify_list_broadcast $mp/.clumanager/statd fi fi # Always invalidate buffers on clusterfs resources clubufflush -f $dev return 0 } main $* diff --git a/rgmanager/src/resources/fs.sh.in b/rgmanager/src/resources/fs.sh.in index 3e1cc1531..c43c17713 100644 --- a/rgmanager/src/resources/fs.sh.in +++ b/rgmanager/src/resources/fs.sh.in @@ -1,462 +1,463 @@ #!/bin/bash # # File system (normal) mount/umount/fsck/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 < + 1.0 This defines a standard file system mount (= not a clustered or otherwise shared file system). Defines a file system mount. Symbolic name for this file system. File System Name Path in file system heirarchy to mount this file system. Mount Point Block device, file system label, or UUID of file system. Device or Label File system type. If not specified, mount(8) will attempt to determine the file system type. File system type 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. Force Unmount Use quick status checks. When set to 0 (the default), this agent behaves normally. When set to 1, this agent will not log errors incurred or perform the file system accessibility check (e.g. it will not try to read from/write to the file system). You should only set this to 1 if you have lots of file systems on your cluster or you are seeing very high load spikes as a direct result of this agent. Quick/brief status checks. 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. Seppuku Unmount If set and unmounting the file system fails, the node will try to kill lockd and issue reclaims across all remaining network interface cards. Enable NFS lock workarounds File system ID for NFS exports. This can be overridden in individual nfsclient entries. NFS File system ID If set, the file system will be checked (even if it is a journalled file system). This option is ignored for non-journalled file systems such as ext2. Force fsck support Options used when the file system is mounted. These are often file-system specific. See mount(8) for supported mount options. Mount Options EOT } verify_fstype() { # Auto detect? [ -z "$OCF_RESKEY_fstype" ] && return 0 case $OCF_RESKEY_fstype in ext2|ext3|ext4|btrfs|jfs|xfs|reiserfs|vfat|tmpfs|vxfs) return 0 ;; *) echo "File system type $OCF_RESKEY_fstype not supported" return $OCF_ERR_ARGS ;; esac } verify_options() { declare -i ret=$OCF_SUCCESS declare o # # From mount(8) # 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 do_verify_option $OCF_RESKEY_fstype "$o" case $OCF_RESKEY_fstype in ext2|ext3|ext4) case $o in bsddf|minixdf|check|check=*|nocheck|debug) continue ;; errors=*|grpid|bsdgroups|nogrpid|sysvgroups) continue ;; resgid=*|resuid=*|sb=*|grpquota|noquota) continue ;; quota|usrquota|nouid32) continue ;; esac if [ "$OCF_RESKEY_fstype" = "ext3" ] || [ "$OCF_RESKEY_fstype" = "ext4" ]; then case $0 in noload|data=*) continue ;; esac fi ;; vfat) case $o in blocksize=512|blocksize=1024|blocksize=2048) continue ;; uid=*|gid=*|umask=*|dmask=*|fmask=*) continue ;; check=r*|check=n*|check=s*|codepage=*) continue ;; conv=b*|conv=t*|conv=a*|cvf_format=*) continue ;; cvf_option=*|debug|fat=12|fat=16|fat=32) continue ;; iocharset=*|quiet) continue ;; esac ;; jfs) case $o in conv|hash=rupasov|hash=tea|hash=r5|hash=detect) continue ;; hashed_relocation|no_unhashed_relocation) continue ;; noborder|nolog|notail|resize=*) continue ;; esac ;; xfs) case $o in biosize=*|dmapi|xdsm|logbufs=*|logbsize=*) continue ;; logdev=*|rtdev=*|noalign|noatime) continue ;; norecovery|osyncisdsync|quota|userquota) continue ;; uqnoenforce|grpquota|gqnoenforce) continue ;; sunit=*|swidth=*) continue ;; esac ;; tmpfs) case $o in size=*|nr_blocks=*|mode=*) continue ;; esac ;; btrfs) # tbd continue ;; esac echo 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_device || return $OCF_ERR_ARGS verify_mountpoint || return $OCF_ERR_ARGS verify_options || return $OCF_ERR_ARGS } do_pre_mount() { declare fstype="$OCF_RESKEY_fstype" # # Check to determine if we need to fsck the filesystem. # # Note: this code should not indicate in any manner suggested # file systems to use in the cluster. Known filesystems are # listed here for correct operation. # case "$fstype" in reiserfs) typeset fsck_needed="" ;; ext3) typeset fsck_needed="" ;; ext4) typeset fsck_needed="" ;; btrfs) typeset fsck_needed="" ;; jfs) typeset fsck_needed="" ;; xfs) typeset fsck_needed="" ;; vxfs) typeset fsck_needed="" ;; ext2) typeset fsck_needed=yes ;; minix) typeset fsck_needed=yes ;; vfat) typeset fsck_needed=yes ;; msdos) typeset fsck_needed=yes ;; "") typeset fsck_needed=yes ;; # assume fsck *) typeset fsck_needed=yes # assume fsck ocf_log warn "\ Unknown file system type '$fstype' for device $dev. Assuming fsck is required." ;; esac # # Fsck the device, if needed. # if [ -n "$fsck_needed" ] || [ "${OCF_RESKEY_force_fsck}" = "yes" ] ||\ [ "${OCF_RESKEY_force_fsck}" = "1" ]; then typeset fsck_log=@LOGDIR@/$(basename $dev).fsck.log ocf_log debug "Running fsck on $dev" fsck -p $dev >> $fsck_log 2>&1 ret_val=$? if [ $ret_val -gt 1 ]; then ocf_log err "\ 'fsck -p $dev' failed, error=$ret_val; check $fsck_log for errors" ocf_log debug "Invalidating buffers for $dev" $INVALIDATEBUFFERS -f $dev return $OCF_ERR_GENERIC fi rm -f $fsck_log fi return 0 } do_post_mount() { # # Create this for the NFS NLM broadcast bit # if [ $NFS_TRICKS -eq 0 ]; then if [ "$OCF_RESKEY_nfslock" = "yes" ] || \ [ "$OCF_RESKEY_nfslock" = "1" ]; then mkdir -p "$mp"/.clumanager/statd notify_list_merge "$mp"/.clumanager/statd fi fi return 0 } 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 # Save for post-umount phase export nfslock_reclaim=1 fi # Proceed with fuser -kvm... return 1 } 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 return 0 } main $* diff --git a/rgmanager/src/resources/ip.sh b/rgmanager/src/resources/ip.sh old mode 100644 new mode 100755 index 04d5230c8..8686f0279 --- a/rgmanager/src/resources/ip.sh +++ b/rgmanager/src/resources/ip.sh @@ -1,1005 +1,1006 @@ #!/bin/bash # # IPv4/IPv6 address management using new /sbin/ifcfg instead of # ifconfig utility. # # # 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. # LC_ALL=C LANG=C PATH=/bin:/sbin:/usr/bin:/usr/sbin export LC_ALL LANG PATH # Grab nfs lock tricks if available export NFS_TRICKS=1 if [ -f "$(dirname $0)/svclib_nfslock" ]; then . $(dirname $0)/svclib_nfslock NFS_TRICKS=0 fi . $(dirname $0)/ocf-shellfuncs meta_data() { cat < + 1.0 This is an IP address. Both IPv4 and IPv6 addresses are supported, as well as NIC link monitoring for each IP address. This is an IP address. IPv4 or IPv6 address to use as a virtual IP resource. IP Address IPv4 or IPv6 address protocol family. Family Enabling this causes the status check to fail if the link on the NIC to which this IP address is bound is not present. Monitor NIC Link If set and unmounting the file system fails, the node will try to kill lockd and issue reclaims across all remaining network interface cards. Enable NFS lock workarounds Amount of time to sleep after removing an IP address. Value is specified in seconds. Default value is 10. Amount of time (seconds) to sleep. Disable updating of routing using RDISC protocol and preserve static routes. Disable updating of routing using RDISC protocol EOT } verify_address() { # XXX TBD return 0 } verify_all() { # XXX TBD return 0 } # # Expand an IPv6 address. # ipv6_expand() { typeset addr=$1 typeset maskbits typeset -i x typeset tempaddr maskbits=${addr/*\//} if [ "$maskbits" = "$addr" ]; then maskbits="" else # chop off mask bits addr=${addr/\/*/} fi # grab each hex quad and expand it to 4 digits if it isn't already # leave doublecolon in place for expansion out to the proper number of zeros later tempaddr="" for count in `seq 1 8`; do quad=`echo $addr|awk -v count=$count -F : '{print $count}'` quadlen=${#quad} if [ $quadlen -eq 0 ]; then quad=:: elif [ $quadlen -eq 1 ]; then quad=000$quad elif [ $quadlen -eq 2 ]; then quad=00$quad elif [ $quadlen -eq 3 ]; then quad=0$quad fi tempaddr=$tempaddr$quad done addr=$tempaddr # use space as placeholder addr=${addr/::/\ } # get rid of colons addr=${addr//:/} # add in zeroes where the doublecolon was len=$((${#addr}-1)) zeroes= while [ $len -lt 32 ]; do zeroes="0$zeroes" ((len++)) done addr=${addr/\ /$zeroes} # probably a better way to do this for (( x=0; x < ${#addr} ; x++)); do naddr=$naddr${addr:x:1} if (( x < (${#addr} - 1) && x%4 == 3)); then naddr=$naddr: fi done if [ -n "$maskbits" ]; then echo "$naddr/$maskbits" return 0 fi echo "$naddr" return 0 } # # see if two ipv6 addrs are in the same subnet # ipv6_same_subnet() { declare addrl=$1 declare addrr=$2 declare m=$3 declare r x llsb rlsb if [ $# -lt 2 ]; then ocf_log err "usage: ipv6_same_subnet addr1 addr2 [mask]" return 255 fi if [ -z "$m" ]; then m=${addrl/*\//} [ -n "$m" ] || return 1 fi if [ "${addrr}" != "${addrr/*\//}" ] && [ "$m" != "${addrr/*\//}" ]; then return 1 fi addrl=${addrl/\/*/} if [ ${#addrl} -lt 39 ]; then addrl=$(ipv6_expand $addrl) fi addrr=${addrr/\/*/} if [ ${#addrr} -lt 39 ]; then addrr=$(ipv6_expand $addrr) fi # Calculate the amount to compare directly x=$(($m/4+$m/16-(($m%4)==0))) # and the remaining number of bits r=$(($m%4)) if [ $r -ne 0 ]; then # If we have any remaining bits, we will need to compare # them later. Get them now. llsb=`printf "%d" 0x${addrl:$x:1}` rlsb=`printf "%d" 0x${addrr:$x:1}` # One less byte to compare directly, please ((--x)) fi # direct (string comparison) to see if they are equal if [ "${addrl:0:$x}" != "${addrr:0:$x}" ]; then return 1 fi case $r in 0) return 0 ;; 1) [ $(($llsb & 8)) -eq $(($rlsb & 8)) ] return $? ;; 2) [ $(($llsb & 12)) -eq $(($rlsb & 12)) ] return $? ;; 3) [ $(($llsb & 14)) -eq $(($rlsb & 14)) ] return $? ;; esac return 1 } ipv4_same_subnet() { declare addrl=$1 declare addrr=$2 declare m=$3 declare r x llsb rlsb if [ $# -lt 2 ]; then ocf_log err "usage: ipv4_same_subnet current_addr new_addr [maskbits]" return 255 fi # # Chop the netmask off of the ipaddr: # e.g. 1.2.3.4/22 -> 22 # if [ -z "$m" ]; then m=${addrl/*\//} [ -n "$m" ] || return 1 fi # # Check to see if there was a subnet mask provided on the # new IP address. If there was one and it does not match # our expected subnet mask, we are done. # if [ "${addrr}" != "${addrr/\/*/}" ] && [ "$m" != "${addrr/*\//}" ]; then return 1 fi # # Chop off subnet bits for good. # addrl=${addrl/\/*/} addrr=${addrr/\/*/} # # Remove '.' characters from dotted decimal notation and save # in arrays. i.e. # # 192.168.1.163 -> array[0] = 192 # array[1] = 168 # array[2] = 1 # array[3] = 163 # let x=0 for quad in ${addrl//./\ }; do ip1[((x++))]=$quad done x=0 for quad in ${addrr//./\ }; do ip2[((x++))]=$quad done x=0 while [ $m -ge 8 ]; do ((m-=8)) if [ ${ip1[x]} -ne ${ip2[x]} ]; then return 1 fi ((x++)) done case $m in 0) return 0 ;; 1) [ $((${ip1[x]} & 128)) -eq $((${ip2[x]} & 128)) ] return $? ;; 2) [ $((${ip1[x]} & 192)) -eq $((${ip2[x]} & 192)) ] return $? ;; 3) [ $((${ip1[x]} & 224)) -eq $((${ip2[x]} & 224)) ] return $? ;; 4) [ $((${ip1[x]} & 240)) -eq $((${ip2[x]} & 240)) ] return $? ;; 5) [ $((${ip1[x]} & 248)) -eq $((${ip2[x]} & 248)) ] return $? ;; 6) [ $((${ip1[x]} & 252)) -eq $((${ip2[x]} & 252)) ] return $? ;; 7) [ $((${ip1[x]} & 254)) -eq $((${ip2[x]} & 254)) ] return $? ;; esac return 1 } ipv6_list_interfaces() { declare idx dev ifaddr declare ifaddr_exp while read idx dev ifaddr; do isSlave $dev if [ $? -ne 2 ]; then continue fi idx=${idx/:/} ifaddr_exp=$(ipv6_expand $ifaddr) echo $dev ${ifaddr_exp/\/*/} ${ifaddr_exp/*\//} done < <(/sbin/ip -o -f inet6 addr | awk '{print $1,$2,$4}') return 0 } isSlave() { declare intf=$1 declare line if [ -z "$intf" ]; then ocf_log err "usage: isSlave " return $OCF_ERR_ARGS fi line=$(/sbin/ip link list dev $intf) if [ $? -ne 0 ]; then ocf_log err "$intf not found" return $OCF_ERR_GENERIC fi if [ "$line" = "${line/<*SLAVE*>/}" ]; then return 2 fi # Yes, it is a slave device. Ignore. return 0 } # # Check if interface is in UP state # interface_up() { declare intf=$1 if [ -z "$intf" ]; then ocf_log err "usage: interface_up " return 1 fi line=$(/sbin/ip -o link show up dev $intf 2> /dev/null) [ -z "$line" ] && return 2 return 0 } ethernet_link_up() { declare linkstate=$(ethtool $1 | grep "Link detected:" |\ awk '{print $3}') [ -n "$linkstate" ] || return 0 case $linkstate in yes) return 0 ;; *) return 1 ;; esac return 1 } # # Checks the physical link status of an ethernet or bonded interface. # network_link_up() { declare slaves declare intf_arg=$1 declare link_up=1 # Assume link down declare intf_test if [ -z "$intf_arg" ]; then ocf_log err "usage: network_link_up " return 1 fi ethernet_link_up $intf_arg link_up=$? if [ $link_up -eq 0 ]; then ocf_log debug "Link for $intf_arg: Detected" else ocf_log warn "Link for $intf_arg: Not detected" fi return $link_up } ipv4_list_interfaces() { declare idx dev ifaddr while read idx dev ifaddr; do isSlave $dev if [ $? -ne 2 ]; then continue fi idx=${idx/:/} echo $dev ${ifaddr/\/*/} ${ifaddr/*\//} done < <(/sbin/ip -o -f inet addr | awk '{print $1,$2,$4}') return 0 } # # Add an IP address to our interface. # ipv6() { declare dev maskbits declare addr=$2 declare addr_exp=$(ipv6_expand $addr) while read dev ifaddr_exp maskbits; do if [ -z "$dev" ]; then continue fi if [ "$1" = "add" ]; then ipv6_same_subnet $ifaddr_exp/$maskbits $addr_exp if [ $? -ne 0 ]; then continue fi interface_up $dev if [ $? -ne 0 ]; then continue fi if [ "$OCF_RESKEY_monitor_link" = "yes" ]; then network_link_up $dev if [ $? -ne 0 ]; then continue fi fi if [ "${addr/\/*/}" = "${addr}" ]; then addr="$addr/$maskbits" fi ocf_log info "Adding IPv6 address $addr to $dev" fi if [ "$1" = "del" ]; then if [ "${addr_exp/\/*/}" != "$ifaddr_exp" ]; then continue fi addr=`/sbin/ip addr list | grep "$addr" | head -n 1 | awk '{print $2}'` ocf_log info "Removing IPv6 address $addr from $dev" fi if [ "$1" = "add" ]; then ocf_log debug "Pinging addr ${addr%%/*} from dev $dev" if ping_check inet6 ${addr%%/*} $dev; then ocf_log err "IPv6 address collision ${addr%%/*}" return 1 fi fi /sbin/ip -f inet6 addr $1 dev $dev $addr [ $? -ne 0 ] && return 1 # # NDP should take of figuring out our new address. Plus, # we do not have something (like arping) to do this for ipv6 # anyway. # # RFC 2461, section 7.2.6 states thusly: # # Note that because unsolicited Neighbor Advertisements do not # reliably update caches in all nodes (the advertisements might # not be received by all nodes), they should only be viewed as # a performance optimization to quickly update the caches in # most neighbors. # # Not sure if this is necessary for ipv6 either. file=$(which rdisc 2>/dev/null) if [ -f "$file" ]; then if [ "$OCF_RESKEY_disable_rdisc" != "yes" ] && \ [ "$OCF_RESKEY_disable_rdisc" != "1" ]; then killall -HUP rdisc || rdisc -fs fi fi return 0 done < <(ipv6_list_interfaces) return 1 } # # Add an IP address to our interface. # ipv4() { declare dev ifaddr maskbits declare addr=$2 while read dev ifaddr maskbits; do if [ -z "$dev" ]; then continue fi if [ "$1" = "add" ]; then ipv4_same_subnet $ifaddr/$maskbits $addr if [ $? -ne 0 ]; then continue fi interface_up $dev if [ $? -ne 0 ]; then continue fi if [ "$OCF_RESKEY_monitor_link" = "yes" ]; then network_link_up $dev if [ $? -ne 0 ]; then continue fi fi if [ "${addr/\/*/}" = "${addr}" ]; then addr="$addr/$maskbits" fi ocf_log info "Adding IPv4 address $addr to $dev" fi if [ "$1" = "del" ]; then if [ "${addr/\/*/}" != "$ifaddr" ]; then continue fi addr=`/sbin/ip addr list | grep "$ifaddr/" | head -n 1 | awk '{print $2}'` ocf_log info "Removing IPv4 address $addr from $dev" fi if [ "$1" = "add" ]; then ocf_log debug "Pinging addr ${addr%%/*} from dev $dev" if ping_check inet ${addr%%/*} $dev; then ocf_log err "IPv4 address collision ${addr%%/*}" return 1 fi fi /sbin/ip -f inet addr $1 dev $dev $addr [ $? -ne 0 ] && return 1 # # The following is needed only with ifconfig; ifcfg does it for us # if [ "$1" = "add" ]; then # do that freak arp thing hwaddr=$(/sbin/ip -o link show $dev) hwaddr=${hwaddr/*link\/ether\ /} hwaddr=${hwaddr/\ \*/} addr=${addr/\/*/} ocf_log debug "Sending gratuitous ARP: $addr $hwaddr" arping -q -c 2 -U -I $dev $addr fi file=$(which rdisc 2>/dev/null) if [ -f "$file" ]; then if [ "$OCF_RESKEY_disable_rdisc" != "yes" ] && \ [ "$OCF_RESKEY_disable_rdisc" != "1" ]; then killall -HUP rdisc || rdisc -fs fi fi return 0 done < <(ipv4_list_interfaces) return 1 } # # Usage: # ping_check
[interface] # ping_check() { declare ops="-c 1 -w 2" declare pingcmd="" if [ "$1" = "inet6" ]; then pingcmd="ping6" else pingcmd="ping" fi if [ -n "$3" ]; then ops="$ops -I $3" fi return $($pingcmd $ops $2 &> /dev/null) } # # Usage: # check_interface_up
# check_interface_up() { declare dev declare addr=${2/\/*/} declare currentAddr caExpanded if [ "$1" == "inet6" ]; then addrExpanded=$(ipv6_expand $addr) for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do caExpanded=$(ipv6_expand $currentAddr) caExpanded=${caExpanded/\/*/} if [ "$addrExpanded" == "$caExpanded" ]; then dev=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}" | awk '{print $2}') break fi done else dev=$(/sbin/ip -f $1 -o addr | grep " $addr/" | awk '{print $2}') fi if [ -z "$dev" ]; then return 1 fi interface_up $dev return $? } # # Usage: # address_configured
# address_configured() { declare line declare addr declare currentAddr caExpanded # Chop off maxk bits addr=${2/\/*/} if [ "$1" == "inet6" ]; then addrExpanded=$(ipv6_expand $addr) for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do caExpanded=$(ipv6_expand $currentAddr) caExpanded=${caExpanded/\/*/} if [ "$addrExpanded" == "$caExpanded" ]; then line=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}"); break fi done else line=$(/sbin/ip -f $1 -o addr | grep " $addr/") fi if [ -z "$line" ]; then return 1 fi return 0 } # # Usage: # ip_op
[quiet] # ip_op() { declare dev declare rtr declare addr=${3/\/*/} declare caExpanded currentAddr if [ "$2" = "status" ]; then ocf_log debug "Checking $3, Level $OCF_CHECK_LEVEL" if [ "$1" == "inet6" ]; then addrExpanded=$(ipv6_expand $addr) for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do caExpanded=$(ipv6_expand $currentAddr) caExpanded=${caExpanded/\/*/} if [ "$addrExpanded" == "$caExpanded" ]; then dev=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}" | awk '{print $2}') break fi done else dev=$(/sbin/ip -f $1 -o addr | grep " $addr/" | awk '{print $2}') fi if [ -z "$dev" ]; then ocf_log warn "$3 is not configured" return 1 fi ocf_log debug "$3 present on $dev" if [ "$OCF_RESKEY_monitor_link" = "yes" ]; then if ! network_link_up $dev; then ocf_log warn "No link on $dev..." return 1 fi ocf_log debug "Link detected on $dev" fi [ $OCF_CHECK_LEVEL -lt 10 ] && return 0 if ! ping_check $1 $addr $dev; then ocf_log warn "Failed to ping $addr" return 1 fi ocf_log debug "Local ping to $addr succeeded" return 0 fi case $1 in inet) ipv4 $2 $3 return $? ;; inet6) if [ "$2" = "del" ]; then addrExpanded=$(ipv6_expand $addr) for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do caExpanded=$(ipv6_expand $currentAddr) caExpanded=${caExpanded/\/*/} if [ "$addrExpanded" == "$caExpanded" ]; then addr6=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}" | awk '{print $4}') ipv6 $2 $addr6 return $? fi done fi ipv6 $2 $3 return $? ;; esac return 1 } case ${OCF_RESKEY_family} in inet) ;; inet6) ;; *) if [ "${OCF_RESKEY_address//:/}" != "${OCF_RESKEY_address}" ]; then export OCF_RESKEY_family=inet6 else export OCF_RESKEY_family=inet fi ;; esac if [ -z "$OCF_CHECK_LEVEL" ]; then OCF_CHECK_LEVEL=0 fi if [ "${OCF_RESKEY_monitor_link}" = "no" ] || [ "${OCF_RESKEY_monitor_link}" = "0" ]; then OCF_RESKEY_monitor_link="no" else OCF_RESKEY_monitor_link="yes" fi case $1 in start) if address_configured ${OCF_RESKEY_family} ${OCF_RESKEY_address}; then ocf_log debug "${OCF_RESKEY_address} already configured" exit 0 fi ip_op ${OCF_RESKEY_family} add ${OCF_RESKEY_address} if [ $? -ne 0 ]; then exit $OCF_ERR_GENERIC fi if [ $NFS_TRICKS -eq 0 ]; then if [ "$OCF_RESKEY_nfslock" = "yes" ] || \ [ "$OCF_RESKEY_nfslock" = "1" ]; then notify_list_broadcast /var/lib/nfs/statd fi fi exit $? ;; stop) if address_configured ${OCF_RESKEY_family} ${OCF_RESKEY_address}; then ip_op ${OCF_RESKEY_family} del ${OCF_RESKEY_address} # Make sure it's down if address_configured ${OCF_RESKEY_family} ${OCF_RESKEY_address}; then ocf_log err "Failed to remove ${OCF_RESKEY_address}" exit 1 fi # XXX Let nfsd/lockd clear their queues; we hope to have a # way to enforce this in the future if [ -z "$OCF_RESKEY_sleeptime" ]; then sleep 10 else if [ "$OCF_RESKEY_sleeptime" -gt "0" ]; then sleep $OCF_RESKEY_sleeptime fi fi else ocf_log debug "${OCF_RESKEY_address} is not configured" fi exit 0 ;; status|monitor) ip_op ${OCF_RESKEY_family} status ${OCF_RESKEY_address} [ $? -ne 0 ] && exit $OCF_NOT_RUNNING check_interface_up ${OCF_RESKEY_family} ${OCF_RESKEY_address} exit $? ;; restart) $0 stop || exit $OCF_ERR_GENERIC $0 start || exit $OCF_ERR_GENERIC exit 0 ;; meta-data) meta_data exit 0 ;; validate-all|verify_all) verify_all exit $? ;; *) echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" exit $OCF_ERR_UNIMPLEMENTED ;; esac diff --git a/rgmanager/src/resources/mysql.metadata b/rgmanager/src/resources/mysql.metadata index 4fa383bcf..d3ade15ce 100644 --- a/rgmanager/src/resources/mysql.metadata +++ b/rgmanager/src/resources/mysql.metadata @@ -1,106 +1,107 @@ + 1.0 This defines an instance of MySQL database server Defines a MySQL database server Define a name Name Define configuration file Define configuration file Define an IP address for MySQL Define an IP address for MySQL server. If the address is not given then first IP address from the service is taken. Other command-line options for mysqld Other command-line options for mysqld Wait X seconds for correct end of service startup Wait X seconds for correct end of service startup Wait X seconds for correct end of service shutdown Wait X seconds for correct end of service shutdown Inherit the service name. We need to know the service name in order to determine file systems and IPs for this service. Inherit the service name. diff --git a/rgmanager/src/resources/mysql.sh b/rgmanager/src/resources/mysql.sh old mode 100644 new mode 100755 index e410cd3d3..5195bc5a5 --- a/rgmanager/src/resources/mysql.sh +++ b/rgmanager/src/resources/mysql.sh @@ -1,192 +1,213 @@ #!/bin/bash # # 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. # export LC_ALL=C export LANG=C export PATH=/bin:/sbin:/usr/bin:/usr/sbin . $(dirname $0)/ocf-shellfuncs . $(dirname $0)/utils/config-utils.sh . $(dirname $0)/utils/messages.sh . $(dirname $0)/utils/ra-skelet.sh declare MYSQL_MYSQLD=/usr/bin/mysqld_safe declare MYSQL_ipAddress declare MYSQL_pid_file="`generate_name_for_pid_file`" verify_all() { clog_service_verify $CLOG_INIT if [ -z "$OCF_RESKEY_name" ]; then clog_service_verify $CLOG_FAILED "Invalid Name Of Service" return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_service_name" ]; then clog_service_verify $CLOG_FAILED_NOT_CHILD return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_config_file" ]; then clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file" clog_service_verify $CLOG_FAILED return $OCF_ERR_ARGS fi if [ ! -r "$OCF_RESKEY_config_file" ]; then clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file clog_service_verify $CLOG_FAILED return $OCF_ERR_ARGS fi if [ -z "$MYSQL_pid_file" ]; then clog_service_verify $CLOG_FAILED "Invalid name of PID file" return $OCF_ERR_ARGS fi clog_service_verify $CLOG_SUCCEED return 0 } start() { + if status; then + ocf_log info "Starting Service $OCF_RESOURCE_INSTANCE > Already running" + return $OCF_SUCCESS + fi + clog_service_start $CLOG_INIT create_pid_directory check_pid_file "$MYSQL_pid_file" if [ $? -ne 0 ]; then clog_check_pid $CLOG_FAILED "$MYSQL_pid_file" clog_service_start $CLOG_FAILED return $OCF_ERR_GENERIC fi if [ -n "$OCF_RESKEY_listen_address" ]; then MYSQL_ipAddress="$OCF_RESKEY_listen_address" else clog_looking_for $CLOG_INIT "IP Address" get_service_ip_keys "$OCF_RESKEY_service_name" ip_addresses=`build_ip_list` if [ -n "$ip_addresses" ]; then for i in $ip_addresses; do MYSQL_ipAddress="$i" break; done else clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Address" fi fi clog_looking_for $CLOG_SUCCEED "IP Address" $MYSQL_MYSQLD --defaults-file="$OCF_RESKEY_config_file" \ --pid-file="$MYSQL_pid_file" \ --bind-address="$MYSQL_ipAddress" \ $OCF_RESKEY_mysqld_options > /dev/null 2>&1 & if [ $? -ne 0 ]; then clog_service_start $CLOG_FAILED return $OCF_ERR_GENERIC fi declare i=$OCF_RESKEY_startup_wait while [ "$i" -gt 0 ]; do if [ -f "$MYSQL_pid_file" ]; then break; fi sleep 1 let i=$i-1 done if [ "$i" -eq 0 ]; then clog_service_start $CLOG_FAILED_TIMEOUT return $OCF_ERR_GENERIC fi clog_service_start $CLOG_SUCCEED return 0; } stop() { clog_service_stop $CLOG_INIT stop_generic "$MYSQL_pid_file" "$OCF_RESKEY_shutdown_wait" if [ $? -ne 0 ]; then clog_service_stop $CLOG_FAILED return $OCF_ERR_GENERIC fi clog_service_stop $CLOG_SUCCEED return 0; } status() { clog_service_status $CLOG_INIT status_check_pid "$MYSQL_pid_file" + case $? in + $OCF_NOT_RUNNING) + clog_service_status $CLOG_FAILED "$MYSL_pid_file" + return $OCF_NOT_RUNNING + ;; + 0) + clog_service_status $CLOG_SUCCEED + exit 0 + ;; + *) + clog_service_status $CLOG_FAILED "$MYSL_pid_file" + return $OCF_ERR_GENERIC + ;; + esac + + if [ $? -ne 0 ]; then clog_service_status $CLOG_FAILED "$MYSQL_pid_file" return $OCF_ERR_GENERIC fi clog_service_status $CLOG_SUCCEED return 0 } case $1 in meta-data) cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'` exit 0 ;; validate-all) verify_all exit $? ;; start) verify_all && start exit $? ;; stop) verify_all && stop exit $? ;; status|monitor) verify_all status exit $? ;; restart) verify_all stop start exit $? ;; *) echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" exit $OCF_ERR_UNIMPLEMENTED ;; esac diff --git a/rgmanager/src/resources/netfs.sh b/rgmanager/src/resources/netfs.sh old mode 100644 new mode 100755 index 52cefc457..f8819177f --- a/rgmanager/src/resources/netfs.sh +++ b/rgmanager/src/resources/netfs.sh @@ -1,395 +1,396 @@ #!/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 < + 1.0 This defines an NFS/CIFS mount for use by cluster services. Defines an NFS/CIFS file system mount. Symbolic name for this file system. File System Name Path in file system heirarchy to mount this file system. Mount Point Server IP address or hostname IP or Host NFS Export directory name or CIFS share Export File System type (nfs, nfs4 or cifs) File System Type Do not unmount the filesystem during a stop or relocation operation Skip unmount opration 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. Force Unmount Provides a list of mount options. If none are specified, the NFS file system is mounted -o sync. Mount Options 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_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 $* diff --git a/rgmanager/src/resources/nfsclient.sh b/rgmanager/src/resources/nfsclient.sh old mode 100644 new mode 100755 index 940c14fcf..c37d87ea7 --- a/rgmanager/src/resources/nfsclient.sh +++ b/rgmanager/src/resources/nfsclient.sh @@ -1,465 +1,466 @@ #!/bin/bash # # NFS Export Client handler agent script # # # 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. # LC_ALL=C LANG=C PATH=/bin:/sbin:/usr/bin:/usr/sbin export LC_ALL LANG PATH . $(dirname $0)/ocf-shellfuncs meta_data() { cat < + 1.0 This defines how a machine or group of machines may access an NFS export on the cluster. IP addresses, IP wildcards, hostnames, hostname wildcards, and netgroups are supported. Defines an NFS client. This is a symbolic name of a client used to reference it in the resource tree. This is NOT the same thing as the target option. Client Name This is either a hostname, a wildcard (IP address or hostname based), or a netgroup to which defining a host or hosts to export to. Target Hostname, Wildcard, or Netgroup This is the path to export to the target. This field is generally left blank, as it inherits the path from the parent export. Path to Export File system ID inherited from the parent nfsexport/ clusterfs/fs resource. Putting fsid in the options field will override this. File system ID Defines a list of options for this particular client. See 'man 5 exports' for a list of available options. Export Options Allows recovery of this NFS client (default = 1) if it disappears from the export list. If set to 0, the service will be restarted. This is useful to help preserve export ordering. Allow recovery Service this NFS export belongs to. Used for caching exports on a per-service basis. Service Name On systems with large numbers of exports, a performance problem in the exportfs command can cause inordinately long status check times for services with lots of mounted NFS clients. This occurs because exportfs does DNS queries on all clients in the export list. Setting this option to '1' will enable caching of the export list returned from the exportfs command on a per-service basis. The cache will last for 30 seconds before expiring instead of being generated each time an nfsclient resource is called. Enable exportfs list caching EOT } verify_options() { declare o declare -i ret=0 [ -z "$OCF_RESKEY_options" ] && return 0 # # From exports(5) # for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do case $o in fsid=*) ocf_log debug "Using designated $o instead of fsid=$OCF_RESKEY_fsid" unset OCF_RESKEY_fsid ;; secure) ;; insecure) ;; rw) ;; ro) ;; async) ;; sync) ;; wdelay) ;; no_wdelay) ;; hide) ;; nohide) ;; subtree_check) ;; no_subtree_check) ;; secure_locks) ;; insecure_locks) ;; auth_nlm) ;; no_auth_nlm) ;; mountpoint=*) ;; mp=*) ;; root_squash) ;; no_root_squash) ;; all_squash) ;; no_all_squash) ;; anonuid=*) ;; anongid=*) ;; *) ocf_log err "Export Option $o invalid" ret=$OCF_ERR_ARGS ;; esac done return $ret } verify_target() { # XXX need to add wildcards, hostname, ip, etc. [ -n "$OCF_RESKEY_target" ] && return 0 return $OCF_ERR_ARGS } verify_path() { if [ -z "$OCF_RESKEY_path" ]; then ocf_log err "No export path specified." return $OCF_ERR_ARGS fi OCF_RESKEY_path="${OCF_RESKEY_path%/}" [ -d "$OCF_RESKEY_path" ] && return 0 ocf_log err "$OCF_RESKEY_path is not a directory" return $OCF_ERR_ARGS } verify_type() { [ -z "$OCF_RESKEY_type" ] && return 0 [ "$OCF_RESKEY_type" = "nfs" ] && return 0 ocf_log err "Export type $OCF_RESKEY_type not supported yet" return $OCF_ERR_ARGS } verify_all() { declare -i ret=0 verify_type || ret=$OCF_ERR_ARGS verify_options || ret=$OCF_ERR_ARGS verify_target || ret=$OCF_ERR_ARGS verify_path || ret=$OCF_ERR_ARGS return $ret } case $1 in start) declare option_str verify_all || exit $OCF_ERR_ARGS # # XXX # Bad: Side-effect of verify_options: unset OCF_RESKEY_fsid if # fsid is specified in the options string. # if [ -z "$OCF_RESKEY_options" ] && [ -n "$OCF_RESKEY_fsid" ]; then option_str="fsid=$OCF_RESKEY_fsid" elif [ -n "$OCF_RESKEY_options" ] && [ -z "$OCF_RESKEY_fsid" ]; then option_str="$OCF_RESKEY_options" elif [ -n "$OCF_RESKEY_fsid" ] && [ -n "$OCF_RESKEY_options" ]; then option_str="fsid=$OCF_RESKEY_fsid,$OCF_RESKEY_options" fi if [ -z "$option_str" ]; then ocf_log info "Adding export: ${OCF_RESKEY_target}:${OCF_RESKEY_path}" exportfs -i "${OCF_RESKEY_target}:${OCF_RESKEY_path}" rv=$? else ocf_log info "Adding export: ${OCF_RESKEY_target}:${OCF_RESKEY_path} ($option_str)" exportfs -i -o $option_str "${OCF_RESKEY_target}:${OCF_RESKEY_path}" rv=$? fi ;; stop) verify_all || exit $OCF_ERR_ARGS ocf_log info "Removing export: ${OCF_RESKEY_target}:${OCF_RESKEY_path}" exportfs -u "${OCF_RESKEY_target}:${OCF_RESKEY_path}" rv=$? ;; status|monitor) verify_all || exit $OCF_ERR_ARGS if [ "${OCF_RESKEY_target}" = "*" ]; then export OCF_RESKEY_target="\" fi # # Status check fix from Birger Wathne: # * Exports longer than 14 chars have line breaks inserted, which # broke the way the status check worked. # # Status check fix from Craig Lewis: # * Exports with RegExp metacharacters need to be escaped. # These metacharacters are: * ? . # export OCF_RESKEY_target_regexp=$(echo $OCF_RESKEY_target | \ sed -e 's/*/[*]/g' -e 's/?/[?]/g' -e 's/\./\\./g') declare tmpfn declare time_created time_now declare -i delta=0 # # Don't let anyone read the cache files. # umask 066 mkdir -p /var/cache/cluster if [ -n "$OCF_RESKEY_service_name" ] && [ "$OCF_RESKEY_use_cache" = "1" ]; then # # For large #s of exports, we need to cache the information # tmpfn=/var/cache/cluster/nfsclient-status-cache-$OCF_RESKEY_service_name if [ -f "$tmpfn" ]; then time_created=$(stat -c "%Y" $tmpfn) time_now=$(date +"%s") delta=$((time_now-time_created)) fi #echo "Cache age = $delta seconds" else delta=100 # # Create a different file if this is a separate instance # tmpfn=/var/cache/cluster/nfsclient-status-cache-$$ fi if ! [ -f "$tmpfn" ] || [ $delta -gt 30 ]; then #echo "Create $tmpfn. Nonexistent / expired / no service name" exportfs -v > $tmpfn fi cat $tmpfn | tr -d "\n" | sed -e 's/([^)]*)/\n/g' | grep -iq \ "^${OCF_RESKEY_path}[\t ]*.*${OCF_RESKEY_target_regexp}" rv=$? if [ $rv -eq 0 ]; then [ "$OCF_RESKEY_use_cache" = "1" ] || rm -f $tmpfn exit 0 fi declare OCF_RESKEY_target_tmp=$(clufindhostname -i "$OCF_RESKEY_target") if [ $? -ne 0 ]; then [ "$OCF_RESKEY_use_cache" = "1" ] || rm -f $tmpfn ocf_log err "nfsclient:$OCF_RESKEY_name is missing!" exit 1 fi cat $tmpfn | tr -d "\n" | sed -e 's/([^)]*)/\n/g' | grep -q \ "^${OCF_RESKEY_path}[\t ]*.*${OCF_RESKEY_target_tmp}" rv=$? [ "$OCF_RESKEY_use_cache" = "1" ] || rm -f $tmpfn if [ $rv -eq 0 ]; then exit 0 fi ocf_log err "nfsclient:$OCF_RESKEY_name is missing!" - exit 1 + exit $OCF_NOT_RUNNING ;; recover) if [ "$OCF_RESKEY_allow_recover" = "0" ] || \ [ "$OCF_RESKEY_allow_recover" = "no" ] || \ [ "$OCF_RESKEY_allow_recover" = "false" ]; then exit 1 fi $0 stop || exit 1 $0 start || exit 1 ;; restart) # # Recover might better be "exportfs -r" - reexport # $0 stop || exit 1 $0 start || exit 1 ;; meta-data) meta_data exit 0 ;; validate-all) verify_all rv=$? ;; *) echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}" rv=$OCF_ERR_UNIMPLEMENTED ;; esac exit $rv diff --git a/rgmanager/src/resources/nfsserver.sh b/rgmanager/src/resources/nfsserver.sh old mode 100644 new mode 100755 index f7b6b7a71..e2161dcbc --- a/rgmanager/src/resources/nfsserver.sh +++ b/rgmanager/src/resources/nfsserver.sh @@ -1,499 +1,500 @@ #!/bin/bash # # NFS Server Script. Handles starting/stopping Servand doing # the strange NFS stuff to get it to fail over properly. # LC_ALL=C LANG=C PATH=/bin:/sbin:/usr/bin:/usr/sbin V4RECOVERY="/var/lib/nfs/v4recovery" PROC_V4RECOVERY="/proc/fs/nfsd/nfsv4recoverydir" export LC_ALL LANG PATH . $(dirname $0)/ocf-shellfuncs # SELinux information which restorecon &> /dev/null && selinuxenabled export SELINUX_ENABLED=$? if [ $SELINUX_ENABLED ]; then export SELINUX_LABEL="$(ls -ldZ /var/lib/nfs/statd | cut -f4 -d' ')" fi log_do() { ocf_log debug $* $* &> /dev/null ret=$? if [ $ret -ne 0 ]; then ocf_log debug "Failed: $*" fi return $ret } meta_data() { cat < + 1.0 This defines an NFS server resource. The NFS server resource is useful for exporting NFSv4 file systems to clients. Because of the way NFSv4 works, only one NFSv4 resource may exist on a server at a time. Additionally, it is not possible to use the nfsserver resource when also using local instances of NFS on each cluster node. This defines an NFS server resource. Descriptive name for this server. Generally, only one server is ever defined per service. Name This is the path you intend to export. Usually, this is left blank, and the mountpoint of the parent file system is used. This path is passed to nfsclient resources as the export path when exportfs is called. This is the path you intend to export. This is the path containing shared NFS information which is used for NFS recovery after a failover. This is relative to the export path, and defaults to ".clumanager/nfs". This is the path containing shared NFS recovery information, relative to the path parameter. EOT } verify_path() { if [ -z "$OCF_RESKEY_path" ]; then ocf_log err "No server path specified." return $OCF_ERR_ARGS fi [ -d "$OCF_RESKEY_path" ] && return 0 ocf_log err "$OCF_RESKEY_path is not a directory" return $OCF_ERR_ARGS } verify_nfspath() { if [ -z "$OCF_RESKEY_nfspath" ]; then echo No NFS data path specified. return 1 fi [ -d "$OCF_RESKEY_path" ] && return 0 # xxx do nothing for now. return 0 } verify_all() { verify_path || return 1 verify_nfspath || return 1 return 0 } nfs_daemons() { declare oper declare val case $1 in start) ocf_log info "Starting NFS daemons" /etc/init.d/nfs start if [ $? -ne 0 ]; then ocf_log err "Failed to start NFS daemons" return 1 fi ocf_log debug "NFS daemons are running" return 0 ;; stop) ocf_log info "Stopping NFS daemons" if ! /etc/init.d/nfs stop; then ocf_log err "Failed to stop NFS daemons" return 1 fi ocf_log debug "NFS daemons are stopped" return 0 ;; status|monitor) declare recoverydir="$OCF_RESKEY_path/$OCF_RESKEY_nfspath/v4recovery" val=$(cat $PROC_V4RECOVERY) [ "$val" = "$recoverydir" ] || ocf_log warning \ "NFSv4 recovery directory is $val instead of $recoverydir" /etc/init.d/nfs status if [ $? -eq 0 ]; then ocf_log debug "NFS daemons are running" return 0 fi - return 1 + return $OCF_NOT_RUNNING ;; esac } create_tree() { declare fp="$OCF_RESKEY_path/$OCF_RESKEY_nfspath" [ -d "$fp" ] || mkdir -p "$fp" [ -d "$fp/statd" ] || mkdir -p "$fp/statd" [ -d "$fp/v4recovery" ] || mkdir -p "$fp/v4recovery" # # Create our own private copy which we use for notifies. # This way, we can be sure to advertise on possibly multiple # IP addresses. # [ -d "$fp/statd/sm" ] || mkdir -p "$fp/statd/sm" [ -d "$fp/statd/sm.bak" ] || mkdir -p "$fp/statd/sm.bak" [ -d "$fp/statd/sm-ha" ] || mkdir -p "$fp/statd/sm-ha" [ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown -R rpcuser.rpcuser "$fp/statd" # Create if they don't exist [ -f "$fp/etab" ] || touch "$fp/etab" [ -f "$fp/xtab" ] || touch "$fp/xtab" [ -f "$fp/rmtab" ] || touch "$fp/rmtab" [ $SELINUX_ENABLED ] && chcon -R "$SELINUX_LABEL" "$fp" # # Generate a random state file. If this ends up being what a client # already has in its list, that's bad, but the chances of this # are small - and relocations should be rare. # dd if=/dev/urandom of=$fp/state bs=1 count=4 &> /dev/null [ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown rpcuser.rpcuser "$fp/state" } setup_v4recovery() { declare recoverydir="$OCF_RESKEY_path/$OCF_RESKEY_nfspath/v4recovery" # mounts /proc/fs/nfsd for us lsmod | grep -q nfsd if [ $? -ne 0 ]; then modprobe nfsd fi val=$(cat "$PROC_V4RECOVERY") # Ensure start-after-start works if [ "$val" = "$recoverydir" ]; then return 0 fi # # If the value is not default, there may be another # cluster service here already which has replaced # the v4 recovery directory. In that case, # we must refuse to go any further. # if [ "$val" != "$V4RECOVERY" ]; then ocf_log err "NFSv4 recovery directory has an unexpected value: $val" return 1 fi # # Redirect nfs v4 recovery dir to shared storage # echo "$recoverydir" > "$PROC_V4RECOVERY" if [ $? -ne 0 ]; then echo "Uh oh... echo failed!?" fi val="$(cat $PROC_V4RECOVERY)" if [ "$val" != "$recoverydir" ]; then ocf_log err "Failed to change NFSv4 recovery path" ocf_log err "Wanted: $recoverydir; got $val" return 1 fi return 0 } cleanup_v4recovery() { # # Restore nfsv4 recovery directory to default # echo "$V4RECOVERY" > "$PROC_V4RECOVERY" return $? } is_bound() { mount | grep -q "$1 on $2 type none (.*bind.*)" return $? } setup_tree() { declare fp="$OCF_RESKEY_path/$OCF_RESKEY_nfspath" if is_bound $fp/statd /var/lib/nfs/statd; then ocf_log debug "$fp is already bound to /var/lib/nfs/statd" return 0 fi mount -o bind "$fp/statd" /var/lib/nfs/statd cp -a "$fp"/*tab /var/lib/nfs [ $SELINUX_ENABLED ] && restorecon /var/lib/nfs } cleanup_tree() { declare fp="$OCF_RESKEY_path/$OCF_RESKEY_nfspath" if is_bound "$fp/statd" /var/lib/nfs/statd; then log_do umount /var/lib/nfs/statd || return 1 else ocf_log debug "$fp is not bound to /var/lib/nfs/statd" fi cp -a /var/lib/nfs/*tab "$fp" return 0 } start_locking() { declare ret [ -x /sbin/rpc.statd ] || return 1 # # Synchronize these before starting statd # cp -f /var/lib/nfs/statd/sm-ha/* /var/lib/nfs/statd/sm 2> /dev/null cp -f /var/lib/nfs/statd/sm/* /var/lib/nfs/statd/sm-ha 2> /dev/null if pidof rpc.statd &> /dev/null; then ocf_log debug "rpc.statd is already running" return 0 fi # # Set this resrouce script as the callout program. We are evil. # In cases where we want to preserve lock information, this is needed # because we can't do the "copy" that we do on the down-state... # ocf_log info "Starting rpc.statd" rm -f /var/run/sm-notify.pid rpc.statd -H $0 -d ret=$? if [ $ret -ne 0 ]; then ocf_log err "Failed to start rpc.statd" return $ret fi touch /var/lock/subsys/nfslock return $ret } terminate() { declare pids declare i=0 while : ; do pids=$(pidof $1) [ -z "$pids" ] && return 0 kill $pids sleep 1 ((i++)) [ $i -gt 3 ] && return 1 done } killkill() { declare pids declare i=0 while : ; do pids=$(pidof $1) [ -z "$pids" ] && return 0 kill -9 $pids sleep 1 ((i++)) [ $i -gt 3 ] && return 1 done } stop_locking() { declare ret ocf_log info "Stopping rpc.statd" if terminate rpc.statd; then ocf_log debug "rpc.statd is stopped" else if killkill rpc.statd; then ocf_log debug "rpc.statd is stopped" else ocf_log debug "Failed to stop rpc.statd" return 1 fi fi } case $1 in start) # Check for and source configuration file ocf_log info "Starting NFS Server $OCF_RESKEY_name" create_tree || exit 1 setup_tree || exit 1 setup_v4recovery || exit 1 start_locking nfs_daemons start rv=$? if [ $rv -eq 0 ]; then ocf_log info "Started NFS Server $OCF_RESKEY_name" exit 0 fi ocf_log err "Failed to start NFS Server $OCF_RESKEY_name" exit $rv ;; status|monitor) nfs_daemons status exit $? ;; stop) if ! nfs_daemons stop; then ocf_log err "Failed to stop NFS Server $OCF_RESKEY_name" exit $OCF_ERR_GENERIC fi # Copy the current notify list into our private area ocf_log debug "Copying sm files for future notification..." rm -f /var/lib/nfs/statd/sm-ha/* &> /dev/null cp -f /var/lib/nfs/statd/sm/* /var/lib/nfs/statd/sm-ha &> /dev/null stop_locking || exit 1 cleanup_v4recovery cleanup_tree || exit 1 exit 0 ;; add-client) ocf_log debug "$0 $1 $2 $3" touch /var/lib/nfs/statd/sm/$2 touch /var/lib/nfs/statd/sm-ha/$2 exit 0 ;; del-client) ocf_log debug "$0 $1 $2 $3" touch /var/lib/nfs/statd/sm/$2 rm -f /var/lib/nfs/statd/sm-ha/$2 exit 0 ;; recover|restart) $0 stop || exit $OCF_ERR_GENERIC $0 start || exit $OCF_ERR_GENERIC exit 0 ;; meta-data) meta_data exit 0 ;; validate-all) verify_all exit $? ;; *) echo "usage: $0 {start|stop|status|monitor|restart|recover|add-client|del-client|meta-data|validate-all}" exit $OCF_ERR_UNIMPLEMENTED ;; esac exit 0 diff --git a/rgmanager/src/resources/utils/httpd-parse-config.pl b/rgmanager/src/resources/utils/httpd-parse-config.pl old mode 100644 new mode 100755 diff --git a/rgmanager/src/resources/utils/ra-skelet.sh b/rgmanager/src/resources/utils/ra-skelet.sh index a80aac8e7..d88a03340 100644 --- a/rgmanager/src/resources/utils/ra-skelet.sh +++ b/rgmanager/src/resources/utils/ra-skelet.sh @@ -1,147 +1,147 @@ #!/bin/bash # # 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. # status_check_pid() { declare pid_file="$1" if [ -z "$pid_file" ]; then clog_check_file_exist $CLOG_FAILED_INVALID "$pid_file" return $OCF_ERR_GENERIC fi if [ ! -e "$pid_file" ]; then clog_check_file_exist $CLOG_FAILED "$pid_file" - return $OCF_ERR_GENERIC + return $OCF_NOT_RUNNING fi read pid < "$pid_file" if [ -z "$pid" ]; then return $OCF_ERR_GENERIC fi if [ ! -d /proc/$pid ]; then return $OCF_ERR_GENERIC fi return 0 } stop_generic() { declare pid_file="$1" declare stop_timeout="$2" declare pid; declare count=0; if [ ! -e "$pid_file" ]; then clog_check_file_exist $CLOG_FAILED_NOT_FOUND "$pid_file" # In stop-after-stop situation there is no PID file but # it will be nice to check for it in stop-after-start # look at bug #449394 return 0 fi if [ -z "$stop_timeout" ]; then stop_timeout=20 fi read pid < "$pid_file" # @todo: PID file empty -> error? if [ -z "$pid" ]; then return 0; fi # @todo: PID is not running -> error? if [ ! -d "/proc/$pid" ]; then return 0; fi kill -TERM "$pid" if [ $? -ne 0 ]; then return $OCF_ERR_GENERIC fi until [ `ps --pid "$pid" &> /dev/null; echo $?` = '1' ] || [ $count -gt $stop_timeout ] do sleep 1 let count=$count+1 done if [ $count -gt $stop_timeout ]; then clog_service_stop $CLOG_FAILED_NOT_STOPPED return $OCF_ERR_GENERIC fi return 0; } stop_generic_sigkill() { # Use stop_generic (kill -TERM) and if application did not stop # correctly then use kill -QUIT and check if it was killed declare pid_file="$1" declare stop_timeout="$2" declare kill_timeout="$3" declare pid ## If stop_timeout is equal to zero then we do not want ## to give -TERM signal at all. if [ $stop_timeout -ne 0 ]; then stop_generic "$pid_file" "$stop_timeout" if [ $? -eq 0 ]; then return 0; fi fi if [ ! -e "$pid_file" ]; then clog_check_file_exist $CLOG_FAILED_NOT_FOUND "$pid_file" # In stop-after-stop situation there is no PID file but # it will be nice to check for it in stop-after-start # look at bug #449394 return 0 fi read pid < "$pid_file" if [ -z "$pid" ]; then return 0; fi if [ ! -d "/proc/$pid" ]; then return 0; fi kill -QUIT "$pid" if [ $? -ne 0 ]; then return $OCF_GENERIC_ERROR fi sleep "$kill_timeout" ps --pid "$pid" &> /dev/null if [ $? -eq 0 ]; then clog_service_stop $CLOG_FAILED_KILL return $OCF_ERR_GENERIC fi clog_service_stop $CLOG_SUCCEED_KILL return 0 } diff --git a/rgmanager/src/resources/vm.sh b/rgmanager/src/resources/vm.sh index 100e34932..d2303fe0c 100644 --- a/rgmanager/src/resources/vm.sh +++ b/rgmanager/src/resources/vm.sh @@ -1,1087 +1,1088 @@ #!/bin/bash # # 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. # PATH=/bin:/sbin:/usr/bin:/usr/sbin export PATH . $(dirname $0)/ocf-shellfuncs || exit 1 # # Virtual Machine start/stop script (requires the virsh command) # # Indeterminate state: xend/libvirtd is down. export OCF_APP_ERR_INDETERMINATE=150 meta_data() { cat < + 1.0 Defines a Virtual Machine Defines a Virtual Machine This is the name of the virtual machine. Name Failover domains define lists of cluster members to try in the event that the host of the virtual machine fails. Cluster failover Domain If set to yes, this resource group will automatically be started after the cluster forms a quorum. If set to no, this virtual machine will start in the 'disabled' state after the cluster forms a quorum. Automatic start after quorum formation If set, this resource group will only relocate to nodes which have no other resource groups running in the event of a failure. If no empty nodes are available, this resource group will not be restarted after a failure. Additionally, resource groups will not automatically relocate to the node running this resource group. This option can be overridden by manual start and/or relocate operations. Exclusive resource group This currently has three possible options: "restart" tries to restart this virtual machine locally before attempting to relocate (default); "relocate" does not bother trying to restart the VM locally; "disable" disables the VM if it fails. Failure recovery policy Mapping of the hostname of a target cluster member to a different hostname memberhost:targethost,memberhost:targethost .. Force use of virsh instead of xm on Xen machines. If set to 1, vm.sh will use the virsh command to manage virtual machines instead of xm. This is required when using non-Xen virtual machines (e.g. qemu / KVM). Full path to libvirt XML file describing the domain. Full path to libvirt XML file describing the domain. Migration type (live or pause, default = live). Migration type (live or pause, default = live). Path specification vm.sh will search for the specified VM configuration file. /path1:/path2:... Path to virtual machine configuration files. Path to the snapshot directory where the virtual machine image will be stored. Path to the snapshot directory where the virtual machine image will be stored. Service dependency; will not start without the specified service running. Top-level service this depends on, in service:name format. Service dependency mode. hard - This service is stopped/started if its dependency is stopped/started soft - This service only depends on the other service for initial startip. If the other service stops, this service is not stopped. Service dependency mode (soft or hard). Maximum restarts for this service. Maximum restarts for this service. Restart expiration time. A restart is forgotten after this time. When combined with the max_restarts option, this lets administrators specify a threshold for when to fail over services. If max_restarts is exceeded in this given expiration time, the service is relocated instead of restarted again. Restart expiration time; amount of time before a restart is forgotten. Ordinarily, only the presence/health of a virtual machine is checked. If specified, the status_program value is executed during a depth 10 check. The intent of this program is to ascertain the status of critical services within a virtual machine. Additional status check program Specify hypervisor tricks to use. Default = auto. Other supported options are xen and qemu. Hypervisor Hypervisor URI. Generally, this is keyed off of the hypervisor and does not need to be set. Hypervisor URI (normally automatic). Migration URI. Generally, this is keyed off of the hypervisor and does not need to be set. Migration URI (normally automatic). EOT } build_virsh_cmdline() { declare cmdline="" declare operation=$1 if [ -n "$OCF_RESKEY_hypervisor_uri" ]; then cmdline="$cmdline -c $OCF_RESKEY_hypervisor_uri" fi cmdline="$cmdline $operation $OCF_RESKEY_name" echo $cmdline } # this is only used on startup build_xm_cmdline() { declare operation=$1 # # Virtual domains should never restart themselves when # controlled externally; the external monitoring app # should. # declare cmdline="on_shutdown=\"destroy\" on_reboot=\"destroy\" on_crash=\"destroy\"" if [ -n "$OCF_RESKEY_path" ]; then operation="$operation --path=\"$OCF_RESKEY_path\"" fi if [ -n "$OCF_RESKEY_name" ]; then cmdline="$operation $OCF_RESKEY_name $cmdline" fi echo $cmdline } do_xm_start() { # Use /dev/null for the configuration file, if xmdefconfig # doesn't exist... # declare cmdline echo -n "Virtual machine $OCF_RESKEY_name is " do_status && return 0 cmdline="`build_xm_cmdline create`" ocf_log debug "xm $cmdline" eval xm $cmdline return $? } get_timeout() { declare -i default_timeout=60 declare -i tout=60 if [ -n "$OCF_RESKEY_RGMANAGER_meta_timeout" ]; then tout=$OCF_RESKEY_RGMANAGER_meta_timeout elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then tout=$OCF_RESKEY_CRM_meta_timeout fi if [ $tout -eq 0 ]; then echo $default_timeout return 0 fi if [ $tout -lt 0 ]; then echo $default_timeout return 0 fi echo $tout return 0 } # # Start a virtual machine given the parameters from # the environment. # do_virsh_start() { declare cmdline declare snapshotimage echo -n "Virtual machine $OCF_RESKEY_name is " do_status && return 0 snapshotimage="$OCF_RESKEY_snapshot/$OCF_RESKEY_name" if [ -n "$OCF_RESKEY_snapshot" -a -f "$snapshotimage" ]; then eval virsh restore $snapshotimage if [ $? -eq 0 ]; then rm -f $snapshotimage return 0 fi return 1 fi if [ -n "$OCF_RESKEY_xmlfile" -a -f "$OCF_RESKEY_xmlfile" ]; then # TODO: try to use build_virsh_cmdline for the hypervisor_uri cmdline="virsh create $OCF_RESKEY_xmlfile" else cmdline="virsh $(build_virsh_cmdline start)" fi ocf_log debug "$cmdline" $cmdline return $? } do_xm_stop() { declare -i timeout=60 declare -i ret=1 declare st for op in $*; do echo "CMD: xm $op $OCF_RESKEY_name" xm $op $OCF_RESKEY_name timeout=60 while [ $timeout -gt 0 ]; do sleep 5 ((timeout -= 5)) do_status&>/dev/null || return 0 while read dom state; do # # State is "stopped". Kill it. # if [ "$dom" != "$OCF_RESKEY_name" ]; then continue fi if [ "$state" != "---s-" ]; then continue fi xm destroy $OCF_RESKEY_name done < <(xm list | awk '{print $1, $5}') done done return 1 } # # Stop a VM. Try to shut it down. Wait a bit, and if it # doesn't shut down, destroy it. # do_virsh_stop() { declare -i timeout=$(get_timeout) declare -i ret=1 declare state state=$(do_status) [ $? -eq 0 ] || return 0 if [ -n "$OCF_RESKEY_snapshot" ]; then virsh save $OCF_RESKEY_name "$OCF_RESKEY_snapshot/$OCF_RESKEY_name" fi for op in $*; do echo virsh $op $OCF_RESKEY_name ... virsh $op $OCF_RESKEY_name timeout=$(get_timeout) while [ $timeout -gt 0 ]; do sleep 5 ((timeout -= 5)) state=$(do_status) [ $? -eq 0 ] || return 0 if [ "$state" = "paused" ]; then virsh destroy $OCF_RESKEY_name fi done done return 1 } do_start() { if [ "$OCF_RESKEY_use_virsh" = "1" ]; then do_virsh_start $* return $? fi do_xm_start $* return $? } do_stop() { declare domstate rv domstate=$(do_status) rv=$? ocf_log debug "Virtual machine $OCF_RESKEY_name is $domstate" if [ $rv -eq $OCF_APP_ERR_INDETERMINATE ]; then ocf_log crit "xend/libvirtd is dead; cannot stop $OCF_RESKEY_name" return 1 fi if [ "$OCF_RESKEY_use_virsh" = "1" ]; then do_virsh_stop $* return $? fi do_xm_stop $* return $? } # # Reconfigure a running VM. # reconfigure() { return 0 } xm_status() { service xend status &> /dev/null if [ $? -ne 0 ]; then # if xend died echo indeterminate return $OCF_APP_ERR_INDETERMINATE fi xm list $OCF_RESKEY_name &> /dev/null if [ $? -eq 0 ]; then echo "running" return 0 fi xm list migrating-$OCF_RESKEY_name &> /dev/null if [ $? -eq 0 ]; then echo "running" return 0 fi echo "not running" - return 1 + return $OCF_NOT_RUNNING } virsh_status() { declare state pid if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then service xend status &> /dev/null if [ $? -ne 0 ]; then echo indeterminate return $OCF_APP_ERR_INDETERMINATE fi fi # # libvirtd is required when using virsh even though # not specifically when also using Xen. This is because # libvirtd is required for migration. # pid=$(pidof libvirtd) if [ -z "$pid" ]; then echo indeterminate return $OCF_APP_ERR_INDETERMINATE fi state=$(virsh domstate $OCF_RESKEY_name) echo $state if [ "$state" = "running" ] || [ "$state" = "paused" ] || [ "$state" = "no state" ] || [ "$state" = "idle" ]; then return 0 fi if [ "$state" = "shut off" ]; then return $OCF_NOT_RUNNING fi return $OCF_ERR_GENERIC } # # Simple status check: Find the VM in the list of running # VMs # do_status() { if [ "$OCF_RESKEY_use_virsh" = "1" ]; then virsh_status return $? fi xm_status return $? } # # virsh "path" attribute support # check_config_file() { declare path=$1 if [ -f "$path/$OCF_RESKEY_name" ]; then echo $path/$OCF_RESKEY_name return 2 elif [ -f "$path/$OCF_RESKEY_name.xml" ]; then echo $path/$OCF_RESKEY_name.xml return 2 fi return 0 } parse_input() { declare delim=$1 declare input=$2 declare func=$3 declare inp declare value while [ -n "$input" ]; do value=${input/$delim*/} if [ -n "$value" ]; then eval $func $value if [ $? -eq 2 ]; then return 0 fi fi inp=${input/$value$delim/} if [ "$input" = "$inp" ]; then inp=${input/$value/} fi input=$inp done } search_config_path() { declare config_file=$(parse_input ":" "$OCF_RESKEY_path" check_config_file) if [ -n "$config_file" ]; then export OCF_RESKEY_xmlfile=$config_file return 0 fi return 1 } choose_management_tool() { declare -i is_xml # # Don't override user value for use_virsh if one is given # if [ -n "$OCF_RESKEY_use_virsh" ]; then return 0 fi which xmllint &> /dev/null if [ $? -ne 0 ]; then ocf_log warning "Could not find xmllint; assuming virsh mode" export OCF_RESKEY_use_virsh=1 unset OCF_RESKEY_path return 0 fi xmllint $OCF_RESKEY_xmlfile &> /dev/null is_xml=$? if [ $is_xml -eq 0 ]; then ocf_log debug "$OCF_RESKEY_xmlfile is XML; using virsh" export OCF_RESKEY_use_virsh=1 unset OCF_RESKEY_path else ocf_log debug "$OCF_RESKEY_xmlfile is not XML; using xm" export OCF_RESKEY_use_virsh=0 unset OCF_RESKEY_xmlfile fi return 0 } validate_all() { if [ "$(id -u)" != "0" ]; then ocf_log err "Cannot control VMs. as non-root user." return 1 fi # # If someone selects a hypervisor, honor it. # Otherwise, ask virsh what the hypervisor is. # if [ -z "$OCF_RESKEY_hypervisor" ] || [ "$OCF_RESKEY_hypervisor" = "auto" ]; then export OCF_RESKEY_hypervisor="`virsh version | grep \"Running hypervisor:\" | awk '{print $3}' | tr A-Z a-z`" if [ -z "$OCF_RESKEY_hypervisor" ]; then ocf_log err "Could not determine Hypervisor" return $OCF_ERR_ARGS fi echo Hypervisor: $OCF_RESKEY_hypervisor fi # # Xen hypervisor only for when use_virsh = 0. # if [ "$OCF_RESKEY_use_virsh" = "0" ]; then if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh" return $OCF_ERR_ARGS fi if [ -n "$OCF_RESKEY_xmlfile" ]; then ocf_log err "Cannot use xmlfile if use_virsh is set to 0" return $OCF_ERR_ARGS fi else # # Virsh path support. # if [ -n "$OCF_RESKEY_path" ] && [ "$OCF_RESKEY_path" != "/etc/xen" ]; then if [ -n "$OCF_RESKEY_xmlfile" ]; then ocf_log warning "Using $OCF_RESKEY_xmlfile instead of searching $OCF_RESKEY_path" else search_config_path if [ $? -ne 0 ]; then ocf_log warning "Could not find $OCF_RESKEY_name or $OCF_RESKEY_name.xml in search path $OCF_RESKEY_path" unset OCF_RESKEY_xmlfile else ocf_log debug "Using $OCF_RESKEY_xmlfile" fi choose_management_tool fi else export OCF_RESKEY_use_virsh=1 fi fi if [ "$OCF_RESKEY_use_virsh" = "0" ]; then echo "Management tool: xm" which xm &> /dev/null if [ $? -ne 0 ]; then ocf_log err "Cannot find 'xm'; is it installed?" return $OCF_ERR_INSTALLED fi if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh" return $OCF_ERR_ARGS fi else echo "Management tool: virsh" which virsh &> /dev/null if [ $? -ne 0 ]; then ocf_log err "Cannot find 'virsh'; is it installed?" return $OCF_ERR_INSTALLED fi fi # # Set the hypervisor URI # if [ -z "$OCF_RESKEY_hypervisor_uri" -o "$OCF_RESKEY_hypervisor_uri" = "auto" ] && [ "$OCF_RESKEY_use_virsh" = "1" ]; then # Virsh makes it easier to do this. Really. if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then OCF_RESKEY_hypervisor_uri="qemu:///system" fi # I just need to believe in it more. if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then OCF_RESKEY_hypervisor_uri="xen:///" fi echo Hypervisor URI: $OCF_RESKEY_hypervisor_uri fi # # Set the migration URI # if [ -z "$OCF_RESKEY_migration_uri" -o "$OCF_RESKEY_migration_uri" = "auto" ] && [ "$OCF_RESKEY_use_virsh" = "1" ]; then # Virsh makes it easier to do this. Really. if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then export OCF_RESKEY_migration_uri="qemu+ssh://%s/system" fi # I just need to believe in it more. if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then export OCF_RESKEY_migration_uri="xenmigr://%s/" fi [ -n "$OCF_RESKEY_migration_uri" ] && echo Migration URI format: $(printf $OCF_RESKEY_migration_uri target_host) fi if [ -z "$OCF_RESKEY_name" ]; then echo No domain name specified return $OCF_ERR_ARGS fi if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then export migrateuriopt="tcp:%s" fi #virsh list --all | awk '{print $2}' | grep -q "^$OCF_RESKEY_name\$" return $? } virsh_migrate() { declare target=$1 declare rv=1 # # Xen and qemu have different migration mechanisms # if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then cmd="virsh migrate $migrate_opt $OCF_RESKEY_name $OCF_RESKEY_hypervisor_uri $(printf $OCF_RESKEY_migration_uri $target)" ocf_log debug "$cmd" err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]}) rv=$? elif [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then cmd="virsh migrate $migrate_opt $OCF_RESKEY_name $(printf $OCF_RESKEY_migration_uri $target) $(printf $migrateuriopt $target)" ocf_log debug "$cmd" err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]}) rv=$? fi if [ $rv -ne 0 ]; then ocf_log err "Migrate $OCF_RESKEY_name to $target failed:" ocf_log err "$err" if [ "$err" != "${err/does not exist/}" ]; then return $OCF_ERR_CONFIGURED fi if [ "$err" != "${err/Domain not found/}" ]; then return $OCF_ERR_CONFIGURED fi return $OCF_ERR_GENERIC fi return $rv } # # XM migrate # xm_migrate() { declare target=$1 declare errstr rv migrate_opt cmd rv=1 if [ "$OCF_RESKEY_migrate" = "live" ]; then migrate_opt="-l" fi # migrate() function sets target using migration_mapping; # no need to do it here anymore cmd="xm migrate $migrate_opt $OCF_RESKEY_name $target" ocf_log debug "$cmd" err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]}) rv=$? if [ $rv -ne 0 ]; then ocf_log err "Migrate $OCF_RESKEY_name to $target failed:" ocf_log err "$err" if [ "$err" != "${err/does not exist/}" ]; then return $OCF_NOT_RUNNING fi if [ "$err" != "${err/Connection refused/}" ]; then return $OCF_ERR_CONFIGURED fi return $OCF_ERR_GENERIC fi return $? } # # Virsh migrate # migrate() { declare target=$1 declare rv migrate_opt if [ "$OCF_RESKEY_migrate" = "live" ]; then migrate_opt="--live" fi # Patch from Marcelo Azevedo to migrate over private # LANs instead of public LANs if [ -n "$OCF_RESKEY_migration_mapping" ] ; then target=${OCF_RESKEY_migration_mapping#*$target:} target=${target%%,*} fi if [ "$OCF_RESKEY_use_virsh" = "1" ]; then virsh_migrate $target rv=$? else xm_migrate $target rv=$? fi return $rv } wait_start() { declare -i timeout_remaining=$(get_timeout) declare -i start_time declare -i end_time declare -i delta declare -i sleep_time if [ -z "$OCF_RESKEY_status_program" ]; then return 0 fi while [ $timeout_remaining -gt 0 ]; do start_time=$(date +%s) bash -c "$OCF_RESKEY_status_program" if [ $? -eq 0 ]; then return 0 fi end_time=$(date +%s) delta=$(((end_time - start_time))) sleep_time=$(((5 - delta))) ((timeout_remaining -= $delta)) if [ $sleep_time -gt 0 ]; then sleep $sleep_time ((timeout_remaining -= $sleep_time)) fi done ocf_log err "Start of $OCF_RESOURCE_INSTANCE has failed" ocf_log err "Timeout exceeded while waiting for \"$OCF_RESKEY_status_program\"" return 1 } # # # case $1 in start) validate_all || exit $OCF_ERR_ARGS do_start rv=$? if [ $rv -ne 0 ]; then exit $rv fi wait_start exit $? ;; stop) validate_all || exit $OCF_ERR_ARGS do_stop shutdown destroy exit $? ;; kill) validate_all || exit $OCF_ERR_ARGS do_stop destroy exit $? ;; recover|restart) exit 0 ;; status|monitor) validate_all || exit $OCF_ERR_ARGS echo -n "Virtual machine $OCF_RESKEY_name is " do_status rv=$? if [ $rv -ne 0 ]; then exit $rv fi [ -z "$OCF_RESKEY_status_program" ] && exit 0 [ -z "$OCF_CHECK_LEVEL" ] && exit 0 [ $OCF_CHECK_LEVEL -lt 10 ] && exit 0 bash -c "$OCF_RESKEY_status_program" &> /dev/null exit $? ;; migrate) validate_all || exit $OCF_ERR_ARGS migrate $2 # Send VM to this node rv=$? if [ $rv -eq $OCF_ERR_GENERIC ]; then # Catch-all: If migration failed with # an unhandled error, do a status check # to see if the VM is really dead. # # If the VM is still in good health, return # a value to rgmanager to indicate the # non-critical error # # OCF states that codes 150-199 are reserved # for application use, so we'll use 150 # do_status > /dev/null if [ $? -eq 0 ]; then rv=150 fi fi exit $rv ;; reload) exit 0 ;; reconfig) validate_all || exit $OCF_ERR_ARGS echo "$0 RECONFIGURING $OCF_RESKEY_memory" reconfigure exit $? ;; meta-data) meta_data exit 0 ;; validate-all) validate_all exit $? ;; *) echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|validate-all}" exit 1 ;; esac