mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 10:39:53 +00:00
Even though "licenced" is proper (British English) spelling, "spellcheck" complains about it (probably being focused on American English). The change should just clean up the output of the spelling linter and should not be interpreted as a language preference. Sorry, (British) folks!
342 lines
8.8 KiB
Perl
Executable file
342 lines
8.8 KiB
Perl
Executable file
#!/usr/bin/perl -w
|
|
#
|
|
# Plugin to monitor apcupsd via apcaccess
|
|
#
|
|
# Version 1.3
|
|
#
|
|
# Copyright (C) 2005-2008 Behan Webster <behanw AT websterwood DOT com>
|
|
# Licensed under GPL 2.0
|
|
#
|
|
# Written by: Behan Webster <behanw AT websterwood DOT com>
|
|
# German translation by: Bianco Veigel <bianco.veigel AT zivillian DOT de>
|
|
#
|
|
#%# family=auto
|
|
#%# capabilities=autoconf
|
|
|
|
use strict;
|
|
use warnings;
|
|
use vars qw(%attrs %data %num);
|
|
|
|
my $apcaccess='/sbin/apcaccess';
|
|
#$apcaccess='/home/behanw/bin/apcaccess';
|
|
my $config='/etc/munin/plugin-conf.d/apcupsd_ww';
|
|
|
|
my $language = $ENV{LANG} || 'en';
|
|
|
|
# Example apcaccess output
|
|
# KEY : VALUE
|
|
#
|
|
# UPSNAME : Elfhild
|
|
# MODEL : SMART-UPS 1400 RM XL
|
|
# STATUS : ONLINE
|
|
# LINEV : 123.5 Volts
|
|
# LOADPCT : 24.9 Percent Load Capacity
|
|
# BCHARGE : 100.0 Percent
|
|
# TIMELEFT : 63.0 Minutes
|
|
# OUTPUTV : 123.5 Volts
|
|
# ITEMP : 39.1 C Internal
|
|
# BATTV : 54.5 Volts
|
|
# NOMOUTV : 115 Volts
|
|
# NOMBATTV : 48.0 Volts
|
|
|
|
# Possible values to graph in munin
|
|
# Only the ones which are available will be graphed
|
|
%attrs = (
|
|
# APCACCESS_KEY => {
|
|
# name => 'attribute_name',
|
|
# label => {
|
|
# en => 'English title',
|
|
# de => 'Titel in Deutsch',
|
|
# fr => 'titre en Francais',
|
|
# },
|
|
# type => 'name_of_functio_for_type', # Default is 'num'
|
|
# # Can use one value, or list of values. If the first value can't be used, try the next.
|
|
# # KEY Key from apcaccess
|
|
# # num,num,num Specify a list of possible nominal values to guess from
|
|
# # num Specify fixed nominal value
|
|
# nominal => [ 'KEY', '100' ],
|
|
# # KEY Key from apcaccess
|
|
# # +-num% Calculate percentage min:max from nominal value
|
|
# # +-num Calculate min:max from nominal value
|
|
# # -num:+num Calculate min:max from nominal value
|
|
# # num:num Specify fixed min:max values
|
|
# # num or :num Specify fixed max value
|
|
# # num: Specify fixed min value
|
|
# warning => [ 'KEY:KEY', '+-10%', '-10:+15' ],
|
|
# critical => [ 'KEY:KEY', '+-10%', '-10:+15' ],
|
|
# },
|
|
BCHARGE => { # BCHARGE : 100.0 Percent
|
|
name => 'battery',
|
|
label => {
|
|
en => 'Percent battery charge',
|
|
de => 'Batterieladung in Prozent',
|
|
},
|
|
warning => '33:', # %
|
|
critical => '5:', # %
|
|
},
|
|
LOADPCT => { # LOADPCT : 28.6 Percent Load Capacity
|
|
name => 'upsload',
|
|
label => {
|
|
en => 'Percent load capacity',
|
|
de => 'Auslastung in Prozent',
|
|
},
|
|
warning => '75', # %
|
|
critical => '90', # %
|
|
},
|
|
TIMELEFT => { # TIMELEFT : 17.0 Minutes
|
|
name => 'timeleft',
|
|
label => {
|
|
en => 'Minutes of run time',
|
|
de => 'Akkulaufzeit in Minuten',
|
|
},
|
|
warning => '5:', # mins
|
|
critical => [ 'DLOWBATT:', '2:' ], # DLOWBATT : 02 Minutes
|
|
},
|
|
LINEV => { # LINEV : 121.5 Volts
|
|
name => 'linevolts',
|
|
label => {
|
|
en => 'Line voltage',
|
|
de => 'Eingangsspannung',
|
|
},
|
|
nominal => [ 'NOMINV', 'NOMOUTV', '115,230' ], # NA=115V, Europe=230V
|
|
warning => [ '+-10%', '108:128' ],
|
|
critical => [ 'LOTRANS:HITRANS', '+-15%', '104:132' ],
|
|
},
|
|
BATTV => { # BATTV : 27.7 Volts
|
|
name => 'batteryvolts',
|
|
label => {
|
|
en => 'Battery voltage',
|
|
de => 'Batteriespannung',
|
|
},
|
|
nominal => [ 'NOMBATTV', '12,24,48' ], # NOMBATTV : 48.0 Volts
|
|
warning => '-5%:+15%',
|
|
critical => '-10%:+25%',
|
|
},
|
|
OUTPUTV => { # OUTPUTV : 122.2 Volts
|
|
name => 'outputvolts',
|
|
label => {
|
|
en => 'Output voltage',
|
|
de => 'Ausgangsspannung',
|
|
},
|
|
nominal => [ 'NOMOUTV', '115,230' ], # NOMOUTV : 115 Volts
|
|
warning => [ '+-10%', '108:128' ],
|
|
critical => [ 'LOTRANS:HITRANS', '+-15%', '104:132' ],
|
|
},
|
|
ITEMP => { # ITEMP : 44.1 C Internal
|
|
name => 'temperature',
|
|
label => {
|
|
en => 'UPS temperature',
|
|
de => 'USV Temperatur',
|
|
},
|
|
warning => 50, # C
|
|
critical => 60, # C
|
|
},
|
|
LINEFAIL => { # LINEFAIL : OK
|
|
name => 'linefail',
|
|
label => {
|
|
en => 'Line voltage status',
|
|
de => 'Status Eingangsspannung',
|
|
},
|
|
type => 'bool',
|
|
critical => '0:', # Failed
|
|
},
|
|
BATTSTAT => { # BATTSTAT : OK
|
|
name => 'battstat',
|
|
label => {
|
|
en => 'Battery status',
|
|
de => 'Batteriestatus',
|
|
},
|
|
type => 'bool',
|
|
critical => '0:', # Failed
|
|
},
|
|
MAINS => { # MAINS : OK
|
|
name => 'mains',
|
|
label => {
|
|
en => 'Mains status',
|
|
de => 'Status Eingangsspannung',
|
|
},
|
|
type => 'bool',
|
|
critical => '0:', # Failed
|
|
},
|
|
#STATUS => { # STATUS : ONLINE
|
|
# name => 'status',
|
|
# label => {
|
|
# en => 'Status',
|
|
# },
|
|
# type => 'status',
|
|
# critical => 0,
|
|
#},
|
|
);
|
|
|
|
# Read config file
|
|
# Can be used to override settings in %attrs
|
|
if (-f $config) {
|
|
require $config;
|
|
}
|
|
|
|
# Determine plugin capabilities
|
|
if (defined $ARGV[0] && $ARGV[0] =~ /autoconf|detect/) {
|
|
if (-x $apcaccess) {
|
|
print "yes\n";
|
|
} else {
|
|
print "no (apcaccess not found)\n";
|
|
}
|
|
exit 0;
|
|
}
|
|
|
|
# Read info from apcupsd using apcaccess
|
|
die "$apcaccess: not found\n" unless -x $apcaccess;
|
|
open (APCACCESS, "$apcaccess 2>&1 |") || die "$apcaccess: $!\n";
|
|
while (<APCACCESS>) {
|
|
chomp;
|
|
die "$apcaccess: $_\n" if /Error contacting apcupsd/;
|
|
$data{$1} = $2 if /^(\S+?)\s*:\s+(.+?)$/;
|
|
$num{$1} = $2 if /^(\S+?)\s*:\s+([\d.x]+)/;
|
|
}
|
|
close APCACCESS;
|
|
|
|
# Auto-configure plugin
|
|
if (defined $ARGV[0] && $ARGV[0] eq 'config') {
|
|
if (defined $data{UPSNAME}) {
|
|
print "graph_title $data{UPSNAME} ($data{MODEL})\n";
|
|
} else {
|
|
print "graph_title $data{MODEL}\n";
|
|
}
|
|
#print "graph_vlabel Units\n";
|
|
print "graph_category sensors\n";
|
|
print "graph_info This graph shows information about your APC uninterruptible power supply.\n";
|
|
|
|
foreach my $what (sort keys %attrs) {
|
|
&label("$what");
|
|
}
|
|
|
|
# Print current values
|
|
} else {
|
|
foreach my $what (sort keys %attrs) {
|
|
next unless defined $data{$what};
|
|
my $func = $attrs{$what}{type} || 'num';
|
|
my $value = eval "\&$func('$what')";
|
|
print "$attrs{$what}{name}.value $value\n";
|
|
}
|
|
}
|
|
|
|
exit 0;
|
|
|
|
##############################################################################
|
|
# Print label/title for value
|
|
sub label {
|
|
my $what = shift;
|
|
return unless defined $data{$what};
|
|
|
|
my $attr = $attrs{$what};
|
|
|
|
# Determine language to use for labels
|
|
my $lang = $language;
|
|
$lang =~ s/_.*$// unless defined $attr->{label}{$lang};
|
|
# Failback to english if translation isn't available
|
|
$lang = 'en' unless defined $attr->{label}{$lang};
|
|
|
|
print "$attr->{name}.label $attr->{label}{$lang}\n";
|
|
&info($what, 'warning');
|
|
&info($what, 'critical');
|
|
}
|
|
|
|
##############################################################################
|
|
# Makes a scalar or array into an array (used in &info)
|
|
sub list {
|
|
return (ref($_[0]) eq 'ARRAY') ? @{$_[0]} : @_;
|
|
}
|
|
|
|
##############################################################################
|
|
# Used to setup warning or critical levels for munin
|
|
sub info {
|
|
my $what = shift;
|
|
my $level = shift; # 'warning' or 'critical'
|
|
|
|
my $attr = $attrs{$what};
|
|
return unless defined $attr->{$level};
|
|
|
|
# Determine nominal value for info calculation
|
|
my $nom = undef;
|
|
if (defined $attr->{nominal}) {
|
|
for my $n (&list($attr->{nominal})) {
|
|
# Guess list: compare guesses to value of $num{$what}
|
|
if ($n =~ /,/) {
|
|
my $fitness = ~0;
|
|
next unless $num{$what};
|
|
foreach my $possibility (split /[,\s]+/, $n) {
|
|
my $diff = abs($num{$what} - $possibility);
|
|
($nom, $fitness) = ($possibility, $diff) if $fitness >= $diff;
|
|
}
|
|
|
|
# Absolute nominal value
|
|
} elsif ($n =~ /^[\d.]+$/) {
|
|
$nom = $n;
|
|
last;
|
|
|
|
# Lookup nominal value as an APCUPSD key
|
|
} elsif (defined $num{$n}) {
|
|
$nom = $num{$n};
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
|
|
# Calculate info value for $level
|
|
foreach my $value (&list($attr->{$level})) {
|
|
$value =~ s/([^:]+)/&calc($1,$nom)/eg;
|
|
if ($value =~ /^[\d.:]+$/) {
|
|
print "$attr->{name}.$level $value\n";
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
##############################################################################
|
|
# Change warning/critical ranges into numbers for munin
|
|
sub calc {
|
|
my $v = shift;
|
|
my $nom = shift;
|
|
|
|
return $v if $v =~ /^[\d.]+$/;
|
|
return $num{$v} if defined $num{$v};
|
|
return '' unless defined $nom;
|
|
if ($v =~ /^\+-([\d.]+)%$/) {
|
|
return sprintf "%.0f:%.0f", (100 - $1) * $nom / 100, (100 + $1) * $nom / 100;
|
|
} elsif ($v =~ /^([-+][\d.]+)%$/) {
|
|
return sprintf "%.0f", (100 + $1) * $nom / 100;
|
|
} elsif ($v =~ /^\+-([\d.]+)$/) {
|
|
return sprintf "%d:%d", $nom - $1, $nom + $1;
|
|
} elsif ($v =~ /^([-+][\d.]+)$/) {
|
|
return $nom + $1;
|
|
} elsif ($v =~ /^\*([\d.]+)$/) {
|
|
return $nom * $1;
|
|
} elsif ($v =~ /^\/([\d.]+)$/) {
|
|
return sprintf "%.0f", $nom / $1;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
##############################################################################
|
|
# Default "type" routine to display values
|
|
sub num {
|
|
my $what = shift;
|
|
return $num{$what};
|
|
}
|
|
|
|
##############################################################################
|
|
# "type" routine to change Ok/Not Ok into 1/0
|
|
sub bool {
|
|
my $what = shift;
|
|
return $num{$what} eq "OK" ? "1" : "0";
|
|
}
|
|
|
|
#sub status {
|
|
# my $what = shift;
|
|
# return unless defined $data{$what};
|
|
# print "$attrs{$what}{name}.value ";
|
|
# print $num{$what} eq "ONLINE" ? "1" : "0";
|
|
# print "\n";
|
|
#}
|
|
|
|
# vim: sw=4 ts=4
|