From 7ed16b61e55a61c3ba98be13dcb6486c3a171088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Tue, 23 Oct 2012 17:14:57 -0700 Subject: [PATCH] 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. --- plugins/sensors/freeipmi | 170 ++++++++++++++++++++++++++++++++++++ plugins/sensors/freeipmi_ | 179 -------------------------------------- 2 files changed, 170 insertions(+), 179 deletions(-) create mode 100755 plugins/sensors/freeipmi delete mode 100755 plugins/sensors/freeipmi_ diff --git a/plugins/sensors/freeipmi b/plugins/sensors/freeipmi new file mode 100755 index 00000000..d821df6e --- /dev/null +++ b/plugins/sensors/freeipmi @@ -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ò . + +=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 <{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"; + } +} diff --git a/plugins/sensors/freeipmi_ b/plugins/sensors/freeipmi_ deleted file mode 100755 index 9dfe7875..00000000 --- a/plugins/sensors/freeipmi_ +++ /dev/null @@ -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ò . -Based on the work of Nicolai Langfeldt , 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 - <