2
0
mirror of https://github.com/munin-monitoring/contrib.git synced 2018-11-08 00:59:34 +01:00
contrib-munin/plugins/snmp/snmp__rms2_

223 lines
7.8 KiB
Plaintext
Raw Normal View History

#!/usr/bin/perl -w
#
# This plugin is for querying Knuerr RMS Compact II Rack Monitoring Units
# by SNMP.
#
# Michael Meier <michael.meier@fau.de>
#
# 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; version 2 dated June,
# 1991.
#
# 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.
#
#
# Usage:
# ln -s /usr/share/munin/node/plugins-auto/snmp__rms2_ /etc/munin/node.d/snmp_HOSTNAME_rms2_MODE
# available MODEs:
# temp for temperature sensors
# humidity for humidity sensors (untested!)
# contact for contact sensors
#
# Note: Due to shortcomings of munin-node-configure, it is not currently
# possible to make this plugin properly autodetect/autoconfigure. That is
# because for SNMP plugins that need more than just a hostname, only numbers
# that come from an SNMP tree can be the second parameter. Parameters like
# "temp" do not exist in the short-sighted world of munin-node-configure.
# Combining SNMP with the "suggest" plugin-feature is currently not possible.
#%# family=snmpauto
#%# capabilities=snmpconf
use strict;
use Net::SNMP;
my $DEBUG = 0;
my $host = $ENV{host} || undef;
my $port = $ENV{port} || 161;
my $community = $ENV{community} || "public";
my $mode = $ENV{mode} || undef;
my $response;
my $graphs = {
'temp' => { 'title' => 'Temperatures',
'unit' => 'degC', # This can actually be overwritten later with retard-units (F)
'scale' => 0.1,
'thatype' => 2,
'list' => '.1.3.6.1.4.1.3711.24.1.1.1.2.2.1.1' },
'humidity' => { 'title' => 'Humidity',
'unit' => '%',
'scale' => 0.1, # FIXME?
'thatype' => 3,
'list' => '.1.3.6.1.4.1.3711.24.1.1.1.2.2.1.1' },
'contact' => { 'title' => 'Contact sensors',
'unit' => 'n',
'list' => '.1.3.6.1.4.1.3711.24.1.1.1.3.1.1.1' },
};
if (defined($ARGV[0]) && ($ARGV[0] eq "snmpconf")) {
print "require .1.3.6.1.4.1.3711.24.1.1.99.1.0\n"; # The inventory tree
exit(0);
}
if ($0 =~ /^(?:|.*\/)snmp_([^_]+)_rms2_(.+)$/) {
$host = $1;
$mode = $2;
if ($host =~ /^([^:]+):(\d+)$/) {
$host = $1;
$port = $2;
}
} elsif (!defined($host)) {
print "# Debug: $0 -- $1 -- $2\n" if $DEBUG;
print("# Error: couldn't understand what I'm supposed to monitor.\n");
print("# You need to either name this plugin properly in the scheme\n");
print("# snmp_HOSTNAME_rms2_MODE\n");
print("# or alternatively set the environment variables 'host' and 'mode'\n");
exit(1);
}
my ($session, $error) = Net::SNMP->session(
-hostname => $host,
-community => $community,
-port => $port,
-version => 'snmpv2c',
-timeout => 1.0
);
if (!defined ($session)) {
print("# Failed to open SNMP session: $error");
exit(1);
}
unless (defined($graphs->{$mode}->{'title'})) {
print("# Unknown mode '$mode'! Available modes are:\n");
foreach my $m (keys(%{$graphs})) {
if (defined($graphs->{$m}->{'title'})) {
printf("# %-18s %s\n", $m, $graphs->{$m}->{'title'});
}
}
exit(1);
}
# This is mostly copy&paste from the snmpwalk.pl-example in the Net::SNMP sourcecode.
# I'm not really sure this is the simplest way to do this, but could not find a
# better WORKING example.
my $last_oid = $graphs->{$mode}->{'list'};
my @indexes = ( );
my @args = ( -varbindlist => [ $last_oid ] );
push(@args, -maxrepetitions => 2);
GET_BULK: while (defined $session->get_bulk_request(@args)) {
my @oids = $session->var_bind_names();
if (!scalar @oids) {
print("# ERROR: Empty SNMP tree\n");
exit(1);
}
foreach my $oid (@oids) {
# Make sure we have not hit the end of the MIB.
if ($session->var_bind_types()->{$oid} == ENDOFMIBVIEW) {
$oid =~ s/.*\.//g;
push(@indexes, $oid);
last GET_BULK;
}
if (substr($oid, 0, length($graphs->{$mode}->{'list'})) ne $graphs->{$mode}->{'list'}) {
last GET_BULK;
}
$last_oid = $oid;
$oid =~ s/.*\.//g;
push(@indexes, $oid);
}
@args = (-maxrepetitions => 2, -varbindlist => [ $last_oid ]);
}
if (defined($graphs->{$mode}->{'thatype'})) { # Analogue sensor requested
if ($graphs->{$mode}->{'thatype'} == 2) { # Temperature-Sensor
if (defined($response = $session->get_request(".1.3.6.1.4.1.3711.24.1.1.1.2.1"))) {
my $tempscale = $response->{".1.3.6.1.4.1.3711.24.1.1.1.2.1"} eq '2';
if ($tempscale == 2) { $graphs->{$mode}->{'unit'} = 'degF'; }
if ($tempscale == 3) { $graphs->{$mode}->{'unit'} = 'K'; }
}
}
}
# Now this is a little cheating: We "calculate" various other start OIDs from
# the list OID.
my $nameoid = my $stateoid = my $valueoid = $graphs->{$mode}->{'list'};
# The start OID for names just ends with .3 instead of .1
$nameoid =~ s/1$/3/;
# the one for input status ends with .2 instead of .1
$stateoid =~ s/1$/2/;
# the start OID for the value ends with .7 instead of .1
$valueoid =~ s/1$/7/;
# Now check which of the inputs we detected are valid
my @validindexes = ( );
foreach my $i (@indexes) {
unless (defined($response = $session->get_request($stateoid . "." . $i))) {
next;
}
if ($response->{$stateoid . "." . $i} ne '1') { # 1 means active and valid.
next;
}
if (defined($graphs->{$mode}->{'thatype'})) { # Analogue sensor requested
my $typeoid = $graphs->{$mode}->{'list'};
$typeoid =~ s/1$/6/;
unless (defined($response = $session->get_request($typeoid . "." . $i))) {
next;
}
if ($response->{$typeoid . "." . $i} ne $graphs->{$mode}->{'thatype'}) {
next; # Not the correct type (humidity vs. temperature)
}
}
push(@validindexes, $i);
}
if ($ARGV[0] and $ARGV[0] eq "config") {
print("host_name $host\n");
printf("graph_title %s\n", $graphs->{$mode}->{'title'});
# print "graph_args --base 1000\n";
print("graph_category sensors\n");
printf("graph_vlabel %s\n", $graphs->{$mode}->{'unit'});
unless (defined($graphs->{$mode}->{'thatype'})) {
print("graph_info For contact sensors, the values mean: 1 = open, 2 = closed, 3 = armed, 4 = triggered\n");
}
foreach my $i (@validindexes) {
if (defined($response = $session->get_request($nameoid . "." . $i))) {
printf("%s%u.label %s\n", $mode, $i, $response->{$nameoid . "." . $i});
} else {
printf("%s%u.label Port %u\n", $mode, $i, $i);
}
if (defined($response = $session->get_request($graphs->{$mode}->{'list'} . "." . $i))) {
printf("%s%u.info Port %s\n", $mode, $i, $response->{$graphs->{$mode}->{'list'} . "." . $i});
}
printf("%s%u.type GAUGE\n", $mode, $i);
if (defined($ENV{"${mode}${i}.warning"})) { printf("%s%s.warning %s\n", $mode, $i, $ENV{"${mode}${i}.warning"}); }
if (defined($ENV{"${mode}${i}.critical"})) { printf("%s%s.critical %s\n", $mode, $i, $ENV{"${mode}${i}.critical"}); }
}
exit(0);
}
foreach my $i (@validindexes) {
if (defined($response = $session->get_request($valueoid . "." . $i))) {
my $v = $response->{$valueoid . "." . $i};
if (defined($graphs->{$mode}->{'scale'})) {
$v = $v * $graphs->{$mode}->{'scale'};
printf("%s%u.value %.1f\n", $mode, $i, $v);
} else {
printf("%s%u.value %u\n", $mode, $i, $v);
}
} else {
printf("%s%u.value U\n", $mode, $i);
}
}