Add new org.osbuild.tuned stage for setting active TuneD profile

Add a new stage for setting active TuneD profile. The stage checks the
value of chosen TuneD profile(s) with the list of available TuneD
profiles installed in the filesystem root. If any of the chosen profiles
does not exist, the stage raises an exception.

Add unit tests for the new stage.

Fix #792

Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
Tomas Hozza 2021-09-06 14:39:30 +02:00 committed by Tomas Hozza
parent 5b5ec8e6b4
commit 1cab686f7a
6 changed files with 1719 additions and 0 deletions

105
stages/org.osbuild.tuned Executable file
View file

@ -0,0 +1,105 @@
#!/usr/bin/python3
"""
Sets active TuneD profile.
The stage calls sets active TuneD profile to 'profiles' as if one called
'tuned-adm profile <profile>'. In the most usual case, only one active profile
is set. However in case multiple profiles are provided, then TuneD tries to
merge all profiles into active configuration. In case of conflicting values,
the value from the latest profile is used.
"""
import os
import sys
import osbuild.api
SCHEMA = """
"additionalProperties": false,
"required": ["profiles"],
"description": "Manually set TuneD profile.",
"properties": {
"profiles": {
"type": "array",
"description": "TuneD profile to activate. If multiple profiles are provided, TuneD will try to merge them.",
"minItems": 1,
"items": {
"type": "string"
}
}
}
"""
class TunedProfilesDB:
"""
Class for loading available TuneD profiles from the given filesystem tree
and checking if a profile with particular name exists.
"""
def __init__(self, tree):
self._available_profiles = self._load_available_profiles(tree)
@staticmethod
def _load_available_profiles(tree):
"""
Loads available TuneD profiles.
TuneD determines available profile names by listing all directories
in 'profile_directories' with "tuned.conf" file inside them. Profile names
are names of the directories.
"""
available_profiles = set()
# Directories, from which TuneD loads profile definitions
profile_directories = [
"/usr/lib/tuned",
"/etc/tuned"
]
profile_config_file = "tuned.conf"
for path in profile_directories:
for dir_entry in os.scandir(f"{tree}{path}"):
if dir_entry.is_dir() and os.path.isfile(f"{tree}{path}/{dir_entry.name}/{profile_config_file}"):
available_profiles.add(dir_entry.name)
return available_profiles
def check_profile_exists(self, profile):
"""
Checks whether a profile with the given name exists.
"""
if profile in self._available_profiles:
return True
return False
def main(tree, options):
# File which holds the name of the active profile
active_profile_file = "/etc/tuned/active_profile"
# File which tells TuneD whether the active profile was set manually or automatically
profile_mode_file = "/etc/tuned/profile_mode"
profiles = options["profiles"]
profiles_db = TunedProfilesDB(tree)
for profile in profiles:
if not profiles_db.check_profile_exists(profile):
raise ValueError(f"TuneD profile '{profile}' does not exist")
# Set the active profile
with open(f"{tree}{active_profile_file}", "w") as f:
f.write(" ".join(profiles) + "\n")
# Mode needs to be set to "manual" if set explicitly
with open(f"{tree}{profile_mode_file}", "w") as f:
f.write("manual\n")
return 0
if __name__ == '__main__':
args = osbuild.api.arguments()
r = main(args["tree"], args["options"])
sys.exit(r)