#!/usr/bin/python
#
# NET-SNMP 'pass_persist' script that retrieves IPMI sensor values
# and hands them over to the snmpd
#
# Written on 2004/12/14 by Mark Bergsma <mark@nedworks.org>
#
# Locking between threads is not really needed, as output results
# will be very similar between calls

import os, sys, thread, time

ipmicmd = 'sudo /usr/local/sbin/sensors -s "6 7 8 12 13 14 15 16 25 26 27 28 29 30 49 51 58 61 62 160 161 162"'
oidbase = '.1.3.6.1.4.1.2021.255.'

sensorvalues = {}
oids = []

def parse_output(output):
	"""
	Parses sensor values from the FreeIPMI 'sensors' program output
	and returns them in a dictionary
	"""
	res = {}
	for line in output:
		cols = line.split(':')
		res[int(cols[0])] = cols[2].strip().split()[0]
	return res

def collector(tid):
	"""
	Separate thread routine for collecting IPMI sensor data through
	(blocking) os.popen() calls
	"""
	global sensorvalues, oids
	
	while 1:
		sensorvalues = parse_output(os.popen(ipmicmd).readlines())
		keys = sensorvalues.keys()
		keys.sort()
		oids = keys
								
		time.sleep(600)

def value_type(value):
	if value.find('.') > 0:
		return ('integer', str(int(float(value)*1000)))
	else:
		return ('integer', value)

def snmp_get(oid):
	"""
	Returns a tuple (OID, type, value) corresponding to the
	requested OID, or an empty tuple in case of a failure
	"""
	if (oid.startswith(oidbase)):
		try:
			octet = int(oid.split('.')[-1])
			value = sensorvalues[octet]
			return (oid, ) + value_type(value)
		except:
			pass
	return ()

def snmp_getnext(oid):
	"""
	Returns a tuple (OID, type, value) corresponding to the
	requested (next) OID, or an empty tuple in case of a failure
	"""
	if (oid+'.' == oidbase):
		octet = -1	# lower bound
	else:
		octet = int(oid.split('.')[-1])
			
	if (octet == -1 or oid.startswith(oidbase)):
		try:
			for i in oids:
				if i > octet:
					next = i
					break
			value = sensorvalues[next]
			return (oidbase+str(next), ) + value_type(value)
		except:
			pass
	return ()
	
if __name__ == '__main__':
	# Start collecting data
	thread.start_new(collector, (0,))	

	# Read commands from stdin
	while 1:
		line = sys.stdin.readline()
		if not line: break
		line = line[:-1]

		if line == 'PING':
			print 'PONG'
		elif line[:3] == 'get':
			oid = sys.stdin.readline().strip()
		
			val = ()
			if line == 'get':
				val = snmp_get(oid)
			elif line == 'getnext':
				val = snmp_getnext(oid)
				
			if val != ():
				print "\n".join(val)
			else:
				print 'NONE'
		else:
			print 'NONE'

		sys.stdout.flush()

# vim:ts=4:sts=4

