Many bug fixes (mainly on the IPMI driver).

Change-Id: I05fa1fa8d34daa212c3cc51d5960e72eebfa82b7
This commit is contained in:
François Rossigneux 2013-02-19 18:32:36 +01:00
parent d0869dcf7d
commit a5ad06da44
5 changed files with 57 additions and 28 deletions

View File

@ -40,8 +40,8 @@ class Dummy(Driver):
def run(self): def run(self):
"""Starts the driver thread.""" """Starts the driver thread."""
while not self.stop_request_pending(): while not self.stop_request_pending():
measurements = {}
for probe_id in self.probe_ids: for probe_id in self.probe_ids:
measurements = {}
measurements['w'] = randrange(self.min_value, self.max_value) measurements['w'] = randrange(self.min_value, self.max_value)
measurements['v'] = 230.0 measurements['v'] = 230.0
measurements['a'] = measurements['w'] / measurements['v'] measurements['a'] = measurements['w'] / measurements['v']

View File

@ -20,8 +20,11 @@ import subprocess
import time import time
import uuid import uuid
from kwapi.openstack.common import log
from driver import Driver from driver import Driver
LOG = log.getLogger(__name__)
class Ipmi(Driver): class Ipmi(Driver):
"""Driver for IPMI cards.""" """Driver for IPMI cards."""
@ -40,11 +43,12 @@ class Ipmi(Driver):
def run(self): def run(self):
"""Starts the driver thread.""" """Starts the driver thread."""
self.create_cache() measurements = {}
while not self.stop_request_pending(): while not self.stop_request_pending():
measurements = {} watts = self.get_watts()
measurements['w'] = self.get_watts() if watts is not None:
self.send_measurements(self.probe_ids[0], measurements) measurements['w'] = watts
self.send_measurements(self.probe_ids[0], measurements)
time.sleep(1) time.sleep(1)
def get_cache_filename(self): def get_cache_filename(self):
@ -54,6 +58,7 @@ class Ipmi(Driver):
def create_cache(self): def create_cache(self):
"""Creates the cache file.""" """Creates the cache file."""
cache_file = self.get_cache_filename()
try: try:
os.makedirs(self.kwargs.get('cache_dir')) os.makedirs(self.kwargs.get('cache_dir'))
except OSError as exception: except OSError as exception:
@ -64,28 +69,47 @@ class Ipmi(Driver):
command += '-H ' + self.kwargs.get('host') + ' ' command += '-H ' + self.kwargs.get('host') + ' '
command += '-U ' + self.kwargs.get('username', 'root') + ' ' command += '-U ' + self.kwargs.get('username', 'root') + ' '
command += '-P ' + self.kwargs.get('password') + ' ' command += '-P ' + self.kwargs.get('password') + ' '
command += 'sdr dump ' + self.get_cache_filename() command += 'sdr dump ' + cache_file
output, error = subprocess.Popen(command, child = subprocess.Popen(command,
shell=True, shell=True,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT stderr=subprocess.PIPE
).communicate() )
output, error = child.communicate()
if child.returncode == 0:
return cache_file
else:
LOG.error('Failed to download cache from probe %s: %s'
% (self.probe_ids[0], error))
return None
def get_watts(self): def get_watts(self):
"""Returns the power consumption.""" """Returns the power consumption."""
cache_file = self.get_cache_filename() cache_file = self.get_cache_filename()
# Try to create cache (not a problem if this fails)
if not os.path.exists(cache_file): if not os.path.exists(cache_file):
self.create_cache() self.create_cache()
# Get power consumption
command = 'ipmitool ' command = 'ipmitool '
command += '-S ' + cache_file + ' ' command += '-S ' + cache_file + ' '
command += '-I ' + self.kwargs.get('interface') + ' ' command += '-I ' + self.kwargs.get('interface') + ' '
command += '-H ' + self.kwargs.get('host') + ' ' command += '-H ' + self.kwargs.get('host') + ' '
command += '-U ' + self.kwargs.get('username', 'root') + ' ' command += '-U ' + self.kwargs.get('username', 'root') + ' '
command += '-P ' + self.kwargs.get('password') + ' ' command += '-P ' + self.kwargs.get('password') + ' '
command += 'sensor reading "System Level" | cut -f2 -d"|"' command += 'sensor reading "System Level"'
output, error = subprocess.Popen(command, child = subprocess.Popen(command,
shell=True, shell=True,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT stderr=subprocess.PIPE
).communicate() )
return int(output) output, error = child.communicate()
if child.returncode == 0:
try:
return int(output.split('|')[1])
except ValueError:
LOG.error('Received data from probe %s are invalid: %s'
% (self.probe_ids[0], output))
else:
LOG.error('Failed to retrieve data from probe %s: %s'
% (self.probe_ids[0], error))
return None

View File

@ -34,33 +34,31 @@ class Wattsup(Driver):
""" """
Driver.__init__(self, probe_ids, kwargs) Driver.__init__(self, probe_ids, kwargs)
def run(self):
"""Starts the driver thread."""
# Configure serial port # Configure serial port
self.serial = serial.Serial( self.serial = serial.Serial(
port=kwargs.get('device', '/dev/ttyUSB0'), port=self.kwargs.get('device', '/dev/ttyUSB0'),
baudrate=115200, baudrate=115200,
parity=serial.PARITY_NONE, parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE, stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS, bytesize=serial.EIGHTBITS,
timeout=2, timeout=2,
) )
# Clear memory # Clear memory
self.serial.write('#R,W,0;') self.serial.write('#R,W,0;')
self.serial.read(256) self.serial.read(256)
# Start external logging with interval = 1 # Start external logging with interval = 1
self.serial.write('#L,W,3,E,1,1;') self.serial.write('#L,W,3,E,1,1;')
self.serial.read(256) self.serial.read(256)
# Take measurements
def run(self): measurements = {}
"""Starts the driver thread."""
while not self.stop_request_pending(): while not self.stop_request_pending():
try: try:
packet = self.get_packet() packet = self.get_packet()
except SerialException: except SerialException:
self.serial.close() self.serial.close()
self.stop() self.stop()
measurements = {}
measurements['w'] = self.extract_watts(packet) measurements['w'] = self.extract_watts(packet)
self.send_measurements(self.probe_ids[0], measurements) self.send_measurements(self.probe_ids[0], measurements)

View File

@ -143,5 +143,8 @@ class Collector:
try: try:
self.add(measurements['probe_id'], self.add(measurements['probe_id'],
float(measurements['w'])) float(measurements['w']))
except (TypeError, ValueError):
LOG.error('Malformed power consumption data: %s'
% measurements['w'])
except KeyError: except KeyError:
LOG.error('Malformed message (missing required key)') LOG.error('Malformed message (missing required key)')

View File

@ -135,7 +135,7 @@ def update_rrd(probe, watts):
create_rrd_file(filename) create_rrd_file(filename)
try: try:
rrdtool.update(filename, 'N:%s' % watts) rrdtool.update(filename, 'N:%s' % watts)
except rrdtool.error, e: except rrdtool.error as e:
LOG.error('Error updating RRD: %s' % e) LOG.error('Error updating RRD: %s' % e)
@ -277,10 +277,14 @@ def listen():
try: try:
probe = measurements['probe_id'].encode('utf-8') probe = measurements['probe_id'].encode('utf-8')
update_rrd(probe, float(measurements['w'])) update_rrd(probe, float(measurements['w']))
except (TypeError, ValueError):
LOG.error('Malformed power consumption data: %s'
% measurements['w'])
except KeyError:
LOG.error('Malformed message (missing required key)')
else:
if not probe in probes: if not probe in probes:
probes.add(probe) probes.add(probe)
color_seq = itertools.cycle(colors) color_seq = itertools.cycle(colors)
for probe in sorted(probes): for probe in sorted(probes):
probe_colors[probe] = color_seq.next() probe_colors[probe] = color_seq.next()
except KeyError:
LOG.error('Malformed message (missing required key)')