diff --git a/plugins/snmp/snmp__ups_ b/plugins/snmp/snmp__ups_ index 0d69b600..a3f0882b 100755 --- a/plugins/snmp/snmp__ups_ +++ b/plugins/snmp/snmp__ups_ @@ -1,7 +1,11 @@ #!/usr/bin/perl -w # -# Jean-Samuel Reynaud -# base on snmp__if_ from Jimmy Olsen, Dagfinn Ilmari Mannsaaker +# 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 Mannsaaker # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -19,17 +23,19 @@ # # # Usage: -# ln -s /usr/share/munin/node/plugins-auto/snmp__ups2_ /etc/munin/node.d/snmp_ups.address.loc_mode -# with mode : batteryVoltage, batteryTemperature,inputVoltage,inputCurrent,inputFrequency,outputVoltage,outputCurrent,outputPower,outputPercentLoad,ChargeRemaining +# 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 -# This plugin is for UPSes that supports the UPS-MIB -# - Not APC (apparently) - - use strict; use Net::SNMP; @@ -38,7 +44,7 @@ my $DEBUG = 0; my $host = $ENV{host} || undef; my $port = $ENV{port} || 161; my $community = $ENV{community} || "public"; -my $mode = $ENV{mode} || undef; +my $mode = $ENV{mode} || undef; my $response; @@ -48,121 +54,164 @@ if (defined $ARGV[0] and $ARGV[0] eq "snmpconf") exit 0; } - if ($0 =~ /^(?:|.*\/)snmp_([^_]+)_ups_(.+)$/) { - $host = $1; - $mode = $2; - if ($host =~ /^([^:]+):(\d+)$/) - { - $host = $1; - $port = $2; - } + $host = $1; + $mode = $2; + if ($host =~ /^([^:]+):(\d+)$/) { + $host = $1; + $port = $2; + } } elsif (!defined($host)) { - print "# Debug: $0 -- $1 -- $2\n" if $DEBUG; - die "# Error: couldn't understand what I'm supposed to monitor."; + 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 = { - 'batteryVoltage' => { 'title' => 'Battery Voltage', - 'category' => 'network', - 'unit' => 'Volt', - 'value' => '.1.3.6.1.2.1.33.1.2.5'}, - 'batteryTemperature' => { 'title' => 'Battery Temperature', - 'category' => 'network', - 'unit' => 'DegC', - 'value' => '.1.3.6.1.2.1.33.1.2.7'}, - 'inputVoltage' => { 'title' => 'Input Voltage', - 'category' => 'network', - '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', - 'category' => 'network', - '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.4'}, - 'inputFrequency' => { 'title' => 'Input Frequency', - 'category' => 'network', - 'list' => '.1.3.6.1.2.1.33.1.3.2', - 'unit' => 'Hz', - 'value' => '.1.3.6.1.2.1.33.1.3.3.1.2'}, - - 'outputVoltage' => { 'title' => 'Output Voltage', - 'category' => 'network', - 'list' => '.1.3.6.1.2.1.33.1.4.3', - 'unit' => 'Hz', - 'value' => '.1.3.6.1.2.1.33.1.4.4.1.2'}, - 'outputCurrent' => { 'title' => 'Output Current', - 'category' => 'network', - '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', - 'category' => 'network', - 'list' => '.1.3.6.1.2.1.33.1.4.3', - 'unit' => 'Hz', - 'value' => '.1.3.6.1.2.1.33.1.4.4.1.4'}, - - 'outputPercentLoad' => { 'title' => 'Output PercentLoad', - 'category' => 'network', - 'list' => '.1.3.6.1.2.1.33.1.4.3', - 'unit' => '%', - 'value' => '.1.3.6.1.2.1.33.1.4.4.1.5'}, - - 'ChargeRemaining' => { 'title' => 'Charge remaining', - 'unit' => 'Seconds', - 'category' => 'network', - 'value' => '.1.3.6.1.2.1.33.1.2.4'} + '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 - ); + -hostname => $host, + -community => $community, + -port => $port, + -timeout => 1.0 +); -if (!defined ($session)) -{ - die "Croaking: $error"; +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'} && - defined ($response = $session->get_request($graphs->{$mode}->{'list'} . ".0"))) { - $count_data = $response->{$graphs->{$mode}->{'list'} . ".0"}; - -} - -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"; - - - for(my $i=0;$i<$count_data;$i++) { - printf "line%u.label Line %u\n",$i+1,$i+1; - printf "line%u.type GAUGE\n",$i+1; - printf "line%u.info %s\n",$i+1,$graphs->{$mode}->{'unit'}; +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'}); + } } - exit 0; } -for(my $i=0;$i<$count_data;$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'}); + + 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)))) { - printf "line%u.value %u\n",$i+1,$response->{$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 "line%u.value U\n",$i+1; + printf("%s%u.value U\n", $mode, $i+1); } - }