From 32cd3f6045e5e80d467f53496c2635c667a023bd Mon Sep 17 00:00:00 2001 From: "pru.mike" Date: Fri, 10 Feb 2017 22:12:57 +0300 Subject: [PATCH 1/3] Added plugin for Powercom UPSMON PRO software --- plugins/sensors/upsmonpro_ | 207 +++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 plugins/sensors/upsmonpro_ diff --git a/plugins/sensors/upsmonpro_ b/plugins/sensors/upsmonpro_ new file mode 100644 index 00000000..cdb3083a --- /dev/null +++ b/plugins/sensors/upsmonpro_ @@ -0,0 +1,207 @@ +#!/usr/bin/perl + +=head1 NAME + +upsmonpro_ - Munin plugin to monitor Powercom UPS via UPSMON PRO program L + +=head1 INSTALLATION + + /etc/munin/plugins/upsmonpro_load -> /usr/share/munin/plugins/upsmonpro_ + /etc/munin/plugins/upsmonpro_status -> /usr/share/munin/plugins/upsmonpro_ + /etc/munin/plugins/upsmonpro_temp -> /usr/share/munin/plugins/upsmonpro_ + /etc/munin/plugins/upsmonpro_voltage -> /usr/share/munin/plugins/upsmonpro_ + +=head1 CONFIGURATION + +Environment variables: + + host - UPSMON PRO server host, default localhost + port - UPSMON PRO port, default 2601 + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf + +=head1 AUTHOR + +Copyright (C) 2017 pru.mike@gmail.com + +=head1 LICENSE + +GPLv2. + +=cut + +use strict; +use warnings; +use feature qw/say/; +use Munin::Plugin; +use IO::Socket::INET; +use Time::HiRes qw/usleep/; +use English qw/-no-math-vars/; +our $VERSION = '0.0.1'; +$OUTPUT_AUTOFLUSH++; + +our $DEFAULT_HOST = 'localhost'; +our $DEFAULT_PORT = 2601; +our %TYPES = ( + voltage => [qw/input output/], + load => [qw/battery_load battery_capacity/], + temp => [q/temp/], + status => [qw/power_failure low_battery voltage_status ups_status battery_test/] +); +our @TYPES = keys %TYPES; + +{ + no strict 'refs'; + for my $t (@TYPES) { + for my $sub (qw/autoconf/) { + *{ __PACKAGE__ . "::run_${sub}_$t" } = "run_$sub"; + } + *{ __PACKAGE__ . "::run_default_$t" } = sub { + run_default(@{ $TYPES{$t} }); + }; + } +} + +{ + no strict 'refs'; + find_key($ARGV[0])->(); +} + +sub find_key { + my $p = shift || ""; + my $type_re = join '|', @TYPES; + unless ($Munin::Plugin::me =~ /upsmonpro_{1,}($type_re)$/) { + die "Could not determine script type [@TYPES] ? name=" . $Munin::Plugin::me . "\n"; + } + my $graph = $1; + + return 'run_' . ((grep { $p eq $_ } qw/autoconf config/) ? $ARGV[0] : 'default') . "_$graph"; +} + +sub run_config_voltage { + print <<'END'; +graph_title UPS Input/Output Voltage +graph_vlabel volt +graph_scale no +graph_category sensors +input.label input +input.info Input Voltage +input.type GAUGE +output.label output +output.info Output Voltage +output.type GAUGE +END + exit(0); +} + +sub run_config_temp { + print <<'END'; +graph_title UPS Temperature +graph_vlabel celsius +graph_scale no +graph_category sensors +temp.label temperature +temp.type GAUGE +END + exit(0); +} + +sub run_config_load { + print <<'END'; +graph_title UPS Battery Load/Capacity +graph_vlabel precent% +graph_scale no +graph_category sensors +battery_load.label battery_load +battery_load.type GAUGE +battery_capacity.label battery_capacity +battery_capacity.type GAUGE +END + exit(0); +} + +sub run_config_status { + print <<'END'; +graph_title UPS Statuses +graph_vlabel status +graph_scale no +graph_category sensors +power_failure.label power_failure +power_failure.type GAUGE +low_battery.label low_battery +low_battery.type GAUGE +voltage_status.label voltage_status +voltage_status.info 0 normal, 1 boost, 2 buck +voltage_status.type GAUGE +ups_status.label ups_status +ups_status.type GAUGE +battery_test.label battery_test +battery_test.type GAUGE +END + exit(0); +} + +sub run_default { + my $host = $ENV{host} || $DEFAULT_HOST; + my $port = $ENV{port} || $DEFAULT_PORT; + my @val_list = @_; + my $r = gather_data($host, $port); + for (@val_list) { + die "Wrong value: $_" if not exists $r->{$_}; + say "${_}.value $r->{$_}"; + } +} + +sub run_autoconf { + if (gather_data($DEFAULT_HOST, $DEFAULT_PORT)->{response} eq 'ok') { + say "yes"; + } else { + say "no ($DEFAULT_HOST:$DEFAULT_PORT not response)"; + } + exit(0); +} + +sub gather_data { + my $host = shift; + my $port = shift; + my %data = map { ($_ => 'U') } map { @{ $TYPES{$_} } } @TYPES; + $data{response} = 'failed'; + + my $sock = IO::Socket::INET->new( + PeerAddr => $host, + Proto => 'udp', + PeerPort => $port, + Blocking => 0 + ) or die "Cannot create socket: $@"; + + my $pattern = pack 'AAAACAAA', split //, 'PCMG1END'; + $sock->send($pattern) or die "send to $host: $!"; + usleep(200); + my $data; + my $buf; + while ($sock->read($buf, 32)) { + $data .= $buf; + } + if (defined $data and $data =~ /^PCMR.*END$/) { + my @data = unpack('C*', $data); + %data = ( + response => 'ok', + input => $data[6] + 256 * $data[5], + output => $data[8] + 256 * $data[7], + battery_load => $data[11], + battery_capacity => $data[12], + temp => $data[15], + power_failure => ($data[18] ? 1 : 0), + low_battery => ($data[19] ? 1 : 0), + + #voltage_status: 0 = normal, 3 = buck, 2 = boost + voltage_status => ($data[17] == 0 ? 0 : ($data[17] == 3 ? 2 : 1)), + ups_status => ($data[21] ? 1 : 0), + battery_test => ($data[23] ? 1 : 0), + ); + } + return \%data; +} From c9bd24bda7fd0f9e85d5691bfdfa5d77a6cabd5f Mon Sep 17 00:00:00 2001 From: "pru.mike" Date: Sat, 11 Feb 2017 21:52:29 +0300 Subject: [PATCH 2/3] Fix for pull request munin-monitoring#798 --- plugins/{sensors => ups}/upsmonpro_ | 63 ++++++++++++++++++----------- 1 file changed, 39 insertions(+), 24 deletions(-) rename plugins/{sensors => ups}/upsmonpro_ (77%) diff --git a/plugins/sensors/upsmonpro_ b/plugins/ups/upsmonpro_ similarity index 77% rename from plugins/sensors/upsmonpro_ rename to plugins/ups/upsmonpro_ index cdb3083a..67e355e8 100644 --- a/plugins/sensors/upsmonpro_ +++ b/plugins/ups/upsmonpro_ @@ -18,10 +18,17 @@ Environment variables: host - UPSMON PRO server host, default localhost port - UPSMON PRO port, default 2601 +Example configuration (optional): + + [upsmonpro_*] + env.host localhost + env.port 2601 + =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf + #%# capabilities=suggest =head1 AUTHOR @@ -51,34 +58,36 @@ our %TYPES = ( temp => [q/temp/], status => [qw/power_failure low_battery voltage_status ups_status battery_test/] ); -our @TYPES = keys %TYPES; +our @TYPES = sort keys %TYPES; +my %DISPATCH_TABLE = (); +my $pkg = __PACKAGE__; -{ - no strict 'refs'; - for my $t (@TYPES) { - for my $sub (qw/autoconf/) { - *{ __PACKAGE__ . "::run_${sub}_$t" } = "run_$sub"; - } - *{ __PACKAGE__ . "::run_default_$t" } = sub { - run_default(@{ $TYPES{$t} }); - }; - } +$DISPATCH_TABLE{"${pkg}::run_suggest"} = \&run_suggest; +$DISPATCH_TABLE{"${pkg}::run_autoconf"} = \&run_autoconf; +for my $t (@TYPES) { + $DISPATCH_TABLE{"${pkg}::run_config_$t"} = \&{"run_config_$t"}; + $DISPATCH_TABLE{"${pkg}::run_autoconf_$t"} = \&run_autoconf; + $DISPATCH_TABLE{"${pkg}::run_default_$t"} = sub { + run_default(@{ $TYPES{$t} }); + }; } -{ - no strict 'refs'; - find_key($ARGV[0])->(); -} +find_key($ARGV[0])->(); sub find_key { - my $p = shift || ""; + my $argv = shift || ''; my $type_re = join '|', @TYPES; - unless ($Munin::Plugin::me =~ /upsmonpro_{1,}($type_re)$/) { - die "Could not determine script type [@TYPES] ? name=" . $Munin::Plugin::me . "\n"; + my $key; + if ($argv =~ /(suggest|autoconf)/i) { + $key = 'run_' . lc($1); + } elsif ($Munin::Plugin::me =~ /upsmonpro_{1,}($type_re)$/) { + my $graph = $1; + $key = 'run_' . ((grep { $argv eq $_ } qw/autoconf config/) ? $argv : 'default') . "_$graph"; + } else { + die "Could not determine script type [@TYPES] ? name=$Munin::Plugin::me\n"; } - my $graph = $1; - return 'run_' . ((grep { $p eq $_ } qw/autoconf config/) ? $ARGV[0] : 'default') . "_$graph"; + return $DISPATCH_TABLE{"${pkg}::$key"}; } sub run_config_voltage { @@ -86,7 +95,7 @@ sub run_config_voltage { graph_title UPS Input/Output Voltage graph_vlabel volt graph_scale no -graph_category sensors +graph_category ups input.label input input.info Input Voltage input.type GAUGE @@ -102,7 +111,7 @@ sub run_config_temp { graph_title UPS Temperature graph_vlabel celsius graph_scale no -graph_category sensors +graph_category ups temp.label temperature temp.type GAUGE END @@ -114,7 +123,7 @@ sub run_config_load { graph_title UPS Battery Load/Capacity graph_vlabel precent% graph_scale no -graph_category sensors +graph_category ups battery_load.label battery_load battery_load.type GAUGE battery_capacity.label battery_capacity @@ -128,7 +137,7 @@ sub run_config_status { graph_title UPS Statuses graph_vlabel status graph_scale no -graph_category sensors +graph_category ups power_failure.label power_failure power_failure.type GAUGE low_battery.label low_battery @@ -155,6 +164,12 @@ sub run_default { } } +sub run_suggest { + local $LIST_SEPARATOR = "\n"; + say "@TYPES"; + exit(0); +} + sub run_autoconf { if (gather_data($DEFAULT_HOST, $DEFAULT_PORT)->{response} eq 'ok') { say "yes"; From 4702b9223668c1cdec7f0d0246f730a1549c7f3c Mon Sep 17 00:00:00 2001 From: "pru.mike" Date: Mon, 13 Feb 2017 22:44:59 +0300 Subject: [PATCH 3/3] Fix graph_category (pull request munin-monitoring#798) --- plugins/ups/upsmonpro_ | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/ups/upsmonpro_ b/plugins/ups/upsmonpro_ index 67e355e8..0008e4e2 100644 --- a/plugins/ups/upsmonpro_ +++ b/plugins/ups/upsmonpro_ @@ -95,7 +95,7 @@ sub run_config_voltage { graph_title UPS Input/Output Voltage graph_vlabel volt graph_scale no -graph_category ups +graph_category sensors input.label input input.info Input Voltage input.type GAUGE @@ -111,7 +111,7 @@ sub run_config_temp { graph_title UPS Temperature graph_vlabel celsius graph_scale no -graph_category ups +graph_category sensors temp.label temperature temp.type GAUGE END @@ -123,7 +123,7 @@ sub run_config_load { graph_title UPS Battery Load/Capacity graph_vlabel precent% graph_scale no -graph_category ups +graph_category sensors battery_load.label battery_load battery_load.type GAUGE battery_capacity.label battery_capacity @@ -137,7 +137,7 @@ sub run_config_status { graph_title UPS Statuses graph_vlabel status graph_scale no -graph_category ups +graph_category sensors power_failure.label power_failure power_failure.type GAUGE low_battery.label low_battery