recommend: add global config option to disable 'recommend' functionality
On some platforms the 'recommend' functionality doens't make sense as there is only one product variant. On such platforms the recommend functionality can be disabled by adding/changing the following in the global config (/etc/tuned/tuned-main.conf): recommend_command = 0 Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
This commit is contained in:
parent
d2043dfaf3
commit
c73bc90ae8
10 changed files with 79 additions and 39 deletions
|
|
@ -25,8 +25,10 @@ import traceback
|
|||
import tuned.admin
|
||||
import tuned.consts as consts
|
||||
import tuned.version as ver
|
||||
from tuned.utils.global_config import GlobalConfig
|
||||
|
||||
if __name__ == "__main__":
|
||||
config = GlobalConfig()
|
||||
parser = argparse.ArgumentParser(description="Manage tuned daemon.")
|
||||
parser.add_argument('--version', "-v", action = "version", version = "%%(prog)s %s.%s.%s" % (ver.TUNED_VERSION_MAJOR, ver.TUNED_VERSION_MINOR, ver.TUNED_VERSION_PATCH))
|
||||
parser.add_argument("--debug", "-d", action="store_true", help="show debug messages")
|
||||
|
|
@ -45,8 +47,9 @@ if __name__ == "__main__":
|
|||
parser_profile.set_defaults(action="profile")
|
||||
parser_profile.add_argument("profiles", metavar="profile", type=str, nargs="+", help="profile name")
|
||||
|
||||
parser_off = subparsers.add_parser("recommend", help="recommend profile")
|
||||
parser_off.set_defaults(action="recommend_profile")
|
||||
if config.get(consts.CFG_RECOMMEND_COMMAND, consts.CFG_DEF_RECOMMEND_COMMAND):
|
||||
parser_off = subparsers.add_parser("recommend", help="recommend profile")
|
||||
parser_off.set_defaults(action="recommend_profile")
|
||||
|
||||
parser_off = subparsers.add_parser("verify", help="verify profile")
|
||||
parser_off.set_defaults(action="verify_profile")
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ class Base(object):
|
|||
|
||||
self._cmd = commands(debug)
|
||||
|
||||
self.config = GlobalConfig()
|
||||
self.builder = Gtk.Builder()
|
||||
try:
|
||||
self.builder.add_from_file(GLADEUI)
|
||||
|
|
@ -298,7 +299,8 @@ class Base(object):
|
|||
self.builder.get_object('buttonDeleteSelectedProfile')
|
||||
|
||||
self.label_actual_profile.set_text(self.controller.active_profile())
|
||||
self.label_recommended_profile.set_text(self.controller.recommend_profile())
|
||||
if self.config.get(consts.CFG_RECOMMEND_COMMAND):
|
||||
self.label_recommended_profile.set_text(self.controller.recommend_profile())
|
||||
self.listbox_summary_of_active_profile = \
|
||||
self.builder.get_object('listboxSummaryOfActiveProfile')
|
||||
|
||||
|
|
|
|||
|
|
@ -10,3 +10,8 @@ sleep_interval = 1
|
|||
# Update interval for dynamic tunings (in seconds).
|
||||
# It must be multiply of the sleep_interval
|
||||
update_interval = 10
|
||||
|
||||
# Recommend functionality, if disabled "recommend" command will be not
|
||||
# available in CLI, daemon will not parse recommend.conf but will return
|
||||
# one hardcoded profile (by default "balanced")
|
||||
recommend_command = 1
|
||||
|
|
|
|||
|
|
@ -39,12 +39,19 @@ ENV_PREFIX = "TUNED_"
|
|||
PREFIX_PROFILE_FACTORY = "Factory"
|
||||
PREFIX_PROFILE_USER = "User"
|
||||
|
||||
CFG_DYNAMIC_TUNING = "dynamic_tuning"
|
||||
CFG_SLEEP_INTERVAL = "sleep_interval"
|
||||
CFG_UPDATE_INTERVAL = "update_interval"
|
||||
CFG_RECOMMEND_COMMAND = "recommend_command"
|
||||
|
||||
# default configuration
|
||||
CFG_DEF_DYNAMIC_TUNING = True
|
||||
# how long to sleep before checking for events (in seconds)
|
||||
CFG_DEF_SLEEP_INTERVAL = 1
|
||||
# update interval for dynamic tuning (in seconds)
|
||||
CFG_DEF_UPDATE_INTERVAL = 10
|
||||
# recommend command availability
|
||||
CFG_DEF_RECOMMEND_COMMAND = 1
|
||||
|
||||
STR_VERIFY_PROFILE_DEVICE_VALUE_OK = "verify: passed: device %s: %s = %s"
|
||||
STR_VERIFY_PROFILE_VALUE_OK = "verify: passed: %s = %s"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
from tuned import storage, units, monitors, plugins, profiles, exports, hardware
|
||||
from tuned.exceptions import TunedException
|
||||
from configobj import ConfigObj, ConfigObjError
|
||||
from validate import Validator
|
||||
import tuned.logs
|
||||
import controller
|
||||
import daemon
|
||||
|
|
@ -10,15 +8,12 @@ import os
|
|||
import sys
|
||||
import select
|
||||
import tuned.consts as consts
|
||||
from tuned.utils.global_config import GlobalConfig
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
__all__ = ["Application"]
|
||||
|
||||
global_config_spec = ["dynamic_tuning = boolean(default=%s)" % consts.CFG_DEF_DYNAMIC_TUNING,
|
||||
"sleep_interval = integer(default=%s)" % consts.CFG_DEF_SLEEP_INTERVAL,
|
||||
"update_interval = integer(default=%s)" % consts.CFG_DEF_UPDATE_INTERVAL]
|
||||
|
||||
class Application(object):
|
||||
def __init__(self, profile_name=None):
|
||||
storage_provider = storage.PickleProvider()
|
||||
|
|
@ -30,8 +25,8 @@ class Application(object):
|
|||
plugin_instance_factory = plugins.instance.Factory()
|
||||
self.variables = profiles.variables.Variables()
|
||||
|
||||
self.config = self._load_global_config()
|
||||
if self.config.get("dynamic_tuning"):
|
||||
self.config = GlobalConfig()
|
||||
if self.config.get(consts.CFG_DYNAMIC_TUNING):
|
||||
log.info("dynamic tuning is enabled (can be overriden in plugins)")
|
||||
else:
|
||||
log.info("dynamic tuning is globally disabled")
|
||||
|
|
@ -44,9 +39,8 @@ class Application(object):
|
|||
profile_locator = profiles.Locator(consts.LOAD_DIRECTORIES)
|
||||
profile_loader = profiles.Loader(profile_locator, profile_factory, profile_merger, self.variables)
|
||||
|
||||
|
||||
self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config)
|
||||
self._controller = controller.Controller(self._daemon)
|
||||
self._controller = controller.Controller(self._daemon, self.config)
|
||||
|
||||
self._dbus_exporter = None
|
||||
self._init_signals()
|
||||
|
|
@ -175,22 +169,6 @@ class Application(object):
|
|||
else:
|
||||
sys.exit(1)
|
||||
|
||||
def _load_global_config(self, file_name = consts.GLOBAL_CONFIG_FILE):
|
||||
"""
|
||||
Loads global configuration file.
|
||||
"""
|
||||
log.debug("reading and parsing global configuration file '%s'" % consts.GLOBAL_CONFIG_FILE)
|
||||
try:
|
||||
config = ConfigObj(file_name, configspec=global_config_spec, raise_errors = True, file_error = True, list_values = False, interpolation = False)
|
||||
except IOError as e:
|
||||
raise TunedException("Global tuned configuration file '%s' not found." % file_name)
|
||||
except ConfigObjError as e:
|
||||
raise TunedException("Error parsing global tuned configuration file '%s'." % file_name)
|
||||
vdt = Validator()
|
||||
if (not config.validate(vdt, copy=True)):
|
||||
raise TunedException("Global tuned configuration file '%s' is not valid." % file_name)
|
||||
return config
|
||||
|
||||
@property
|
||||
def daemon(self):
|
||||
return self._daemon
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from tuned import exports
|
|||
import tuned.logs
|
||||
import tuned.exceptions
|
||||
import threading
|
||||
import tuned.consts as consts
|
||||
from tuned.utils.commands import commands
|
||||
|
||||
__all__ = ["Controller"]
|
||||
|
|
@ -14,9 +15,10 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
|
|||
and export the controller interface (currently only over D-Bus).
|
||||
"""
|
||||
|
||||
def __init__(self, daemon):
|
||||
def __init__(self, daemon, global_config):
|
||||
super(self.__class__, self).__init__()
|
||||
self._daemon = daemon
|
||||
self._global_config = global_config
|
||||
self._terminate = threading.Event()
|
||||
self._cmd = commands()
|
||||
|
||||
|
|
@ -105,7 +107,7 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
|
|||
|
||||
@exports.export("", "s")
|
||||
def recommend_profile(self):
|
||||
return self._cmd.recommend_profile()
|
||||
return self._cmd.recommend_profile(hardcoded = not self._global_config.get(consts.CFG_RECOMMEND_COMMAND, consts.CFG_DEF_RECOMMEND_COMMAND))
|
||||
|
||||
@exports.export("", "b")
|
||||
def verify_profile(self):
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@ class Daemon(object):
|
|||
self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
|
||||
self._update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL)
|
||||
self._dynamic_tuning = consts.CFG_DEF_DYNAMIC_TUNING
|
||||
self._recommend_command = True
|
||||
if config is not None:
|
||||
self._sleep_interval = int(config.get("sleep_interval", consts.CFG_DEF_SLEEP_INTERVAL))
|
||||
self._update_interval = int(config.get("update_interval", consts.CFG_DEF_UPDATE_INTERVAL))
|
||||
self._dynamic_tuning = config.get("dynamic_tuning", consts.CFG_DEF_DYNAMIC_TUNING)
|
||||
self._sleep_interval = int(config.get(consts.CFG_SLEEP_INTERVAL, consts.CFG_DEF_SLEEP_INTERVAL))
|
||||
self._update_interval = int(config.get(consts.CFG_UPDATE_INTERVAL, consts.CFG_DEF_UPDATE_INTERVAL))
|
||||
self._dynamic_tuning = config.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING)
|
||||
self._recommend_command = config.get(consts.CFG_RECOMMEND_COMMAND, consts.CFG_DEF_RECOMMEND_COMMAND)
|
||||
if self._sleep_interval <= 0:
|
||||
self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
|
||||
if self._update_interval == 0:
|
||||
|
|
@ -136,7 +138,7 @@ class Daemon(object):
|
|||
|
||||
def _set_recommended_profile(self):
|
||||
log.info("no profile preset, checking what is recommended for your configuration")
|
||||
profile = self._cmd.recommend_profile()
|
||||
profile = self._cmd.recommend_profile(hardcoded = not self._recommend_command)
|
||||
log.info("using '%s' profile and setting it as active" % profile)
|
||||
self._save_active_profile(profile)
|
||||
return profile
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ class Plugin(object):
|
|||
|
||||
if instance.has_static_tuning:
|
||||
self._instance_apply_static(instance)
|
||||
if instance.has_dynamic_tuning and self._global_cfg.get("dynamic_tuning", consts.CFG_DEF_DYNAMIC_TUNING):
|
||||
if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING):
|
||||
self._run_for_each_device(instance, self._instance_apply_dynamic)
|
||||
|
||||
def instance_verify_tuning(self, instance):
|
||||
|
|
@ -206,7 +206,7 @@ class Plugin(object):
|
|||
"""
|
||||
if not instance.active:
|
||||
return
|
||||
if instance.has_dynamic_tuning and self._global_cfg.get("dynamic_tuning", consts.CFG_DEF_DYNAMIC_TUNING):
|
||||
if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING):
|
||||
self._run_for_each_device(instance, self._instance_update_dynamic)
|
||||
|
||||
# profile_switch is true if unapplying tuning due to profile switch
|
||||
|
|
@ -214,7 +214,7 @@ class Plugin(object):
|
|||
"""
|
||||
Remove all tunings applied by the plugin instance.
|
||||
"""
|
||||
if instance.has_dynamic_tuning and self._global_cfg.get("dynamic_tuning", consts.CFG_DEF_DYNAMIC_TUNING):
|
||||
if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING):
|
||||
self._run_for_each_device(instance, self._instance_unapply_dynamic)
|
||||
if instance.has_static_tuning:
|
||||
self._instance_unapply_static(instance, profile_switch)
|
||||
|
|
|
|||
|
|
@ -203,8 +203,10 @@ class commands:
|
|||
s = s.zfill(ls)
|
||||
return ",".join(s[i:i + 8] for i in range(0, len(s), 8))
|
||||
|
||||
def recommend_profile(self):
|
||||
def recommend_profile(self, hardcoded = False):
|
||||
profile = consts.DEFAULT_PROFILE
|
||||
if hardcoded:
|
||||
return profile
|
||||
for f in consts.LOAD_DIRECTORIES:
|
||||
config = ConfigObj(os.path.join(f, consts.AUTODETECT_FILE), list_values = False, interpolation = False)
|
||||
for section in reversed(config.keys()):
|
||||
|
|
|
|||
39
tuned/utils/global_config.py
Normal file
39
tuned/utils/global_config.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import tuned.logs
|
||||
from configobj import ConfigObj, ConfigObjError
|
||||
from validate import Validator
|
||||
from tuned.exceptions import TunedException
|
||||
import tuned.consts as consts
|
||||
|
||||
__all__ = ["GlobalConfig"]
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
class GlobalConfig():
|
||||
|
||||
global_config_spec = ["dynamic_tuning = boolean(default=%s)" % consts.CFG_DEF_DYNAMIC_TUNING,
|
||||
"sleep_interval = integer(default=%s)" % consts.CFG_DEF_SLEEP_INTERVAL,
|
||||
"update_interval = integer(default=%s)" % consts.CFG_DEF_UPDATE_INTERVAL,
|
||||
"recommend_command = boolean(default=%s)" % consts.CFG_DEF_RECOMMEND_COMMAND]
|
||||
|
||||
def __init__(self):
|
||||
self._cfg = {}
|
||||
self.load_config()
|
||||
|
||||
def load_config(self, file_name = consts.GLOBAL_CONFIG_FILE):
|
||||
"""
|
||||
Loads global configuration file.
|
||||
"""
|
||||
log.debug("reading and parsing global configuration file '%s'" % consts.GLOBAL_CONFIG_FILE)
|
||||
try:
|
||||
self._cfg = ConfigObj(file_name, configspec = self.global_config_spec, raise_errors = True, \
|
||||
file_error = True, list_values = False, interpolation = False)
|
||||
except IOError as e:
|
||||
raise TunedException("Global tuned configuration file '%s' not found." % file_name)
|
||||
except ConfigObjError as e:
|
||||
raise TunedException("Error parsing global tuned configuration file '%s'." % file_name)
|
||||
vdt = Validator()
|
||||
if (not self._cfg.validate(vdt, copy=True)):
|
||||
raise TunedException("Global tuned configuration file '%s' is not valid." % file_name)
|
||||
|
||||
def get(self, key, default = None):
|
||||
return self._cfg.get(key, default)
|
||||
Loading…
Reference in a new issue