Add an option to configure profile directories
Resolves: RHEL-26157
This commit is contained in:
parent
a916594a49
commit
90ea23b8b3
8 changed files with 45 additions and 28 deletions
|
|
@ -6,10 +6,19 @@
|
|||
*TuneD* stores profiles in the following directories:
|
||||
|
||||
[filename]`/usr/lib/tuned/`::
|
||||
Distribution-specific profiles are stored in the directory. Each profile has its own directory. The profile consists of the main configuration file called `tuned.conf`, and optionally other files, for example helper scripts.
|
||||
Distribution-specific profiles are stored in the [filename]`/usr/lib/tuned/` directory. Each profile has its own directory. The profile consists of the main configuration file called `tuned.conf`, and optionally other files, for example helper scripts.
|
||||
|
||||
[filename]`/etc/tuned/`::
|
||||
If you need to customize a profile, copy the profile directory into the directory, which is used for custom profiles. If there are two profiles of the same name, the custom profile located in [filename]`/etc/tuned/` is used.
|
||||
If you need to customize a profile, copy the profile directory into the [filename]`/etc/tuned/` directory, which is used for custom profiles, and then adjust it. If there is a system profile and a custom profile of the same name, the custom profile located in [filename]`/etc/tuned/` is used.
|
||||
|
||||
.User-defined profile directories
|
||||
====
|
||||
If you want to make TuneD load profiles from a directory other than [filename]`/usr/lib/tuned/` and [filename]`/etc/tuned/`, you can list it in [filename]`/etc/tuned/tuned-main.conf` as follows:
|
||||
----
|
||||
profile_dirs=/usr/lib/tuned,/etc/tuned,/my/custom/profiles
|
||||
----
|
||||
In this example, profiles are loaded also from [filename]`/my/custom/profiles/`. If two directories contain profiles with the same names, the one that is listed later takes precedence.
|
||||
====
|
||||
|
||||
[role="_additional-resources"]
|
||||
.Additional resources
|
||||
|
|
|
|||
|
|
@ -124,10 +124,11 @@ if __name__ == "__main__":
|
|||
log_level = options.pop("loglevel")
|
||||
result = False
|
||||
|
||||
profile_dirs = config.get_list(consts.CFG_PROFILE_DIRS, consts.CFG_DEF_PROFILE_DIRS)
|
||||
dbus = config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON)
|
||||
|
||||
try:
|
||||
admin = tuned.admin.Admin(dbus, debug, asynco, timeout, log_level)
|
||||
admin = tuned.admin.Admin(profile_dirs, dbus, debug, asynco, timeout, log_level)
|
||||
|
||||
result = admin.action(action_name, **options)
|
||||
except:
|
||||
|
|
|
|||
10
tuned-gui.py
10
tuned-gui.py
|
|
@ -130,7 +130,7 @@ class Base(object):
|
|||
return
|
||||
|
||||
self.manager = tuned.gtk.gui_profile_loader.GuiProfileLoader(
|
||||
tuned.consts.LOAD_DIRECTORIES)
|
||||
self.config.get_list(consts.CFG_PROFILE_DIRS, consts.CFG_DEF_PROFILE_DIRS))
|
||||
|
||||
self.plugin_loader = tuned.gtk.gui_plugin_loader.GuiPluginLoader()
|
||||
|
||||
|
|
@ -373,8 +373,8 @@ class Base(object):
|
|||
|
||||
try:
|
||||
self.manager.remove_profile(profile, is_admin=self.is_admin)
|
||||
except ManagerException:
|
||||
self.error_dialog('failed to authorize', '')
|
||||
except ManagerException as ex:
|
||||
self.error_dialog('Removing profile failed', ex.__str__())
|
||||
return
|
||||
|
||||
for item in self.treestore_profiles:
|
||||
|
|
@ -591,8 +591,8 @@ class Base(object):
|
|||
copied_profile.name = self.editing_profile_name + '-modified'
|
||||
try:
|
||||
self.manager.save_profile(copied_profile)
|
||||
except ManagerException:
|
||||
self.error_dialog('failed to authorize', '')
|
||||
except ManagerException as ex:
|
||||
self.error_dialog('Error saving profile', ex.__str__())
|
||||
return
|
||||
else:
|
||||
if not TunedDialog('System profile can not be modified '
|
||||
|
|
|
|||
|
|
@ -82,3 +82,8 @@ log_file_max_size = 1MB
|
|||
# - not_on_exit: rollbacks are always performed on a profile
|
||||
# switch, but not on any kind of TuneD process exit
|
||||
# rollback = auto
|
||||
|
||||
# Directories to search for profiles separated by , or ;
|
||||
# In case of conflicts in profile names, the later directory
|
||||
# takes precedence
|
||||
# profile_dirs = /usr/lib/tuned,/etc/tuned
|
||||
|
|
|
|||
|
|
@ -15,15 +15,15 @@ import threading
|
|||
import logging
|
||||
|
||||
class Admin(object):
|
||||
def __init__(self, dbus = True, debug = False, asynco = False,
|
||||
timeout = consts.ADMIN_TIMEOUT,
|
||||
def __init__(self, profile_dirs, dbus = True, debug = False,
|
||||
asynco = False, timeout = consts.ADMIN_TIMEOUT,
|
||||
log_level = logging.ERROR):
|
||||
self._dbus = dbus
|
||||
self._debug = debug
|
||||
self._async = asynco
|
||||
self._timeout = timeout
|
||||
self._cmd = commands(debug)
|
||||
self._profiles_locator = profiles_locator(consts.LOAD_DIRECTORIES)
|
||||
self._profiles_locator = profiles_locator(profile_dirs)
|
||||
self._daemon_action_finished = threading.Event()
|
||||
self._daemon_action_profile = ""
|
||||
self._daemon_action_result = True
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ DBUS_INTERFACE = "com.redhat.tuned.control"
|
|||
DBUS_OBJECT = "/Tuned"
|
||||
DEFAULT_PROFILE = "balanced"
|
||||
DEFAULT_STORAGE_FILE = "/run/tuned/save.pickle"
|
||||
LOAD_DIRECTORIES = ["/usr/lib/tuned", "/etc/tuned"]
|
||||
SYSTEM_PROFILE_DIR = "/usr/lib/tuned"
|
||||
PERSISTENT_STORAGE_DIR = "/var/lib/tuned"
|
||||
PLUGIN_MAIN_UNIT_NAME = "main"
|
||||
# Magic section header because ConfigParser does not support "headerless" config
|
||||
|
|
@ -122,6 +122,7 @@ CFG_UNIX_SOCKET_PERMISIONS = "unix_socket_permissions"
|
|||
CFG_UNIX_SOCKET_CONNECTIONS_BACKLOG = "connections_backlog"
|
||||
CFG_CPU_EPP_FLAG = "hwp_epp"
|
||||
CFG_ROLLBACK = "rollback"
|
||||
CFG_PROFILE_DIRS = "profile_dirs"
|
||||
|
||||
# no_daemon mode
|
||||
CFG_DEF_DAEMON = True
|
||||
|
|
@ -171,6 +172,8 @@ CFG_DEF_UNIX_SOCKET_CONNECTIONS_BACKLOG = "1024"
|
|||
CFG_FUNC_UNIX_SOCKET_CONNECTIONS_BACKLOG = "getint"
|
||||
# default rollback strategy
|
||||
CFG_DEF_ROLLBACK = "auto"
|
||||
# default profile directories
|
||||
CFG_DEF_PROFILE_DIRS = [SYSTEM_PROFILE_DIR, "/etc/tuned"]
|
||||
|
||||
PATH_CPU_DMA_LATENCY = "/dev/cpu_dma_latency"
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class Application(object):
|
|||
|
||||
profile_factory = profiles.Factory()
|
||||
profile_merger = profiles.Merger()
|
||||
profile_locator = profiles.Locator(consts.LOAD_DIRECTORIES)
|
||||
profile_locator = profiles.Locator(self.config.get_list(consts.CFG_PROFILE_DIRS, consts.CFG_DEF_PROFILE_DIRS))
|
||||
profile_loader = profiles.Loader(profile_locator, profile_factory, profile_merger, self.config, self.variables)
|
||||
|
||||
self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config, self)
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class GuiProfileLoader(object):
|
|||
|
||||
profilePath = self._locate_profile_path(profile_name)
|
||||
|
||||
if profilePath == tuned.consts.LOAD_DIRECTORIES[1]:
|
||||
if profilePath != tuned.consts.SYSTEM_PROFILE_DIR:
|
||||
file_path = profilePath + '/' + profile_name + '/' + tuned.consts.PROFILE_FILE
|
||||
config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
config_parser.optionxform = str
|
||||
|
|
@ -127,7 +127,15 @@ class GuiProfileLoader(object):
|
|||
self._load_all_profiles()
|
||||
|
||||
def save_profile(self, profile):
|
||||
path = tuned.consts.LOAD_DIRECTORIES[1] + '/' + profile.name
|
||||
# save the new profile to a non-system directory with the highest priority
|
||||
path = None
|
||||
for d in reversed(self.directories):
|
||||
if d != tuned.consts.SYSTEM_PROFILE_DIR:
|
||||
path = os.path.join(d, profile.name)
|
||||
break
|
||||
if path is None:
|
||||
raise managerException.ManagerException('Cannot save profile to a system directory')
|
||||
|
||||
config = {
|
||||
'main': collections.OrderedDict(),
|
||||
'filename': path + '/' + tuned.consts.PROFILE_FILE,
|
||||
|
|
@ -160,7 +168,7 @@ class GuiProfileLoader(object):
|
|||
raise managerException.ManagerException('Profile: '
|
||||
+ old_profile_name + ' is not in profiles')
|
||||
|
||||
path = tuned.consts.LOAD_DIRECTORIES[1] + '/' + profile.name
|
||||
path = os.path.join(self._locate_profile_path(old_profile_name), profile.name)
|
||||
|
||||
if old_profile_name != profile.name:
|
||||
self.remove_profile(old_profile_name, is_admin=is_admin)
|
||||
|
|
@ -207,20 +215,11 @@ class GuiProfileLoader(object):
|
|||
+ ' profile is stored in ' + profile_path)
|
||||
|
||||
def is_profile_removable(self, profile_name):
|
||||
|
||||
# profile is in /etc/profile
|
||||
|
||||
profile_path = self._locate_profile_path(profile_name)
|
||||
if profile_path == tuned.consts.LOAD_DIRECTORIES[1]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return not self.is_profile_factory(profile_name)
|
||||
|
||||
def is_profile_factory(self, profile_name):
|
||||
|
||||
# profile is in /usr/lib/tuned
|
||||
|
||||
return not self.is_profile_removable(profile_name)
|
||||
profile_path = self._locate_profile_path(profile_name)
|
||||
return profile_path == tuned.consts.SYSTEM_PROFILE_DIR
|
||||
|
||||
def _save_profile(self, config):
|
||||
ec = subprocess.call(['pkexec', sys.executable, tuned.gtk.gui_profile_saver.__file__ , json.dumps(config)])
|
||||
|
|
|
|||
Loading…
Reference in a new issue