diff options
-rw-r--r-- | files/munin/apc_nis | 122 | ||||
-rw-r--r-- | files/munin/apcupsd_pct | 259 | ||||
-rw-r--r-- | files/munin/apcupsd_ww | 352 | ||||
-rw-r--r-- | manifests/init.pp | 3 | ||||
-rw-r--r-- | manifests/munin.pp | 20 | ||||
-rw-r--r-- | templates/apcupsd.conf.erb | 6 |
6 files changed, 759 insertions, 3 deletions
diff --git a/files/munin/apc_nis b/files/munin/apc_nis new file mode 100644 index 0000000..0bfcfaa --- /dev/null +++ b/files/munin/apc_nis @@ -0,0 +1,122 @@ +#!/usr/bin/perl -w +# -*- perl -*- + +=head1 NAME + +apc_nis - Plugin to monitor APC UPS via the nis port of apcupsd + +=head1 CONFIGURATION + +The following configuration parameters are used by this plugin + + [apc_nis] + env.host - hostname to connect to + env.port - port number to connect to + +=head2 DEFAULT CONFIGURATION + + [apc_nis] + env.host 127.0.0.1 + env.port 3551 + +=head1 MAGIC MARKERS + + #%# family=contrib + #%# capabilities=autoconf + +=cut + +use IO::Socket; +use strict; + +if($ARGV[0] and $ARGV[0] eq "autoconf") { + print "yes\n"; + exit 0; +} + +my $host = exists $ENV{'host'} ? $ENV{'host'} : "127.0.0.1"; +my $port = exists $ENV{'port'} ? $ENV{'port'} : "3551"; + +my $sock = new IO::Socket::INET ( + PeerAddr => $host, + PeerPort => $port, + Proto => 'tcp' + ); + +die "Could not create socket: $!\n" unless $sock; + +my $buf = pack("CC", 0, 6); +print $sock $buf; +print $sock "status\n"; + +if($ARGV[0] and $ARGV[0] eq "config") { + # Test for some capabilities. + my $has_temperature = 0, my $line_volt_min, my $line_volt_max; + my $line; + do { + $line = <$sock>; + chomp($line); + if ($line =~ /\WITEMP /) { + $has_temperature = 1; + } elsif ($line =~ /\WLOTRANS /) { + $line =~ s/.* (\d+.\d+).*/$1/; + $line_volt_min = $line; + } elsif ($line =~ /\WHITRANS /) { + $line =~ s/.* (\d+.\d+).*/$1/; + $line_volt_max = $line; + } + } while(!($line =~ /END APC/)); + + close($sock); + + print "graph_title APC UPS measurements\n"; + print "graph_args -l 0 --base 1000\n"; + print "graph_vlabel A bit of all (Volt, time, %)\n"; + print "graph_info Values received for apcupsd available at $host:$port\n"; + print "battery_volt.label batt volt (V)\n"; + print "battery_volt.type GAUGE\n"; + print "battery_volt.max 300\n"; + print "battery_charge.label batt charge (%)\n"; + print "battery_charge.type GAUGE\n"; + print "battery_charge.max 100\n"; + print "line_volt.label line (V)\n"; + print "line_volt.type GAUGE\n"; + print "line_volt.max 300\n"; + print "line_volt.warning ${line_volt_min}:${line_volt_max}\n"; + print "load.label ups load (%)\n"; + print "load.type GAUGE\n"; + print "time_left.label time left (min)\n"; + print "time_left.type GAUGE\n"; + if ($has_temperature) { + print "temperature.label internal temperature (°C)\n"; + print "temperature.type GAUGE\n"; + } + exit 0; +} + +my $line; +do { + $line = <$sock>; + chomp($line); + if($line =~ /\WBATTV /) { + $line =~ s/.* (\d+.\d+).*/$1/; + print "battery_volt.value $line\n"; + } elsif($line =~ /\WLINEV /) { + $line =~ s/.* (\d+.\d+).*/$1/; + print "line_volt.value $line\n"; + } elsif($line =~ /\WLOADPCT /) { + $line =~ s/.* (\d+.\d+).*/$1/; + print "load.value $line\n"; + } elsif($line =~ /\WBCHARGE /) { + $line =~ s/.* (\d+.\d+).*/$1/; + print "battery_charge.value $line\n"; + } elsif($line =~ /\WTIMELEFT /) { + $line =~ s/.* (\d+.\d+).*/$1/; + print "time_left.value $line\n"; + } elsif($line =~ /\WITEMP /) { + $line =~ s/.* (\d+.\d+).*/$1/; + print "temperature.value $line\n"; + } +} while(!($line =~ /END APC/)); + +close($sock); diff --git a/files/munin/apcupsd_pct b/files/munin/apcupsd_pct new file mode 100644 index 0000000..65e34ea --- /dev/null +++ b/files/munin/apcupsd_pct @@ -0,0 +1,259 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Carp; +use Pod::Usage; + +our $APCACCESS = $ENV{apcaccess} || "/sbin/apcaccess"; +our $UPS_MODEL = $ENV{ups_model} || "ES 725"; +our $VERSION = 1.0; +my %Graph; +my %Metric; + +MAIN: { + decide_monitor_type(); + + my $mode = $ARGV[0] || "fetch"; + $mode =~ /^-/ && pod2usage(); + + ### $mode + eval "do_${mode}();" + or croak "do_${mode}: $@"; + + ### end + exit 0; +} + +=begin comment + +pct + LOADPCT is the percentage of load capacity as estimated by the UPS. + 15.0 Percent Load Capacity + BCHARGE is the percentage charge on the batteries. + 100.0 Percent + +volt + LINEV is the current line voltage as returned by the UPS. + 102.0 Volts + BATTV is the battery voltage as supplied by the UPS. + 13.5 Volts + +time + TIMELEFT is the remaining runtime left on batteries as estimated by the UPS. + 38.4 Minutes + +pwr + LOADPCT is the percentage of load capacity as estimated by the UPS. + 15.0 Percent Load Capacity + NOMPOWER + 330 Watts + LOADMETRIC=LOADPCT/100*NOMPOWER gives realtime power consumption in WATTS + +=end comment + +=cut + +sub decide_monitor_type { + my $type = $0 =~ /_pct/ ? "pct" : + $0 =~ /_volt/ ? "volt" : + $0 =~ /_time/ ? "time" : + $0 =~ /_pwr/ ? "pwr" : undef + or croak "unknown monitor type: $0"; + + # common + %Graph = ( + graph_title => "APC Status".($UPS_MODEL?" ($UPS_MODEL)":"")." - ", + graph_category => "ups", + graph_info => "This graph shows information about your APC UPS", + graph_args => "--base 1000 --lower-limit 0", + ); + + if ($type eq "pct") { + $Graph{graph_title} .= "Percentage"; + $Graph{graph_vlabel} = "%"; + %Metric =( + LOADPCT => { + label => "load capacity pct", + }, + BCHARGE => { + label => "charge on the batteries pct", + }, + ); + } elsif ($type eq "volt") { + $Graph{graph_title} .= "Voltage"; + $Graph{graph_vlabel} = "Volts"; + %Metric =( + LINEV => { + label => "line voltage as returned by the UPS", + }, + BATTV => { + label => "battery voltage as supplied by the UPS", + }, + ); + } elsif ($type eq "time") { + $Graph{graph_title} .= "Time"; + $Graph{graph_vlabel} = "minutes"; + %Metric =( + TIMELEFT => { + label => "remaining runtime left on batteries", + }, + ); + } elsif ($type eq "pwr") { + $Graph{graph_title} .= "Power"; + $Graph{graph_vlabel} = "watts"; + %Metric =( + LOADMETRIC => { + label => "absolute power consumption", + }, + ); + } +} + +sub do_fetch { + ### do_fetch + + my @status_data = retrieve_apcupsd_status() + or croak "failed: retrieve_apcupsd_status"; + ### status_data: \@status_data + + my $status = parse_status_data(@status_data); + ### status: $status + my $prod_status = proccess_status($status); + + my $FIELD; + while (my($field,$attr) = each %Metric) { + $field = lc $field; + $FIELD = uc $field; + printf "%s.value %.1f\n", $field, (exists $status->{$FIELD} ? ($status->{$FIELD} =~ /([\d]+\.?[\d]*)/) : ( exists $prod_status->{$FIELD} ? ( $prod_status->{$FIELD} =~ /([\d]+\.?[\d]*)/) : 0 ) ); + } + + return 1; +} + +sub do_config { + ### do_config + + while (my($k,$v) = each %Graph) { + printf "%s %s\n", $k, $v; + } + while (my($field,$attr) = each %Metric) { + $field = lc $field; + while (my($k,$v) = each %$attr) { + printf "%s.%s %s\n", $field, $k, $v; + } + } + + return 1; +} + +sub do_autoconf { + ### do_config + print "yes\n"; +} + +sub retrieve_apcupsd_status { + open my $apc, '-|', $APCACCESS + or croak $!; + my @status_data = <$apc>; + close $apc; + chomp @status_data; + return @status_data; +} + +sub proccess_status { + my $prod = {}; + my($status) = @_; + + if (exists $status->{NOMPOWER} && exists $status->{LOADPCT}) { + my $pwr_pct = sprintf "%.1f", ($status->{LOADPCT} =~ /([\d]+\.?[\d]*)/) ; + my $nom_pwr = sprintf "%.1f", ($status->{NOMPOWER} =~ /([\d]+\.?[\d]*)/) ; + $prod->{LOADMETRIC} = $pwr_pct/100 * $nom_pwr ; + } + + return $prod; +} + +sub parse_status_data { + my $status = {}; + my($k,$v); + for (@_) { + ($k,$v) = split /\s*:\s*/, $_, 2; + $status->{$k} = $v; + } + return $status; +} + + +__END__ + +=head1 NAME + +B<apcupsd_pct>, B<apcupsd_volt>, B<apcupsd_time>, B<apcupsd_pwr>- munin plugin for APC UPS + +=head1 SYNOPSIS + +B<apcupsd_pct> [ I<config>|I<fetch> ] + +B<apcupsd_volt> [ I<config>|I<fetch> ] + +B<apcupsd_time> [ I<config>|I<fetch> ] + +B<apcupsd_pwr> [ I<config>|I<fetch> ] + +=head1 DESCRIPTION + +munin plugin to monitor APC UPS via apcupsd by apcaccess. + +=head1 INSTALLATION + + cp apcupsd_pct $MUNIN_LIBDIR/plugsin/ + + cd YOUR_MUNIN_PLUGINS_DIR + (make symbolic links different name) + ln -s $MUNIN_LIBDIR/plugsin/apcupsd_pct apcupsd_pct + ln -s $MUNIN_LIBDIR/plugsin/apcupsd_pct apcupsd_volt + ln -s $MUNIN_LIBDIR/plugsin/apcupsd_pct apcupsd_time + ln -s $MUNIN_LIBDIR/plugsin/apcupsd_pwr apcupsd_pwr + + restart munin-node + +=head1 REPOSITORY + +L<http://github.com/hirose31/munin-apcupsd> + + git clone git://github.com/hirose31/munin-apcupsd.git + +patches and collaborators are welcome. + +=head1 SEE ALSO + +L<http://exchange.munin-monitoring.org/plugins/apcupsd_pct/details> + +L<http://munin.projects.linpro.no/wiki/HowToWritePlugins>, +L<http://munin.projects.linpro.no/wiki/protocol-config> + +=head1 AUTHOR + +HIROSE, Masaaki E<lt>hirose31 _at_ gmail.comE<gt> + +=head1 CHANGELOG + + * 10/11/2010 - basos - added support for absolute power display + +=head1 COPYRIGHT & LICENSE + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=cut + +# for Emacsen +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# indent-tabs-mode: nil +# coding: utf-8 +# End: + +# vi: set ts=4 sw=4 sts=0 : 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 diff --git a/manifests/init.pp b/manifests/init.pp index 9c963f6..06c0d02 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -22,6 +22,9 @@ class apcupsd( $device = '/dev/ttyS0', $ensure = 'present', $nisip = '127.0.0.1', + $onbatterydelay = '6', + $batterylevel = '5', + $minutes = '3') $admin = 'root', $mail = 'mail', $polltime = '60' ) diff --git a/manifests/munin.pp b/manifests/munin.pp new file mode 100644 index 0000000..46b75bd --- /dev/null +++ b/manifests/munin.pp @@ -0,0 +1,20 @@ +class apcupsd::munin( + $ensure = present +) { + munin::plugin::deploy { 'apc_nis': + source => "apcupsd/munin/apc_nis", + ensure => $ensure, + } + + # From http://munin-monitoring.org/browser/munin-contrib/plugins/ups/apcupsd_ww + munin::plugin::deploy { 'apcupsd_ww': + source => "apcupsd/munin/apcupsd_ww", + ensure => absent, + } + + # From https://raw.githubusercontent.com/munin-monitoring/contrib/master/plugins/ups/apcupsd_pct + #munin::plugin::deploy { 'apcupsd_pct': + # source => "apcupsd/munin/apcupsd_pct", + # ensure => $ensure, + #} +} diff --git a/templates/apcupsd.conf.erb b/templates/apcupsd.conf.erb index 03a9c08..6f96775 100644 --- a/templates/apcupsd.conf.erb +++ b/templates/apcupsd.conf.erb @@ -118,7 +118,7 @@ NOLOGINDIR /etc # ONBATTERYDELAY time. If you don't want to be annoyed by short # powerfailures, make sure that apccontrol powerout does nothing # i.e. comment out the wall. -ONBATTERYDELAY 6 +ONBATTERYDELAY <%= onbatterydelay %> # # Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so @@ -128,12 +128,12 @@ ONBATTERYDELAY 6 # If during a power failure, the remaining battery percentage # (as reported by the UPS) is below or equal to BATTERYLEVEL, # apcupsd will initiate a system shutdown. -BATTERYLEVEL 5 +BATTERYLEVEL <%= batterylevel %> # If during a power failure, the remaining runtime in minutes # (as calculated internally by the UPS) is below or equal to MINUTES, # apcupsd, will initiate a system shutdown. -MINUTES 3 +MINUTES <%= minutes %> # If during a power failure, the UPS has run on batteries for TIMEOUT # many seconds or longer, apcupsd will initiate a system shutdown. |