Munin plugin for OMSA

L.P.H. van Belle belle at bazuin.nl
Tue Sep 11 01:36:43 CDT 2007


switch you monitoring to the munin ipmi plugin. 

/snap here it is.

#!/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 amps watts}

CACHEDIR = "/var/lib/munin/plugin-state"
CACHEFILE = "plugin-ipmi_sensor.cache"
CACHE_AGE = 275
IPMITOOL = '/usr/bin/ipmitool'

Thread.abort_on_exception = true

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 fetch_cache
	fn = CACHEDIR+"/"+CACHEFILE
	return nil unless FileTest.exists? fn
	cache = YAML::load( File.open(fn) )
	return nil unless cache
	return nil unless cache[:version] == 1
	return nil if Time.now - cache[:timestamp] > CACHE_AGE
	return cache[:data]
end
def write_cache(data)
	fn = CACHEDIR+"/"+CACHEFILE
	return unless FileTest.directory? CACHEDIR
	return unless FileTest.writable? CACHEDIR or FileTest.writable? fn
	File.open(fn, "w", 0600) { |f|
		cache = {
				:version => 1,
				:timestamp => Time.now,
				:data => data
			}
		f.puts cache.to_yaml
	}
end
def get_sensor_data
	data = fetch_cache
	return data if data

	data = []
	names = {}

	rdout, wrout = IO.pipe
	rderr, wrerr = IO.pipe

	pid = fork
	unless pid
		# child
		rdout.close
		rderr.close
		STDOUT.reopen wrout
		STDERR.reopen wrerr
		exec(IPMITOOL, '-I', 'open', 'sensor')
		bail_out("fell through exec(). WTF.")
	end
	wrout.close
	wrerr.close


	out = []
	err = []
	tout = Thread.new { out = rdout.readlines }
	terr = Thread.new { err = rderr.readlines }
	tout.join
	terr.join
	Process.wait pid

	bail_out("ipmitool printed stuff on stdout: "+err.join('')) if
(err.length > 0)

	out.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_recov) = 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_recov => upper_non_recov,
			:line => line
		}
	end

	write_cache data
	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]}"
				puts "#{n}.warning
#{d[:lower_non_crit]}:#{d[:upper_non_crit]}"
				puts "#{n}.critical
#{d[:lower_non_recov]}:#{d[:upper_non_recov]}"
			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]}"
				puts "#{n}.warning
#{d[:lower_non_crit]}:#{d[:upper_non_crit]}"
				puts "#{n}.critical
#{d[:lower_non_recov]}:#{d[:upper_non_recov]}"
			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]}"
				# no warning, only critical puts
"#{n}.warning #{d[:lower_non_crit]}:#{d[:upper_non_crit]}"
				puts "#{n}.critical
#{d[:lower_non_recov]}:#{d[:upper_non_recov]}"
			end
		when "amps"
			puts "graph_title IPMI Sensors: Amperes"
			puts "graph_args --base 1000"
			puts "graph_vlabel Amperes";
			puts "graph_category sensors"
			puts "graph_info This graph shows the amperes 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 "watts"
			puts "graph_title IPMI Sensors: Watts"
			puts "graph_args --base 1000"
			puts "graph_vlabel Watts";
			puts "graph_category sensors"
			puts "graph_info This graph shows the watts 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

/snap

good luck, this one works 4 me ;-) 




 

>-----Oorspronkelijk bericht-----
>Van: linux-poweredge-bounces at dell.com 
>[mailto:linux-poweredge-bounces at dell.com] Namens Jim Nelson
>Verzonden: maandag 10 september 2007 21:56
>Aan: linux-poweredge at lists.us.dell.com
>Onderwerp: Munin plugin for OMSA
>
>I modified the sensors_ plugin for munin to work with omreport 
>- it works with
>the PE 750, 1750, and 1950's I have at hand, and I'm looking 
>for feedback before
>I submit it for inclusion.
>
>Resending it with the script attached :p
>



More information about the Linux-PowerEdge mailing list