Import 3ware-status

This commit is contained in:
Adam Cécile (Le_Vert) 2013-08-14 22:49:55 +02:00
parent 80b14dcfb2
commit 5e69b38912
10 changed files with 478 additions and 0 deletions

View File

@ -0,0 +1,191 @@
#! /bin/sh
# Author: Petter Reinholdtsen <pere@hungry.com>
# License: GNU General Public License v2 or later
#
### BEGIN INIT INFO
# Provides: 3ware-statusd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Check 3ware-status values in the background.
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DESC="3ware-status monitor"
NAME=3ware-statusd
PIDFILE=/var/run/$NAME.pid
STATUSFILE=/var/run/$NAME.status
SCRIPTNAME=/etc/init.d/$NAME
# Do not touch you can configure this in /etc/default/3ware-statusd
MAILTO=root # Where to report problems
PERIOD=600 # Seconds between each check (default 10 minutes)
REMIND=7200 # Seconds between each reminder (default 2 hours)
RUN_DAEMON=yes
[ -e /etc/default/3ware-statusd ] && . /etc/default/3ware-statusd
# Gracefully exit if the package has been removed.
test -x /usr/sbin/3ware-status || exit 0
. /lib/lsb/init-functions
[ -e /etc/default/rcS ] && . /etc/default/rcS
if [ $RUN_DAEMON = "no" ] ; then
log_begin_msg "3ware-statusd is disabled in /etc/default/3ware-statusd, not starting."
log_end_msg 0
exit 0
fi
check_3ware() {
echo $$ > $PIDFILE.new && mv $PIDFILE.new $PIDFILE
while true ; do
# Check ever $PERIOD seconds, send email on every status
# change and repeat ever $REMIND seconds if the raid is still
# bad.
if (3ware-status) |grep -q 'NOT OPTIMAL' ; then
BADRAID=true
logger -t 3ware-statusd "detected non-optimal RAID status"
else
BADRAID=false
fi
STATUSCHANGE=false
if [ true = "$BADRAID" ] ; then
# RAID not OK
(3ware-status) > $STATUSFILE.new
if [ ! -f $STATUSFILE ] ; then # RAID just became broken
STATUSCHANGE=true
mv $STATUSFILE.new $STATUSFILE
elif cmp -s $STATUSFILE $STATUSFILE.new ; then
# No change. Should we send reminder?
LASTTIME="`stat -c '%Z' $STATUSFILE`"
NOW="`date +%s`"
SINCELAST="`expr $NOW - $LASTTIME`"
if [ $REMIND -le "$SINCELAST" ]; then
# Time to send reminder
STATUSCHANGE=true
mv $STATUSFILE.new $STATUSFILE
else
rm $STATUSFILE.new
fi
else
STATUSCHANGE=true
mv $STATUSFILE.new $STATUSFILE
fi
else
# RAID OK
if [ -f $STATUSFILE ] ; then
rm $STATUSFILE
STATUSCHANGE=true
fi
fi
if [ true = "$STATUSCHANGE" ]; then
hostname="`uname -n`"
(
cat <<EOF
This is a RAID status update from 3ware-statusd.
The 3ware-status program reports that one of the RAIDs changed state:
EOF
if [ -f $STATUSFILE ] ; then
cat $STATUSFILE
else
(3ware-status)
fi
echo
echo "Report from $0 on $hostname"
) | mail -s "info: 3ware raid status change on $hostname" $MAILTO
fi
sleep $PERIOD
done
}
check_daemon() {
# Let's check if there is a daemon which is really running and not timing out
DAEMON_RUN=`ps aux | grep "/etc/init.d/3ware-statusd check_3ware" | grep -v grep | grep -v daemon`
if [ -n "$DAEMON_RUN" ] ; then
return 1;
else
return 0;
fi
}
#
# Function that starts the daemon/service.
#
d_start() {
[ -f $PIDFILE ] && PID="`cat $PIDFILE`"
if [ "$PID" ] ; then
log_progress_msg "Daemon already running. Refusing to start another"
return 0
elif check_daemon ; then
# Use the daemon package to turn this script into a daemon
start-stop-daemon --start --quiet --pidfile $PIDFILE \
--oknodo --exec /usr/bin/daemon /usr/bin/daemon $SCRIPTNAME check_3ware
return 0
else
log_progress_msg "Daemon is already running. Refusing to start another"
return 0
fi
}
#
# Function that stops the daemon/service.
#
d_stop() {
if [ -f $PIDFILE ] ; then
start-stop-daemon --stop --oknodo --quiet --pidfile $PIDFILE > /dev/null 2>&1
rm -f $PIDFILE
else
log_progress_msg "Daemon is already stopped."
return 0
fi
}
# This is a workaround function which does not directly exit and
# therefore can be used by a restart
d_stop_by_restart() {
if [ -f $PIDFILE ] ; then
start-stop-daemon --oknodo --stop --quiet --pidfile $PIDFILE
rm -f $PIDFILE
log_end_msg 0
else
log_progress_msg "Daemon is already stopped."
log_end_msg 0
fi
}
case "$1" in
start)
echo -n ""
log_begin_msg "Starting $DESC: $NAME"
d_start ; CODE=$?
log_end_msg $CODE
;;
stop)
log_begin_msg "Stopping $DESC: $NAME"
d_stop ; CODE=$?
log_end_msg $CODE
;;
check_3ware)
check_3ware
;;
restart|force-reload)
log_begin_msg "Restarting $DESC: $NAME"
d_stop_by_restart
sleep 1
d_start || CODE=$?
log_end_msg $CODE
;;
*)
# echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,23 @@
README.Debian for 3ware-status package
--------------------------------------
Possible configuration:
-----------------------
If you want to change the default configuration of the init script you
can create the file /etc/default/3ware-statusd and specify the following
values.
MAILTO=
PERIOD=
REMIND=
Use MAILTO to specify which user shall get the status mails
(default is root).
With PERIOD you can fix the seconds between each check.
And REMIND specifies the seconds between each reminder.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Wed, 10 Oct 2007 10:19:28 +0200

View File

@ -0,0 +1,26 @@
3ware-status (0.4) unstable; urgency=low
* Now handle different tw-cli output for 9000 series cards.
* Will now fail if tw-cli binary cannot be found.
* Add --nagios parameter (run through nrpe).
* Import initscript changes from mpt-status 1.2.0-7 package.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Thu, 02 Feb 2012 11:31:45 +0100
3ware-status (0.3) unstable; urgency=low
* Do not fail with empty ports.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Mon, 16 Aug 2010 09:27:55 +0200
3ware-status (0.2) unstable; urgency=low
* Switch logical disk id and disk id.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Wed, 10 Oct 2007 10:55:57 +0200
3ware-status (0.1) unstable; urgency=low
* Intial release.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Wed, 10 Oct 2007 10:19:28 +0200

View File

@ -0,0 +1 @@
5

View File

@ -0,0 +1,14 @@
Source: 3ware-status
Section: admin
Priority: extra
Maintainer: Adam Cécile (Le_Vert) <gandalf@le-vert.net>
Build-Depends: debhelper (>= 5)
Standards-Version: 3.9.2
Package: 3ware-status
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, python, lsb-base, daemon, bsd-mailx | mailx, tw-cli (>= 9.5.0)
Description: get RAID status out of 3ware Eskalad HW RAID controllers
The 3ware-status software is a query tool to access the running
configuration and status of 3Ware HBAs. 3ware-status allows you to
monitor the health and status of your RAID setup.

View File

@ -0,0 +1,26 @@
This package was debianized by Adam Cécile (Le_Vert) <gandalf@le-vert.net> on
Wed, 10 Oct 2007 10:19:28 +0200.
It was downloaded from http://hwraid.le-vert.net
Copyright Holder:
Copyright (C) 2007-2012 Adam Cécile (Le_Vert) <gandalf@le-vert.net>
License:
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License, version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANDABILITY of FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for details.
On Debian GNU/Linux systems, the complete text of the GNU General Public
License version 2 (or later) see `/usr/share/common-licenses/GPL-2'.
This package is highly based on Steffen Joeris <white@debian.org> works done
for the mpt-status package.
Thanks a lot Steffen!

View File

@ -0,0 +1 @@
usr/sbin

View File

@ -0,0 +1 @@
3ware-status usr/sbin

View File

@ -0,0 +1,42 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
build: build-arch build-indep
build-arch:
build-indep:
clean:
dh_testdir
dh_testroot
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
binary-arch: build install
binary-indep: build install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_install
dh_installinit --name 3ware-statusd \
--update-rcd-params="start 21 2 3 4 5 . stop 19 0 1 6 ."
dh_link
dh_strip
dh_compress
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

153
wrapper-scripts/3ware-status Executable file
View File

@ -0,0 +1,153 @@
#!/usr/bin/python
import os
import re
import sys
binarypath = "/usr/sbin/tw-cli"
if len(sys.argv) > 2:
print 'Usage: 3ware-status [--nagios]'
sys.exit(1)
nagiosmode=False
nagiosoutput=''
nagiosgoodarray=0
nagiosbadarray=0
nagiosgooddisk=0
nagiosbaddisk=0
if len(sys.argv) > 1:
if sys.argv[1] == '--nagios':
nagiosmode=True
else:
print 'Usage: 3ware-status [--nagios]'
sys.exit(1)
# Check binary exists (and +x), if not print an error message
# or return UNKNOWN nagios error code
if os.path.exists(binarypath) and os.access(binarypath, os.X_OK):
pass
else:
if nagiosmode:
print 'UNKNOWN - Cannot find '+binarypath
else:
print 'Cannot find '+binarypath+'. Please install it.'
sys.exit(3)
# Get command output
def getOutput(cmd):
output = os.popen(cmd)
lines = []
for line in output:
if not re.match(r'^$',line.strip()):
lines.append(line.strip())
return lines
def returnControllerList(output):
lines = []
for line in output:
if re.match(r'^c[0-9]+\s.*$',line.strip()):
lines.append(line.split()[0])
return lines
def returnDiskList(output):
lines = []
for line in output:
if re.match(r'^[p][0-9]+\s.*$',line.strip()):
# Shoudl contain something like 'u0'
# '-' means the drive doesn't belong to any array
# If is NOT PRESENT too, it just means this is an empty port
if not line.split()[2].strip() == '-' and not line.split()[1].strip() == 'NOT-PRESENT':
lines.append(line.split())
if fake_failure:
lines[0][1] = 'NOT PRESENT'
return lines
def returnArrayList(output):
lines = []
for line in output:
if re.match(r'^[u][0-9]+\s.*$',line.strip()):
lines.append(line.split())
if fake_failure:
lines[0][2] = 'DEGRADED'
return lines
# A way to force a fake failure
fake_failure = False
if os.path.exists('/root/fake_3ware_failure'):
fake_failure = True
cmd = binarypath+' info'
output = getOutput(cmd)
controllerlist = returnControllerList(output)
bad = False
# List available controller
if not nagiosmode:
print '-- Controller informations --'
print '-- ID | Model'
for controller in controllerlist:
cmd = binarypath+' info '+controller+' model'
model = getOutput(cmd)[0].split(' = ')[1].strip()
print controller+' | '+model
print ''
# List arrays
if not nagiosmode:
print '-- Arrays informations --'
print '-- ID\tType\tSize\tStatus'
for controller in controllerlist:
cmd = binarypath+' info '+controller
output = getOutput(cmd)
arraylist = returnArrayList(output)
for array in arraylist:
type = array[1].replace('-','')
id = controller+array[0]
size = array[6].split('.')[0]+'G'
status = array[2]
if not status == 'OK':
bad = True
nagiosbadarray=nagiosbadarray+1
else:
nagiosgoodarray=nagiosgoodarray+1
if not nagiosmode:
print id+'\t'+type+'\t'+size+'\t'+status
if not nagiosmode:
print ''
# List disks
if not nagiosmode:
print '-- Disks informations'
print '-- ID\tModel\t\t\tStatus'
for controller in controllerlist:
cmd = binarypath+' info '+controller
output = getOutput(cmd)
disklist = returnDiskList(output)
for disk in disklist:
id = controller+disk[2]+disk[0]
cmd = binarypath+' info '+controller+' '+disk[0]+' model'
model = getOutput(cmd)[0].split(' = ')[1].strip()
cmd = binarypath+' info '+controller+' '+disk[0]+' status'
status = getOutput(cmd)[0].split(' = ')[1].strip()
if not status == 'OK':
bad = Truei
nagiosbaddisk=nagiosbaddisk+1
else:
nagiosgooddisk=nagiosgooddisk+1
if not nagiosmode:
print id+'\t'+model+'\t'+status
if nagiosmode:
if bad:
print 'RAID ERROR - Arrays: OK:'+str(nagiosgoodarray)+' Bad:'+str(nagiosbadarray)+' - Disks: OK:'+str(nagiosgooddisk)+' Bad:'+str(nagiosbaddisk)
sys.exit(2)
else:
print 'RAID OK - Arrays: OK:'+str(nagiosgoodarray)+' Bad:'+str(nagiosbadarray)+' - Disks: OK:'+str(nagiosgooddisk)+' Bad:'+str(nagiosbaddisk)
else:
if bad:
print '\nThere is at least one disk/array in a NOT OPTIMAL state.'
sys.exit(1)