1
0
Fork 0

Merge branch 'redhat-performance:master' into test-fix

This commit is contained in:
RHEmployee 2024-01-19 10:16:07 +01:00 committed by GitHub
commit 18af9e5799
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
51 changed files with 891 additions and 318 deletions

View file

@ -227,4 +227,24 @@
</defaults>
</action>
<action id="com.redhat.tuned.get_instances">
<description>Get list of active TuneD plugin instances</description>
<message>Authentication is required to get list of active TuneD plugin instances</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="com.redhat.tuned.instance_get_devices">
<description>Get list of devices assigned to the instance</description>
<message>Authentication is required to get list of devices assigned to the instance</message>
<defaults>
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
</policyconfig>

View file

@ -24,7 +24,7 @@
tuned\-adm - command line tool for switching between different tuning profiles
.SH SYNOPSIS
.B tuned\-adm
.RB [ list " | " active " | " "profile \fI[profile]\fP..." " | " "profile_info \fI[profile]\fP..." " | " off " | " auto_profile " | " profile_mode " | " "verify \fI[\-i | \-\-ignore\-missing]\fP" " | " recommend ]
.RB [ list " | " active " | " "profile \fI[profile]\fP..." " | " "profile_info \fI[profile]\fP..." " | " off " | " auto_profile " | " profile_mode " | " "verify \fI[\-i | \-\-ignore\-missing]\fP" " | " recommend " | " "instance_acquire_devices \fIdevices\fP \fIinstance\fP" " | " "get_instances \fI[plugin]\fP" " | " "instance_get_devices \fIinstance\fP" ]
.SH DESCRIPTION
This command line utility allows you to switch between user definable tuning
@ -110,6 +110,23 @@ Enable automatic profile selection mode, switch to the recommended profile.
.B profile_mode
Show current profile selection mode.
.TP
.B "instance_acquire_devices \fIdevices\fP \fIinstance\fP"
Move all provided \fIdevices\fP under the given plugin \fIinstance\fP. The plugin
instance is identified using its name from the TuneD profile.
The devices are specified using a comma-separated list. When moving a set of CPUs,
it is possible to use the cpulist syntax by including the 'cpulist:' prefix.
For instance, 'cpulist:0,2-4' will move the devices cpu0, cpu1, cpu2, and cpu4.
.TP
.B "get_instances \fI[plugin]\fP"
List active instances of a given plugin or all active instances if no plugin is specified.
.TP
.B "instance_get_devices \fIinstance\fP"
List devices currently assigned to a given instance.
.TP
.B off
Unload tunings.

View file

@ -12,6 +12,7 @@ cpufreq_conservative=+r
priority=10
governor=conservative|powersave
energy_perf_bias=normal
energy_performance_preference=balance_performance
[audio]
timeout=10

View file

@ -1,8 +1,17 @@
#
# Core isolation
#
# The 'isolated_cores=' variable below controls which cores should be
# isolated. By default we reserve 1 core per socket for housekeeping
# and isolate the rest. But you can isolate any range as shown in the
# examples below. Just remember to keep only one isolated_cores= line.
#
# Examples:
# isolated_cores=2,4-7
# isolated_cores=2-23
#
# Reserve 1 core per socket for housekeeping, isolate the rest.
# Change this for a core list or range as shown above.
isolated_cores=${f:calc_isolated_cores:1}
# To disable the kernel load balancing in certain isolated CPUs:

View file

@ -566,7 +566,7 @@ disable_ksm()
die "failed to create $KSM_MASK_FILE"
fi
# Do not run any systemctl commands if $KSM_SERVICES units do not exist
systemctl cat -- $KSM_SERVICES &> /dev/null || return
systemctl cat -- $KSM_SERVICES &> /dev/null || return 0
systemctl --now --quiet mask $KSM_SERVICES
# Unmerge all shared pages
test -f $KSM_RUN_PATH && echo 2 > $KSM_RUN_PATH
@ -578,7 +578,7 @@ enable_ksm()
{
if [ -f $KSM_MASK_FILE ]; then
# Do not run any systemctl commands if $KSM_SERVICES units do not exist
systemctl cat -- $KSM_SERVICES &> /dev/null || return
systemctl cat -- $KSM_SERVICES &> /dev/null || return 0
if systemctl --quiet unmask $KSM_SERVICES; then
rm -f $KSM_MASK_FILE
fi

View file

@ -8,6 +8,7 @@ summary=Optimize for low power consumption
[cpu]
governor=ondemand|powersave
energy_perf_bias=powersave|power
energy_performance_preference=power
[eeepc_she]

View file

@ -1,12 +1,21 @@
#
# Variable settings below override the definitions from the
# /etc/tuned/realtime-variables.conf file.
#
# Core isolation
#
# The 'isolated_cores=' variable below controls which cores should be
# isolated. By default we reserve 1 core per socket for housekeeping
# and isolate the rest. But you can isolate any range as shown in the
# examples below. Just remember to keep only one isolated_cores= line.
#
# Examples:
# isolated_cores=2,4-7
# isolated_cores=2-23
#
# Reserve 1 core per socket for housekeeping, isolate the rest.
# Change this for a core list or range as shown above.
isolated_cores=${f:calc_isolated_cores:1}
#

View file

@ -1,12 +1,21 @@
#
# Variable settings below override the definitions from the
# /etc/tuned/realtime-variables.conf file.
#
# Core isolation
#
# The 'isolated_cores=' variable below controls which cores should be
# isolated. By default we reserve 1 core per socket for housekeeping
# and isolate the rest. But you can isolate any range as shown in the
# examples below. Just remember to keep only one isolated_cores= line.
#
# Examples:
# isolated_cores=2,4-7
# isolated_cores=2-23
#
# Reserve 1 core per socket for housekeeping, isolate the rest.
# Change this for a core list or range as shown above.
isolated_cores=${f:calc_isolated_cores:1}
# Uncomment the 'isolate_managed_irq=Y' bellow if you want to move kernel

View file

@ -1,8 +1,17 @@
#
# Core isolation
#
# The 'isolated_cores=' variable below controls which cores should be
# isolated. By default we reserve 1 core per socket for housekeeping
# and isolate the rest. But you can isolate any range as shown in the
# examples below. Just remember to keep only one isolated_cores= line.
#
# Examples:
# isolated_cores=2,4-7
# isolated_cores=2-23
#
# Reserve 1 core per socket for housekeeping, isolate the rest.
# Change this for a core list or range as shown above.
isolated_cores=${f:calc_isolated_cores:1}
#

View file

@ -15,4 +15,4 @@ priority=10
/sys/module/haltpoll/parameters/guest_halt_poll_grow_start=2400000
[bootloader]
cmdline_saphana=skew_tick=1
cmdline_saphana=skew_tick=1

View file

@ -6,6 +6,7 @@
summary=Optimize for server power savings
[cpu]
energy_performance_preference=balance_power
[disk]

View file

@ -13,6 +13,7 @@ amd_cpuinfo_regex=model name\s+:.*\bAMD\b
governor=performance
energy_perf_bias=performance
min_perf_pct=100
energy_performance_preference=performance
# Marvell ThunderX
[vm.thunderx]

View file

@ -211,7 +211,7 @@ class CommandsPlugin(Plugin):
return {'size':'S','device_setting':'101'}
@decorators.command_set('size')
def _set_size(self, new_size, sim):
def _set_size(self, new_size, sim, remove):
self._size = new_size
return new_size
@ -220,7 +220,7 @@ class CommandsPlugin(Plugin):
return self._size
@decorators.command_set('device_setting',per_device = True)
def _set_device_setting(self,value,device,sim):
def _set_device_setting(self,value,device,sim,remove):
device.setting = value
return device.setting

View file

@ -97,6 +97,19 @@ if __name__ == "__main__":
parser_profile_mode = subparsers.add_parser("profile_mode", help="show current profile selection mode")
parser_profile_mode.set_defaults(action="profile_mode")
parser_instance_acquire_devices = subparsers.add_parser("instance_acquire_devices", help="acquire devices from other instances and assign them to the given instance")
parser_instance_acquire_devices.set_defaults(action="instance_acquire_devices")
parser_instance_acquire_devices.add_argument("devices", metavar="devices", type=str, help="comma-separated list of device names; may use the cpulist syntax if prefixed with 'cpulist:'")
parser_instance_acquire_devices.add_argument("instance", metavar="instance", type=str, help="name of the plugin instance which should acquire the devices")
parser_get_instances = subparsers.add_parser("get_instances", help="list active instances of a given plugin or all active instances if no plugin is specified")
parser_get_instances.set_defaults(action="get_instances")
parser_get_instances.add_argument("plugin_name", metavar="plugin_name", type=str, nargs="?", default="", help="name of the plugin to restrict the list of instances to")
parser_instance_get_devices = subparsers.add_parser("instance_get_devices", help="list devices assigned to a given instance")
parser_instance_get_devices.set_defaults(action="instance_get_devices")
parser_instance_get_devices.add_argument("instance", metavar="instance", type=str, help="name of the plugin instance")
args = parser.parse_args(sys.argv[1:])
options = vars(args)

View file

@ -134,6 +134,137 @@
<action-widget response="-1">buttonCancel1</action-widget>
</action-widgets>
</object>
<object class="GtkMenu" id="menuAddPluginValue">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="AddPluginValueMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Add Value</property>
<property name="use_underline">True</property>
<signal name="activate" handler="add_plugin_value_to_treeview" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="AddCustomPluginValueItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Add Custom Value</property>
<property name="use_underline">True</property>
<signal name="activate" handler="add_custom_plugin_value_to_treeview" swapped="no"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="DeleteValueMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Delete Value</property>
<property name="use_underline">True</property>
<signal name="activate" handler="delete_plugin_value_to_treeview" swapped="no"/>
</object>
</child>
</object>
<object class="GtkDialog" id="dialogAddCustomPluginValue">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox8">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area8">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button3">
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="xalign">0.40999999642372131</property>
<property name="yalign">0.60000002384185791</property>
<property name="image_position">bottom</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button4">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box13">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="Choose plugin value to add:1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Choose plugin value to add:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="placeholder_text" translatable="yes">Value ...</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="1">button3</action-widget>
<action-widget response="-1">button4</action-widget>
</action-widgets>
</object>
<object class="GtkDialog" id="dialogAddPlugin">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
@ -230,6 +361,99 @@
<action-widget response="-1">buttonCloseAddPlugin</action-widget>
</action-widgets>
</object>
<object class="GtkDialog" id="dialogAddPluginValue">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox5">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area5">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="xalign">0.40999999642372131</property>
<property name="yalign">0.60000002384185791</property>
<property name="image_position">bottom</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="Choose plugin value to add:">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Choose plugin value to add:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="comboboxPluginsValues">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="1">button1</action-widget>
<action-widget response="-1">button2</action-widget>
</action-widgets>
</object>
<object class="GtkDialog" id="dialogYesNo">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
@ -1561,6 +1785,8 @@
</object>
<object class="GtkWindow" id="windowProfileEditorRaw">
<property name="can_focus">False</property>
<property name="width-request">600</property>
<property name="height-request">500</property>
<signal name="delete-event" handler="on_delete_event" swapped="no"/>
<child>
<placeholder/>
@ -1601,7 +1827,7 @@
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>

View file

@ -41,7 +41,7 @@ except ValueError:
"to be installed.")
try:
from gi.repository import Gtk, GObject
from gi.repository import Gtk, GObject, GLib
except ImportError:
raise ImportError("Gtk3 backend requires pygobject to be installed.")
@ -116,8 +116,8 @@ class Base(object):
self.builder = Gtk.Builder()
try:
self.builder.add_from_file(GLADEUI)
except GObject.GError as e:
print("Error loading '%s'" % GLADEUI, file=sys.stderr)
except GLib.GError as e:
print("Error loading '%s', error: '%s'" % (GLADEUI, e), file=sys.stderr)
sys.exit(1)
#
@ -249,14 +249,14 @@ class Base(object):
self.manager.get_profile(self.controller.active_profile())
else:
self.active_profile = None
self._gobj('summaryProfileName').set_text(self.active_profile.name)
try:
self._gobj('summaryProfileName').set_text(self.active_profile.name)
except AttributeError:
self.error_dialog('No active profile set', '')
try:
self._gobj('summaryIncludedProfileName').set_text(self.active_profile.options['include'
])
except:
# keyerror probably
except (AttributeError, KeyError):
self._gobj('summaryIncludedProfileName').set_text('None')
row = Gtk.ListBoxRow()
@ -275,32 +275,33 @@ class Base(object):
self._gobj('listboxSummaryOfActiveProfile').add(sep)
sep.show()
for u in self.active_profile.units:
row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL,
spacing=0)
hbox.set_homogeneous(True)
row.add(hbox)
label = Gtk.Label()
label.set_markup(u)
label.set_justify(Gtk.Justification.LEFT)
hbox.pack_start(label, False, True, 1)
if self.active_profile:
for u in self.active_profile.units:
row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL,
spacing=0)
hbox.set_homogeneous(True)
row.add(hbox)
label = Gtk.Label()
label.set_markup(u)
label.set_justify(Gtk.Justification.LEFT)
hbox.pack_start(label, False, True, 1)
grid = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
spacing=0)
grid.set_homogeneous(True)
for o in self.active_profile.units[u].options:
label_option = Gtk.Label()
label_option.set_markup(o + ' = ' + '<b>'
+ self.active_profile.units[u].options[o]
+ '</b>')
grid.pack_start(label_option, False, True, 0)
grid = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
spacing=0)
grid.set_homogeneous(True)
for o in self.active_profile.units[u].options:
label_option = Gtk.Label()
label_option.set_markup(o + ' = ' + '<b>'
+ self.active_profile.units[u].options[o]
+ '</b>')
grid.pack_start(label_option, False, True, 0)
hbox.pack_start(grid, False, True, 0)
self._gobj('listboxSummaryOfActiveProfile').add(row)
separator = Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)
self._gobj('listboxSummaryOfActiveProfile').add(separator)
separator.show()
hbox.pack_start(grid, False, True, 0)
self._gobj('listboxSummaryOfActiveProfile').add(row)
separator = Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)
self._gobj('listboxSummaryOfActiveProfile').add(separator)
separator.show()
self._gobj('listboxSummaryOfActiveProfile').show_all()
@ -411,8 +412,8 @@ class Base(object):
self._gobj('notebookPlugins').append_page_menu(
self.treeview_for_data(
config_options, plugin),
Gtk.Label(plugin),
Gtk.Label(plugin)
Gtk.Label(label = plugin),
Gtk.Label(label = plugin)
)
self._gobj('notebookPlugins').show_all()
@ -445,7 +446,7 @@ class Base(object):
self.manager.set_raw_profile(profile_name,
text_buffer.get_text(start, end, True))
except Exception:
self.error_dialog('Error while parsing raw configuration')
self.error_dialog('Error while parsing raw configuration', '')
return
self.error_dialog('Profile Editor will be closed.',
@ -629,7 +630,7 @@ class Base(object):
for (name, unit) in list(profile.units.items()):
self._gobj('notebookPlugins').append_page_menu(self.treeview_for_data(unit.options, unit.name),
Gtk.Label(unit.name), Gtk.Label(unit.name))
Gtk.Label(label = unit.name), Gtk.Label(label = unit.name))
self._gobj('notebookPlugins').show_all()
self._gobj('windowProfileEditor').show()
@ -639,11 +640,11 @@ class Base(object):
"""
treestore = Gtk.ListStore(GObject.TYPE_STRING,
GObject.TYPE_STRING)
GObject.TYPE_STRING)
for (option, value) in list(data.items()):
treestore.append([str(value), option])
treeview = Gtk.TreeView(treestore)
treeview = Gtk.TreeView(model = treestore)
renderer = Gtk.CellRendererText()
column_option = Gtk.TreeViewColumn('Option', renderer, text=0)
column_value = Gtk.TreeViewColumn('Value', renderer, text=1)
@ -694,7 +695,7 @@ class Base(object):
def execute_switch_tuned(self, switch, data):
"""
Suported switch_tuned_start_stop and switch_tuned_startup_start_stop.
Supported switch_tuned_start_stop and switch_tuned_startup_start_stop.
"""
if switch == self._gobj('switchTunedStartStop'):
@ -798,8 +799,8 @@ class Base(object):
if event.button == 3:
popup = Gtk.Menu()
popup.append(Gtk.MenuItem('add'))
popup.append(Gtk.MenuItem('delete'))
popup.append(Gtk.MenuItem(label = 'add'))
popup.append(Gtk.MenuItem(label = 'delete'))
time = event.time
self._gobj('menuAddPluginValue').popup(
None,
@ -818,6 +819,70 @@ class Base(object):
return True
return False
def add_plugin_value_to_treeview(self, action):
notebook_plugins = self._gobj('notebookPlugins')
current_plugin = \
notebook_plugins.get_tab_label(notebook_plugins.get_nth_page(notebook_plugins.get_current_page())).get_text()
current_plugin_options = \
self.plugin_loader.plugins.get(current_plugin)
curent_plugin_values_model = \
notebook_plugins.get_nth_page(notebook_plugins.get_current_page()).get_model()
treestore_plugins_values = Gtk.ListStore(GObject.TYPE_STRING)
for (vl_name, vl_val) in current_plugin_options.items():
if not self.liststore_contains_item(curent_plugin_values_model,
vl_name):
treestore_plugins_values.append([vl_name])
dialog_add_plugin_value = \
self.builder.get_object('dialogAddPluginValue')
dialog_add_plugin_value.connect('destroy', lambda d: \
dialog_add_plugin_value.hide())
combobox = self.builder.get_object('comboboxPluginsValues')
combobox.set_model(treestore_plugins_values)
response = dialog_add_plugin_value.run()
dialog_add_plugin_value.hide()
if response == 1:
active = combobox.get_active_text()
curent_plugin_values_model.append([current_plugin_options.get(active),
active])
return True
return False
def add_custom_plugin_value_to_treeview(self, action):
notebook_plugins = self._gobj('notebookPlugins')
curent_plugin_values_model = \
notebook_plugins.get_nth_page(notebook_plugins.get_current_page()).get_model()
dialog_add_custom_plugin_value = \
self.builder.get_object('dialogAddCustomPluginValue')
text = self.builder.get_object('entry2')
dialog_add_custom_plugin_value.connect('destroy', lambda d: \
dialog_add_custom_plugin_value.hide())
response = dialog_add_custom_plugin_value.run()
dialog_add_custom_plugin_value.hide()
if response == 1:
curent_plugin_values_model.append(['', text.get_text()])
return True
return False
def delete_plugin_value_to_treeview(self, action):
notebook_plugins = self._gobj('notebookPlugins')
curent_plugin_values_tree = \
notebook_plugins.get_nth_page(notebook_plugins.get_current_page())
(model, iter) = \
curent_plugin_values_tree.get_selection().get_selected()
if model is None or iter is None:
return False
model.remove(iter)
return True
def _start_tuned(self):
self._su_execute(['service', 'tuned', 'start'])
time.sleep(10)

View file

@ -44,9 +44,9 @@
Summary: A dynamic adaptive system tuning daemon
Name: tuned
Version: 2.20.0
Version: 2.21.0
Release: 1%{?prerel1}%{?with_snapshot:.%{git_suffix}}%{?dist}
License: GPLv2+
License: GPL-2.0-or-later AND CC-BY-SA-3.0
Source0: https://github.com/redhat-performance/%{name}/archive/v%{version}%{?prerel2}/%{name}-%{version}%{?prerel2}.tar.gz
URL: http://www.tuned-project.org/
BuildArch: noarch
@ -557,6 +557,28 @@ fi
%{_mandir}/man7/tuned-profiles-openshift.7*
%changelog
* Tue Aug 29 2023 Jaroslav Škarvada <jskarvad@redhat.com> - 2.21.0-1
- new release
- rebased tuned to latest upstream
related: rhbz#2182117
- api: fixed stop method not to require any parameter
resolves: rhbz#2235637
* Sun Aug 20 2023 Jaroslav Škarvada <jskarvad@redhat.com> - 2.21.0-0.1.rc1
- new release
- rebased tuned to latest upstream
resolves: rhbz#2182117
- plugin_scheduler: fix perf fd leaks
resolves: rhbz#2173938
- allow skipping rollback when restarting TuneD or switching profile
resolves: rhbz#2203142
- function_calc_isolated_cores: no errors for offline CPUs
resolves: rhbz#2217015
- sap-hana: new profile sap-hana-kvm-guest
resolves: rhbz#2173740
- serialized SIGHUP handler to prevent possible bootcmdline corruption
resolves: rhbz#2215298
* Fri Feb 17 2023 Jaroslav Škarvada <jskarvad@redhat.com> - 2.20.0-1
- new release
- rebased tuned to latest upstream

View file

@ -439,3 +439,39 @@ class Admin(object):
def _action_list_plugins(self, verbose=False):
print("Not supported in no_daemon mode.")
return False
def _action_dbus_instance_acquire_devices(self, devices, instance):
(ret, msg) = self._controller.instance_acquire_devices(devices, instance)
if not ret:
self._error("Unable to acquire devices: %s" % msg)
return self._controller.exit(ret)
def _action_instance_acquire_devices(self, devices, instance):
print("Not supported in no_daemon mode.")
return False
def _action_dbus_get_instances(self, plugin_name):
(ret, msg, pairs) = self._controller.get_instances(plugin_name)
if not ret:
self._error("Unable to list instances: %s" % msg)
return self._controller.exit(False)
for instance, plugin in pairs:
print("%s (%s)" % (instance, plugin))
return self._controller.exit(True)
def _action_get_instances(self, plugin_name):
print("Not supported in no_daemon mode.")
return False
def _action_dbus_instance_get_devices(self, instance):
(ret, msg, devices) = self._controller.instance_get_devices(instance)
if not ret:
self._error("Unable to list devices: %s" % msg)
return self._controller.exit(False)
for device in devices:
print(device)
return self._controller.exit(True)
def _action_instance_get_devices(self, instance):
print("Not supported in no_daemon mode.")
return False

View file

@ -163,6 +163,15 @@ class DBusController(object):
"""
return self._call("get_plugin_hints", plugin_name)
def instance_acquire_devices(self, devices, instance):
return self._call("instance_acquire_devices", devices, instance)
def get_instances(self, plugin_name):
return self._call("get_instances", plugin_name)
def instance_get_devices(self, instance):
return self._call("instance_get_devices", instance)
def exit(self, ret):
self.set_action(None)
self._ret = ret

View file

@ -79,7 +79,7 @@ SYSTEM_RELEASE_FILE = "/etc/system-release-cpe"
FUNCTION_PREFIX = "function_"
# prefix for exported environment variables when calling scripts
ENV_PREFIX = "TUNED_"
ROLLBACK_NOT_ON_EXIT = 0
ROLLBACK_NONE = 0
ROLLBACK_SOFT = 1
ROLLBACK_FULL = 2

View file

@ -67,7 +67,7 @@ class Application(object):
signal.signal(signal_number, handler_wrapper)
def _init_signals(self):
self._handle_signal(signal.SIGHUP, self._controller.reload)
self._handle_signal(signal.SIGHUP, self._controller.sighup)
self._handle_signal(signal.SIGINT, self._controller.terminate)
self._handle_signal(signal.SIGTERM, self._controller.terminate)

View file

@ -70,6 +70,12 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
def terminate(self):
self._terminate.set()
def sighup(self):
if not self._daemon._sighup_processing.is_set():
self._daemon._sighup_processing.set()
if not self.reload():
self._daemon._sighup_processing.clear()
@exports.signal("sbs")
def profile_changed(self, profile_name, result, errstr):
pass
@ -116,10 +122,7 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
return False
return self._daemon.start()
@exports.export("", "b")
def stop(self, caller = None, profile_switch = False):
if caller == "":
return False
def _stop(self, profile_switch = False):
if not self._daemon.is_running():
res = True
else:
@ -127,12 +130,18 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
self._timer_store.cancel_all()
return res
@exports.export("", "b")
def stop(self, caller = None):
if caller == "":
return False
return self._stop(profile_switch = False)
@exports.export("", "b")
def reload(self, caller = None):
if caller == "":
return False
if self._daemon.is_running():
stop_ok = self.stop(profile_switch = True)
stop_ok = self._stop(profile_switch = True)
if not stop_ok:
return False
try:
@ -364,3 +373,47 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
log.info(rets)
return (False, rets)
return (True, "OK")
@exports.export("s", "(bsa(ss))")
def get_instances(self, plugin_name, caller = None):
"""Return a list of active instances of a plugin or all active instances
Parameters:
plugin_name -- name of the plugin or an empty string
Return:
bool -- True on success
string -- error message or "OK"
list of string pairs -- [(instance_name, plugin_name)]
"""
if caller == "":
return (False, "Unauthorized", [])
if plugin_name != "" and plugin_name not in self.get_all_plugins().keys():
rets = "Plugin '%s' does not exist" % plugin_name
log.error(rets)
return (False, rets, [])
instances = filter(lambda instance: instance.active, self._daemon._unit_manager.instances)
if plugin_name != "":
instances = filter(lambda instance: instance.plugin.name == plugin_name, instances)
return (True, "OK", list(map(lambda instance: (instance.name, instance.plugin.name), instances)))
@exports.export("s", "(bsas)")
def instance_get_devices(self, instance_name, caller = None):
"""Return a list of devices assigned to an instance
Parameters:
instance_name -- name of the instance
Return:
bool -- True on success
string -- error message or "OK"
list of strings -- device names
"""
if caller == "":
return (False, "Unauthorized", [])
for instance in self._daemon._unit_manager.instances:
if instance.name == instance_name:
return (True, "OK", sorted(list(instance.processed_devices)))
rets = "Instance '%s' not found" % instance_name
log.error(rets)
return (False, rets, [])

View file

@ -59,6 +59,8 @@ class Daemon(object):
self._terminate_profile_switch = threading.Event()
# Flag which is set if there is no operation in progress
self._not_used = threading.Event()
# Flag which is set if SIGHUP is being processed
self._sighup_processing = threading.Event()
self._not_used.set()
self._profile_applied = threading.Event()
@ -203,6 +205,7 @@ class Daemon(object):
exports.start()
profile_names = " ".join(self._active_profiles)
self._notify_profile_changed(profile_names, True, "OK")
self._sighup_processing.clear()
if self._daemon:
# In python 2 interpreter with applied patch for rhbz#917709 we need to periodically
@ -231,7 +234,7 @@ class Daemon(object):
# if terminating due to profile switch
if self._terminate_profile_switch.is_set():
full_rollback = consts.ROLLBACK_FULL
rollback = consts.ROLLBACK_FULL
else:
# Assume only soft rollback is needed. Soft rollback means reverting all
# non-persistent tunings applied by a plugin instance. In contrast to full
@ -241,21 +244,21 @@ class Daemon(object):
# perform full cleanup. If the system is not shutting down, it means that TuneD
# was explicitly stopped by the user and in such case do the full cleanup. On
# systems without systemd, full cleanup is never performed.
full_rollback = consts.ROLLBACK_SOFT
rollback = consts.ROLLBACK_SOFT
if not self._full_rollback_required():
log.info("terminating TuneD due to system shutdown / reboot")
elif self._rollback == "not_on_exit":
# no rollback on TuneD exit whatsoever
full_rollback = consts.ROLLBACK_NOT_ON_EXIT
rollback = consts.ROLLBACK_NONE
log.info("terminating TuneD and not rolling back any changes due to '%s' option in '%s'" % (consts.CFG_ROLLBACK, consts.GLOBAL_CONFIG_FILE))
else:
if self._daemon:
log.info("terminating TuneD, rolling back all changes")
full_rollback = consts.ROLLBACK_FULL
rollback = consts.ROLLBACK_FULL
else:
log.info("terminating TuneD in one-shot mode")
if self._daemon:
self._unit_manager.stop_tuning(full_rollback)
self._unit_manager.stop_tuning(rollback)
self._unit_manager.destroy_all()
def _save_active_profile(self, profile_names, manual):

View file

@ -40,7 +40,7 @@ __all__ = ['GuiPluginLoader']
class GuiPluginLoader():
'''
Class for scan, import and load actual avaible plugins.
Class for scan, import and load actual variable plugins.
'''
def __init__(self):
@ -53,7 +53,7 @@ class GuiPluginLoader():
self._prefix = 'plugin_'
self._sufix = '.py'
self._dbus_controller = DBusController(consts.DBUS_BUS,
consts.DBUS_INTERFACE, consts.DBUS_OBJECT
consts.DBUS_INTERFACE, consts.DBUS_OBJECT
)
self._get_plugins()

View file

@ -212,7 +212,7 @@ class Plugin(object):
def _instance_post_static(self, instance, enabling):
pass
def _call_device_script(self, instance, script, op, devices, full_rollback = consts.ROLLBACK_SOFT):
def _call_device_script(self, instance, script, op, devices, rollback = consts.ROLLBACK_SOFT):
if script is None:
return None
if len(devices) == 0:
@ -228,7 +228,7 @@ class Plugin(object):
environ = os.environ
environ.update(self._variables.get_env())
arguments = [op]
if full_rollback == consts.ROLLBACK_FULL:
if rollback == consts.ROLLBACK_FULL:
arguments.append("full_rollback")
arguments.append(dev)
log.info("calling script '%s' with arguments '%s'" % (script, str(arguments)))
@ -298,11 +298,11 @@ 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_update_dynamic, instance.processed_devices.copy())
def instance_unapply_tuning(self, instance, full_rollback = consts.ROLLBACK_SOFT):
def instance_unapply_tuning(self, instance, rollback = consts.ROLLBACK_SOFT):
"""
Remove all tunings applied by the plugin instance.
"""
if full_rollback == consts.ROLLBACK_NOT_ON_EXIT:
if rollback == consts.ROLLBACK_NONE:
return
if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING):
@ -310,11 +310,11 @@ class Plugin(object):
if instance.has_static_tuning:
self._call_device_script(instance, instance.script_post,
"unapply", instance.processed_devices,
full_rollback = full_rollback)
rollback = rollback)
self._instance_pre_static(instance, False)
self._instance_unapply_static(instance, full_rollback)
self._instance_unapply_static(instance, rollback)
self._instance_post_static(instance, False)
self._call_device_script(instance, instance.script_pre, "unapply", instance.processed_devices, full_rollback = full_rollback)
self._call_device_script(instance, instance.script_pre, "unapply", instance.processed_devices, rollback = rollback)
def _instance_apply_static(self, instance):
self._execute_all_non_device_commands(instance)
@ -328,7 +328,7 @@ class Plugin(object):
ret = False
return ret
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
self._cleanup_all_device_commands(instance,
instance.processed_devices)
self._cleanup_all_non_device_commands(instance)
@ -506,7 +506,7 @@ class Plugin(object):
else:
new_value = self._check_and_save_value(instance, command, device, new_value)
if new_value is not None:
command["set"](new_value, device, sim = False)
command["set"](new_value, device, sim = False, remove = False)
def _execute_non_device_command(self, instance, command, new_value):
if command["custom"] is not None:
@ -514,7 +514,7 @@ class Plugin(object):
else:
new_value = self._check_and_save_value(instance, command, None, new_value)
if new_value is not None:
command["set"](new_value, sim = False)
command["set"](new_value, sim = False, remove = False)
def _norm_value(self, value):
v = self._cmd.unquote(str(value))
@ -576,7 +576,7 @@ class Plugin(object):
new_value = self._process_assignment_modifiers(new_value, current_value)
if new_value is None:
return None
new_value = command["set"](new_value, device, True)
new_value = command["set"](new_value, device, True, False)
return self._verify_value(command["name"], new_value, current_value, ignore_missing, device)
def _verify_non_device_command(self, instance, command, new_value, ignore_missing):
@ -586,7 +586,7 @@ class Plugin(object):
new_value = self._process_assignment_modifiers(new_value, current_value)
if new_value is None:
return None
new_value = command["set"](new_value, True)
new_value = command["set"](new_value, True, False)
return self._verify_value(command["name"], new_value, current_value, ignore_missing)
def _cleanup_all_non_device_commands(self, instance):
@ -594,19 +594,19 @@ class Plugin(object):
if (instance.options.get(command["name"], None) is not None) or (command["name"] in self._options_used_by_dynamic):
self._cleanup_non_device_command(instance, command)
def _cleanup_all_device_commands(self, instance, devices):
def _cleanup_all_device_commands(self, instance, devices, remove = False):
for command in reversed([command for command in list(self._commands.values()) if command["per_device"]]):
if (instance.options.get(command["name"], None) is not None) or (command["name"] in self._options_used_by_dynamic):
for device in devices:
self._cleanup_device_command(instance, command, device)
self._cleanup_device_command(instance, command, device, remove)
def _cleanup_device_command(self, instance, command, device):
def _cleanup_device_command(self, instance, command, device, remove = False):
if command["custom"] is not None:
command["custom"](False, None, device, False, False)
else:
old_value = self._storage_get(instance, command, device)
if old_value is not None:
command["set"](old_value, device, sim = False)
command["set"](old_value, device, sim = False, remove = remove)
self._storage_unset(instance, command, device)
def _cleanup_non_device_command(self, instance, command):
@ -615,5 +615,5 @@ class Plugin(object):
else:
old_value = self._storage_get(instance, command)
if old_value is not None:
command["set"](old_value, sim = False)
command["set"](old_value, sim = False, remove = False)
self._storage_unset(instance, command)

View file

@ -109,4 +109,4 @@ class Plugin(base.Plugin):
def _removed_device_unapply_tuning(self, instance, device_name):
if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING):
self._instance_unapply_dynamic(instance, device_name)
self._cleanup_all_device_commands(instance, [device_name])
self._cleanup_all_device_commands(instance, [device_name], remove = True)

View file

@ -85,8 +85,8 @@ class Instance(object):
def update_tuning(self):
self._plugin.instance_update_tuning(self)
def unapply_tuning(self, full_rollback = consts.ROLLBACK_SOFT):
self._plugin.instance_unapply_tuning(self, full_rollback)
def unapply_tuning(self, rollback = consts.ROLLBACK_SOFT):
self._plugin.instance_unapply_tuning(self, rollback)
def destroy(self):
self.unapply_tuning()

View file

@ -4,6 +4,7 @@ import tuned.logs
from tuned.utils.commands import commands
import os
import errno
import struct
import glob
@ -73,7 +74,7 @@ class AudioPlugin(hotplug.Plugin):
return "/sys/module/%s/parameters/power_save_controller" % device
@command_set("timeout", per_device = True)
def _set_timeout(self, value, device, sim):
def _set_timeout(self, value, device, sim, remove):
try:
timeout = int(value)
except ValueError:
@ -82,7 +83,8 @@ class AudioPlugin(hotplug.Plugin):
if timeout >= 0:
sys_file = self._timeout_path(device)
if not sim:
cmd.write_to_file(sys_file, "%d" % timeout)
cmd.write_to_file(sys_file, "%d" % timeout, \
no_error = [errno.ENOENT] if remove else False)
return timeout
else:
return None
@ -96,12 +98,13 @@ class AudioPlugin(hotplug.Plugin):
return None
@command_set("reset_controller", per_device = True)
def _set_reset_controller(self, value, device, sim):
def _set_reset_controller(self, value, device, sim, remove):
v = cmd.get_bool(value)
sys_file = self._reset_controller_path(device)
if os.path.exists(sys_file):
if not sim:
cmd.write_to_file(sys_file, v)
cmd.write_to_file(sys_file, v, \
no_error = [errno.ENOENT] if remove else False)
return v
return None

View file

@ -373,7 +373,7 @@ class BootloaderPlugin(base.Plugin):
log.info("cannot find grub.cfg to patch")
return
for f in self._grub2_cfg_file_names:
self._cmd.add_modify_option_in_file(f, {"set\s+" + consts.GRUB2_TUNED_VAR : "", "set\s+" + consts.GRUB2_TUNED_INITRD_VAR : ""}, add = False)
self._cmd.add_modify_option_in_file(f, {r"set\s+" + consts.GRUB2_TUNED_VAR : "", r"set\s+" + consts.GRUB2_TUNED_INITRD_VAR : ""}, add = False)
if self._initrd_dst_img_val is not None:
log.info("removing initrd image '%s'" % self._initrd_dst_img_val)
self._cmd.unlink(self._initrd_dst_img_val)
@ -391,8 +391,8 @@ class BootloaderPlugin(base.Plugin):
self._rpm_ostree_kargs(append=self._options_to_dict(deleted), delete=self._options_to_dict(appended))
self._patch_bootcmdline({consts.BOOT_CMDLINE_TUNED_VAR: "", consts.BOOT_CMDLINE_KARGS_DELETED_VAR: ""})
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
if full_rollback == consts.ROLLBACK_FULL and not self._skip_grub_config_val:
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
if rollback == consts.ROLLBACK_FULL and not self._skip_grub_config_val:
if self._rpm_ostree:
log.info("removing rpm-ostree tuning previously added by Tuned")
self._remove_rpm_ostree_tuning()
@ -403,9 +403,9 @@ class BootloaderPlugin(base.Plugin):
def _grub2_cfg_unpatch(self, grub2_cfg):
log.debug("unpatching grub.cfg")
cfg = re.sub(r"^\s*set\s+" + consts.GRUB2_TUNED_VAR + "\s*=.*\n", "", grub2_cfg, flags = re.MULTILINE)
cfg = re.sub(r"^\s*set\s+" + consts.GRUB2_TUNED_VAR + "\\s*=.*\n", "", grub2_cfg, flags = re.MULTILINE)
grub2_cfg = re.sub(r" *\$" + consts.GRUB2_TUNED_VAR, "", cfg, flags = re.MULTILINE)
cfg = re.sub(r"^\s*set\s+" + consts.GRUB2_TUNED_INITRD_VAR + "\s*=.*\n", "", grub2_cfg, flags = re.MULTILINE)
cfg = re.sub(r"^\s*set\s+" + consts.GRUB2_TUNED_INITRD_VAR + "\\s*=.*\n", "", grub2_cfg, flags = re.MULTILINE)
grub2_cfg = re.sub(r" *\$" + consts.GRUB2_TUNED_INITRD_VAR, "", cfg, flags = re.MULTILINE)
cfg = re.sub(consts.GRUB2_TEMPLATE_HEADER_BEGIN + r"\n", "", grub2_cfg, flags = re.MULTILINE)
return re.sub(consts.GRUB2_TEMPLATE_HEADER_END + r"\n+", "", cfg, flags = re.MULTILINE)
@ -480,7 +480,7 @@ class BootloaderPlugin(base.Plugin):
grub2_cfg_new = grub2_cfg
patch_initial = False
for opt in d:
(grub2_cfg_new, nsubs) = re.subn(r"\b(set\s+" + opt + "\s*=).*$", r"\1" + "\"" + self._cmd.escape(d[opt]) + "\"", grub2_cfg_new, flags = re.MULTILINE)
(grub2_cfg_new, nsubs) = re.subn(r"\b(set\s+" + opt + r"\s*=).*$", r"\1" + "\"" + self._cmd.escape(d[opt]) + "\"", grub2_cfg_new, flags = re.MULTILINE)
if nsubs < 1 or re.search(r"\$" + opt, grub2_cfg, flags = re.MULTILINE) is None:
patch_initial = True

View file

@ -5,6 +5,7 @@ from tuned.utils.commands import commands
import tuned.consts as consts
import os
import errno
import struct
import errno
import platform
@ -81,7 +82,8 @@ class CPULatencyPlugin(hotplug.Plugin):
`energy_performance_preference`:::
[option]`energy_performance_preference` supports managing energy
vs. performance hints on some newer Intel processors. Multiple alternative
vs. performance hints on newer Intel and AMD processors with active P-State
CPU scaling drivers (intel_pstate or amd-pstate). Multiple alternative
Energy Performance Preferences (EPP) values are supported. The alternative
values are separated using the '|' character. Available values can be found
in `energy_performance_available_preferences` file in `CPUFreq` policy
@ -196,6 +198,7 @@ class CPULatencyPlugin(hotplug.Plugin):
self._is_amd = False
self._has_energy_perf_bias = False
self._has_intel_pstate = False
self._has_amd_pstate = False
self._has_pm_qos_resume_latency_us = None
self._min_perf_pct_save = None
@ -240,15 +243,15 @@ class CPULatencyPlugin(hotplug.Plugin):
self._arch = platform.machine()
if self._arch in intel_archs:
# Possible other x86 vendors (from arch/x86/kernel/cpu/*):
# "CentaurHauls", "CyrixInstead", "Geode by NSC", "HygonGenuine", "GenuineTMx86",
# "TransmetaCPU", "UMC UMC UMC"
# Possible other x86 vendors (from arch/x86/kernel/cpu/*):
# "CentaurHauls", "CyrixInstead", "Geode by NSC", "HygonGenuine", "GenuineTMx86",
# "TransmetaCPU", "UMC UMC UMC"
cpu = procfs.cpuinfo()
vendor = cpu.tags.get("vendor_id")
if vendor == "GenuineIntel":
self._is_intel = True
self._is_intel = True
elif vendor == "AuthenticAMD" or vendor == "HygonGenuine":
self._is_amd = True
self._is_amd = True
else:
# We always assign Intel, unless we know better
self._is_intel = True
@ -256,12 +259,16 @@ class CPULatencyPlugin(hotplug.Plugin):
else:
log.info("We are running on %s (non x86)" % self._arch)
if self._is_intel is True:
if self._is_intel:
# Check for x86_energy_perf_policy, ignore if not available / supported
self._check_energy_perf_bias()
# Check for intel_pstate
self._check_intel_pstate()
if self._is_amd:
# Check for amd-pstate
self._check_amd_pstate()
def _check_energy_perf_bias(self):
self._has_energy_perf_bias = False
retcode_unsupported = 1
@ -281,6 +288,11 @@ class CPULatencyPlugin(hotplug.Plugin):
if self._has_intel_pstate:
log.info("intel_pstate detected")
def _check_amd_pstate(self):
self._has_amd_pstate = os.path.exists("/sys/devices/system/cpu/amd_pstate")
if self._has_amd_pstate:
log.info("amd-pstate detected")
def _get_cpuinfo_flags(self):
if self._flags is None:
self._flags = procfs.cpuinfo().tags.get("flags", [])
@ -377,8 +389,8 @@ class CPULatencyPlugin(hotplug.Plugin):
self._no_turbo_save = self._getset_intel_pstate_attr(
"no_turbo", new_value)
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
super(CPULatencyPlugin, self)._instance_unapply_static(instance, full_rollback)
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
super(CPULatencyPlugin, self)._instance_unapply_static(instance, rollback)
if instance._first_instance and self._has_intel_pstate:
self._set_intel_pstate_attr("min_perf_pct", self._min_perf_pct_save)
@ -489,7 +501,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_available_governors" % device).strip().split()
@command_set("governor", per_device=True)
def _set_governor(self, governors, device, sim):
def _set_governor(self, governors, device, sim, remove):
if not self._check_cpu_can_change_governor(device):
return None
governors = str(governors)
@ -506,7 +518,7 @@ class CPULatencyPlugin(hotplug.Plugin):
log.info("setting governor '%s' on cpu '%s'"
% (governor, device))
self._cmd.write_to_file("/sys/devices/system/cpu/%s/cpufreq/scaling_governor"
% device, governor)
% device, governor, no_error = [errno.ENOENT] if remove else False)
break
elif not sim:
log.debug("Ignoring governor '%s' on cpu '%s', it is not supported"
@ -535,7 +547,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return "/sys/devices/system/cpu/cpufreq/%s/sampling_down_factor" % governor
@command_set("sampling_down_factor", per_device = True, priority = 10)
def _set_sampling_down_factor(self, sampling_down_factor, device, sim):
def _set_sampling_down_factor(self, sampling_down_factor, device, sim, remove):
val = None
# hack to clear governors map when the profile starts unloading
@ -558,7 +570,7 @@ class CPULatencyPlugin(hotplug.Plugin):
val = str(sampling_down_factor)
if not sim:
log.info("setting sampling_down_factor to '%s' for governor '%s'" % (val, governor))
self._cmd.write_to_file(path, val)
self._cmd.write_to_file(path, val, no_error = [errno.ENOENT] if remove else False)
return val
@command_get("sampling_down_factor")
@ -580,14 +592,14 @@ class CPULatencyPlugin(hotplug.Plugin):
return_err = True)
return (retcode, err_msg)
def _intel_preference_path(self, cpu_id, available = False):
def _pstate_preference_path(self, cpu_id, available = False):
return "/sys/devices/system/cpu/cpufreq/policy%s/energy_performance_%s" % (cpu_id, "available_preferences" if available else "preference")
def _energy_perf_bias_path(self, cpu_id):
return "/sys/devices/system/cpu/cpu%s/power/energy_perf_bias" % cpu_id
@command_set("energy_perf_bias", per_device=True)
def _set_energy_perf_bias(self, energy_perf_bias, device, sim):
def _set_energy_perf_bias(self, energy_perf_bias, device, sim, remove):
if not self._is_cpu_online(device):
log.debug("%s is not online, skipping" % device)
return None
@ -602,10 +614,11 @@ class CPULatencyPlugin(hotplug.Plugin):
if not sim:
for val in vals:
val = val.strip()
if self._cmd.write_to_file(energy_perf_bias_path, val):
log.info("energy_perf_bias successfully set to '%s' on cpu '%s'"
% (val, device))
break
if self._cmd.write_to_file(energy_perf_bias_path, val, \
no_error = [errno.ENOENT] if remove else False):
log.info("energy_perf_bias successfully set to '%s' on cpu '%s'"
% (val, device))
break
else:
log.error("Failed to set energy_perf_bias on cpu '%s'. Is the value in the profile correct?"
% device)
@ -700,7 +713,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return self._has_pm_qos_resume_latency_us
@command_set("pm_qos_resume_latency_us", per_device=True)
def _set_pm_qos_resume_latency_us(self, pm_qos_resume_latency_us, device, sim):
def _set_pm_qos_resume_latency_us(self, pm_qos_resume_latency_us, device, sim, remove):
if not self._is_cpu_online(device):
log.debug("%s is not online, skipping" % device)
return None
@ -718,7 +731,8 @@ class CPULatencyPlugin(hotplug.Plugin):
if not self._check_pm_qos_resume_latency_us(device):
return None
if not sim:
self._cmd.write_to_file(self._pm_qos_resume_latency_us_path(device), latency)
self._cmd.write_to_file(self._pm_qos_resume_latency_us_path(device), latency, \
no_error = [errno.ENOENT] if remove else False)
return latency
@command_get("pm_qos_resume_latency_us")
@ -731,18 +745,19 @@ class CPULatencyPlugin(hotplug.Plugin):
return self._cmd.read_file(self._pm_qos_resume_latency_us_path(device), no_error=ignore_missing).strip()
@command_set("energy_performance_preference", per_device=True)
def _set_energy_performance_preference(self, energy_performance_preference, device, sim):
def _set_energy_performance_preference(self, energy_performance_preference, device, sim, remove):
if not self._is_cpu_online(device):
log.debug("%s is not online, skipping" % device)
return None
cpu_id = device.lstrip("cpu")
if os.path.exists(self._intel_preference_path(cpu_id, True)):
if os.path.exists(self._pstate_preference_path(cpu_id, True)):
vals = energy_performance_preference.split('|')
if not sim:
avail_vals = set(self._cmd.read_file(self._intel_preference_path(cpu_id, True)).split())
avail_vals = set(self._cmd.read_file(self._pstate_preference_path(cpu_id, True)).split())
for val in vals:
if val in avail_vals:
self._cmd.write_to_file(self._intel_preference_path(cpu_id), val)
self._cmd.write_to_file(self._pstate_preference_path(cpu_id), val, \
no_error = [errno.ENOENT] if remove else False)
log.info("Setting energy_performance_preference value '%s' for cpu '%s'" % (val, device))
break
else:
@ -752,7 +767,7 @@ class CPULatencyPlugin(hotplug.Plugin):
% device)
return str(energy_performance_preference)
else:
log.debug("energy_performance_available_preferences file missing, which can happen if the system is booted without the intel_pstate driver.")
log.debug("energy_performance_available_preferences file missing, which can happen if the system is booted without a P-state driver.")
return None
@command_get("energy_performance_preference")
@ -761,9 +776,9 @@ class CPULatencyPlugin(hotplug.Plugin):
log.debug("%s is not online, skipping" % device)
return None
cpu_id = device.lstrip("cpu")
# intel_pstate CPU scaling driver
if os.path.exists(self._intel_preference_path(cpu_id, True)):
return self._cmd.read_file(self._intel_preference_path(cpu_id)).strip()
# read the EPP hint used by the intel_pstate and amd-pstate CPU scaling drivers
if os.path.exists(self._pstate_preference_path(cpu_id, True)):
return self._cmd.read_file(self._pstate_preference_path(cpu_id)).strip()
else:
log.debug("energy_performance_available_preferences file missing, which can happen if the system is booted without the intel_pstate driver.")
log.debug("energy_performance_available_preferences file missing, which can happen if the system is booted without a P-state driver.")
return None

View file

@ -335,10 +335,11 @@ class DiskPlugin(hotplug.Plugin):
return self._sysfs_path(device, "queue/scheduler")
@command_set("elevator", per_device=True)
def _set_elevator(self, value, device, sim):
def _set_elevator(self, value, device, sim, remove):
sys_file = self._elevator_file(device)
if not sim:
self._cmd.write_to_file(sys_file, value)
self._cmd.write_to_file(sys_file, value, \
no_error = [errno.ENOENT] if remove else False)
return value
@command_get("elevator")
@ -349,7 +350,7 @@ class DiskPlugin(hotplug.Plugin):
return self._cmd.get_active_option(self._cmd.read_file(sys_file, no_error=ignore_missing))
@command_set("apm", per_device=True)
def _set_apm(self, value, device, sim):
def _set_apm(self, value, device, sim, remove):
if device not in self._hdparm_apm_devices:
if not sim:
log.info("apm option is not supported for device '%s'" % device)
@ -389,7 +390,7 @@ class DiskPlugin(hotplug.Plugin):
return value
@command_set("spindown", per_device=True)
def _set_spindown(self, value, device, sim):
def _set_spindown(self, value, device, sim, remove):
if device not in self._hdparm_apm_devices:
if not sim:
log.info("spindown option is not supported for device '%s'" % device)
@ -428,14 +429,15 @@ class DiskPlugin(hotplug.Plugin):
return v
@command_set("readahead", per_device=True)
def _set_readahead(self, value, device, sim):
def _set_readahead(self, value, device, sim, remove):
sys_file = self._readahead_file(device)
val = self._parse_ra(value)
if val is None:
log.error("Invalid readahead value '%s' for device '%s'" % (value, device))
else:
if not sim:
self._cmd.write_to_file(sys_file, "%d" % val)
self._cmd.write_to_file(sys_file, "%d" % val, \
no_error = [errno.ENOENT] if remove else False)
return val
@command_get("readahead")
@ -471,10 +473,11 @@ class DiskPlugin(hotplug.Plugin):
return self._sysfs_path(device, "queue/iosched/quantum")
@command_set("scheduler_quantum", per_device=True)
def _set_scheduler_quantum(self, value, device, sim):
def _set_scheduler_quantum(self, value, device, sim, remove):
sys_file = self._scheduler_quantum_file(device)
if not sim:
self._cmd.write_to_file(sys_file, "%d" % int(value))
self._cmd.write_to_file(sys_file, "%d" % int(value), \
no_error = [errno.ENOENT] if remove else False)
return value
@command_get("scheduler_quantum")

View file

@ -134,8 +134,8 @@ class ModulesPlugin(base.Plugin):
ret = False
return ret
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
if full_rollback == consts.ROLLBACK_FULL:
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
if rollback == consts.ROLLBACK_FULL:
self._clear_modprobe_file()
def _clear_modprobe_file(self):

View file

@ -329,6 +329,8 @@ class NetTuningPlugin(hotplug.Plugin):
# parse features/coalesce config parameters (those defined in profile configuration)
# context is for error message
def _parse_config_parameters(self, value, context):
# expand config variables
value = self._variables.expand(value)
# split supporting various dellimeters
v = str(re.sub(r"(:\s*)|(\s+)|(\s*;\s*)|(\s*,\s*)", " ", value)).split()
lv = len(v)
@ -347,7 +349,7 @@ class NetTuningPlugin(hotplug.Plugin):
# (rhbz#1225375)
value = self._cmd.multiple_re_replace({
"Adaptive RX:": "adaptive-rx:",
"\s+TX:": "\nadaptive-tx:",
"\\s+TX:": "\nadaptive-tx:",
"rx-frame-low:": "rx-frames-low:",
"rx-frame-high:": "rx-frames-high:",
"tx-frame-low:": "tx-frames-low:",
@ -366,7 +368,7 @@ class NetTuningPlugin(hotplug.Plugin):
"receive-hashing:": "rxhash:",
}, value)
# remove empty lines, remove fixed parameters (those with "[fixed]")
vl = [v for v in value.split('\n') if len(str(v)) > 0 and not re.search("\[fixed\]$", str(v))]
vl = [v for v in value.split('\n') if len(str(v)) > 0 and not re.search(r"\[fixed\]$", str(v))]
if len(vl) < 2:
return None
# skip first line (device name), split to key/value,
@ -378,7 +380,7 @@ class NetTuningPlugin(hotplug.Plugin):
return "/sys/module/nf_conntrack/parameters/hashsize"
@command_set("wake_on_lan", per_device=True)
def _set_wake_on_lan(self, value, device, sim):
def _set_wake_on_lan(self, value, device, sim, remove):
if value is None:
return None
@ -404,14 +406,15 @@ class NetTuningPlugin(hotplug.Plugin):
return value
@command_set("nf_conntrack_hashsize")
def _set_nf_conntrack_hashsize(self, value, sim):
def _set_nf_conntrack_hashsize(self, value, sim, remove):
if value is None:
return None
hashsize = int(value)
if hashsize >= 0:
if not sim:
self._cmd.write_to_file(self._nf_conntrack_hashsize_path(), hashsize)
self._cmd.write_to_file(self._nf_conntrack_hashsize_path(), hashsize, \
no_error = [errno.ENOENT] if remove else False)
return hashsize
else:
return None
@ -445,7 +448,7 @@ class NetTuningPlugin(hotplug.Plugin):
return self._call_ip_link(args)
@command_set("txqueuelen", per_device=True)
def _set_txqueuelen(self, value, device, sim):
def _set_txqueuelen(self, value, device, sim, remove):
if value is None:
return None
try:
@ -485,7 +488,7 @@ class NetTuningPlugin(hotplug.Plugin):
return res.group(1)
@command_set("mtu", per_device=True)
def _set_mtu(self, value, device, sim):
def _set_mtu(self, value, device, sim, remove):
if value is None:
return None
try:

View file

@ -135,7 +135,7 @@ class SchedulerUtilsSchedutils(SchedulerUtils):
return schedutils.get_priority_max(sched)
class SchedulerPlugin(base.Plugin):
"""
r"""
`scheduler`::
Allows tuning of scheduling priorities, process/thread/IRQ
@ -1003,8 +1003,8 @@ class SchedulerPlugin(base.Plugin):
for cg in self._cgroups:
self._cgroup_cleanup_tasks_one(cg)
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
super(SchedulerPlugin, self)._instance_unapply_static(instance, full_rollback)
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
super(SchedulerPlugin, self)._instance_unapply_static(instance, rollback)
if self._daemon and instance._runtime_tuning:
instance._terminate.set()
instance._thread.join()
@ -1414,12 +1414,13 @@ class SchedulerPlugin(base.Plugin):
self._secure_boot_hint = False
return data
def _set_sched_knob(self, prefix, namespace, knob, value, sim):
def _set_sched_knob(self, prefix, namespace, knob, value, sim, remove = False):
if value is None:
return None
if not sim:
if not self._cmd.write_to_file(self._get_sched_knob_path(prefix, namespace, knob), value):
log.error("Error writing value '%s' to '%s'" % (value, knob))
if not self._cmd.write_to_file(self._get_sched_knob_path(prefix, namespace, knob), value, \
no_error = [errno.ENOENT] if remove else False):
log.error("Error writing value '%s' to '%s'" % (value, knob))
return value
@command_get("sched_min_granularity_ns")
@ -1427,77 +1428,77 @@ class SchedulerPlugin(base.Plugin):
return self._get_sched_knob("", "sched", "min_granularity_ns")
@command_set("sched_min_granularity_ns")
def _set_sched_min_granularity_ns(self, value, sim):
return self._set_sched_knob("", "sched", "min_granularity_ns", value, sim)
def _set_sched_min_granularity_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "min_granularity_ns", value, sim, remove)
@command_get("sched_latency_ns")
def _get_sched_latency_ns(self):
return self._get_sched_knob("", "sched", "latency_ns")
@command_set("sched_latency_ns")
def _set_sched_latency_ns(self, value, sim):
return self._set_sched_knob("", "sched", "latency_ns", value, sim)
def _set_sched_latency_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "latency_ns", value, sim, remove)
@command_get("sched_wakeup_granularity_ns")
def _get_sched_wakeup_granularity_ns(self):
return self._get_sched_knob("", "sched", "wakeup_granularity_ns")
@command_set("sched_wakeup_granularity_ns")
def _set_sched_wakeup_granularity_ns(self, value, sim):
return self._set_sched_knob("", "sched", "wakeup_granularity_ns", value, sim)
def _set_sched_wakeup_granularity_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "wakeup_granularity_ns", value, sim, remove)
@command_get("sched_tunable_scaling")
def _get_sched_tunable_scaling(self):
return self._get_sched_knob("", "sched", "tunable_scaling")
@command_set("sched_tunable_scaling")
def _set_sched_tunable_scaling(self, value, sim):
return self._set_sched_knob("", "sched", "tunable_scaling", value, sim)
def _set_sched_tunable_scaling(self, value, sim, remove):
return self._set_sched_knob("", "sched", "tunable_scaling", value, sim, remove)
@command_get("sched_migration_cost_ns")
def _get_sched_migration_cost_ns(self):
return self._get_sched_knob("", "sched", "migration_cost_ns")
@command_set("sched_migration_cost_ns")
def _set_sched_migration_cost_ns(self, value, sim):
return self._set_sched_knob("", "sched", "migration_cost_ns", value, sim)
def _set_sched_migration_cost_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "migration_cost_ns", value, sim, remove)
@command_get("sched_nr_migrate")
def _get_sched_nr_migrate(self):
return self._get_sched_knob("", "sched", "nr_migrate")
@command_set("sched_nr_migrate")
def _set_sched_nr_migrate(self, value, sim):
return self._set_sched_knob("", "sched", "nr_migrate", value, sim)
def _set_sched_nr_migrate(self, value, sim, remove):
return self._set_sched_knob("", "sched", "nr_migrate", value, sim, remove)
@command_get("numa_balancing_scan_delay_ms")
def _get_numa_balancing_scan_delay_ms(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_delay_ms")
@command_set("numa_balancing_scan_delay_ms")
def _set_numa_balancing_scan_delay_ms(self, value, sim):
return self._set_sched_knob("sched", "numa_balancing", "scan_delay_ms", value, sim)
def _set_numa_balancing_scan_delay_ms(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_delay_ms", value, sim, remove)
@command_get("numa_balancing_scan_period_min_ms")
def _get_numa_balancing_scan_period_min_ms(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_period_min_ms")
@command_set("numa_balancing_scan_period_min_ms")
def _set_numa_balancing_scan_period_min_ms(self, value, sim):
return self._set_sched_knob("sched", "numa_balancing", "scan_period_min_ms", value, sim)
def _set_numa_balancing_scan_period_min_ms(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_period_min_ms", value, sim, remove)
@command_get("numa_balancing_scan_period_max_ms")
def _get_numa_balancing_scan_period_max_ms(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_period_max_ms")
@command_set("numa_balancing_scan_period_max_ms")
def _set_numa_balancing_scan_period_max_ms(self, value, sim):
return self._set_sched_knob("sched", "numa_balancing", "scan_period_max_ms", value, sim)
def _set_numa_balancing_scan_period_max_ms(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_period_max_ms", value, sim, remove)
@command_get("numa_balancing_scan_size_mb")
def _get_numa_balancing_scan_size_mb(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_size_mb")
@command_set("numa_balancing_scan_size_mb")
def _set_numa_balancing_scan_size_mb(self, value, sim):
return self._set_sched_knob("sched", "numa_balancing", "scan_size_mb", value, sim)
def _set_numa_balancing_scan_size_mb(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_size_mb", value, sim, remove)

View file

@ -113,9 +113,9 @@ class ScriptPlugin(base.Plugin):
ret = False
return ret
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
args = ["stop"]
if full_rollback == consts.ROLLBACK_FULL:
if rollback == consts.ROLLBACK_FULL:
args = args + ["full_rollback"]
self._call_scripts(reversed(instance._scripts), args)
super(ScriptPlugin, self)._instance_unapply_static(instance, full_rollback)
super(ScriptPlugin, self)._instance_unapply_static(instance, rollback)

View file

@ -86,13 +86,14 @@ class SCSIHostPlugin(hotplug.Plugin):
return os.path.join("/sys/class/scsi_host/", str(device), "link_power_management_policy")
@command_set("alpm", per_device = True)
def _set_alpm(self, policy, device, sim):
def _set_alpm(self, policy, device, sim, remove):
if policy is None:
return None
policy_file = self._get_alpm_policy_file(device)
if not sim:
if os.path.exists(policy_file):
self._cmd.write_to_file(policy_file, policy)
self._cmd.write_to_file(policy_file, policy, \
no_error = [errno.ENOENT] if remove else False)
else:
log.info("ALPM control file ('%s') not found, skipping ALPM setting for '%s'" % (policy_file, str(device)))
return None

View file

@ -1,4 +1,5 @@
import os
import errno
from . import base
from .decorators import *
import tuned.logs
@ -63,13 +64,14 @@ class SelinuxPlugin(base.Plugin):
pass
@command_set("avc_cache_threshold")
def _set_avc_cache_threshold(self, value, sim):
def _set_avc_cache_threshold(self, value, sim, remove):
if value is None:
return None
threshold = int(value)
if threshold >= 0:
if not sim:
self._cmd.write_to_file(self._cache_threshold_path, threshold)
self._cmd.write_to_file(self._cache_threshold_path, threshold, \
no_error = [errno.ENOENT] if remove else False)
return threshold
else:
return None

View file

@ -313,7 +313,7 @@ class ServicePlugin(base.Plugin):
ret = False
return ret
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
for name, value in list(instance._services_original.items()):
if value.cfg_file:
self._init_handler.cfg_uninstall(name, value.cfg_file)

View file

@ -66,7 +66,7 @@ class SysctlPlugin(base.Plugin):
def _instance_apply_static(self, instance):
for option, value in list(instance._sysctl.items()):
original_value = _read_sysctl(option)
original_value = self._read_sysctl(option)
if original_value is None:
log.error("sysctl option %s will not be set, failed to read the original value."
% option)
@ -77,130 +77,134 @@ class SysctlPlugin(base.Plugin):
new_value, original_value)
if new_value is not None:
instance._sysctl_original[option] = original_value
_write_sysctl(option, new_value)
self._write_sysctl(option, new_value)
storage_key = self._storage_key(instance.name)
self._storage.set(storage_key, instance._sysctl_original)
if self._global_cfg.get_bool(consts.CFG_REAPPLY_SYSCTL, consts.CFG_DEF_REAPPLY_SYSCTL):
log.info("reapplying system sysctl")
_apply_system_sysctl(instance._sysctl)
self._apply_system_sysctl(instance._sysctl)
def _instance_verify_static(self, instance, ignore_missing, devices):
ret = True
# override, so always skip missing
ignore_missing = True
for option, value in list(instance._sysctl.items()):
curr_val = _read_sysctl(option)
curr_val = self._read_sysctl(option)
value = self._process_assignment_modifiers(self._variables.expand(value), curr_val)
if value is not None:
if self._verify_value(option, self._cmd.remove_ws(value), self._cmd.remove_ws(curr_val), ignore_missing) == False:
ret = False
return ret
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
for option, value in list(instance._sysctl_original.items()):
_write_sysctl(option, value)
self._write_sysctl(option, value)
def _apply_system_sysctl(instance_sysctl):
files = {}
for d in SYSCTL_CONFIG_DIRS:
try:
flist = os.listdir(d)
except OSError:
continue
for fname in flist:
if not fname.endswith(".conf"):
def _apply_system_sysctl(self, instance_sysctl):
files = {}
for d in SYSCTL_CONFIG_DIRS:
try:
flist = os.listdir(d)
except OSError:
continue
if fname not in files:
files[fname] = d
for fname in flist:
if not fname.endswith(".conf"):
continue
if fname not in files:
files[fname] = d
for fname in sorted(files.keys()):
d = files[fname]
path = "%s/%s" % (d, fname)
_apply_sysctl_config_file(path, instance_sysctl)
_apply_sysctl_config_file("/etc/sysctl.conf", instance_sysctl)
for fname in sorted(files.keys()):
d = files[fname]
path = "%s/%s" % (d, fname)
self._apply_sysctl_config_file(path, instance_sysctl)
self._apply_sysctl_config_file("/etc/sysctl.conf", instance_sysctl)
def _apply_sysctl_config_file(path, instance_sysctl):
log.debug("Applying sysctl settings from file %s" % path)
try:
with open(path, "r") as f:
for lineno, line in enumerate(f, 1):
_apply_sysctl_config_line(path, lineno, line, instance_sysctl)
log.debug("Finished applying sysctl settings from file %s"
% path)
except (OSError, IOError) as e:
if e.errno != errno.ENOENT:
log.error("Error reading sysctl settings from file %s: %s"
% (path, str(e)))
def _apply_sysctl_config_file(self, path, instance_sysctl):
log.debug("Applying sysctl settings from file %s" % path)
try:
with open(path, "r") as f:
for lineno, line in enumerate(f, 1):
self._apply_sysctl_config_line(path, lineno, line, instance_sysctl)
log.debug("Finished applying sysctl settings from file %s"
% path)
except (OSError, IOError) as e:
if e.errno != errno.ENOENT:
log.error("Error reading sysctl settings from file %s: %s"
% (path, str(e)))
def _apply_sysctl_config_line(path, lineno, line, instance_sysctl):
line = line.strip()
if len(line) == 0 or line[0] == "#" or line[0] == ";":
return
tmp = line.split("=", 1)
if len(tmp) != 2:
log.error("Syntax error in file %s, line %d"
% (path, lineno))
return
option, value = tmp
option = option.strip()
if len(option) == 0:
log.error("Syntax error in file %s, line %d"
% (path, lineno))
return
value = value.strip()
if option in instance_sysctl and instance_sysctl[option] != value:
log.info("Overriding sysctl parameter '%s' from '%s' to '%s'"
% (option, instance_sysctl[option], value))
def _apply_sysctl_config_line(self, path, lineno, line, instance_sysctl):
line = line.strip()
if len(line) == 0 or line[0] == "#" or line[0] == ";":
return
tmp = line.split("=", 1)
if len(tmp) != 2:
log.error("Syntax error in file %s, line %d"
% (path, lineno))
return
option, value = tmp
option = option.strip()
if len(option) == 0:
log.error("Syntax error in file %s, line %d"
% (path, lineno))
return
value = value.strip()
if option in instance_sysctl:
instance_value = self._variables.expand(instance_sysctl[option])
if instance_value != value:
log.info("Overriding sysctl parameter '%s' from '%s' to '%s'"
% (option, instance_value, value))
self._write_sysctl(option, value, ignore_missing = True)
_write_sysctl(option, value, ignore_missing = True)
def _get_sysctl_path(self, option):
# The sysctl name in sysctl tool and in /proc/sys differs.
# All dots (.) in sysctl name are represented by /proc/sys
# directories and all slashes in the name (/) are converted
# to dots (.) in the /proc/sys filenames.
return "/proc/sys/%s" % self._cmd.tr(option, "./", "/.")
def _get_sysctl_path(option):
return "/proc/sys/%s" % option.replace(".", "/")
def _read_sysctl(option):
path = _get_sysctl_path(option)
try:
with open(path, "r") as f:
line = ""
for i, line in enumerate(f):
if i > 0:
log.error("Failed to read sysctl parameter '%s', multi-line values are unsupported"
% option)
return None
value = line.strip()
log.debug("Value of sysctl parameter '%s' is '%s'"
% (option, value))
return value
except (OSError, IOError) as e:
if e.errno == errno.ENOENT:
log.error("Failed to read sysctl parameter '%s', the parameter does not exist"
% option)
else:
log.error("Failed to read sysctl parameter '%s': %s"
% (option, str(e)))
return None
def _write_sysctl(option, value, ignore_missing = False):
path = _get_sysctl_path(option)
if os.path.basename(path) in DEPRECATED_SYSCTL_OPTIONS:
log.error("Refusing to set deprecated sysctl option %s"
% option)
return False
try:
log.debug("Setting sysctl parameter '%s' to '%s'"
% (option, value))
with open(path, "w") as f:
f.write(value)
return True
except (OSError, IOError) as e:
if e.errno == errno.ENOENT:
log_func = log.debug if ignore_missing else log.error
log_func("Failed to set sysctl parameter '%s' to '%s', the parameter does not exist"
def _read_sysctl(self, option):
path = self._get_sysctl_path(option)
try:
with open(path, "r") as f:
line = ""
for i, line in enumerate(f):
if i > 0:
log.error("Failed to read sysctl parameter '%s', multi-line values are unsupported"
% option)
return None
value = line.strip()
log.debug("Value of sysctl parameter '%s' is '%s'"
% (option, value))
else:
log.error("Failed to set sysctl parameter '%s' to '%s': %s"
% (option, value, str(e)))
return False
return value
except (OSError, IOError) as e:
if e.errno == errno.ENOENT:
log.error("Failed to read sysctl parameter '%s', the parameter does not exist"
% option)
else:
log.error("Failed to read sysctl parameter '%s': %s"
% (option, str(e)))
return None
def _write_sysctl(self, option, value, ignore_missing = False):
path = self._get_sysctl_path(option)
if os.path.basename(path) in DEPRECATED_SYSCTL_OPTIONS:
log.error("Refusing to set deprecated sysctl option %s"
% option)
return False
try:
log.debug("Setting sysctl parameter '%s' to '%s'"
% (option, value))
with open(path, "w") as f:
f.write(value)
return True
except (OSError, IOError) as e:
if e.errno == errno.ENOENT:
log_func = log.debug if ignore_missing else log.error
log_func("Failed to set sysctl parameter '%s' to '%s', the parameter does not exist"
% (option, value))
else:
log.error("Failed to set sysctl parameter '%s' to '%s': %s"
% (option, value, str(e)))
return False

View file

@ -72,7 +72,7 @@ class SysfsPlugin(base.Plugin):
ret = False
return ret
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
for key, value in list(instance._sysfs_original.items()):
self._write_sysfs(key, value)

View file

@ -111,8 +111,8 @@ class SystemdPlugin(base.Plugin):
conf = self._add_keyval(conf, consts.SYSTEMD_CPUAFFINITY_VAR, cpu_affinity_saved)
self._write_systemd_system_conf(conf)
def _instance_unapply_static(self, instance, full_rollback = consts.ROLLBACK_SOFT):
if full_rollback == consts.ROLLBACK_FULL:
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
if rollback == consts.ROLLBACK_FULL:
log.info("removing '%s' systemd tuning previously added by TuneD" % consts.SYSTEMD_CPUAFFINITY_VAR)
self._remove_systemd_tuning()
log.console("you may need to manualy run 'dracut -f' to update the systemd configuration in initrd image")

View file

@ -3,6 +3,7 @@ from .decorators import *
import tuned.logs
from tuned.utils.commands import commands
import glob
import errno
log = tuned.logs.get()
@ -57,7 +58,7 @@ class USBPlugin(base.Plugin):
return "/sys/bus/usb/devices/%s/power/autosuspend" % device
@command_set("autosuspend", per_device=True)
def _set_autosuspend(self, value, device, sim):
def _set_autosuspend(self, value, device, sim, remove):
enable = self._option_bool(value)
if enable is None:
return None
@ -65,7 +66,8 @@ class USBPlugin(base.Plugin):
val = "1" if enable else "0"
if not sim:
sys_file = self._autosuspend_sysfile(device)
self._cmd.write_to_file(sys_file, val)
self._cmd.write_to_file(sys_file, val, \
no_error = [errno.ENOENT] if remove else False)
return val
@command_get("autosuspend")

View file

@ -3,6 +3,7 @@ from .decorators import *
import tuned.logs
from tuned.utils.commands import commands
import os
import errno
import re
log = tuned.logs.get()
@ -76,7 +77,7 @@ class VideoPlugin(base.Plugin):
}
@command_set("radeon_powersave", per_device=True)
def _set_radeon_powersave(self, value, device, sim):
def _set_radeon_powersave(self, value, device, sim, remove):
sys_files = self._radeon_powersave_files(device)
va = str(re.sub(r"(\s*:\s*)|(\s+)|(\s*;\s*)|(\s*,\s*)", " ", value)).split()
if not os.path.exists(sys_files["method"]):
@ -86,20 +87,25 @@ class VideoPlugin(base.Plugin):
for v in va:
if v in ["default", "auto", "low", "mid", "high"]:
if not sim:
if (self._cmd.write_to_file(sys_files["method"], "profile") and
self._cmd.write_to_file(sys_files["profile"], v)):
return v
if (self._cmd.write_to_file(sys_files["method"], "profile", \
no_error = [errno.ENOENT] if remove else False) and
self._cmd.write_to_file(sys_files["profile"], v, \
no_error = [errno.ENOENT] if remove else False)):
return v
elif v == "dynpm":
if not sim:
if (self._cmd.write_to_file(sys_files["method"], "dynpm")):
return "dynpm"
if (self._cmd.write_to_file(sys_files["method"], "dynpm", \
no_error = [errno.ENOENT] if remove else False)):
return "dynpm"
# new DPM profiles, recommended to use if supported
elif v in ["dpm-battery", "dpm-balanced", "dpm-performance"]:
if not sim:
state = v[len("dpm-"):]
if (self._cmd.write_to_file(sys_files["method"], "dpm") and
self._cmd.write_to_file(sys_files["dpm_state"], state)):
return v
if (self._cmd.write_to_file(sys_files["method"], "dpm", \
no_error = [errno.ENOENT] if remove else False) and
self._cmd.write_to_file(sys_files["dpm_state"], state, \
no_error = [errno.ENOENT] if remove else False)):
return v
else:
if not sim:
log.warn("Invalid option for radeon_powersave.")

View file

@ -3,6 +3,7 @@ from .decorators import *
import tuned.logs
import os
import errno
import struct
import glob
from tuned.utils.commands import commands
@ -57,7 +58,7 @@ class VMPlugin(base.Plugin):
return path
@command_set("transparent_hugepages")
def _set_transparent_hugepages(self, value, sim):
def _set_transparent_hugepages(self, value, sim, remove):
if value not in ["always", "never", "madvise"]:
if not sim:
log.warn("Incorrect 'transparent_hugepages' value '%s'." % str(value))
@ -72,7 +73,8 @@ class VMPlugin(base.Plugin):
sys_file = os.path.join(self._thp_path(), "enabled")
if os.path.exists(sys_file):
if not sim:
cmd.write_to_file(sys_file, value)
cmd.write_to_file(sys_file, value, \
no_error = [errno.ENOENT] if remove else False)
return value
else:
if not sim:
@ -81,8 +83,8 @@ class VMPlugin(base.Plugin):
# just an alias to transparent_hugepages
@command_set("transparent_hugepage")
def _set_transparent_hugepage(self, value, sim):
self._set_transparent_hugepages(value, sim)
def _set_transparent_hugepage(self, value, sim, remove):
self._set_transparent_hugepages(value, sim, remove)
@command_get("transparent_hugepages")
def _get_transparent_hugepages(self):
@ -98,11 +100,12 @@ class VMPlugin(base.Plugin):
return self._get_transparent_hugepages()
@command_set("transparent_hugepage.defrag")
def _set_transparent_hugepage_defrag(self, value, sim):
def _set_transparent_hugepage_defrag(self, value, sim, remove):
sys_file = os.path.join(self._thp_path(), "defrag")
if os.path.exists(sys_file):
if not sim:
cmd.write_to_file(sys_file, value)
cmd.write_to_file(sys_file, value, \
no_error = [errno.ENOENT] if remove else False)
return value
else:
if not sim:

View file

@ -32,7 +32,12 @@ class calc_isolated_cores(base.Function):
for cpu in glob.iglob(os.path.join(consts.SYSFS_CPUS_PATH, "cpu*")):
cpuid = os.path.basename(cpu)[3:]
if cpuid.isdecimal():
socket = self._cmd.read_file(os.path.join(cpu, "topology/physical_package_id")).strip()
physical_package_id = os.path.join(cpu, "topology/physical_package_id")
# Show no errors when the physical_package_id file does not exist -- the CPU may be offline.
if not os.path.exists(physical_package_id):
log.debug("file '%s' does not exist, cpu%s offline?" % (physical_package_id, cpuid))
continue
socket = self._cmd.read_file(physical_package_id).strip()
if socket.isdecimal():
topo[socket] = topo.get(socket, []) + [cpuid]

View file

@ -46,7 +46,7 @@ class Functions():
sl = re.split(r'(?<!\\):', self._str[_from:self._cnt])
if sl[0] != "${f":
return
sl = [str(v).replace("\:", ":") for v in sl]
sl = [str(v).replace(r"\:", ":") for v in sl]
if not re.match(r'\w+$', sl[1]):
log.error("invalid function name '%s'" % sl[1])
return
@ -80,7 +80,7 @@ class Functions():
self._esc = False
self._cnt += 1
if len(self._stack):
log.error("invalid varialbe syntax, non pair '{' in: '%s'" % s)
log.error("invalid variable syntax, non pair '{' in: '%s'" % s)
return self._str
def expand(self, s):

View file

@ -161,16 +161,16 @@ class Manager(object):
self._try_call("update_tuning", None,
instance.update_tuning)
# full_rollback is a helper telling plugins whether soft or full
# rollback parameter is a helper telling plugins whether soft or full
# rollback is needed, e.g. for bootloader plugin we need grub.cfg
# tuning to persist across reboots and restarts of the daemon, so in
# this case the full_rollback is usually set to consts.ROLLBACK_SOFT,
# this case the rollback is usually set to consts.ROLLBACK_SOFT,
# but we also need to clean it all up when TuneD is disabled or the
# profile is changed. In this case the full_rollback is set to
# profile is changed. In this case the rollback is set to
# consts.ROLLBACK_FULL. In practice it means to remove all temporal
# or helper files, unpatch third party config files, etc.
def stop_tuning(self, full_rollback = consts.ROLLBACK_SOFT):
def stop_tuning(self, rollback = consts.ROLLBACK_SOFT):
self._hardware_inventory.stop_processing_events()
for instance in reversed(self._instances):
self._try_call("stop_tuning", None,
instance.unapply_tuning, full_rollback)
instance.unapply_tuning, rollback)

View file

@ -29,7 +29,7 @@ class commands:
return {"Y":"1", "YES":"1", "T":"1", "TRUE":"1", "N":"0", "NO":"0", "F":"0", "FALSE":"0"}.get(v, value)
def remove_ws(self, s):
return re.sub('\s+', ' ', str(s)).strip()
return re.sub(r'\s+', ' ', str(s)).strip()
def unquote(self, v):
return re.sub("^\"(.*)\"$", r"\1", v)
@ -91,6 +91,17 @@ class commands:
return None
def write_to_file(self, f, data, makedir = False, no_error = False):
"""Write data to a file.
Parameters:
f -- filename where to write
data -- data to write
makedir -- if True and the path doesn't exist, it will be created
no_error -- if True errors are silenced, it can be also list of ignored errnos
Return:
bool -- True on success
"""
self._debug("Writing to file: '%s' < '%s'" % (f, data))
if makedir:
d = os.path.dirname(f)
@ -103,10 +114,11 @@ class commands:
fd.write(str(data))
fd.close()
rc = True
except (OSError,IOError) as e:
except (OSError, IOError) as e:
rc = False
if not no_error:
self._error("Writing to file '%s' error: '%s'" % (f, e))
if isinstance(no_error, bool) and not no_error or \
isinstance(no_error, list) and e.errno not in no_error:
self._error("Writing to file '%s' error: '%s'" % (f, e))
return rc
def read_file(self, f, err_ret = "", no_error = False):
@ -235,13 +247,13 @@ class commands:
err_out = err[:-1]
if len(err_out) == 0:
err_out = out[:-1]
err_msg = "Executing %s error: %s" % (args[0], err_out)
err_msg = "Executing '%s' error: %s" % (' '.join(args), err_out)
if not return_err:
self._error(err_msg)
except (OSError, IOError) as e:
retcode = -e.errno if e.errno is not None else -1
if not abs(retcode) in no_errors and not 0 in no_errors:
err_msg = "Executing %s error: %s" % (args[0], e)
err_msg = "Executing '%s' error: %s" % (' '.join(args), e)
if not return_err:
self._error(err_msg)
if return_err:
@ -427,7 +439,7 @@ class commands:
if s[0:8].lower() != "cpulist:":
return [("cpu" + str(v)) for v in self.cpulist_unpack(s)]
l = re.split(r"\s*(?<!\\),\s*", s)
return [str(v).replace("\,", ",") for v in l]
return [str(v).replace(r"\,", ",") for v in l]
# Do not make balancing on patched Python 2 interpreter (rhbz#1028122).
# It means less CPU usage on patchet interpreter. On non-patched interpreter
@ -523,3 +535,12 @@ class commands:
f.write(profile_name + "\n")
except (OSError,IOError) as e:
raise TunedException("Failed to save the active post-loaded profile: %s" % e.strerror)
# Translates characters in 'text' from 'source_chars' to 'dest_chars'
def tr(self, text, source_chars, dest_chars):
try:
trans = str.maketrans(source_chars, dest_chars)
except AttributeError:
import string
trans = string.maketrans(source_chars, dest_chars)
return text.translate(trans)

View file

@ -25,19 +25,19 @@ else:
delims = "".join(list(delimiters))
# REs taken from the python-2.7 ConfigParser
self.OPTCRE = re.compile(
r'(?P<option>[^' + delims + '\s][^' + delims + ']*)'
r'\s*(?P<vi>[' + delims + '])\s*'
r'(?P<option>[^' + delims + r'\s][^' + delims + ']*)'
r'\s*(?P<vi>[' + delims + r'])\s*'
r'(?P<value>.*)$'
)
self.OPTCRE_NV = re.compile(
r'(?P<option>[^' + delims + '\s][^' + delims + ']*)'
r'(?P<option>[^' + delims + r'\s][^' + delims + ']*)'
r'\s*(?:'
r'(?P<vi>[' + delims + '])\s*'
r'(?P<vi>[' + delims + r'])\s*'
r'(?P<value>.*))?$'
)
cp.ConfigParser.__init__(self, *args, **kwargs)
self._inline_comment_prefixes = inline_comment_prefixes or []
self._re = re.compile("\s+(%s).*" % ")|(".join(list(self._inline_comment_prefixes)))
self._re = re.compile(r"\s+(%s).*" % ")|(".join(list(self._inline_comment_prefixes)))
def read_string(self, string, source="<string>"):
sfile = StringIO(string)

View file

@ -116,7 +116,7 @@ class Nettool:
p_ethtool = Popen(["ethtool", self._interface], \
stdout=PIPE, stderr=PIPE, close_fds=True, \
universal_newlines = True)
p_filter = Popen(["sed", "s/^\s*//;s/:\s*/:\\n/g"], \
p_filter = Popen(["sed", r"s/^\s*//;s/:\s*/:\n/g"], \
stdin=p_ethtool.stdout, stdout=PIPE, \
universal_newlines = True, \
close_fds=True)

View file

@ -1,5 +1,5 @@
TUNED_VERSION_MAJOR = 2
TUNED_VERSION_MINOR = 20
TUNED_VERSION_MINOR = 21
TUNED_VERSION_PATCH = 0
TUNED_VERSION_STR = "%d.%d.%d" % (TUNED_VERSION_MAJOR, TUNED_VERSION_MINOR, TUNED_VERSION_PATCH)