From 3948453c1760db1d511c90cc16a00134a40d7e9d Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 3 Feb 2012 08:44:39 +0100 Subject: [PATCH] KTune plugin --- test.cfg | 4 ++ tuned/plugins/plugin_ktune.py | 84 ++++++++++++++++++++++++++++++++++ tuned/plugins/plugin_sysctl.py | 17 +++++-- tuned/profile.py | 72 ++--------------------------- 4 files changed, 105 insertions(+), 72 deletions(-) create mode 100644 tuned/plugins/plugin_ktune.py diff --git a/test.cfg b/test.cfg index 91a76ce..c0c757e 100644 --- a/test.cfg +++ b/test.cfg @@ -57,6 +57,10 @@ vm.dirty_ratio = 50 # Doesn't exist for 2.6.30++ anymore # vm.pagecache = 90 +[my_ktune_plugin] +type=ktune +script=test.sh +elevator=deadline [my_cpu_plugin] type=cpu diff --git a/tuned/plugins/plugin_ktune.py b/tuned/plugins/plugin_ktune.py new file mode 100644 index 0000000..962f29f --- /dev/null +++ b/tuned/plugins/plugin_ktune.py @@ -0,0 +1,84 @@ +import tuned.plugins +import tuned.logs +import tuned.monitors +import os +import struct +import glob +from subprocess import * + +log = tuned.logs.get() + +class KTunePlugin(tuned.plugins.Plugin): + """ + """ + + def __init__(self, devices, options): + """ + """ + super(self.__class__, self).__init__(None, options) + self._updated = False + self._scripts = [] + self._load_ktuned() + self._scripts.append(self._options["script"]) + + @classmethod + def _get_default_options(cls): + # TODO: match cciss* somehow + return { + "elevator" : "", + "script" : "", + "elevator_devs" : "/sys/block/sd*/queue/scheduler", + } + + def _load_ktuned(self): + for sh in glob.glob("/etc/ktune.d/*.sh"): + script = os.path.join("/etc/ktune.d/", sh) + if not script in self._scripts: + self._scripts.append(script) + return True + + def _apply_elevator(self): + for dev in glob.glob(self._options["elevator_devs"]): + log.debug("Applying elevator: %s < %s" % (dev, self._options["elevator"])) + try: + f = open(dev, "w") + f.write(self._options["elevator"]) + f.close() + except (OSError,IOError) as e: + log.error("Setting elevator on %s error: %s" % (dev, e)) + return True + + def _revert_elevator(self): + for dev in glob.glob(self._options["elevator_devs"]): + log.debug("Applying elevator: %s < cfs" % (dev)) + try: + f = open(dev, "w") + f.write("cfs") + f.close() + except (OSError,IOError) as e: + log.error("Setting elevator on %s error: %s" % (dev, e)) + + def _call_scripts(self, arg = "start"): + for script in self._scripts: + log.info("Calling script %s" % (script)) + try: + proc = Popen([script, arg], stdout=PIPE, stderr=PIPE) + out, err = proc.communicate() + + if proc.returncode: + log.error("script %s error: %s" % (script, err[:-1])) + except (OSError,IOError) as e: + log.error("Script %s error: %s" % (script, e)) + return True + + def cleanup(self): + self._revert_elevator() + self._call_scripts("stop") + + def update_tuning(self): + if self._updated: + return + + self._updated = True + self._apply_elevator() + self._call_scripts() diff --git a/tuned/plugins/plugin_sysctl.py b/tuned/plugins/plugin_sysctl.py index c83001c..a9943e1 100644 --- a/tuned/plugins/plugin_sysctl.py +++ b/tuned/plugins/plugin_sysctl.py @@ -3,6 +3,7 @@ import tuned.logs import tuned.monitors import os import struct +import glob from subprocess import * log = tuned.logs.get() @@ -16,9 +17,20 @@ class SysctlPlugin(tuned.plugins.Plugin): """ super(self.__class__, self).__init__(None, options) self._options = options - self._latency = None self._updated = False self._sysctl_original = {} + self._load_ktuned() + + def _load_ktuned(self): + for cfg in glob.glob("/etc/ktune.d/*.conf"): + f = open(os.path.join("/etc/ktune.d/", cfg)) + for line in f.readlines(): + if not line.strip().startswith("#") and line.find("=") != -1: + k = line.split('=')[0].strip() + v = line.split('=')[1].strip() + self._options[k] = v + f.close() + return True def _exec_sysctl(self, data, write = False): if write: @@ -49,7 +61,6 @@ class SysctlPlugin(tuned.plugins.Plugin): def cleanup(self): self._revert_sysctl() - os.close(self._cpu_latency_fd) def update_tuning(self): if self._updated: @@ -57,5 +68,3 @@ class SysctlPlugin(tuned.plugins.Plugin): self._updated = True self._apply_sysctl() - - diff --git a/tuned/profile.py b/tuned/profile.py index 496e937..ef63609 100644 --- a/tuned/profile.py +++ b/tuned/profile.py @@ -34,61 +34,8 @@ class Profile(object): def __init__(self, manager, config_file): self._manager = manager self._config_file = config_file - self._scripts = [] - self._elevator = "" - # TODO: match cciss* somehow - self._elevator_devs = "/sys/block/sd*/queue/scheduler" self._plugin_configs = {} - def _load_ktuned(self): - for cfg in glob.glob("/etc/ktune.d/*.conf"): - f = open(os.path.join("/etc/ktune.d/", cfg)) - for line in f.readlines(): - if not line.strip().startswith("#") and line.find("=") != -1: - k = out.split('=')[0].strip() - v = out.split('=')[1].strip() - self._sysctl[k] = v - f.close() - for sh in glob.glob("/etc/ktune.d/*.sh"): - script = os.path.join("/etc/ktune.d/", sh) - if not script in self._scripts: - self._scripts.append(script) - return True - - def _apply_elevator(self): - for dev in glob.glob(self._elevator_devs): - log.debug("Applying elevator: %s < %s" % (dev, self._elevator)) - try: - f = open(dev, "w") - f.write(self._elevator) - f.close() - except (OSError,IOError) as e: - log.error("Setting elevator on %s error: %s" % (dev, e)) - return True - - def _revert_elevator(self): - for dev in glob.glob(self._elevator_devs): - log.debug("Applying elevator: %s < cfs" % (dev)) - try: - f = open(dev, "w") - f.write("cfs") - f.close() - except (OSError,IOError) as e: - log.error("Setting elevator on %s error: %s" % (dev, e)) - - def _call_scripts(self, arg = "start"): - for script in self._scripts: - log.info("Calling script %s" % (script)) - try: - proc = Popen([script, arg], stdout=PIPE, stderr=PIPE) - out, err = proc.communicate() - - if proc.returncode: - log.error("script %s error: %s" % (script, err[:-1])) - except (OSError,IOError) as e: - log.error("Script %s error: %s" % (script, e)) - return True - def _replace_plugin(self, name, plugin_cfg): # Iterates over already loaded plugins. # If the already loaded plugin contains the same device as the newly @@ -176,18 +123,9 @@ class Profile(object): if cfg.has_option("main", "include"): self._load_config(manager, cfg.get("main", "include")) - if cfg.has_option("main", "script"): - script = os.path.abspath(cfg.get("main", "script")) - if not script in self._scripts: - self._scripts.append(script) - - if cfg.has_option("main", "elevator"): - self._elevator = cfg.get("main", "elevator") - - if cfg.has_option("main", "elevator_tune_devs"): - self._elevator_devs = cfg.get("main", "elevator_tune_devs") - for section in cfg.sections(): + if section == "main": + continue if not cfg.has_option(section, "type"): log.error("No 'type' option for %s plugin" % (section)) continue @@ -198,9 +136,7 @@ class Profile(object): def load(self): return (self._load_config(self._manager, self._config_file) and - self._apply_config() and self._load_ktuned() and - self._apply_elevator() and self._call_scripts()) + self._apply_config()) def cleanup(self): - self._revert_elevator() - self._call_scripts("stop") + pass