1
0
Fork 0

WIP: dump: added new command

The dump command dumps active profile. It's good for debugging, because
the output is flattened, i.e. it shows the resulting profile after
inheritance (profiles merging) is processed.

It keeps naming conventions - for tuned-adm it's named 'dump' action,
for API it's named 'dump_profile' method.

The 'priority' value is not output, but output is ordered according to
it.

The 'cpuinfo_regex' and 'uname_regex' are not output, but output is
rendered according to it.

Variables are not expanded.

Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
This commit is contained in:
Jaroslav Škarvada 2024-04-14 17:26:07 +02:00
parent 1fb7c803b6
commit d1a63c7b5a
No known key found for this signature in database
GPG key ID: D8E1C00E076E840B
9 changed files with 89 additions and 0 deletions

View file

@ -177,6 +177,16 @@
</defaults>
</action>
<action id="com.redhat.tuned.dump_profile">
<description>Dump TuneD profile</description>
<message>Authentication is required to dump TuneD profile</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="com.redhat.tuned.verify_profile_ignore_missing">
<description>Verify TuneD profile, ignore missing values</description>
<message>Authentication is required to verify TuneD profile</message>

View file

@ -91,6 +91,9 @@ if __name__ == "__main__":
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")
parser_dump = subparsers.add_parser("dump", help="dump current profile")
parser_dump.set_defaults(action="dump")
parser_auto_profile = subparsers.add_parser("auto_profile", help="enable automatic profile selection mode, switch to the recommended profile")
parser_auto_profile.set_defaults(action="auto_profile")

View file

@ -375,6 +375,18 @@ class Admin(object):
print("Not supported in no_daemon mode.")
return False
def _action_dbus_dump(self):
(ret, msg) = self._controller.dump()
if ret:
print(msg)
else:
self._error("Unable to dump profile: '%s'" % msg)
return self._controller.exit(ret)
def _action_dump(self):
print("Not supported in no_daemon mode.")
return False
def _action_dbus_off(self):
# 25 seconds default DBus timeout + 5 secs safety margin
timeout = 25 + 5

View file

@ -134,6 +134,9 @@ class DBusController(object):
def verify_profile(self):
return self._call("verify_profile")
def dump(self):
return self._call("dump_profile")
def verify_profile_ignore_missing(self):
return self._call("verify_profile_ignore_missing")

View file

@ -279,6 +279,12 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
return False
return self._daemon.verify_profile(ignore_missing = True)
@exports.export("", "(bs)")
def dump_profile(self, caller = None):
if caller == "":
return False
return self._daemon.dump_profile()
@exports.export("", "a{sa{ss}}")
def get_all_plugins(self, caller = None):
"""Return dictionary with accesible plugins

View file

@ -360,6 +360,30 @@ class Daemon(object):
self._not_used.set()
return ret
def dump_profile(self):
if not self.is_running():
s = "TuneD is not running"
log.error(s)
return (False, s)
if self._profile is None:
s = "no profile is set"
log.error(s)
return (False, s)
if not self._profile_applied.is_set():
s = "profile is not applied"
log.error(s)
return (False, s)
# using daemon, the main loop mustn't exit before our completion
self._not_used.clear()
log.info("dumping profile(s): %s" % self._profile.name)
s = self._unit_manager.dump_tuning()
# main loop is allowed to exit
self._not_used.set()
return (True, s)
# profile_switch is helper telling plugins whether the stop is due to profile switch
def stop(self, profile_switch = False):
if not self.is_running():

View file

@ -290,6 +290,27 @@ class Plugin(object):
else:
return None
def instance_dump_tuning(self, instance):
"""
Dump tuning if the plugin instance is active.
"""
if not instance.active:
return ""
s = "[%s]\n" % instance.name
s += "type = %s\n" % self.name
if instance._devices_expression:
s += "devices = %s\n" % instance._devices_expression
if instance._devices_udev_regex:
s += "devices_udev_regex = %s\n" % instance._devices_udev_regex
if instance._script_pre:
s += "script_pre = %s\n" % instance._script_pre
if instance._script_post:
s += "script_post = %s\n" % instance._script_post
for option, val in instance._options.items():
s += "%s = %s\n" % (option, val)
return s
def instance_update_tuning(self, instance):
"""
Apply dynamic tuning if the plugin instance is active.

View file

@ -82,6 +82,9 @@ class Instance(object):
def verify_tuning(self, ignore_missing):
return self._plugin.instance_verify_tuning(self, ignore_missing)
def dump_tuning(self):
return self._plugin.instance_dump_tuning(self)
def update_tuning(self):
self._plugin.instance_update_tuning(self)

View file

@ -156,6 +156,13 @@ class Manager(object):
ret = False
return ret
def dump_tuning(self):
s = ""
for instance in self._instances:
s += self._try_call("dump_tuning", None,
instance.dump_tuning) + "\n"
return s[:-1]
def update_tuning(self):
for instance in self._instances:
self._try_call("update_tuning", None,