Merge pull request #71 from olysonek/auto_profile
Store profile selection mode in a separate file
This commit is contained in:
commit
513a6ca25f
7 changed files with 118 additions and 91 deletions
1
Makefile
1
Makefile
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
Loading…
Reference in a new issue