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..dd58d63cd
--- 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 "$APACHE_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 806a5d6be..c43c17713 100644
--- a/rgmanager/src/resources/fs.sh.in
+++ b/rgmanager/src/resources/fs.sh.in
@@ -1,461 +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
- return 0
+ # 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..c7a7723ee
--- 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 "$MYSQL_pid_file"
+ return $OCF_NOT_RUNNING
+ ;;
+ 0)
+ clog_service_status $CLOG_SUCCEED
+ exit 0
+ ;;
+ *)
+ clog_service_status $CLOG_FAILED "$MYSQL_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 f911ae254..f8819177f
--- a/rgmanager/src/resources/netfs.sh
+++ b/rgmanager/src/resources/netfs.sh
@@ -1,394 +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 0 # Returning 0 lets stop_filesystem do add'l checks
+ 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/fs-lib.sh b/rgmanager/src/resources/utils/fs-lib.sh
index 38c242d38..163cfb7a2 100644
--- a/rgmanager/src/resources/utils/fs-lib.sh
+++ b/rgmanager/src/resources/utils/fs-lib.sh
@@ -1,975 +1,983 @@
#!/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.
#
#
# 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
# 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
# If our provided blockdev is a device, we are done
if [ -b "$dev" ]; then
REAL_DEVICE="$dev"
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
+# return = nonzero if successful, or 0 if unsuccessful
+# (unsuccessful = try harder)
do_force_unmount() {
- return 0
+ return 1
}
#
# 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 ;;
on) force_umount=$YES ;;
true) force_umount=$YES ;;
1) force_umount=$YES ;;
*) force_umount="" ;;
esac
case ${OCF_RESKEY_self_fence} in
$YES_STR) self_fence=$YES ;;
on) self_fence=$YES ;;
true) 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
+ # Try fs-specific force-unmount, if provided
+ do_force_unmount
+ if [ $? -eq 0 ]; then
+ # if this succeeds, we should be done
+ continue
+ fi
+
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() {
#
# 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_NOT_RUNNING
fi
is_mounted "$dev" "${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
}
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