#!/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 => "sensors", 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, B, B, B- munin plugin for APC UPS =head1 SYNOPSIS B [ I|I ] B [ I|I ] B [ I|I ] B [ I|I ] =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 git clone git://github.com/hirose31/munin-apcupsd.git patches and collaborators are welcome. =head1 SEE ALSO L L, L =head1 AUTHOR HIROSE, Masaaki Ehirose31 _at_ gmail.comE =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 :