2016-01-14 00:18:27 +00:00
|
|
|
#!/bin/bash
|
|
|
|
|
#
|
|
|
|
|
# All rights reserved.
|
|
|
|
|
#
|
|
|
|
|
# Redistribution and use in source and binary forms, with or without
|
|
|
|
|
# modification, are permitted provided that the following conditions are met:
|
|
|
|
|
#
|
|
|
|
|
# * Redistributions of source code must retain the above copyright notice, this
|
|
|
|
|
# list of conditions and the following disclaimer.
|
|
|
|
|
#
|
|
|
|
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
|
|
|
# and/or other materials provided with the distribution.
|
|
|
|
|
#
|
|
|
|
|
# * Neither the name of the Novell nor the names of its contributors may be
|
|
|
|
|
# used to endorse or promote products derived from this software without
|
|
|
|
|
# specific prior written permission.
|
|
|
|
|
#
|
|
|
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
export PATH="/usr/local/bin:/usr/bin:/bin"
|
|
|
|
|
|
2018-02-23 14:37:03 +00:00
|
|
|
REVISION=0.1.5
|
2016-01-14 00:18:27 +00:00
|
|
|
PROGNAME=$(basename "$0")
|
|
|
|
|
PROGPATH=$(dirname "$PROGNAME")
|
2018-02-23 14:37:03 +00:00
|
|
|
#STATEFILE='/var/run/keepalived.state'
|
|
|
|
|
STATEFILE='/tmp/keepalived.stats'
|
2016-01-14 00:18:27 +00:00
|
|
|
PIDFILE='/var/run/keepalived.pid'
|
2017-09-17 18:31:31 +00:00
|
|
|
STATE='UNKOWN - no data processed'
|
2016-01-14 00:18:27 +00:00
|
|
|
PROGPATH='/usr/lib/nagios/plugins/'
|
2018-02-23 14:37:03 +00:00
|
|
|
USE_SNMP=false
|
|
|
|
|
SNMP_VERSION='2c'
|
|
|
|
|
SNMP_HOSTNAME='localhost'
|
|
|
|
|
SNMP_COMMUNITY='public'
|
|
|
|
|
SNMP_WALK='/usr/bin/snmpwalk'
|
|
|
|
|
AWK='/usr/bin/awk'
|
|
|
|
|
TR='/usr/bin/tr'
|
|
|
|
|
KEEPALIVED_INSTANCE_STATE_OID='.1.3.6.1.4.1.9586.100.5.2.3.1.4.1'
|
|
|
|
|
KEEPALIVED_WANTED_STATE_OID='.1.3.6.1.4.1.9586.100.5.2.3.1.6.1'
|
2016-01-14 00:18:27 +00:00
|
|
|
|
|
|
|
|
if [ -r "$PROGPATH/utils.sh" ]; then
|
2016-01-26 10:19:32 +00:00
|
|
|
. "$PROGPATH/utils.sh"
|
2016-01-14 00:18:27 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
print_usage() {
|
|
|
|
|
echo "Usage: $PROGNAME [-F keepalived_statefile] [-p keepalived_pidfile] [-S|-M] [-h] [-v]"
|
2016-01-26 10:19:32 +00:00
|
|
|
echo " -F keepalived_statefile : URI to the status file (default: $STATEFILE)"
|
|
|
|
|
echo " -p keepalived_pidfile : URI to the pidfile of the keepalived process (default: $PIDFILE)"
|
|
|
|
|
echo " -S : expect the machine to run in SLAVE state"
|
|
|
|
|
echo " -M : expect the machine to run in MASTER state"
|
|
|
|
|
echo " -h : print this usage"
|
2018-02-23 14:37:03 +00:00
|
|
|
echo " -V : print version information"
|
|
|
|
|
echo " -s : use SNMP"
|
|
|
|
|
echo " -H <hostname> : SNMP host to query"
|
|
|
|
|
echo " -v <snmp_version> : SNMP version (currently only 2c is supported, therefor default)"
|
|
|
|
|
echo " -c <snmp_community> : SNMP v2 community string"
|
2016-01-26 10:19:32 +00:00
|
|
|
echo
|
2018-02-23 14:37:03 +00:00
|
|
|
echo "To successfully run this script via the 'notify'-script configuration, the following pre-requires need to be fulfilled:"
|
2016-01-26 10:19:32 +00:00
|
|
|
echo "* in your keepalived.conf, add 'notify /usr/bin/keepalived_notify_monitoring.sh'"
|
|
|
|
|
echo " in at least one vrrp_instance section (see 'keepalived_notify_monitoring.sh -h'"
|
|
|
|
|
echo " output for more details"
|
2018-02-23 14:37:03 +00:00
|
|
|
echo
|
|
|
|
|
echo "In case of using the SNMP option, the following pre-requires need to be fulfilled:"
|
|
|
|
|
echo "* a running SNMP daemon with agentx support"
|
|
|
|
|
echo "* keepalived needs to be started with the '-x' or '--snmp' option"
|
|
|
|
|
echo
|
|
|
|
|
echo "In any of the above options:"
|
2016-01-26 10:19:32 +00:00
|
|
|
echo "* keepalive should be restarted after the changes"
|
2018-02-23 14:37:03 +00:00
|
|
|
echo
|
|
|
|
|
echo "Check https://en.opensuse.org/Monitoring-plugins-keepalived for more information."
|
2016-01-26 10:19:32 +00:00
|
|
|
echo
|
2016-01-14 00:18:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_help() {
|
|
|
|
|
print_revision $PROGNAME $REVISION
|
|
|
|
|
echo
|
|
|
|
|
print_usage
|
|
|
|
|
echo
|
|
|
|
|
support
|
|
|
|
|
exit $STATE_OK
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-23 14:37:03 +00:00
|
|
|
while getopts 'F:p:SMhVv:sH:c:' OPTION ; do
|
2016-01-26 10:19:32 +00:00
|
|
|
case $OPTION in
|
2016-01-14 00:18:27 +00:00
|
|
|
v|V)
|
2016-01-26 10:19:32 +00:00
|
|
|
print_revision $PROGNAME $REVISION
|
|
|
|
|
exit $STATE_OK
|
2016-01-14 00:18:27 +00:00
|
|
|
;;
|
|
|
|
|
F)
|
2016-01-26 10:19:32 +00:00
|
|
|
STATEFILE="$OPTARG"
|
|
|
|
|
;;
|
|
|
|
|
M)
|
|
|
|
|
MASTER='true'
|
2016-01-14 00:18:27 +00:00
|
|
|
;;
|
|
|
|
|
p)
|
2016-01-26 10:19:32 +00:00
|
|
|
PIDFILE="$OPTARG"
|
|
|
|
|
;;
|
|
|
|
|
S)
|
|
|
|
|
SLAVE='true'
|
2016-01-14 00:18:27 +00:00
|
|
|
;;
|
|
|
|
|
h)
|
2016-01-26 10:19:32 +00:00
|
|
|
print_help
|
|
|
|
|
exit $STATE_OK
|
|
|
|
|
;;
|
2018-02-23 14:37:03 +00:00
|
|
|
s)
|
|
|
|
|
USE_SNMP=true
|
|
|
|
|
;;
|
|
|
|
|
H)
|
|
|
|
|
SNMP_HOSTNAME="$OPTARG"
|
|
|
|
|
;;
|
|
|
|
|
v)
|
|
|
|
|
SNMP_VERSION="$OPTARG"
|
|
|
|
|
;;
|
|
|
|
|
c)
|
|
|
|
|
SNMP_COMMUNITY="$OPTARG"
|
|
|
|
|
;;
|
2016-01-14 00:18:27 +00:00
|
|
|
*)
|
2016-01-26 10:19:32 +00:00
|
|
|
echo "Unkown argument: $OPTION" >&2
|
|
|
|
|
print_usage
|
|
|
|
|
exit $STATE_UNKNOWN
|
|
|
|
|
;;
|
|
|
|
|
esac
|
2016-01-14 00:18:27 +00:00
|
|
|
done
|
|
|
|
|
|
|
|
|
|
if [ -r "$PIDFILE" ]; then
|
2016-01-26 10:19:32 +00:00
|
|
|
PID=$(cat "$PIDFILE")
|
2017-09-17 18:31:31 +00:00
|
|
|
KEEPALIVERUN=$(cat "/proc/$PID/status" | grep ^State: | awk '" " { print $2 }')
|
2016-01-26 10:19:32 +00:00
|
|
|
case $KEEPALIVERUN in
|
|
|
|
|
S|R)
|
|
|
|
|
KEEPALIVESTATE=$STATE_OK
|
|
|
|
|
;;
|
|
|
|
|
Z)
|
|
|
|
|
echo "WARNING: main keepalived process is a Zombie"
|
|
|
|
|
exit $STATE_WARNING
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "UNKOWN: found $PIDFILE but got no state for keepalived"
|
|
|
|
|
exit $STATE_UNKNOWN
|
|
|
|
|
;;
|
|
|
|
|
esac
|
2016-01-14 00:18:27 +00:00
|
|
|
else
|
2018-02-23 14:42:25 +00:00
|
|
|
KEEPALIVENUM=$(ps ax | grep [k]eepalived | wc -l | $TR -d "\n")
|
2016-01-26 10:19:32 +00:00
|
|
|
if [ $KEEPALIVENUM -gt 0 ]; then
|
|
|
|
|
KEEPALIVESTATE=$STATE_OK
|
|
|
|
|
fi
|
2016-01-14 00:18:27 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ $KEEPALIVESTATE -eq $STATE_OK ]; then
|
2018-02-23 14:37:03 +00:00
|
|
|
if [ $USE_SNMP == "true" ]; then
|
|
|
|
|
for command in $AWK $SNMP_WALK $TR ; do
|
|
|
|
|
if [ ! -x $command ]; then
|
|
|
|
|
echo "ERROR: $command not found or not executable"
|
|
|
|
|
exit $STATE_CRITICAL
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
# snmpwalk -On -v2c -cpublic localhost .1.3.6.1.4.1.9586.100.5.2.3.1.4.1
|
2018-02-23 14:42:25 +00:00
|
|
|
SNMP_CURRENT_STATE=$($SNMP_WALK -v${SNMP_VERSION} -c${SNMP_COMMUNITY} $SNMP_HOSTNAME $KEEPALIVED_INSTANCE_STATE_OID | $AWK ' { print $4 }')
|
2018-02-23 14:37:03 +00:00
|
|
|
case $SNMP_CURRENT_STATE in
|
|
|
|
|
*1*) STATE="SLAVE" ;;
|
|
|
|
|
*2*) STATE="MASTER" ;;
|
|
|
|
|
*) STATE="UNKNOWN" ;;
|
|
|
|
|
esac
|
|
|
|
|
if [ "$MASTER" == "true" ]; then
|
|
|
|
|
if [ "$STATE" = "MASTER" ]; then
|
|
|
|
|
echo "OK: $SNMP_HOSTNAME is master"
|
|
|
|
|
exit $STATE_OK
|
|
|
|
|
else
|
|
|
|
|
echo "CRIT: $SNMP_HOSTNAME is not master (state is: $STATE)"
|
|
|
|
|
exit $STATE_CRITICAL
|
|
|
|
|
fi
|
|
|
|
|
elif [ "$SLAVE" == "true" ]; then
|
|
|
|
|
if [ $STATE = "SLAVE" ]; then
|
|
|
|
|
echo "OK: $SNMP_HOSTNAME is slave"
|
|
|
|
|
exit $STATE_OK
|
|
|
|
|
else
|
|
|
|
|
echo "CRIT: $SNMP_HOSTNAME is not slave (state is: $STATE)"
|
|
|
|
|
exit $STATE_CRITICAL
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
# snmpwalk -On -v2c -cpublic localhost .1.3.6.1.4.1.9586.100.5.2.3.1.6.1
|
2018-02-23 14:42:25 +00:00
|
|
|
SNMP_WANTED_STATE=$($SNMP_WALK -v${SNMP_VERSION} -c${SNMP_COMMUNITY} $SNMP_HOSTNAME $KEEPALIVED_WANTED_STATE_OID | $AWK ' { print $4 }')
|
2018-02-23 14:37:03 +00:00
|
|
|
if [ "$SNMP_CURRENT_STATE" = "$SNMP_WANTED_STATE" ]; then
|
|
|
|
|
echo "OK: $SNMP_HOSTNAME is in wanted state (state is: $STATE)"
|
|
|
|
|
exit $STATE_OK
|
|
|
|
|
else
|
|
|
|
|
echo "CRIT: $SNMP_HOSTNAME is not in wanted state (state is: $STATE)"
|
|
|
|
|
exit $STATE_CRITICAL
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
rm -f $STATEFILE
|
|
|
|
|
kill -USR2 $PID
|
|
|
|
|
sleep 1
|
|
|
|
|
if [ -r "$STATEFILE" ] ; then
|
|
|
|
|
STATE1=$(grep "Became master:" "$STATEFILE")
|
|
|
|
|
STATE2=$(grep "Released master:" "$STATEFILE")
|
2016-01-26 10:19:32 +00:00
|
|
|
else
|
|
|
|
|
echo "UNKOWN: could not read $STATEFILE"
|
|
|
|
|
exit $STATE_UNKNOWN
|
|
|
|
|
fi
|
2018-02-23 14:37:03 +00:00
|
|
|
rm -f $STATEFILE
|
|
|
|
|
if [[ $STATE1 == *"Became master: 0"* ]];then
|
|
|
|
|
echo "$STATE1"
|
2016-01-26 10:19:32 +00:00
|
|
|
exit $STATE_CRITICAL
|
|
|
|
|
fi
|
2016-01-14 00:18:27 +00:00
|
|
|
|
2016-01-26 10:19:32 +00:00
|
|
|
if [ "$MASTER" == "true" ]; then
|
2018-02-23 14:37:03 +00:00
|
|
|
if [[ $STATE2 == *"Released master: 0"* ]]; then
|
|
|
|
|
echo "$STATE1 $STATE2"
|
2016-01-26 10:19:32 +00:00
|
|
|
exit $STATE_OK
|
|
|
|
|
fi
|
2018-02-23 14:37:03 +00:00
|
|
|
if [[ $STATE2 == *"Released master: 1"* ]]; then
|
|
|
|
|
echo "$STATE1 $STATE2"
|
2016-01-26 10:19:32 +00:00
|
|
|
exit $STATE_CRITICAL
|
|
|
|
|
fi
|
|
|
|
|
elif [ "$SLAVE" == "true" ]; then
|
2018-02-23 14:37:03 +00:00
|
|
|
if [[ $STATE2 == *"Released master: 1"* ]]; then
|
|
|
|
|
echo "$STATE1 $STATE2"
|
2016-01-26 10:19:32 +00:00
|
|
|
exit $STATE_OK
|
2018-02-23 14:37:03 +00:00
|
|
|
elif [[ $STATE2 == *"Released master: 0"* ]]; then
|
|
|
|
|
echo "$STATE1 $STATE2"
|
2016-01-26 10:19:32 +00:00
|
|
|
exit $STATE_CRITICAL
|
2017-09-17 18:31:31 +00:00
|
|
|
else
|
2018-02-23 14:37:03 +00:00
|
|
|
echo "UNKOWN: could not detect state from $STATEFILE : $STATE1 $STATE2"
|
2017-09-17 18:31:31 +00:00
|
|
|
exit $STATE_UNKNOWN
|
2016-01-26 10:19:32 +00:00
|
|
|
fi
|
|
|
|
|
else
|
2018-02-23 14:37:03 +00:00
|
|
|
if [[ $STATE2 == *"Released master: 0"* ]] || [[ $STATE2 == *"Released master: 1"* ]]; then
|
|
|
|
|
echo "$STATE1 $STATE2"
|
2016-01-26 10:19:32 +00:00
|
|
|
exit $STATE_OK
|
2017-09-17 18:31:31 +00:00
|
|
|
else
|
2018-02-23 14:37:03 +00:00
|
|
|
echo "UNKOWN: could not detect state from $STATEFILE : $STATE1 $STATE2"
|
2017-09-17 18:31:31 +00:00
|
|
|
exit $STATE_UNKNOWN
|
2016-01-26 10:19:32 +00:00
|
|
|
fi
|
|
|
|
|
fi
|
2018-02-23 14:37:03 +00:00
|
|
|
fi
|
2016-01-14 00:18:27 +00:00
|
|
|
else
|
2016-01-26 10:19:32 +00:00
|
|
|
echo "Keepalived is in UNKNOWN state"
|
|
|
|
|
exit $STATE_UNKNOWN
|
2016-01-14 00:18:27 +00:00
|
|
|
fi
|