2
0
mirror of https://github.com/munin-monitoring/contrib.git synced 2018-11-08 00:59:34 +01:00

freeipmi: replace wildcard plugin with a multigraph one.

This new plugin is written in Perl rather than sh+awk, executes
ipmi-sensors only once per call (config/fetch still require two calls
total), and with one call it produces all the available graphs
depending on the available sensors.

This still allows for monitoring a remote system, and that becomes
even more interesting since it only fetches data once.

The plugin will also now fail autoconf if there is no sensor output
that can be monitored.
This commit is contained in:
Diego Elio Pettenò 2012-10-23 17:14:57 -07:00
parent fd5126e02b
commit 7ed16b61e5
2 changed files with 170 additions and 179 deletions

170
plugins/sensors/freeipmi Executable file
View File

@ -0,0 +1,170 @@
#!/usr/bin/perl -w
# -*- cperl -*-
=head1 NAME
freeipmi - Multigraph-plugin to monitor sensors using FreeIPMI
=head1 CONFIGURATION
=head2 ENVIRONMENT VARIABLES
When used to monitor a foreign host, this plugins use the variables
IPMI_USERNAME and IPMI_PASSWORD to log in on the remote system.
=head2 WILDCARD PLUGIN
When used for the local host, the plugin should be linked as
non-wildcard plugin, i.e., 'freeipmi', whereas when used to monitor a
foreign host it should be, e.g., 'freeipmi_192.168.0.253'.
=head1 AUTHOR
Diego Elio Pettenò <flameeyes@flameeyes.eu>.
=head1 LICENSE
GPLv2
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf
=cut
use strict;
use Munin::Plugin;
$ENV{'LANG'} = "C"; # Force parsable output from sensors.
$ENV{'LC_ALL'} = "C"; # Force parsable output from sensors.
my $IPMISENSORS = $ENV{'ipmisensors'} || 'ipmi-sensors';
$0 =~ /freeipmi(?:_(.+))$/;
my $hostname = $1;
$IPMISENSORS .= " --quiet-cache --comma-separated-output --no-header-output --ignore-not-available-sensors --sensor-types=Temperature,Fan,Current,Voltage --output-sensor-thresholds";
$IPMISENSORS .= " --hostname=$hostname" if defined($hostname);
$IPMISENSORS .= " --username=$ENV{IPMI_USERNAME}" if defined($ENV{IPMI_USERNAME});
$IPMISENSORS .= " --password=$ENV{IPMI_PASSWORD}" if defined($ENV{IPMI_PASSWORD});
my $output=`$IPMISENSORS --output-sensor-thresholds 2>/dev/null`;
my $retval=$?;
if ( defined $ARGV[0] and $ARGV[0] eq 'autoconf' ) {
if ($retval >= 1) {
print "no (ipmi-sensors died)\n";
} elsif ($retval == -1) {
print "no (ipmi-sensors not found)\n";
} elsif ($output eq "\n") {
print "no (no compatible sensors)\n";
} else {
print "yes\n";
}
exit 0;
}
my %sensors = (
temp => {
inputs => [],
title => "Temperatures by IPMI",
vlabel => "Degrees Celsius",
graph_args => "--base 1000 -l 0",
},
fan => {
inputs => [],
title => "Fans speed by IPMI",
vlabel => "RPM",
graph_args => "--base 1000 -l 0",
},
power => {
inputs => [],
title => "Power by IPMI",
vlabel => "W",
graph_args => "--base 1000 -l 0",
},
current => {
inputs => [],
title => "Current by IPMI",
vlabel => "A",
graph_args => "--base 1000 -l 0",
},
voltage => {
inputs => [],
title => "Voltages by IPMI",
vlabel => "Volt",
graph_args => "--base 1000 --logarithmic",
},
);
my @data = split(/\n/, $output);
foreach my $line (@data) {
my @dataline = split(/,/, $line);
my %sensor = (
graphid => "ipmi" . $dataline[0],
value => $dataline[3],
label => $dataline[1]
);
$sensor{lwarn} = $dataline[7] if $dataline[7] ne "N/A";
$sensor{hwarn} = $dataline[9] if $dataline[9] ne "N/A";
$sensor{lcrit} = $dataline[6] if $dataline[6] ne "N/A";
$sensor{hcrit} = $dataline[10] if $dataline[10] ne "N/A";
my $type;
if ( $dataline[2] eq "Temperature" ) {
$type = "temp";
} elsif ( $dataline[2] eq "Fan" ) {
$type = "fan"
} elsif ( $dataline[2] eq "Current" and $dataline[4] eq "W" ) {
$type = "power";
} elsif ( $dataline[2] eq "Current" and $dataline[4] eq "A" ) {
$type = "current";
} elsif ( $dataline[2] eq "Voltage" ) {
$type = "voltage";
}
push(@{$sensors{$type}->{inputs}}, \%sensor);
}
if ( defined $ARGV[0] and $ARGV[0] eq 'config' ) {
foreach my $type (keys %sensors) {
# don't print anything if no value is found
next if scalar(@{$sensors{$type}->{inputs}}) == 0;
print "host_name $hostname" if defined($hostname);
print <<END;
multigraph freeipmi_$type
graph_title $sensors{$type}->{title}
graph_vlabel $sensors{$type}->{vlabel}
graph_args $sensors{$type}->{graph_args}
graph_category sensors
END
foreach my $sensor (@{$sensors{$type}->{inputs}}) {
print "$sensor->{graphid}.label $sensor->{label}\n";
print "$sensor->{graphid}.warning $sensor->{lwarn}:$sensor->{hwarn}\n"
if defined($sensor->{lwarn}) or defined($sensor->{hwarn});
print "$sensor->{graphid}.critical $sensor->{lcrit}:$sensor->{hcrit}\n"
if defined($sensor->{lcrit}) or defined($sensor->{hcrit});
}
}
exit 0;
}
foreach my $type (keys %sensors) {
# don't print anything if no value is found
next if scalar(@{$sensors{$type}->{inputs}}) == 0;
print "multigraph sensors_$type\n";
foreach my $sensor (@{$sensors{$type}->{inputs}}) {
print "$sensor->{graphid}.value $sensor->{value}\n";
}
}

View File

@ -1,179 +0,0 @@
#!/bin/sh
# -*- sh -*-
: << =cut
=head1 NAME
freeipmi_ - Plugin to monitor temperature or fan speed using FreeIPMI
=head1 CONFIGURATION
=head2 ENVIRONMENT VARIABLES
When used to monitor a foreign host, this plugins use the variables
IPMI_USERNAME and IPMI_PASSWORD to log in on the remote system.
=head2 WILDCARD PLUGIN
You can monitor either the current system (via /dev/ipmi0 and the
like) or a remote system (via the LAN protocols), and for each of the
two options you can select your sensors:
- fans;
- temp;
- power;
- current;
- voltage.
When used for the local host, the plugin should be linked as, e.g.,
'ipmi_temp', whereas when used to monitor a foreign host it should be,
e.g., 'ipmi_192.168.0.253_temp'.
=head1 NOTE
=head1 AUTHOR
Rewritten by Diego Elio Pettenò <flameeyes@flameeyes.eu>.
Based on the work of Nicolai Langfeldt <janl@linpro.no>, Logilab and
Peter Palfrader.
=head1 LICENSE
GPLv2
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf suggest
=cut
#### Parse commandline to determine what the job is
_ipmisensors() {
params="--quiet-cache --comma-separated-output --no-header-output --ignore-not-available-sensors"
if [ "x${hostname}" != "x" ]; then
params="${params} --hostname=${hostname}"
[ "x${IPMI_USERNAME}" != "x" ] && params="${params} --username=${IPMI_USERNAME}"
[ "x${IPMI_PASSWORD}" != "x" ] && params="${params} --password=${IPMI_PASSWORD}"
fi
if ! ipmi-sensors ${params} --output-sensor-thresholds "$@"; then
ipmi-sensors ${params} "$@"
fi
}
# extract and eventual hostname out of the called name; we
# have to check whether it's set to "u" as that's what happens
# when the compatibility with ipmi_sensor_ is used.
hostname1=${0#*_}
hostname=${hostname1%%_*}
if [ "x${hostname}" = "xu" -o "x${hostname}" = "x${hostname1}" ]; then
hostname=""
fi
case $0 in
*_temp|*_u_degrees_c)
title="Temperatures"
vlabel="degrees Celsius"
type=Temperature
unit=C
;;
*_fans|*_u_rpm)
title="Fan speeds"
vlabel="Rotations per Minute (RPM)"
type=Fan
unit=RPM
;;
*_power|*_u_watts)
title="Power consumption"
vlabel="Watts"
type=Current
unit=W
;;
*_current|*_u_amps)
title="Current drain"
vlabel="Amperes"
type=Current
unit=A
;;
*_voltage|*_u_volts)
title="Voltages"
vlabel="Volts"
type=Voltage
unit=V
;;
*)
if [ x"$1" != x"autoconf" -a x"$1" != x"suggest" ]; then
echo "Please invoke as one of the supported sensors types:" >&2
echo freeipmi_{temp,fans,power,current} >&2
exit 1
fi
esac
case $1 in
autoconf)
if ! command -v ipmi-sensors >/dev/null 2>&1 ; then
echo 'no (missing ipmi-sensors command)'
exit 0
fi
if ! _ipmisensors -t OS_Boot >/dev/null 2>&1 ; then
echo 'no (unable to access IPMI device)'
exit 0
fi
echo yes
exit 0
;;
suggest)
_ipmisensors | awk -F, '
$3 == "Temperature" { print "temp"; }
$3 == "Fan" { print "fans"; }
$3 == "Current" && $5 == "W" { print "power"; }
$3 == "Current" && $5 == "A" { print "current"; }
$3 == "Voltage" { print "voltage"; }
'
exit 0;;
config)
cat - <<EOF
graph_title ${title} based on IPMI sensors
graph_vlabel ${vlabel}
graph_category Sensors
EOF
if [ "x${hostname}" != "x" ]; then
echo "host_name ${hostname}"
fi
;;
esac
_ipmisensors -t ${type} | awk -F, -v CONFIG=$1 -v UNIT=$unit '
$5 == UNIT {
if ( CONFIG != "config" ) {
printf("ipmi%s.value %s\n", $1, $4);
} else {
printf("ipmi%s.label %s\n", $1, $2);
# This can only happen if FreeIPMI is new enough
if ( NF == 12 ) {
if ( $8 != "N/A" && $10 != "N/A" )
printf("ipmi%s.warning %s:%s\n", $1, $8, $10);
else if ( $8 == "N/A" && $10 != "N/A" )
printf("ipmi%s.warning :%s\n", $1, $10);
else if ( $8 != "N/A" && $10 == "N/A" )
printf("ipmi%s.warning %s:\n", $1, $8);
if ( $7 != "N/A" && $11 != "N/A" )
printf("ipmi%s.critical %s:%s\n", $1, $7, $11);
else if ( $7 == "N/A" && $11 != "N/A" )
printf("ipmi%s.critical :%s\n", $1, $11);
else if ( $7 != "N/A" && $11 == "N/A" )
printf("ipmi%s.critical %s:\n", $1, $7);
}
}
}
'
# vim: syntax=sh ts=4 et