#!/usr/bin/ruby # # Copyright (c) 2006 Peter Palfrader # #%# family=auto #%# capabilities=autoconf suggest # # # # ipmitool probably needs to be run as root, and it may take more than 10 seconds on some hosts. # # Add the following to your /etc/munin/plugin-conf.d/munin-node: # [ipmi_sensor_*] # user root # timeout 20 # require 'yaml'; VALID_UNITS = %w{volts degrees_c rpm} def bail_out(m) STDERR.puts "#{$0}: #{m}" exit 1 end def normalize_sensor(s) s = s.downcase s = s.tr('-', 'M') s = s.tr('+', 'P') s.tr('^a-zA-Z0-9', '_') end def normalize_unit(s) s.downcase.tr('^a-z0-9', '_') end def get_sensor_data data = [] names = {} IO.popen("ipmitool -I open sensor") do |f| f.each do |line| line.strip! # cpu1.vtt-s3 | 1.200 | Volts | ok | na | 1.080 | na | na | 1.320 | na # CPU0 IERR | 0x0 | discrete | 0x0100| na | na | na | na | na | na········ items = line.split(/\s*\|\s*/) unless items.size == 10 bail_out "Got weird number of fields in ipmitool output. Expected 10 but got #{items.size} for line '#{line}'." end (name, value, unit, status, lower_non_recov, lower_crit, lower_non_crit, upper_non_crit, upper_crit, upper_non_recv) = items nname = normalize_sensor name; if names.has_key?(nname) bail_out "Sensor name #{name} (normalized to #{nname}) appears more than once in ipmitool output." end names[nname] = 1 data << { :name => name, :value => value, :unit => unit, :status => status, :lower_non_recov => lower_non_recov, :lower_crit => lower_crit, :lower_non_crit => lower_non_crit, :upper_non_crit => upper_non_crit, :upper_crit => upper_crit, :upper_non_recv => upper_non_recv, :line => line } end end data end def autoconf if get_sensor_data.length > 0 puts "yes" else puts "no (no ipmitool output" end end def suggest #puts get_sensor_data.collect{ |i| normalize_unit(i[:unit]) }.uniq.sort.delete_if{ |i| i == "discrete" } VALID_UNITS.each do |u| puts "u_#{u}" end end def query_unit match = /_u_(.*?)$/.match($0) unless match bail_out "Could not figure out which unit you want based on executeable name." end match[1] end def config u = query_unit case u when "volts" puts "graph_title IPMI Sensors: Voltages" puts "graph_args --base 1000" puts "graph_vlabel Volts"; puts "graph_category sensors" puts "graph_info This graph shows the voltages as reported by IPMI" get_sensor_data.each do |d| next unless normalize_unit(d[:unit]) == u n = normalize_sensor(d[:name]) puts "#{n}.label #{d[:name]}" end when "degrees_c" puts "graph_title IPMI Sensors: Temperature" puts "graph_args --base 1000 -l 0" puts "graph_vlabel Degrees C"; puts "graph_category sensors" puts "graph_info This graph shows the temperatures as reported by IPMI" get_sensor_data.each do |d| next unless normalize_unit(d[:unit]) == u n = normalize_sensor(d[:name]) puts "#{n}.label #{d[:name]}" end when "rpm" puts "graph_title IPMI Sensors: RPMs" puts "graph_args --base 1000 -l 0" puts "graph_vlabel RPM"; puts "graph_category sensors" puts "graph_info This graph shows the RPMs as reported by IPMI" get_sensor_data.each do |d| next unless normalize_unit(d[:unit]) == u n = normalize_sensor(d[:name]) puts "#{n}.label #{d[:name]}" end else bail_out "Do not know how to handle unit '#{u}'" end end def report u = query_unit get_sensor_data.each do |d| next unless normalize_unit(d[:unit]) == u n = normalize_sensor(d[:name]) puts "#{n}.value #{d[:value]}" end end case ARGV[0] when "autoconf" autoconf when "suggest" suggest when "config" config else report end