1
0
Fork 0

verify: added ignore-missing mode

The verify command can now be run in ignore-missing mode. In this mode
missing/non-supported settings (i.e. those which current value is None)
are ignored and not treated as errors.

The tuned-adm got new verify options -i and --ignore-missing which
enables the ignore-missing mode, usage:
  tuned-adm verify -i
or:
  tuned-adm verify --ignore-missing

The DBus interface got new method 'verify_profile_ignore_missing' which
does the verification in ignore-missing mode.

Resolves: rhbz#1243807

Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
This commit is contained in:
Jaroslav Škarvada 2016-04-22 18:05:16 +02:00
parent b556805fe3
commit a174592cfd
13 changed files with 67 additions and 44 deletions

View file

@ -56,8 +56,9 @@ if __name__ == "__main__":
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")
parser_verify = subparsers.add_parser("verify", help="verify profile")
parser_verify.set_defaults(action="verify_profile")
parser_verify.add_argument("--ignore-missing", "-i", action="store_true", help="do not treat missing/non-supported tunings as errors")
args = parser.parse_args(sys.argv[1:])

View file

@ -180,17 +180,21 @@ class Admin(object):
profile = self._cmd.recommend_profile()
print profile
def verify_profile(self):
def verify_profile(self, ignore_missing):
ret = False
if self._controller is None:
print "Not supported in no_daemon mode."
return False
try:
ret = self._controller.verify_profile()
except TunedAdminDBusException as e:
self._error(e)
self._error("Cannot verify profile if there is no connection to daemon")
return False
else:
try:
if ignore_missing:
ret = self._controller.verify_profile_ignore_missing()
else:
ret = self._controller.verify_profile()
except TunedAdminDBusException as e:
self._error(e)
self._error("Cannot verify profile if there is no compatible running Tuned daemon (or Tuned daemon is too old).")
return False
if ret:
print "Verfication succeeded, current system settings match the preset profile."

View file

@ -80,6 +80,9 @@ class DBusController(object):
def verify_profile(self):
return self._call("verify_profile")
def verify_profile_ignore_missing(self):
return self._call("verify_profile_ignore_missing")
def off(self):
return self._call("disable")

View file

@ -68,6 +68,8 @@ DBUS_SIGNAL_PROFILE_CHANGED = "profile_changed"
STR_VERIFY_PROFILE_DEVICE_VALUE_OK = "verify: passed: device %s: %s = %s"
STR_VERIFY_PROFILE_VALUE_OK = "verify: passed: %s = %s"
STR_VERIFY_PROFILE_OK = "verify: passed: %s"
STR_VERIFY_PROFILE_DEVICE_VALUE_MISSING = "verify: skipped, missing: device %s: %s"
STR_VERIFY_PROFILE_VALUE_MISSING = "verify: skipped, missing: %s"
STR_VERIFY_PROFILE_DEVICE_VALUE_FAIL = "verify: failed: device %s: %s = %s, expected %s"
STR_VERIFY_PROFILE_VALUE_FAIL = "verify: failed: %s = %s, expected %s"
STR_VERIFY_PROFILE_FAIL = "verify: failed: %s"

View file

@ -126,4 +126,8 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
@exports.export("", "b")
def verify_profile(self):
return self._daemon.verify_profile()
return self._daemon.verify_profile(ignore_missing = False)
@exports.export("", "b")
def verify_profile_ignore_missing(self):
return self._daemon.verify_profile(ignore_missing = True)

View file

@ -197,7 +197,7 @@ class Daemon(object):
self._thread.start()
return True
def verify_profile(self):
def verify_profile(self, ignore_missing):
if not self.is_running():
log.error("tuned is not running")
return False
@ -213,7 +213,7 @@ class Daemon(object):
# using deamon, the main loop mustn't exit before our completion
self._not_used.clear()
log.info("verifying profile(s): %s" % self._profile.name)
ret = self._unit_manager.verify_tuning()
ret = self._unit_manager.verify_tuning(ignore_missing)
# main loop is allowed to exit
self._not_used.set()
return ret

View file

@ -192,7 +192,7 @@ class Plugin(object):
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):
def instance_verify_tuning(self, instance, ignore_missing):
"""
Verify static tuning if the plugin instance is active.
"""
@ -200,7 +200,7 @@ class Plugin(object):
return None
if instance.has_static_tuning:
return self._instance_verify_static(instance)
return self._instance_verify_static(instance, ignore_missing)
else:
return None
@ -227,11 +227,11 @@ class Plugin(object):
self._execute_all_non_device_commands(instance)
self._execute_all_device_commands(instance, instance.devices)
def _instance_verify_static(self, instance):
def _instance_verify_static(self, instance, ignore_missing):
ret = True
if self._verify_all_non_device_commands(instance) == False:
if self._verify_all_non_device_commands(instance, ignore_missing) == False:
ret = False
if self._verify_all_device_commands(instance, instance.devices) == False:
if self._verify_all_device_commands(instance, instance.devices, ignore_missing) == False:
ret = False
return ret
@ -346,23 +346,23 @@ class Plugin(object):
for device in devices:
self._execute_device_command(instance, command, device, new_value)
def _verify_all_non_device_commands(self, instance):
def _verify_all_non_device_commands(self, instance, ignore_missing):
ret = True
for command in filter(lambda command: not command["per_device"], self._commands.values()):
new_value = self._variables.expand(instance.options.get(command["name"], None))
if new_value is not None:
if self._verify_non_device_command(instance, command, new_value) == False:
if self._verify_non_device_command(instance, command, new_value, ignore_missing) == False:
ret = False
return ret
def _verify_all_device_commands(self, instance, devices):
def _verify_all_device_commands(self, instance, devices, ignore_missing):
ret = True
for command in filter(lambda command: command["per_device"], self._commands.values()):
new_value = instance.options.get(command["name"], None)
if new_value is None:
continue
for device in devices:
if self._verify_device_command(instance, command, device, new_value) == False:
if self._verify_device_command(instance, command, device, new_value, ignore_missing) == False:
ret = False
return ret
@ -423,10 +423,17 @@ class Plugin(object):
return re.sub(r'^\s*(0+,)+', "", v)
return v
def _verify_value(self, name, new_value, current_value, device = None):
def _verify_value(self, name, new_value, current_value, ignore_missing, device = None):
if new_value is None:
return None
ret = False
if current_value is None and ignore_missing:
if device is None:
log.info(consts.STR_VERIFY_PROFILE_VALUE_MISSING % name)
else:
log.info(consts.STR_VERIFY_PROFILE_DEVICE_VALUE_MISSING % (device, name))
return True
if current_value is not None:
current_value = self._norm_value(current_value)
new_value = self._norm_value(new_value)
@ -450,7 +457,7 @@ class Plugin(object):
log.error(consts.STR_VERIFY_PROFILE_DEVICE_VALUE_FAIL % (device, name, str(current_value).strip(), str(new_value).strip()))
return False
def _verify_device_command(self, instance, command, device, new_value):
def _verify_device_command(self, instance, command, device, new_value, ignore_missing):
if command["custom"] is not None:
return command["custom"](True, new_value, device, True)
current_value = self._get_current_value(command, device)
@ -458,9 +465,9 @@ class Plugin(object):
if new_value is None:
return None
new_value = command["set"](new_value, device, True)
return self._verify_value(command["name"], new_value, current_value, device)
return self._verify_value(command["name"], new_value, current_value, ignore_missing, device)
def _verify_non_device_command(self, instance, command, new_value):
def _verify_non_device_command(self, instance, command, new_value, ignore_missing):
if command["custom"] is not None:
return command["custom"](True, new_value, True)
current_value = self._get_current_value(command)
@ -468,7 +475,7 @@ class Plugin(object):
if new_value is None:
return None
new_value = command["set"](new_value, True)
return self._verify_value(command["name"], new_value, current_value)
return self._verify_value(command["name"], new_value, current_value, ignore_missing)
def _cleanup_all_non_device_commands(self, instance):
for command in filter(lambda command: not command["per_device"], self._commands.values()):

View file

@ -53,8 +53,8 @@ class Instance(object):
def apply_tuning(self):
self._plugin.instance_apply_tuning(self)
def verify_tuning(self):
return self._plugin.instance_verify_tuning(self)
def verify_tuning(self, ignore_missing):
return self._plugin.instance_verify_tuning(self, ignore_missing)
def update_tuning(self):
self._plugin.instance_update_tuning(self)

View file

@ -52,11 +52,14 @@ class ScriptPlugin(base.Plugin):
super(self.__class__, self)._instance_apply_static(instance)
self._call_scripts(instance._scripts, ["start"])
def _instance_verify_static(self, instance):
def _instance_verify_static(self, instance, ignore_missing):
ret = True
if super(self.__class__, self)._instance_verify_static(instance) == False:
if super(self.__class__, self)._instance_verify_static(instance, ignore_missing) == False:
ret = False
if self._call_scripts(instance._scripts, ["verify"]) == True:
args = ["verify"]
if ignore_missing:
args += ["ignore_missing"]
if self._call_scripts(instance._scripts, args) == True:
log.info(consts.STR_VERIFY_PROFILE_OK % instance._scripts)
else:
log.error(consts.STR_VERIFY_PROFILE_FAIL % instance._scripts)

View file

@ -4,6 +4,7 @@ from decorators import *
import tuned.logs
from subprocess import *
from tuned.utils.commands import commands
import tuned.consts as consts
log = tuned.logs.get()
@ -47,16 +48,14 @@ class SysctlPlugin(base.Plugin):
self._storage.set("options", instance._sysctl_original)
def _instance_verify_static(self, instance):
def _instance_verify_static(self, instance, ignore_missing):
ret = True
# override, so always skip missing
ignore_missing = True
for option, value in instance._sysctl.iteritems():
curr_val = self._read_sysctl(option)
if curr_val is None:
log.warn("verify: option '%s' is None, option is probably unavailable/unsupported on your system, skipping it",
str(option))
else:
if self._verify_value(option, self._cmd.remove_ws(self._variables.expand(value)), curr_val) == False:
ret = False
if self._verify_value(option, self._cmd.remove_ws(self._variables.expand(value)), curr_val, ignore_missing) == False:
ret = False
return ret
def _instance_unapply_static(self, instance, profile_switch = False):

View file

@ -41,14 +41,14 @@ class SysfsPlugin(base.Plugin):
else:
log.error("rejecting write to '%s' (not inside /sys)" % f)
def _instance_verify_static(self, instance):
def _instance_verify_static(self, instance, ignore_missing):
ret = True
for key, value in instance._sysfs.iteritems():
v = self._variables.expand(value)
for f in glob.iglob(key):
if self._check_sysfs(f):
curr_val = self._read_sysfs(f)
if self._verify_value(f, v, curr_val) == False:
if self._verify_value(f, v, curr_val, ignore_missing) == False:
ret = False
return ret

View file

@ -47,7 +47,7 @@ class VideoPlugin(base.Plugin):
if not os.path.exists(sys_files["method"]):
if not sim:
log.warn("radeon_powersave is not supported on '%s'" % device)
return None
return None
if value in ["default", "auto", "low", "mid", "high"]:
if not sim:
@ -73,4 +73,4 @@ class VideoPlugin(base.Plugin):
elif method == "dynpm":
return "dynpm"
else:
return None
return None

View file

@ -80,10 +80,10 @@ class Manager(object):
for instance in self._instances:
instance.apply_tuning()
def verify_tuning(self):
def verify_tuning(self, ignore_missing):
ret = True
for instance in self._instances:
if instance.verify_tuning() == False:
if instance.verify_tuning(ignore_missing) == False:
ret = False
return ret