1
0
Fork 0

Monitors for the same devices are loaded only once, disk plugin ported from tuned1

This commit is contained in:
Jan Kaluza 2012-02-07 12:43:58 +01:00
parent 1da86d6a14
commit fa4e8745b8
5 changed files with 122 additions and 5 deletions

View file

@ -72,3 +72,7 @@ merge=1
[my_broken_plugin] [my_broken_plugin]
type=broken type=broken
[my_disk_plugin]
type=disk

View file

@ -11,6 +11,13 @@ class DiskMonitor(tuned.monitors.Monitor):
available = set(filter(cls._is_device_supported, block_devices)) available = set(filter(cls._is_device_supported, block_devices))
cls._available_devices = available cls._available_devices = available
for d in available:
cls._load[d] = {}
cls._load[d]["new"] = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
cls._load[d]["max"] = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
cls._update_disk(d)
cls._load[d]["max"] = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
@classmethod @classmethod
def _is_device_supported(cls, device): def _is_device_supported(cls, device):
vendor_file = "/sys/block/%s/device/vendor" % device vendor_file = "/sys/block/%s/device/vendor" % device
@ -24,9 +31,26 @@ class DiskMonitor(tuned.monitors.Monitor):
@classmethod @classmethod
def update(cls): def update(cls):
for device in cls._updating_devices: for device in cls._updating_devices:
# TODO cls._update_disk(device)
cls._load[device] = None
@classmethod @classmethod
def _update_disk(cls, name): def _update_disk(cls, dev):
pass l = open("/sys/block/"+dev+"/stat", "r").read()
cls._load[dev]["old"] = cls._load[dev]["new"]
cls._load[dev]["new"] = l.split()
l = cls._calcdiff(dev)
for i in xrange(len(l)):
if l[i] > cls._load[dev]["max"][i]:
cls._load[dev]["max"][i] = l[i]
cls._load[dev]['diff'] = cls._calcdiff(dev)
cls._load[dev]["READ"] = float(cls._load[dev]["diff"][1]) / float(cls._load[dev]["max"][1])
cls._load[dev]["WRITE"] = float(cls._load[dev]["diff"][5]) / float(cls._load[dev]["max"][5])
@classmethod
def _calcdiff(cls, dev):
l = []
for i in xrange(len(cls._load[dev]["old"])):
l.append(int(cls._load[dev]["new"][i]) - int(cls._load[dev]["old"][i]))
return l

View file

@ -14,6 +14,12 @@ class MonitorRepository(tuned.patterns.Singleton):
log.debug("creating monitor %s" % plugin_name) log.debug("creating monitor %s" % plugin_name)
# TODO: exception handling # TODO: exception handling
monitor_cls = self._loader.load(plugin_name) monitor_cls = self._loader.load(plugin_name)
for monitor in self._monitors:
if (isinstance(monitor, monitor_cls) and
(monitor.devices == devices or devices == None)):
return monitor
monitor_instance = monitor_cls(devices) monitor_instance = monitor_cls(devices)
self._monitors.add(monitor_instance) self._monitors.add(monitor_instance)
return monitor_instance return monitor_instance

View file

@ -0,0 +1,84 @@
import os, copy
import tuned.plugins
import tuned.logs
import tuned.monitors
import struct
log = tuned.logs.get()
class DiskPlugin(tuned.plugins.Plugin):
_supported_vendors = ["ATA", "SCSI"]
def __init__(self, devices, options):
"""
"""
super(self.__class__, self).__init__(None, options)
self.devidle = {}
self.power = ["255", "225", "195", "165", "145", "125", "105", "85", "70", "55", "30", "20"]
self.spindown = ["0", "250", "230", "210", "190", "170", "150", "130", "110", "90", "70", "60"]
self.levels = len(self.power)
self._load_monitor = tuned.monitors.get_repository().create("disk", devices)
@classmethod
def tunable_devices(cls):
block_devices = os.listdir("/sys/block")
available = set(filter(cls._is_device_supported, block_devices))
cls._available_devices = available
@classmethod
def _is_device_supported(cls, device):
vendor_file = "/sys/block/%s/device/vendor" % device
try:
vendor = open(vendor_file).read().strip()
except IOError:
return False
return vendor in cls._supported_vendors
def _updateIdle(self, dev, devload):
idle = self.devidle.setdefault(dev, {})
idle.setdefault("LEVEL", 0)
for type in ("READ", "WRITE"):
if devload[type] == 0.0:
idle.setdefault(type, 0)
idle[type] += 1
else:
idle.setdefault(type, 0)
idle[type] = 0
def cleanup(self):
log.debug("Cleanup")
for dev in self.devidle.keys():
if self.devidle[dev]["LEVEL"] > 0:
os.system("hdparm -S0 -B255 /dev/"+dev+" > /dev/null 2>&1")
def update_tuning(self):
load = self._load_monitor.get_load()
for dev, devload in load.iteritems():
self._updateIdle(dev, devload)
if self.devidle[dev]["LEVEL"] < self.levels-1 and self.devidle[dev]["READ"] >= 6 and self.devidle[dev]["WRITE"] >= 6:
self.devidle[dev].setdefault("LEVEL", 0)
self.devidle[dev]["LEVEL"] += 1
level = self.devidle[dev]["LEVEL"]
log.debug("Level changed to %d (power %s, spindown %s)" % (level, self.power[level], self.spindown[level]))
os.system("hdparm -S"+self.power[level]+" -B"+self.spindown[level]+" /dev/"+dev+" > /dev/null 2>&1")
if self.devidle[dev]["LEVEL"] > 0 and (self.devidle[dev]["READ"] == 0 or self.devidle[dev]["WRITE"] == 0):
self.devidle[dev].setdefault("LEVEL", 0)
self.devidle[dev]["LEVEL"] -= 2
if self.devidle[dev]["LEVEL"] < 0:
self.devidle[dev]["LEVEL"] = 0
level = self.devidle[dev]["LEVEL"]
log.debug("Level changed to %d (power %s, spindown %s)" % (level, self.power[level], self.spindown[level]))
os.system("hdparm -S"+self.power[level]+" -B"+self.spindown[level]+" /dev/"+dev+" > /dev/null 2>&1")
log.debug("%s load: read %f, write %f" % (dev, load[dev]["READ"], load[dev]["WRITE"]))
log.debug("%s idle: read %d, write %d, level %d" % (dev, self.devidle[dev]["READ"], self.devidle[dev]["WRITE"], self.devidle[dev]["LEVEL"]))

View file

@ -49,7 +49,6 @@ class NetTuningPlugin(tuned.plugins.Plugin):
load = self._load_monitor.get_load() load = self._load_monitor.get_load()
for dev, devload in load.iteritems(): for dev, devload in load.iteritems():
self._updateIdle(dev, devload) self._updateIdle(dev, devload)
print self.devidle
if self.devidle[dev]["LEVEL"] == 0 and self.devidle[dev]["READ"] >= 6 and self.devidle[dev]["WRITE"] >= 6: if self.devidle[dev]["LEVEL"] == 0 and self.devidle[dev]["READ"] >= 6 and self.devidle[dev]["WRITE"] >= 6:
self.devidle[dev]["LEVEL"] = 1 self.devidle[dev]["LEVEL"] = 1