#!/usr/bin/perl -w # # This plugin is for querying UPSes that support the UPS-MIB from RFC 1628 # - NOT APC (apparently) # # current version by Michael Meier # previous version by Jean-Samuel Reynaud # based on snmp__if_ from Jimmy Olsen, Dagfinn Ilmari Mannsåker # # 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__ups_ /etc/munin/node.d/snmp_ups.domain.tld_ups_mode # available modes: # batteryruntime, batteryremaining, batterypercent, batteryvoltage, # batterycurrent, batterytemperature, # inputfrequency, inputvoltage, inputcurrent, inputpower, # outputvoltage, outputcurrent, outputpower, outputpercentload, # inputlinebads # Most UPSs only support a small subset of these modes. # #%# 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; if (defined $ARGV[0] and $ARGV[0] eq "snmpconf") { print "require .1.3.6.1.2.1.33.1.2.7 [0-9]\n"; # Bat temp exit 0; } if ($0 =~ /^(?:|.*\/)snmp_([^_]+)_ups_(.+)$/) { $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_ups_MODE\n"); print("# or alternatively set the environment variables 'host' and 'mode'\n"); exit(1); } my $graphs = { 'batteryruntime' => { 'title' => 'Seconds running on battery', 'unit' => 'seconds', 'label' => 'onbatteryfor', 'value' => '.1.3.6.1.2.1.33.1.2.2' }, 'batteryremaining' => { 'title' => 'Estimated remaining runtime on battery', 'unit' => 'minutes', 'label' => 'remaining', 'value' => '.1.3.6.1.2.1.33.1.2.3' }, 'batterypercent' => { 'title' => 'Estimated remaining charge', 'unit' => '%', 'label' => 'remaining', 'value' => '.1.3.6.1.2.1.33.1.2.4' }, 'batteryvoltage' => { 'title' => 'Battery Voltage', 'unit' => 'Volt', 'scale' => 0.1, 'value' => '.1.3.6.1.2.1.33.1.2.5' }, 'batterycurrent' => { 'title' => 'Battery current', 'unit' => 'Ampere', 'scale' => 0.1, 'value' => '.1.3.6.1.2.1.33.1.2.6' }, 'batterytemperature' => { 'title' => 'Battery Temperature', 'unit' => 'degC', 'label' => 'Temperature %u', 'value' => '.1.3.6.1.2.1.33.1.2.7' }, 'inputfrequency' => { 'title' => 'Input Frequency', 'scale' => 0.1, 'unit' => 'Hz', 'list' => '.1.3.6.1.2.1.33.1.3.2', 'value' => '.1.3.6.1.2.1.33.1.3.3.1.2' }, 'inputvoltage' => { 'title' => 'Input Voltage', 'unit' => 'Volt', 'list' => '.1.3.6.1.2.1.33.1.3.2', 'value' => '.1.3.6.1.2.1.33.1.3.3.1.3' }, 'inputcurrent' => { 'title' => 'Input Current', 'unit' => 'Ampere', 'scale' => 0.1, 'list' => '.1.3.6.1.2.1.33.1.3.2', 'value' => '.1.3.6.1.2.1.33.1.3.3.1.4' }, 'inputpower' => { 'title' => 'Input Power', 'unit' => 'Watt', 'list' => '.1.3.6.1.2.1.33.1.3.2', 'value' => '.1.3.6.1.2.1.33.1.3.3.1.5' }, 'outputvoltage' => { 'title' => 'Output Voltage', 'list' => '.1.3.6.1.2.1.33.1.4.3', 'unit' => 'Volt', 'value' => '.1.3.6.1.2.1.33.1.4.4.1.2' }, 'outputcurrent' => { 'title' => 'Output Current', 'unit' => 'Ampere', 'scale' => 0.1, 'list' => '.1.3.6.1.2.1.33.1.4.3', 'value' => '.1.3.6.1.2.1.33.1.4.4.1.3' }, 'outputpower' => { 'title' => 'Output Power', 'unit' => 'Watt', 'list' => '.1.3.6.1.2.1.33.1.4.3', 'value' => '.1.3.6.1.2.1.33.1.4.4.1.4' }, 'outputpercentload' => { 'title' => 'Output Load', 'unit' => '%', 'list' => '.1.3.6.1.2.1.33.1.4.3', 'value' => '.1.3.6.1.2.1.33.1.4.4.1.5' }, 'inputlinebads' => { 'title' => 'Number of times input power went bad', 'unit' => 'n', 'value' => '.1.3.6.1.2.1.33.1.3.1' } }; my ($session, $error) = Net::SNMP->session( -hostname => $host, -community => $community, -port => $port, -timeout => 1.0 ); if (!defined($session)) { print("# Failed to open SNMP session: $error\n"); 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); } my $count_data = 1; if (defined $graphs->{$mode}->{'list'}) { if (defined ($response = $session->get_request($graphs->{$mode}->{'list'} . ".0"))) { $count_data = $response->{$graphs->{$mode}->{'list'} . ".0"}; } else { # Unfortunately, some UPSs do not properly implement RFC 1628: # They fail to report the number of lines. # We will default to 3 as that will work in most cases. # The environment variable 'numlines' can be used to override the default. $count_data = 3; if (defined($ENV{'numlines'})) { $count_data = int($ENV{'numlines'}); } } } 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'}); for (my $i=0; $i < $count_data; $i++) { my $ip1 = $i + 1; if (defined($graphs->{$mode}->{'label'})) { printf("%s%u.label %s\n", $mode, $ip1, sprintf($graphs->{$mode}->{'label'}, $ip1)); } else { printf("%s%u.label Line %u\n", $mode, $ip1, $ip1); } printf("%s%u.type GAUGE\n", $mode, $ip1); #printf "line%u.info %s\n",$i+1,$graphs->{$mode}->{'unit'}; if (defined($ENV{"${mode}${ip1}.warning"})) { printf("%s%s.warning %s\n", $mode, $ip1, $ENV{"${mode}${ip1}.warning"}); } if (defined($ENV{"${mode}${ip1}.critical"})) { printf("%s%s.critical %s\n", $mode, $ip1, $ENV{"${mode}${ip1}.critical"}); } } exit(0); } for (my $i = 0; $i < $count_data; $i++) { my $l_current = $i+1; if ($count_data == 1) { $l_current = 0; } if (defined ($response = $session->get_request($graphs->{$mode}->{'value'} . sprintf(".%u",$l_current)))) { my $v = $response->{$graphs->{$mode}->{'value'} . sprintf(".%u",$l_current)}; if (defined($graphs->{$mode}->{'scale'})) { $v = $v * $graphs->{$mode}->{'scale'}; printf("%s%u.value %.1f\n", $mode, $i+1, $v); } else { printf("%s%u.value %u\n", $mode, $i+1, $v); } } else { printf("%s%u.value U\n", $mode, $i+1); } }