contrib-munin/plugins/poseidon/snmp__poseidon-sensors

347 lines
10 KiB
Bash
Executable File

#!/bin/bash
#==============================================================================#
# #
# check status of sensor of HW Group Poseidon 3268. For more info refer to: #
# http://www.hw-group.com/products/poseidon/poseidon_3268_en.html #
# 2012 by Florian Lechner #
# #
#==============================================================================#
# #
# 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, see <http://www.gnu.org/licenses/>. #
# #
#==============================================================================#
# Munin autoconf and snmpautoconf magic
#%# family=auto snmpauto contrib
#%# capabilities=snmpconf
E_OK="0" # everything went allright
E_UNKNOWN="1" # "catch all" for otherwise unhandled errors
E_ARG="81" # invalid argument
E_USAGE="82" # wrong program name or arguments
E_SNMPGET="83" # error while executing the 'snmpget' utility
E_COMMANDNOTFOUND="127" # unable to locate binary
#==============================================================================#
# SNMP OIDs from the Poseidon MIB #
#==============================================================================#
SYS_LOC_OID=".1.3.6.1.2.1.1.6.0" # SNMP-location
SYS_NAME_OID=".1.3.6.1.2.1.1.5.0" # device name (string)
SYS_DESCR_OID=".1.3.6.1.2.1.1.1" # text describing the device
SYS_UPTIME_OID=".1.3.6.1.2.1.1.3.0" # time(in tens of milliseconds
#+ since the last reboot
IN_NAME_OID=".1.3.6.1.4.1.21796.3.3.1.1.3." # binary input name (string)
IN_STATE_OID=".1.3.6.1.4.1.21796.3.3.1.1.2." # binary input states(integer)
IN_ALARM_OID=".1.3.6.1.4.1.21796.3.3.1.1.4." # alarm for the binary input,
#+ generated by the device
#+ under defined conditions
#+ 0=Invalid, 1=Normal,
#+ 2=AlarmState, 3=Alarm
SENS_NAME_OID=".1.3.6.1.4.1.21796.3.3.3.1.2." # sensor name (string)
SENS_STATE_OID=".1.3.6.1.4.1.21796.3.3.3.1.4." # binary input states(integer)
SENS_VALUE_OID=".1.3.6.1.4.1.21796.3.3.3.1.6." # integer (decimal * 10)
SENS_ID_OID=".1.3.6.1.4.1.21796.3.3.99.1.2.1.4." # unique sensor ID (integer)
#+ representation of the
#+ temperature (integer)
SENS_UNIT_OID=".1.3.6.1.4.1.21796.3.3.3.1.9." # 0=°C,1=°F,2=°K,3=%,4=V,5=mA,
RTS_OUTPUT_OID=".1.3.6.1.4.1.21796.3.3.2.1.2." # binary input state (integer)
#+ 6=unknown, 7=pulse, 8=switch
# define some Poseidon specific stuff:
STATE_OK="1"
STATE_WARN="2"
STATE_CRIT="3"
UNITS=("C" "F" "K" "%" "V" "mA" "unknown" "pulse" "switch")
TYPES=("Temp" "Temp" "Temp" "Hum" "Volt" "Curr" "Unkn" "Pulse" "Switch")
declare -A sensorsOfType
IFS="
"
#==============================================================================#
# printMuninConfig ()
# print output for munin auto configuration
printMuninConfig () {
if [ ! $hostAddr = 'localhost' ]; then
cat <<- EOT
host_name $hostAddr
EOT
fi
for ((_sensorType=0; _sensorType<=${#UNITS[*]};_sensorType++)); do
# skip graphs without sensors
if [ -z "${sensorsOfType[$_sensorType]}" ]; then
continue
fi
_firstSensor="1"
# print specific config for each sensor
for _sensorNr in ${sensorsOfType[$_sensorType]}; do
getSensorData $_sensorNr
getSystemInfo
if [ $_firstSensor = "1" ]; then
# graph headers
cat <<- EOT
multigraph $sensorType
graph_title $sensorLocation - $sensorType [$sensorUnit]
graph_args --base 1000 -l 0
graph_vlabel $sensorUnit
graph_category sensors
graph_info This graph shows $sensorType history.
EOT
fi
_firstSensor="0"
cat <<- EOT
$sensorType$_sensorNr.label $sensorName
$sensorType$_sensorNr.info This graph shows $sensorType$_sensorNr history.
$sensorType$_sensorNr.draw LINE2
EOT
done
done
}
# printMuninSnmpConfig ()
# print output for munin snmp auto configuration
printMuninSnmpConfig () {
cat <<- EOT
require $SENS_VALUE_OID$sensorNumber [0-9]
require $SENS_STATE_OID$sensorNumber
EOT
return 0;
}
# printMuninStatus ()
# print status output for munin
printMuninStatus () {
for ((_sensorType=0; _sensorType<=${#UNITS[*]};_sensorType++)); do
# skip graphs without sensors
if [ -z "${sensorsOfType[$_sensorType]}" ]; then
continue
fi
_firstSensor="1"
# print config section
for _sensorNr in ${sensorsOfType[$_sensorType]}; do
getSensorData $_sensorNr
if [ $_firstSensor = "1" ]; then
# graph headers
cat <<- EOT
multigraph $sensorType
EOT
fi
_firstSensor="0"
# print graph details
cat <<- EOT
$sensorType$_sensorNr.value $(( $sensorValue / 10 ))
EOT
done
echo ""
done
}
# getSensorData(sensorNr)
# fetch state, value, name unit and sensor type for the sensor
#+ with the number "sensorNr"
getSensorData() {
_sensorNr=$1
sensorState=`snmpGet $hostAddr $SENS_STATE_OID$_sensorNr || err \
"Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
sensorValue=`snmpGet $hostAddr $SENS_VALUE_OID$_sensorNr || err \
"Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
sensorName=`snmpGet $hostAddr $SENS_NAME_OID$_sensorNr || err \
"Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
sensorUnit=`getSensorUnitString $_sensorNr`
sensorType=`getSensorType $_sensorNr`
}
# getSystemInfo()
# fetch general information about the system
getSystemInfo() {
sensorLocation="`snmpGet $hostAddr $SYS_LOC_OID`"
}
# snmpGet (hostAddr, OID)
# use snmpget to fetch a given OID, using above configuration
snmpGet () {
_oid="$2"
_host="$1"
_exit="0"
# fetch the requested OID
_longValue="`snmpget -O v\
-m $MIBS\
-v $SNMPVERSION\
-c $SNMPCOMMUNITY\
$_host $_oid 2>/dev/null`"
_exitStatus="$?"
echo ${_longValue#*:} # remove the type from the answer
return $_exitStatus
}
# get unit (string)
#+ find out the unit of the output of a given sensor. possible units are:
#+ "C" "F" "K" "%" "V" "mA" "unknown" "pulse" "switch"
getSensorUnitString () {
_sensorNr=$1
_sensorUnit=`snmpGet $hostAddr $SENS_UNIT_OID$_sensorNr || err \
"Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
echo ${UNITS[$_sensorUnit]}
}
# get type (string)
#+ find out what type of sensor we are dealing with. possible types are:
#+ "Temp" "Hum" "Volt" "Curr" "Unkn" "Pulse" "Switch"
getSensorType () {
_sensorNr=$1
_sensorUnit=`snmpGet $hostAddr $SENS_UNIT_OID$_sensorNr || err \
"Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
echo ${TYPES[$_sensorUnit]}
}
# getAvailableSensorsByType ()
# check what sensors are available and store them
#+ in the array for the respective unit
getAvailableSensorsByType () {
_thisSensorNr="1"
# initial fetch
_snmpget=`snmpGet $hostAddr $SENS_UNIT_OID$_thisSensorNr`
_nextSensorExits=$?
_unit=`echo "$_snmpget" | tr -d " "`
# add next sensor if it exists
while [ true ]; do
# add sensors of the same type to a list
sensorsOfType[$_unit]="${sensorsOfType[$_unit]} $_thisSensorNr"
# fetch next sensor
_thisSensorNr=$(($_thisSensorNr+1))
_snmpget=`snmpGet $hostAddr $SENS_UNIT_OID$_thisSensorNr`
_nextSensorExits=$?
# are we done?
if [ $_nextSensorExits -ne 0 ]; then
break
fi
_unit=`echo "$_snmpget" |cut -d" " -f 4`
done
}
# sanitize (<string>)
# use bash builtin substitutions to sanitize string
#+ allowed chars are: a-z,A-Z,0-9 and "."
#+ if chars have been removed return 1, else return 0
sanitize () {
input="$1"
sanitizedInput="${1//[^a-zA-Z0-9.]/}"
echo "$sanitizedInput"
if [ "$input" = "$sanitizedInput" ]; then
return 0
else
return 1
fi
}
# usage ()
# print usage
usage () {
echo "usage: snmp_<host>_poseidon-sensors [config|snmpconf]" 1>&2
exit $E_USAGE
}
# err (ErrorMsg, Exitcode)
# basic error handling
err () {
if [ $# -eq 2 -a "$2" -lt 256 ]; then
_errorMsg="$1"
_exitCode="$2"
else
_errorMsg="Fatal: An unknown error occurred! Exiting..."
_exitCode="$E_UNKNOWN"
fi
# print error message to STDERR ...
echo "$_errorMsg" >&2
# ... and exit with error code.
exit $_exitCode
}
#==============================================================================#
# SNMP Config
MIBS=":" # we don't use any configured MIBs so we don't
#+ have to deal with errors in the MIBs
if [ -z $SNMPVERSION ]; then
SNMPVERSION="1" # as of firmware 3.1.5 only SNMPv1 is supported
fi
if [ -z $SNMPCOMMUNITY ]; then
SNMPCOMMUNITY="public" # SNMP community string to read from the device
fi
# handle -h option
while getopts ":h" opt; do
case $opt in
h) usage
;;
\?) echo "Invalid option: -$OPTARG" >&2
usage
;;
esac
done
# check for snmpget binary
if [ ! -x `which snmpget` ]; then
err "Fatal: unable to locate \'snmpget\'! Exiting..." $E_COMMANDNOTFOUND
fi
# extract pluginname ...
myName="`basename "$0" | cut -d "_" -f 1,3`"
# ...and hostname
hostAddr="`basename "$0" | cut -d "_" -f 2`"
if [ "$myName" = "snmp_poseidon-sensors" ]; then
hostAddr=`sanitize $hostAddr || err \
"Fatal: Invalid argument \"$hostAddr\"! Exiting..." $E_ARG`
if [ -z "$hostAddr" ]; then
usage munin
fi
getAvailableSensorsByType
if [ "$1" = "config" ]; then
printMuninConfig
exit $E_OK
elif [ "$1" = "snmpconfig" ]; then
printMuninSnmpConfig
exit $E_OK
else
printMuninStatus
exit $E_OK
fi
else
usage
fi