summaryrefslogtreecommitdiff
path: root/files/munin/apcupsd_ww
diff options
context:
space:
mode:
Diffstat (limited to 'files/munin/apcupsd_ww')
-rw-r--r--files/munin/apcupsd_ww352
1 files changed, 352 insertions, 0 deletions
diff --git a/files/munin/apcupsd_ww b/files/munin/apcupsd_ww
new file mode 100644
index 0000000..9a6d024
--- /dev/null
+++ b/files/munin/apcupsd_ww
@@ -0,0 +1,352 @@
+#!/usr/bin/perl -w
+#
+# Plugin to monitor apcupsd via apcaccess
+#
+# Version 1.3
+#
+# Copyright (C) 2005-2008 Behan Webster <behanw AT websterwood DOT com>
+# Licenced 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' ],
+ },
+ #NOMPOWER => { # NOMPOWER
+ # name => 'outputwatts',
+ # label => {
+ # en => 'Nominal power output in Watts',
+ # },
+ # nominal => [ 'NOMPOWER', '0,1500' ],
+ # warning => 1200,
+ # critical => 1300,
+ #},
+ 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";
+ exit 0;
+ } else {
+ print "no (apcaccess not found)\n";
+ exit 1;
+ }
+}
+
+# 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 ups\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