Import megaclisas-status

This commit is contained in:
Adam Cécile (Le_Vert) 2013-08-14 23:07:09 +02:00
parent fabe7423e7
commit 55ccd5f752
10 changed files with 572 additions and 0 deletions

View File

@ -0,0 +1,23 @@
README.Debian for megaclisas-status package
-------------------------------------------
Possible configuration:
----------------------
If you want to change the default configuration of the init script you
can create the file /etc/default/megaclisas-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> Tue, 11 Dec 2007 17:06:56 +0100

View File

@ -0,0 +1,59 @@
megaclisas-status (0.9) unstable; urgency=low
* Fix the duplicate disk issue (Closes: #26).
Many thanks to Nicolas Raspail who provided a patch.
* Will now fail if megacli binary cannot be found.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Thu, 02 Feb 2012 13:38:15 +0100
megaclisas-status (0.8) unstable; urgency=low
* Support megacli 8.02.16.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Mon, 30 Jan 2012 20:59:13 +0100
megaclisas-status (0.7) unstable; urgency=low
* Add nagios mode (--nagios).
* improve disk error reporting.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Mon, 31 Oct 2011 15:58:39 +0100
megaclisas-status (0.6) unstable; urgency=low
* Import init script changes from mpt-status-1.2.0-7 package:
- Script won't stop anymore because of set -e
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Wed, 11 May 2011 14:52:38 +0200
megaclisas-status (0.5) unstable; urgency=low
* Some new cards report array size in TB.
* Bump Standards-Version to 3.8.2.
* Improve debian/copyright.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Mon, 27 Jul 2009 10:28:24 +0200
megaclisas-status (0.4) unstable; urgency=low
* Fix a nasty bug with cards reporting size in GB instead of MB (Closes: #2).
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Tue, 19 May 2009 18:42:06 +0200
megaclisas-status (0.3) unstable; urgency=low
* Depends on megacli instead of megaclisas.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Thu, 11 Dec 2008 17:41:18 +0100
megaclisas-status (0.2) unstable; urgency=low
* Packaging cleanup.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Thu, 21 Aug 2008 15:36:27 +0200
megaclisas-status (0.1) unstable; urgency=low
* Initial release.
-- Adam Cécile (Le_Vert) <gandalf@le-vert.net> Tue, 11 Dec 2007 17:06:56 +0100

View File

@ -0,0 +1 @@
5

View File

@ -0,0 +1,15 @@
Source: megaclisas-status
Section: admin
Priority: optional
Maintainer: Adam Cécile (Le_Vert) <gandalf@le-vert.net>
Build-Depends: debhelper (>= 5)
Standards-Version: 3.9.2
Package: megaclisas-status
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, python, lsb-base, daemon, bsd-mailx | mailx, megacli
Description: get RAID status out of LSI MegaRAID SAS HW RAID controllers
The megacli-status software is a query tool to access the running
configuration and status of LSI MegaRAID SAS HBAs.
.
It uses LSI MegaCli proprietary command line tool.

View File

@ -0,0 +1,25 @@
This package was debianized by Adam Cécile (Le_Vert) <gandalf@le-vert.net> on
Tue, 11 Dec 2007 17:06:56 +0100.
It was downloaded from http://hwraid.le-vert.net
Copyright Holder:
Copyright (C) 2007-2009 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 can be found in `/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 @@
megaclisas-status usr/sbin

View File

@ -0,0 +1,199 @@
#! /bin/sh
# Author: Petter Reinholdtsen <pere@hungry.com>
# License: GNU General Public License v2 or later
#
### BEGIN INIT INFO
# Provides: megaclisas-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 megaclisas-status values in the background.
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DESC="megaclisas-status monitor"
NAME=megaclisas-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/megaclisas-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/megaclisas-statusd ] && . /etc/default/megaclisas-statusd
# Gracefully exit if the package has been removed.
test -x /usr/sbin/megaclisas-status || exit 0
. /lib/lsb/init-functions
[ -e /etc/default/rcS ] && . /etc/default/rcS
if [ $RUN_DAEMON = "no" ] ; then
log_begin_msg "megaclisas-statusd is disabled in /etc/default/megaclisas-statusd, not starting."
log_end_msg 0
exit 0
fi
check_megaclisas() {
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 (megaclisas-status) |grep -q 'NOT OPTIMAL' ; then
BADRAID=true
logger -t megaclisas-statusd "detected non-optimal RAID status"
else
BADRAID=false
fi
STATUSCHANGE=false
if [ true = "$BADRAID" ] ; then
# RAID not OK
(megaclisas-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 megaclisas-statusd. The megaclisas-status
program reports that one of the RAIDs changed state:
EOF
if [ -f $STATUSFILE ] ; then
cat $STATUSFILE
else
(megaclisas-status)
fi
echo
echo "Report from $0 on $hostname"
) | mail -s "info: MegaRAID 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/megaclisas-statusd check_megaclisas" | 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_megaclisas
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
# Doesn't work (kill init script instance, but not daemon...)
#start-stop-daemon --stop --oknodo --quiet --pidfile $PIDFILE > /dev/null 2>&1
DAEMONPID=`ps aux | grep '/usr/bin/daemon /etc/init.d/megaclisas-statusd check_megaclisas' | grep -v 'grep' | awk '{ print $2 }'`
SCRIPTPID=`cat $PIDFILE`
kill -9 $DAEMONPID $SCRIPTPID || true
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
# Doesn't work (kill init script instance, but not daemon...)
#start-stop-daemon --oknodo --stop --quiet --pidfile $PIDFILE
DAEMONPID=`ps aux | grep '/usr/bin/daemon /etc/init.d/megaclisas-statusd check_megaclisas' | grep -v 'grep' | awk '{ print $2 }'`
SCRIPTPID=`cat $PIDFILE`
kill -9 $DAEMONPID $SCRIPTPID || true
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_megaclisas)
check_megaclisas
;;
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,40 @@
#!/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:
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
binary-arch: build install
binary-indep: build install
dh_testdir -i
dh_testroot -i
dh_installchangelogs -i
dh_installdocs -i
dh_install -i
dh_installinit -i --name megaclisas-statusd
dh_link -i
dh_strip -i
dh_compress -i
dh_fixperms -i
dh_installdeb -i
dh_shlibdeps -i
dh_gencontrol -i
dh_md5sums -i
dh_builddeb -i
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

208
wrapper-scripts/megaclisas-status Executable file
View File

@ -0,0 +1,208 @@
#!/usr/bin/python
import os
import re
import sys
binarypath = "/usr/sbin/megacli"
if len(sys.argv) > 2:
print 'Usage: megaclisas-status [--nagios]'
sys.exit(1)
nagiosmode=False
nagiosoutput=''
nagiosgoodarray=0
nagiosbadarray=0
nagiosgooddisk=0
nagiosbaddisk=0
# Check command line arguments to enable nagios or not
if len(sys.argv) > 1:
if sys.argv[1] == '--nagios':
nagiosmode=True
else:
print 'Usage: megaclisas-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 returnControllerNumber(output):
for line in output:
if re.match(r'^Controller Count.*$',line.strip()):
return int(line.split(':')[1].strip().strip('.'))
def returnControllerModel(output):
for line in output:
if re.match(r'^Product Name.*$',line.strip()):
return line.split(':')[1].strip()
def returnArrayNumber(output):
i = 0
for line in output:
if re.match(r'^Number of Virtual (Disk|Drive).*$',line.strip()):
i = line.strip().split(':')[1].strip()
return i
def returnArrayInfo(output,controllerid,arrayid):
id = 'c'+str(controllerid)+'u'+str(arrayid)
operationlinennumber = False
linenumber = 0
for line in output:
if re.match(r'Number Of Drives\s*((per span))?:.*[0-9]+$',line.strip()):
ldpdcount = line.split(':')[1].strip()
if re.match(r'Span Depth *:.*[0-9]+$',line.strip()):
spandepth = line.split(':')[1].strip()
if re.match(r'^RAID Level\s*:.*$',line.strip()):
raidlevel = line.strip().split(':')[1].split(',')[0].split('-')[1].strip()
type = 'RAID' + raidlevel
if re.match(r'^Size\s*:.*$',line.strip()):
# Size reported in MB
if re.match(r'^.*MB$',line.strip().split(':')[1]):
size = line.strip().split(':')[1].strip('MB').strip()
size = str(int(round((float(size) / 1000))))+'G'
# Size reported in TB
elif re.match(r'^.*TB$',line.strip().split(':')[1]):
size = line.strip().split(':')[1].strip('TB').strip()
size = str(int(round((float(size) * 1000))))+'G'
# Size reported in GB (default)
else:
size = line.strip().split(':')[1].strip('GB').strip()
size = str(int(round((float(size)))))+'G'
if re.match(r'^State\s*:.*$',line.strip()):
state = line.strip().split(':')[1].strip()
if re.match(r'^Ongoing Progresses\s*:.*$',line.strip()):
operationlinennumber = linenumber
linenumber += 1
if operationlinennumber:
inprogress = output[operationlinennumber+1]
else:
inprogress = 'None'
if ldpdcount and (int(spandepth) > 1):
ldpdcount = int(ldpdcount) * int(spandepth)
if int(raidlevel) < 10:
type = type + "0"
return [id,type,size,state,inprogress]
def returnDiskInfo(output,controllerid):
arrayid = False
diskid = False
table = []
state = 'undef'
model = 'undef'
for line in output:
if re.match(r'^Virtual (Disk|Drive): [0-9]+.*$',line.strip()):
arrayid = line.split('(')[0].split(':')[1].strip()
if re.match(r'Firmware state: .*$',line.strip()):
state = line.split(':')[1].strip()
if re.match(r'Inquiry Data: .*$',line.strip()):
model = line.split(':')[1].strip()
model = re.sub(' +', ' ', model)
if re.match(r'PD: [0-9]+ Information.*$',line.strip()):
diskid = line.split()[1].strip()
if arrayid != False and state != 'undef' and model != 'undef' and diskid != False:
table.append([str(arrayid), str(diskid), state, model])
state = 'undef'
model = 'undef'
return table
cmd = binarypath+' -adpCount -NoLog'
output = getOutput(cmd)
controllernumber = returnControllerNumber(output)
bad = False
# List available controller
if not nagiosmode:
print '-- Controller informations --'
print '-- ID | Model'
controllerid = 0
while controllerid < controllernumber:
cmd = binarypath+' -AdpAllInfo -a'+str(controllerid)+' -NoLog'
output = getOutput(cmd)
controllermodel = returnControllerModel(output)
print 'c'+str(controllerid)+' | '+controllermodel
controllerid += 1
print ''
controllerid = 0
if not nagiosmode:
print '-- Arrays informations --'
print '-- ID | Type | Size | Status | InProgress'
while controllerid < controllernumber:
arrayid = 0
cmd = binarypath+' -LdGetNum -a'+str(controllerid)+' -NoLog'
output = getOutput(cmd)
arraynumber = returnArrayNumber(output)
while arrayid < int(arraynumber):
cmd = binarypath+' -LDInfo -l'+str(arrayid)+' -a'+str(controllerid)+' -NoLog'
output = getOutput(cmd)
arrayinfo = returnArrayInfo(output,controllerid,arrayid)
if not nagiosmode:
print arrayinfo[0]+' | '+arrayinfo[1]+' | '+arrayinfo[2]+' | '+arrayinfo[3]+' | '+arrayinfo[4]
if not arrayinfo[3] == 'Optimal':
bad = True
nagiosbadarray=nagiosbadarray+1
else:
nagiosgoodarray=nagiosgoodarray+1
arrayid += 1
controllerid += 1
if not nagiosmode:
print ''
if not nagiosmode:
print '-- Disks informations'
print '-- ID | Model | Status'
controllerid = 0
while controllerid < controllernumber:
arrayid = 0
cmd = binarypath+' -LDInfo -lall -a'+str(controllerid)+' -NoLog'
output = getOutput(cmd)
cmd = binarypath+' -LdPdInfo -a'+str(controllerid)+' -NoLog'
output = getOutput(cmd)
arraydisk = returnDiskInfo(output,controllerid)
for array in arraydisk:
if not array[2] == 'Online' and not array[2] == 'Online, Spun Up':
bad=True
nagiosbaddisk=nagiosbaddisk+1
else:
nagiosgooddisk=nagiosgooddisk+1
if not nagiosmode:
print 'c'+str(controllerid)+'u'+array[0]+'p'+array[1]+' | '+array[3]+' | '+array[2]
controllerid += 1
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)