#!/usr/bin/perl -w # # IPMI data gathering for munin. # # Author: 2008 Benjamin Pineau # This work is hereby released into the Public Domain. # To view a copy of the public domain dedication, visit # http://creativecommons.org/licenses/publicdomain/ # # Requirements : # # - ipmitool command line utility (and kernel drivers) # - access rights to /dev/ipmi0 device (ie, root privileges # can be configured in /etc/munin/plugin-conf.d/munin-node) # # Parameters supported: # # config # autoconf # # Setup : # # ipmitool sdr || echo "please load IPMI kernel modules" # cp ipmi_sdr_ /usr/share/munin/plugins/ # chmod +x /usr/share/munin/plugins/ipmi_sdr_ # ln -s /usr/share/munin/plugins/ipmi_sdr_ /etc/munin/plugins/ipmi_sdr_fan # ln -s /usr/share/munin/plugins/ipmi_sdr_ /etc/munin/plugins/ipmi_sdr_current # ln -s /usr/share/munin/plugins/ipmi_sdr_ /etc/munin/plugins/ipmi_sdr_voltage # ln -s /usr/share/munin/plugins/ipmi_sdr_ /etc/munin/plugins/ipmi_sdr_temperature # echo -e "\n[ipmi_sdr*]\nuser root\ntimeout 15\n" >> /etc/munin/plugin-conf.d/munin-node # /etc/init.d/munin-node restart # # Magic markers #%# family=auto #%# capabilities=autoconf use strict; use warnings; $ENV{'LANG'} = 'C'; $ENV{'LC_ALL'} = 'C'; my $ipmidump = $ENV{'ipmidump'} || '/var/lib/munin/plugin-state/ipmi_sdr'; my $ipmitool = $ENV{'ipmitool'} || 'ipmitool'; my $drefresh = $ENV{'drefresh'} || 86400; my %sensors; my $desc = { 'fan' => { 'graph_title' => 'Fans rotations per minute', 'graph_vlabel' => 'RPM', 'graph_info' => 'Fans rotations per minute', }, 'voltage' => { 'graph_title' => 'Electrical tensions', 'graph_vlabel' => 'Volts', 'graph_info' => 'Electrical tensions', }, 'temperature' => { 'graph_title' => 'Hardware temperatures', 'graph_vlabel' => 'Degrees Celsius', 'graph_info' => 'Hardware temperature sensors output', }, 'current' => { 'graph_title' => 'Hardware power consumption', 'graph_vlabel' => 'Watts or Amperes', 'graph_info' => 'Hardware power consumption', }, }; my $stype = $0 =~ /.*ipmi_sdr_(\w+)$/ ? lc($1) : 'temperature'; if (!defined($desc->{"$stype"})) { printf STDERR "Unknown sensor type : '$stype'. Aborting.\n"; exit 1; } sub strip_spaces($) { (my $s = shift) =~ s/^\s*(.*?)\s*\n?$/$1/; return $s; } sub normalize_name($) { (my $l = lc(strip_spaces(shift))) =~ tr/\t ./_/; return $l; } sub sdrlist_parse(@) { foreach(@_) { next unless /^([^\|]+)\s*\|\s*(\w+)\s*\|[^\|]+\|[^\|]+\|\s*([\d\.]+)\s+/; $sensors{$_}{"name"} = strip_spaces($1); $sensors{$_}{"value"} = strip_spaces($3); $sensors{$_}{"label"} = normalize_name($1) . normalize_name($2); } } if (defined $ARGV[0] and $ARGV[0] eq 'autoconf') { `$ipmitool help 2> /dev/null`; if ($?) { print "no ($ipmitool not found)"; exit 1; } `$ipmitool sdr dump $ipmidump`; if ($?) { printf "no (ipmitool sdr dump returned code %d)\n", $? >> 8; exit 1; } `$ipmitool sdr type $stype -S $ipmidump`; if ($?) { print "no (ipmitool didn't found any sensor of type "; printf "'$stype', returned code %d)\n", $? >> 8; exit 1; } print "yes\n"; exit 0; } # "ipmitool dump" dumps speeds up data retreival big time, by avoiding # IPMI sensors autodiscovery. This only caches sensors names/types/ids # (not values/datas), so we can have a very long cache lifetime policy. if (-f $ipmidump) { unlink($ipmidump) if (time - (stat($ipmidump))[9] >= $drefresh); } unless (-f $ipmidump) { `$ipmitool sdr dump $ipmidump` || die $!; } (my @dt = `$ipmitool sdr type $stype -S $ipmidump`) || die $!; sdrlist_parse(@dt); if (defined($ARGV[0]) && $ARGV[0] eq "config") { print "graph_category system\n"; print "graph_title " . $desc->{$stype}->{"graph_title"} . "\n"; print "graph_vlabel " . $desc->{$stype}->{"graph_vlabel"} . "\n"; print "graph_info " . $desc->{$stype}->{"graph_info"} . "\n"; foreach my $v (values(%sensors)) { print $v->{"label"} . ".label " . $v->{"name"} . "\n"; print $v->{"label"} . ".type GAUGE\n"; } exit 0; } foreach my $v (values(%sensors)) { print $v->{"label"} . ".value " . $v->{"value"} . "\n"; }