1
0
Fork 0

Merge pull request #71 from olysonek/auto_profile

Store profile selection mode in a separate file
This commit is contained in:
Jaroslav Škarvada 2017-09-19 17:23:13 +02:00 committed by GitHub
commit 513a6ca25f
7 changed files with 118 additions and 91 deletions

View file

@ -124,6 +124,7 @@ install: install-dirs
install -Dpm 0644 tuned-main.conf $(DESTDIR)/etc/tuned/tuned-main.conf
# None profile in the moment, autodetection will be used
echo -n > $(DESTDIR)/etc/tuned/active_profile
echo -n > $(DESTDIR)/etc/tuned/profile_mode
install -Dpm 0644 bootcmdline $(DESTDIR)/etc/tuned/bootcmdline
install -Dpm 0644 modules.conf $(DESTDIR)/etc/modprobe.d/tuned.conf

View file

@ -290,6 +290,7 @@ fi
%dir %{_libexecdir}/tuned
%{_libexecdir}/tuned/defirqaffinity*
%config(noreplace) %verify(not size mtime md5) %{_sysconfdir}/tuned/active_profile
%config(noreplace) %verify(not size mtime md5) %{_sysconfdir}/tuned/profile_mode
%config(noreplace) %{_sysconfdir}/tuned/tuned-main.conf
%config(noreplace) %verify(not size mtime md5) %{_sysconfdir}/tuned/bootcmdline
%{_sysconfdir}/dbus-1/system.d/com.redhat.tuned.conf

View file

@ -3,6 +3,7 @@ import tuned.admin
from tuned.utils.commands import commands
from tuned.profiles import Locator as profiles_locator
from exceptions import TunedAdminDBusException
from tuned.exceptions import TunedException
import tuned.consts as consts
import os
import sys
@ -111,29 +112,14 @@ class Admin(object):
return profile_name
def _get_active_profile(self):
profile_name = None
contents = str.strip(self._cmd.read_file(consts.ACTIVE_PROFILE_FILE))
if contents == '':
profile_name = ''
else:
arr = contents.split('\n')
profile_name = arr[0]
if profile_name == "":
profile_name = None
profile_name, manual = self._cmd.get_active_profile()
return profile_name
def _get_profile_mode(self):
contents = str.strip(self._cmd.read_file(consts.ACTIVE_PROFILE_FILE))
if contents == '':
mode = consts.ACTIVE_PROFILE_AUTO
else:
arr = contents.split('\n')
if len(arr) == 1:
# The file was generated by old Tuned -> manual mode
mode = consts.ACTIVE_PROFILE_MANUAL
else:
mode = arr[1]
return mode
(profile, manual) = self._cmd.get_active_profile()
if manual is None:
manual = profile is not None
return consts.ACTIVE_PROFILE_MANUAL if manual else consts.ACTIVE_PROFILE_AUTO
def _print_profile_info(self, profile, profile_info):
if profile_info[0] == True:
@ -157,7 +143,14 @@ class Admin(object):
def _action_profile_info(self, profile = ""):
if profile == "":
profile = self._get_active_profile()
try:
profile = self._get_active_profile()
if profile is None:
print("No current active profile.")
return False
except TunedException as e:
self._error(str(e))
return False
return self._print_profile_info(profile, self._profiles_locator.get_profile_attrs(profile, [consts.PROFILE_ATTR_SUMMARY, consts.PROFILE_ATTR_DESCRIPTION], ["", ""]))
def _print_profile_name(self, profile_name):
@ -172,7 +165,11 @@ class Admin(object):
return self._controller.exit(self._print_profile_name(self._dbus_get_active_profile()))
def _action_active(self):
profile_name = self._get_active_profile()
try:
profile_name = self._get_active_profile()
except TunedException as e:
self._error(str(e))
return False
if profile_name is not None and not self._tuned_is_running():
print("It seems that tuned daemon is not running, preset profile is not activated.")
print("Preset profile: %s" % profile_name)
@ -183,14 +180,21 @@ class Admin(object):
print("Profile selection mode: " + mode)
def _action_dbus_profile_mode(self):
mode = self._controller.profile_mode()
mode, error = self._controller.profile_mode()
self._print_profile_mode(mode)
if error != "":
self._error(error)
return self._controller.exit(False)
return self._controller.exit(True)
def _action_profile_mode(self):
mode = self._get_profile_mode()
self._print_profile_mode(mode)
return True
try:
mode = self._get_profile_mode()
self._print_profile_mode(mode)
return True
except TunedException as e:
self._error(str(e))
return False
def _profile_print_status(self, ret, msg):
if ret:
@ -238,16 +242,13 @@ class Admin(object):
def _set_profile(self, profile_name, manual):
if profile_name in self._profiles_locator.get_known_names():
s = profile_name + '\n'
if manual:
s += consts.ACTIVE_PROFILE_MANUAL + '\n'
else:
s += consts.ACTIVE_PROFILE_AUTO + '\n'
if self._cmd.write_to_file(consts.ACTIVE_PROFILE_FILE, s):
try:
self._cmd.save_active_profile(profile_name, manual)
self._restart_tuned()
return True
else:
self._error("Unable to switch profile, do you have enough permissions?")
except TunedException as e:
self._error(str(e))
self._error("Unable to switch profile.")
return False
else:
self._error("Requested profile '%s' doesn't exist." % profile_name)

View file

@ -1,5 +1,6 @@
GLOBAL_CONFIG_FILE = "/etc/tuned/tuned-main.conf"
ACTIVE_PROFILE_FILE = "/etc/tuned/active_profile"
PROFILE_MODE_FILE = "/etc/tuned/profile_mode"
PROFILE_FILE = "tuned.conf"
RECOMMEND_CONF_FILE = "/etc/tuned/recommend.conf"
DAEMONIZE_PARENT_TIMEOUT = 5
@ -104,7 +105,7 @@ STR_VERIFY_PROFILE_FAIL = "verify: failed: '%s'"
# timout for tuned-adm operations in seconds
ADMIN_TIMEOUT = 600
# Strings for /etc/tuned/active_profile specifying if the active profile
# Strings for /etc/tuned/profile_mode specifying if the active profile
# was set automatically or manually
ACTIVE_PROFILE_AUTO = "auto"
ACTIVE_PROFILE_MANUAL = "manual"

View file

@ -1,6 +1,7 @@
from tuned import exports
import tuned.logs
import tuned.exceptions
from tuned.exceptions import TunedException
import threading
import tuned.consts as consts
from tuned.utils.commands import commands
@ -128,14 +129,23 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
else:
return ""
@exports.export("", "s")
@exports.export("", "(ss)")
def profile_mode(self, caller = None):
if caller == "":
return ""
if self._daemon.manual:
return consts.ACTIVE_PROFILE_MANUAL
else:
return consts.ACTIVE_PROFILE_AUTO
return "unknown", "Unauthorized"
manual = self._daemon.manual
if manual is None:
# This means no profile is applied. Check the preset value.
try:
profile, manual = self._cmd.get_active_profile()
if manual is None:
manual = profile is not None
except TunedException as e:
mode = "unknown"
error = str(e)
return mode, error
mode = consts.ACTIVE_PROFILE_MANUAL if manual else consts.ACTIVE_PROFILE_AUTO
return mode, ""
@exports.export("", "b")
def disable(self, caller = None):

View file

@ -61,6 +61,11 @@ class Daemon(object):
manual = True
if profile_name is None:
(profile_name, manual) = self._get_startup_profile()
if profile_name is None:
log.info("No profile is preset, running in manual mode. No profile will be enabled.")
# Passed through '-p' cmdline option
elif profile_name == "":
log.info("No profile will be enabled.")
self._profile = None
self._manual = None
@ -72,7 +77,7 @@ class Daemon(object):
if profile_name == "" or profile_name is None:
self._profile = None
self._manual = None
self._manual = manual
elif profile_name not in self.profile_loader.profile_locator.get_known_names():
raise TunedException(self._notify_profile_changed(profile_name, False, "Requested profile '%s' doesn't exist." % profile_name))
else:
@ -93,8 +98,7 @@ class Daemon(object):
@property
def manual(self):
# manual == None means /etc/tuned/active_profile is empty -> automatic mode
return self._manual == True or self._manual is None
return self._manual
@property
def profile_loader(self):
@ -170,58 +174,23 @@ class Daemon(object):
def _save_active_profile(self, profile_name, manual):
try:
with open(consts.ACTIVE_PROFILE_FILE, "w") as f:
if len(profile_name) > 0:
f.write(profile_name + "\n")
if manual:
f.write(consts.ACTIVE_PROFILE_MANUAL + "\n")
else:
f.write(consts.ACTIVE_PROFILE_AUTO + "\n")
except (OSError,IOError) as e:
log.error("Cannot write active profile into %s: %s" % (consts.ACTIVE_PROFILE_FILE, str(e)))
self._cmd.save_active_profile(profile_name, manual)
except TunedException as e:
log.error(str(e))
def _set_recommended_profile(self):
log.info("no profile preset, checking what is recommended for your configuration")
def _get_recommended_profile(self):
log.info("Running in automatic mode, checking what profile is recommended for your configuration.")
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, False)
log.info("Using '%s' profile" % profile)
return profile
def _get_startup_profile(self):
manual = False
try:
with open(consts.ACTIVE_PROFILE_FILE, "r") as f:
content = f.read().strip()
if content == "":
profile = self._set_recommended_profile()
else:
arr = content.split('\n')
if len(arr) > 2 or (len(arr) == 2 and arr[1] != consts.ACTIVE_PROFILE_AUTO and arr[1] != consts.ACTIVE_PROFILE_MANUAL):
profile = self._set_recommended_profile()
log.error("cannot read active profile from '%s': bad format. Falling back to '%s' profile."
% consts.ACTIVE_PROFILE_FILE, profile)
else:
profile = arr[0]
if len(arr) == 2:
manual = arr[1] == consts.ACTIVE_PROFILE_MANUAL
if not manual:
profile = self._set_recommended_profile()
else:
# The file has only one line - generated by previous Tuned version.
# Treat the profile as manually set.
manual = True
return (profile, manual)
except IOError as e:
if e.errno == errno.ENOENT:
# No such file or directory
profile = self._set_recommended_profile()
else:
profile = consts.DEFAULT_PROFILE
log.error("error reading active profile from '%s', falling back to '%s' profile" % (consts.ACTIVE_PROFILE_FILE, profile))
return (profile, manual)
except (OSError, EOFError) as e:
log.error("cannot read active profile, falling back to '%s' profile" % consts.DEFAULT_PROFILE)
return (consts.DEFAULT_PROFILE, manual)
profile, manual = self._cmd.get_active_profile()
if manual is None:
manual = profile is not None
if not manual:
profile = self._get_recommended_profile()
return profile, manual
def is_enabled(self):
return self._profile is not None

View file

@ -8,6 +8,7 @@ from configobj import ConfigObj, ConfigObjError
import re
import procfs
from subprocess import *
from tuned.exceptions import TunedException
log = tuned.logs.get()
@ -463,3 +464,46 @@ class commands:
return val
except ValueError:
return None
def get_active_profile(self):
profile_name = ""
mode = ""
try:
with open(consts.ACTIVE_PROFILE_FILE, "r") as f:
profile_name = f.read().strip()
except IOError as e:
if e.errno != errno.ENOENT:
raise TunedException("Failed to read active profile: %s" % e)
except (OSError, EOFError) as e:
raise TunedException("Failed to read active profile: %s" % e)
try:
with open(consts.PROFILE_MODE_FILE, "r") as f:
mode = f.read().strip()
if mode not in ["", consts.ACTIVE_PROFILE_AUTO, consts.ACTIVE_PROFILE_MANUAL]:
raise TunedException("Invalid value in file %s." % consts.PROFILE_MODE_FILE)
except IOError as e:
if e.errno != errno.ENOENT:
raise TunedException("Failed to read profile mode: %s" % e)
except (OSError, EOFError) as e:
raise TunedException("Failed to read profile mode: %s" % e)
if mode == "":
manual = None
else:
manual = mode == consts.ACTIVE_PROFILE_MANUAL
if profile_name == "":
profile_name = None
return (profile_name, manual)
def save_active_profile(self, profile_name, manual):
try:
with open(consts.ACTIVE_PROFILE_FILE, "w") as f:
if profile_name is not None:
f.write(profile_name + "\n")
except (OSError,IOError) as e:
raise TunedException("Cannot write active profile into %s: %s" % (consts.ACTIVE_PROFILE_FILE, str(e)))
try:
with open(consts.PROFILE_MODE_FILE, "w") as f:
mode = consts.ACTIVE_PROFILE_MANUAL if manual else consts.ACTIVE_PROFILE_AUTO
f.write(mode + "\n")
except (OSError,IOError) as e:
raise TunedException("Cannot write profile mode into %s: %s" % (consts.PROFILE_MODE_FILE, str(e)))