Merge branch 'master' into rhbz2118786_pm_qos_resume_latency_us_option
This commit is contained in:
commit
613c7afd57
33 changed files with 506 additions and 68 deletions
41
.github/workflows/codeql.yml
vendored
Normal file
41
.github/workflows/codeql.yml
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: "48 13 * * 1"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ python ]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
9
Makefile
9
Makefile
|
|
@ -23,11 +23,12 @@ else
|
|||
GIT_PSUFFIX = .$(GIT_SUFFIX)
|
||||
RPM_VERSION = $(NAME)-$(VERSION)-1$(GIT_PSUFFIX)
|
||||
endif
|
||||
PKG_CONFIG = pkg-config
|
||||
UNITDIR_FALLBACK = /usr/lib/systemd/system
|
||||
UNITDIR_DETECT = $(shell pkg-config systemd --variable systemdsystemunitdir || rpm --eval '%{_unitdir}' 2>/dev/null || echo $(UNITDIR_FALLBACK))
|
||||
UNITDIR_DETECT = $(shell $(PKG_CONFIG) systemd --variable systemdsystemunitdir || rpm --eval '%{_unitdir}' 2>/dev/null || echo $(UNITDIR_FALLBACK))
|
||||
UNITDIR = $(UNITDIR_DETECT:%{_unitdir}=$(UNITDIR_FALLBACK))
|
||||
TMPFILESDIR_FALLBACK = /usr/lib/tmpfiles.d
|
||||
TMPFILESDIR_DETECT = $(shell pkg-config systemd --variable tmpfilesdir || rpm --eval '%{_tmpfilesdir}' 2>/dev/null || echo $(TMPFILESDIR_FALLBACK))
|
||||
TMPFILESDIR_DETECT = $(shell $(PKG_CONFIG) systemd --variable tmpfilesdir || rpm --eval '%{_tmpfilesdir}' 2>/dev/null || echo $(TMPFILESDIR_FALLBACK))
|
||||
TMPFILESDIR = $(TMPFILESDIR_DETECT:%{_tmpfilesdir}=$(TMPFILESDIR_FALLBACK))
|
||||
VERSIONED_NAME = $(NAME)-$(VERSION)$(PRERELEASE)$(GIT_PSUFFIX)
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ ifeq ($(PYTHON),python2)
|
|||
PYLINT = pylint-2
|
||||
endif
|
||||
SHEBANG_REWRITE_REGEX= '1s|^\#!/usr/bin/\<python3\>|\#!$(PYTHON)|'
|
||||
PYTHON_SITELIB = $(shell $(PYTHON) -c 'from distutils.sysconfig import get_python_lib; print(get_python_lib());')
|
||||
PYTHON_SITELIB = $(shell $(PYTHON) -c 'from sysconfig import get_path; print(get_path("purelib"));')
|
||||
ifeq ($(PYTHON_SITELIB),)
|
||||
$(error Failed to determine python library directory)
|
||||
endif
|
||||
|
|
@ -176,6 +177,8 @@ install: install-dirs
|
|||
$(DESTDIR)$(SYSCONFDIR)/tuned/realtime-virtual-host-variables.conf
|
||||
mv $(DESTDIR)$(TUNED_PROFILESDIR)/cpu-partitioning/cpu-partitioning-variables.conf \
|
||||
$(DESTDIR)$(SYSCONFDIR)/tuned/cpu-partitioning-variables.conf
|
||||
mv $(DESTDIR)$(TUNED_PROFILESDIR)/cpu-partitioning-powersave/cpu-partitioning-powersave-variables.conf \
|
||||
$(DESTDIR)$(SYSCONFDIR)/tuned/cpu-partitioning-powersave-variables.conf
|
||||
install -pm 0644 recommend.conf $(DESTDIR)$(TUNED_RECOMMEND_DIR)/50-tuned.conf
|
||||
|
||||
# bash completion
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<policyconfig>
|
||||
|
||||
<vendor>TuneD</vendor>
|
||||
<vendor_url>https://fedorahosted.org/tuned/</vendor_url>
|
||||
<vendor_url>https://tuned-project.org/</vendor_url>
|
||||
<icon_name>tuned</icon_name>
|
||||
|
||||
<action id="com.redhat.tuned.active_profile">
|
||||
|
|
@ -216,4 +216,15 @@
|
|||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="com.redhat.tuned.instance_acquire_devices">
|
||||
<description>Acquire devices from other instances and assign them to the instance</description>
|
||||
<message>Authentication is required to get hints for parameters of TuneD plugin</message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
|
|
|
|||
67
man/tuned-profiles-cpu-partitioning-powersave.7
Normal file
67
man/tuned-profiles-cpu-partitioning-powersave.7
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
.\"/*
|
||||
.\" * All rights reserved
|
||||
.\" * Copyright (C) 2022 Red Hat, Inc.
|
||||
.\" * Authors: Christophe Fontaine
|
||||
.\" *
|
||||
.\" * This program is free software; you can redistribute it and/or
|
||||
.\" * modify it under the terms of the GNU General Public License
|
||||
.\" * as published by the Free Software Foundation; either version 2
|
||||
.\" * of the License, or (at your option) any later version.
|
||||
.\" *
|
||||
.\" * This program is distributed in the hope that it will be useful,
|
||||
.\" * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
.\" * GNU General Public License for more details.
|
||||
.\" *
|
||||
.\" * You should have received a copy of the GNU General Public License
|
||||
.\" * along with this program; if not, write to the Free Software
|
||||
.\" * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
.\" */
|
||||
.\"
|
||||
.TH TUNED_PROFILES_CPU_PARTITIONING "7" "22 Nov 2022" "TuneD"
|
||||
.SH NAME
|
||||
tuned\-profiles\-cpu\-partitioning\-powersave - Partition CPUs into isolated and housekeeping with C-States enabled
|
||||
|
||||
.SH DESCRIPTION
|
||||
The cpu\-partitioning\-powersave profile is similar to cpu\-partitioning profile,
|
||||
but gives more flexibility on the C-States configuration.
|
||||
|
||||
.SH CONFIGURATION
|
||||
The cpu-partitioning-powersave profile is configured by editing the
|
||||
.I /etc/tuned/cpu-partitioning-powersave-variables.conf
|
||||
file. There are three configuration options:
|
||||
|
||||
.TP
|
||||
.B isolated_cores=<CPU\-LIST>
|
||||
List of CPUs to isolate. This option is mandatory. Any CPUs not in this list
|
||||
is automatically considered a housekeeping CPU.
|
||||
.TP
|
||||
.B no_balance_cores=<CPU\-LIST>
|
||||
List of CPUs not be considered by the kernel when doing system wide
|
||||
process load\-balancing. Usually, this list should be the same as
|
||||
isolated_cores=. This option is optional.
|
||||
.TP
|
||||
.B max_power_state=<MAX_CSTATE>
|
||||
Maximum c-state the cores are allowed to enter. Can be expressed as it's name (C1E)
|
||||
or minimum wake-up latency, in micro-seconds.
|
||||
This parameter is provided as-is to `force_latency`.
|
||||
Default is set to "cstate.name:C1|10" to behave as cpu\-partitioning profile.
|
||||
|
||||
|
||||
.SH IMPORTANT NOTES
|
||||
|
||||
.IP *
|
||||
Same recommendations as tuned\-profiles\-cpu\-partitioning (7) apply.
|
||||
|
||||
.SH "FILES"
|
||||
.nf
|
||||
.I /etc/tuned/cpu\-partitioning\-variables.conf
|
||||
.I /etc/tuned/tuned\-main.conf
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR tuned (8)
|
||||
.BR tuned\-adm (8)
|
||||
.BR tuned\-profiles\-cpu\-partitioning (7)
|
||||
.SH AUTHOR
|
||||
.nf
|
||||
Christophe Fontaine <cfontain@redhat.com>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
.\" * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
.\" */
|
||||
.\"
|
||||
.TH TUNED_PROFILES_OPENSHIFT "8" "02 Aug 2021" "Fedora Power Management SIG" "TuneD"
|
||||
.TH TUNED_PROFILES_OPENSHIFT "7" "02 Aug 2021" "Fedora Power Management SIG" "TuneD"
|
||||
.SH NAME
|
||||
tuned\-profiles\-openshift - description of profiles provided for the OpenShift platform
|
||||
|
||||
|
|
|
|||
21
profiles/aws/tuned.conf
Normal file
21
profiles/aws/tuned.conf
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# tuned configuration
|
||||
#
|
||||
|
||||
[main]
|
||||
summary=Optimize for aws ec2 instances
|
||||
include=throughput-performance
|
||||
|
||||
# Marvell ThunderX
|
||||
[bootloader.thunderx]
|
||||
# rhbz:1836058
|
||||
type=bootloader
|
||||
uname_regex=aarch64
|
||||
cmdline=+iommu.strict=0
|
||||
|
||||
[bootloader]
|
||||
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html#timeout-nvme-ebs-volumes
|
||||
# set nvme_core.io_timeout to 4294967295
|
||||
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enhanced-networking-ena.html
|
||||
# set net.ifnames to 0
|
||||
cmdline=+net.ifnames=0 nvme_core.io_timeout=4294967295
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Examples:
|
||||
# isolated_cores=2,4-7
|
||||
# isolated_cores=2-23
|
||||
#
|
||||
# Reserve 1 core per socket for housekeeping, isolate the rest.
|
||||
isolated_cores=${f:calc_isolated_cores:1}
|
||||
|
||||
# To disable the kernel load balancing in certain isolated CPUs:
|
||||
# no_balance_cores=5-10
|
||||
|
||||
# Specifies the maximum powerstate for idling cores.
|
||||
# given to force_latency tuned parameter. To have the same behavior
|
||||
# as cpu-partitioning profile, set to "cstate.name:C1|10"
|
||||
max_power_state=cstate.name:C1|10
|
||||
31
profiles/cpu-partitioning-powersave/tuned.conf
Normal file
31
profiles/cpu-partitioning-powersave/tuned.conf
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# tuned configuration
|
||||
#
|
||||
|
||||
[main]
|
||||
summary=Optimize for CPU partitioning with additional powersave
|
||||
include=cpu-partitioning
|
||||
|
||||
[variables]
|
||||
# User is responsible for updating variables.conf with variable content such as isolated_cores=X-Y
|
||||
include=/etc/tuned/cpu-partitioning-powersave-variables.conf
|
||||
|
||||
isolated_cores_assert_check = \\${isolated_cores}
|
||||
# Make sure isolated_cores is defined before any of the variables that
|
||||
# use it (such as assert1) are defined, so that child profiles can set
|
||||
# isolated_cores directly in the profile (tuned.conf)
|
||||
isolated_cores = ${isolated_cores}
|
||||
# Fail if isolated_cores are not set
|
||||
assert1=${f:assertion_non_equal:isolated_cores are set:${isolated_cores}:${isolated_cores_assert_check}}
|
||||
|
||||
max_power_state_assert_check = \\${max_power_state}
|
||||
max_power_state = ${max_power_state}
|
||||
|
||||
# Fail if max_power_state is not set
|
||||
assert2=${f:assertion_non_equal:max_power_state is set:${max_power_state}:${max_power_state_assert_check}}
|
||||
|
||||
[cpu]
|
||||
force_latency=${max_power_state}
|
||||
no_turbo=true
|
||||
|
||||
[bootloader]
|
||||
cmdline_cpu_part=+nohz=on${cmd_isolcpus} nohz_full=${isolated_cores} rcu_nocbs=${isolated_cores} tuned.non_isolcpus=${not_isolated_cpumask} intel_pstate=passive nosoftlockup
|
||||
|
|
@ -58,6 +58,11 @@ vm.dirty_background_ratio = 10
|
|||
# and move them to swap cache
|
||||
vm.swappiness=10
|
||||
|
||||
# The default kernel value 128 was over twenty years old default,
|
||||
# kernel-5.4 increased it to 4096, thus do not have it lower than 2048
|
||||
# on older kernels
|
||||
net.core.somaxconn=>2048
|
||||
|
||||
# Marvell ThunderX
|
||||
[sysctl.thunderx]
|
||||
type=sysctl
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ class Base(object):
|
|||
|
||||
def is_tuned_connection_ok(self):
|
||||
"""
|
||||
Result True, False depends on if tuned daemon is running. If its not runing this method try to start tuned.
|
||||
Result True, False depends on if tuned daemon is running. If its not running this method try to start tuned.
|
||||
"""
|
||||
|
||||
try:
|
||||
|
|
@ -236,7 +236,7 @@ class Base(object):
|
|||
This add rows to object listbox_summary_of_active_profile.
|
||||
Row consist of grid. Inside grid on first possition is label, second possition is vertical grid.
|
||||
label = name of plugin
|
||||
verical grid consist of labels where are stored values for plugin option and value.
|
||||
vertical grid consist of labels where are stored values for plugin option and value.
|
||||
|
||||
This method is emited after change profile and on startup of app.
|
||||
"""
|
||||
|
|
@ -356,14 +356,14 @@ class Base(object):
|
|||
try:
|
||||
if self._get_active_profile_name() == profile:
|
||||
self.error_dialog('You can not remove active profile',
|
||||
'Please deactivate profile by choosind another!'
|
||||
'Please deactivate profile by choosing another!'
|
||||
)
|
||||
return
|
||||
if profile is None:
|
||||
self.error_dialog('No profile selected!', '')
|
||||
return
|
||||
if self._gobj('windowProfileEditor').is_active():
|
||||
self.error_dialog('You are ediding '
|
||||
self.error_dialog('You are editing '
|
||||
+ self.editing_profile_name
|
||||
+ ' profile.',
|
||||
'Please close edit window and try again.'
|
||||
|
|
|
|||
|
|
@ -406,6 +406,7 @@ fi
|
|||
%exclude %{_sysconfdir}/tuned/realtime-virtual-guest-variables.conf
|
||||
%exclude %{_sysconfdir}/tuned/realtime-virtual-host-variables.conf
|
||||
%exclude %{_sysconfdir}/tuned/cpu-partitioning-variables.conf
|
||||
%exclude %{_sysconfdir}/tuned/cpu-partitioning-powersave-variables.conf
|
||||
%exclude %{_prefix}/lib/tuned/default
|
||||
%exclude %{_prefix}/lib/tuned/desktop-powersave
|
||||
%exclude %{_prefix}/lib/tuned/laptop-ac-powersave
|
||||
|
|
@ -423,6 +424,7 @@ fi
|
|||
%exclude %{_prefix}/lib/tuned/realtime-virtual-guest
|
||||
%exclude %{_prefix}/lib/tuned/realtime-virtual-host
|
||||
%exclude %{_prefix}/lib/tuned/cpu-partitioning
|
||||
%exclude %{_prefix}/lib/tuned/cpu-partitioning-powersave
|
||||
%exclude %{_prefix}/lib/tuned/spectrumscale-ece
|
||||
%exclude %{_prefix}/lib/tuned/postgresql
|
||||
%exclude %{_prefix}/lib/tuned/openshift
|
||||
|
|
@ -524,8 +526,11 @@ fi
|
|||
|
||||
%files profiles-cpu-partitioning
|
||||
%config(noreplace) %{_sysconfdir}/tuned/cpu-partitioning-variables.conf
|
||||
%config(noreplace) %{_sysconfdir}/tuned/cpu-partitioning-powersave-variables.conf
|
||||
%{_prefix}/lib/tuned/cpu-partitioning
|
||||
%{_prefix}/lib/tuned/cpu-partitioning-powersave
|
||||
%{_mandir}/man7/tuned-profiles-cpu-partitioning.7*
|
||||
%{_mandir}/man7/tuned-profiles-cpu-partitioning-powersave.7*
|
||||
|
||||
%files profiles-spectrumscale
|
||||
%{_prefix}/lib/tuned/spectrumscale-ece
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ CFG_LOG_FILE_COUNT = "log_file_count"
|
|||
CFG_LOG_FILE_MAX_SIZE = "log_file_max_size"
|
||||
CFG_UNAME_STRING = "uname_string"
|
||||
CFG_CPUINFO_STRING = "cpuinfo_string"
|
||||
CFG_CPU_EPP_FLAG = "hwp_epp"
|
||||
|
||||
# no_daemon mode
|
||||
CFG_DEF_DAEMON = True
|
||||
|
|
|
|||
|
|
@ -308,3 +308,42 @@ class Controller(tuned.exports.interfaces.ExportableInterface):
|
|||
if caller == "":
|
||||
return False
|
||||
return self._daemon.get_plugin_hints(str(plugin_name))
|
||||
|
||||
# devices - devices to migrate from other instances, string of form "dev1,dev2,dev3,..."
|
||||
# or "cpulist:CPULIST", where CPULIST is e.g. "0-3,6,8-9"
|
||||
# instance_name - instance where to migrate devices
|
||||
@exports.export("ss", "(bs)")
|
||||
def instance_acquire_devices(self, devices, instance_name, caller = None):
|
||||
if caller == "":
|
||||
return (False, "Unauthorized")
|
||||
found = False
|
||||
for instance_target in self._daemon._unit_manager.instances:
|
||||
if instance_target.name == instance_name:
|
||||
log.debug("Found instance '%s'." % instance_target.name)
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
rets = "Instance '%s' not found" % instance_name
|
||||
log.error(rets)
|
||||
return (False, rets)
|
||||
devs = set(self._cmd.devstr2devs(devices))
|
||||
log.debug("Instance '%s' trying to acquire devices '%s'." % (instance_target.name, str(devs)))
|
||||
for instance in self._daemon._unit_manager.instances:
|
||||
devs_moving = instance.processed_devices & devs
|
||||
if len(devs_moving):
|
||||
devs -= devs_moving
|
||||
log.info("Moving devices '%s' from instance '%s' to instance '%s'." % (str(devs_moving),
|
||||
instance.name, instance_target.name))
|
||||
if (instance.plugin.name != instance_target.plugin.name):
|
||||
rets = "Target instance '%s' is of type '%s', but devices '%s' are currently handled by " \
|
||||
"instance '%s' which is of type '%s'." % (instance_target.name,
|
||||
instance_target.plugin.name, str(devs_moving), instance.name, instance.plugin.name)
|
||||
log.error(rets)
|
||||
return (False, rets)
|
||||
instance.plugin._remove_devices_nocheck(instance, devs_moving)
|
||||
instance_target.plugin._add_devices_nocheck(instance_target, devs_moving)
|
||||
if (len(devs)):
|
||||
rets = "Ignoring devices not handled by any instance '%s'." % str(devs)
|
||||
log.info(rets)
|
||||
return (False, rets)
|
||||
return (True, "OK")
|
||||
|
|
|
|||
|
|
@ -6,10 +6,14 @@ import threading
|
|||
import signal
|
||||
import tuned.logs
|
||||
import tuned.consts as consts
|
||||
import traceback
|
||||
import logging
|
||||
from inspect import ismethod
|
||||
from tuned.utils.polkit import polkit
|
||||
from gi.repository import GLib
|
||||
from types import FunctionType
|
||||
from dbus.exceptions import DBusException
|
||||
from dbus.lowlevel import ErrorMessage
|
||||
|
||||
try:
|
||||
# Python3 version
|
||||
|
|
@ -26,6 +30,29 @@ except ImportError:
|
|||
|
||||
log = tuned.logs.get()
|
||||
|
||||
# This is mostly copy of the code from the dbus.service module without the
|
||||
# code that sends tracebacks through the D-Bus (i.e. no library tracebacks
|
||||
# are exposed on the D-Bus now).
|
||||
def _method_reply_error(connection, message, exception):
|
||||
name = getattr(exception, '_dbus_error_name', None)
|
||||
|
||||
if name is not None:
|
||||
pass
|
||||
elif getattr(exception, '__module__', '') in ('', '__main__'):
|
||||
name = 'org.freedesktop.DBus.Python.%s' % exception.__class__.__name__
|
||||
else:
|
||||
name = 'org.freedesktop.DBus.Python.%s.%s' % (exception.__module__, exception.__class__.__name__)
|
||||
|
||||
if isinstance(exception, DBusException):
|
||||
contents = exception.get_dbus_message()
|
||||
else:
|
||||
contents = ''.join(traceback.format_exception_only(exception.__class__,
|
||||
exception))
|
||||
reply = ErrorMessage(message, name, contents)
|
||||
|
||||
if not message.get_no_reply():
|
||||
connection.send_message(reply)
|
||||
|
||||
class DBusExporter(interfaces.ExporterInterface):
|
||||
"""
|
||||
Export method calls through DBus Interface.
|
||||
|
|
@ -37,6 +64,14 @@ class DBusExporter(interfaces.ExporterInterface):
|
|||
"""
|
||||
|
||||
def __init__(self, bus_name, interface_name, object_name):
|
||||
# Monkey patching of the D-Bus library _method_reply_error() to reply
|
||||
# tracebacks via D-Bus only if in the debug mode. It doesn't seem there is a
|
||||
# more simple way how to cover all possible exceptions that could occur in
|
||||
# the D-Bus library. Just setting the exception.include_traceback to False doesn't
|
||||
# seem to help because there is only a subset of exceptions that support this flag.
|
||||
if log.getEffectiveLevel() != logging.DEBUG:
|
||||
dbus.service._method_reply_error = _method_reply_error
|
||||
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
self._dbus_object_cls = None
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class GuiPluginLoader():
|
|||
"""
|
||||
|
||||
try:
|
||||
config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
|
||||
config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
config_parser.optionxform = str
|
||||
with open(file_name) as f:
|
||||
config_parser.read_string("[" + consts.MAGIC_HEADER_NAME + "]\n" + f.read(), file_name)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class GuiProfileLoader(object):
|
|||
|
||||
if profilePath == tuned.consts.LOAD_DIRECTORIES[1]:
|
||||
file_path = profilePath + '/' + profile_name + '/' + tuned.consts.PROFILE_FILE
|
||||
config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
|
||||
config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
config_parser.optionxform = str
|
||||
config_parser.read_string(config)
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ class GuiProfileLoader(object):
|
|||
|
||||
def load_profile_config(self, profile_name, path):
|
||||
conf_path = path + '/' + profile_name + '/' + tuned.consts.PROFILE_FILE
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
config.optionxform = str
|
||||
profile_config = collections.OrderedDict()
|
||||
with open(conf_path) as f:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ if __name__ == "__main__":
|
|||
if not os.path.exists(profile_dict['filename']):
|
||||
os.makedirs(os.path.dirname(profile_dict['filename']))
|
||||
|
||||
profile_configobj = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
|
||||
profile_configobj = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
profile_configobj.optionxform = str
|
||||
for section, options in profile_dict['main'].items():
|
||||
profile_configobj.add_section(section)
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ class Plugin(base.Plugin):
|
|||
self._hardware_events_cleanup()
|
||||
|
||||
def _hardware_events_init(self):
|
||||
raise NotImplementedError()
|
||||
pass
|
||||
|
||||
def _hardware_events_cleanup(self):
|
||||
raise NotImplementedError()
|
||||
pass
|
||||
|
||||
def _init_devices(self):
|
||||
self._hardware_events_init()
|
||||
|
|
@ -28,49 +28,79 @@ class Plugin(base.Plugin):
|
|||
def _hardware_events_callback(self, event, device):
|
||||
if event == "add":
|
||||
log.info("device '%s' added" % device.sys_name)
|
||||
self._add_device(device)
|
||||
self._add_device(device.sys_name)
|
||||
elif event == "remove":
|
||||
log.info("device '%s' removed" % device.sys_name)
|
||||
self._remove_device(device)
|
||||
self._remove_device(device.sys_name)
|
||||
|
||||
def _add_device(self, device):
|
||||
device_name = device.sys_name
|
||||
def _add_device_process(self, instance, device_name):
|
||||
log.info("instance %s: adding new device %s" % (instance.name, device_name))
|
||||
self._assigned_devices.add(device_name)
|
||||
self._call_device_script(instance, instance.script_pre, "apply", [device_name])
|
||||
self._added_device_apply_tuning(instance, device_name)
|
||||
self._call_device_script(instance, instance.script_post, "apply", [device_name])
|
||||
instance.processed_devices.add(device_name)
|
||||
|
||||
def _add_device(self, device_name):
|
||||
if device_name in (self._assigned_devices | self._free_devices):
|
||||
return
|
||||
|
||||
for instance_name, instance in list(self._instances.items()):
|
||||
if len(self._get_matching_devices(instance, [device_name])) == 1:
|
||||
log.info("instance %s: adding new device %s" % (instance_name, device_name))
|
||||
self._assigned_devices.add(device_name)
|
||||
self._call_device_script(instance, instance.script_pre, "apply", [device_name])
|
||||
self._added_device_apply_tuning(instance, device_name)
|
||||
self._call_device_script(instance, instance.script_post, "apply", [device_name])
|
||||
instance.processed_devices.add(device_name)
|
||||
self._add_device_process(instance, device_name)
|
||||
break
|
||||
else:
|
||||
log.debug("no instance wants %s" % device_name)
|
||||
self._free_devices.add(device_name)
|
||||
|
||||
def _remove_device(self, device):
|
||||
device_name = device.sys_name
|
||||
def _add_devices_nocheck(self, instance, device_names):
|
||||
"""
|
||||
Add devices specified by the set to the instance, no check is performed.
|
||||
"""
|
||||
for dev in device_names:
|
||||
self._add_device_process(instance, dev)
|
||||
# This can be a bit racy (we can overcount),
|
||||
# but it shouldn't affect the boolean result
|
||||
instance.active = len(instance.processed_devices) \
|
||||
+ len(instance.assigned_devices) > 0
|
||||
|
||||
def _remove_device_process(self, instance, device_name):
|
||||
if device_name in instance.processed_devices:
|
||||
self._call_device_script(instance, instance.script_post, "unapply", [device_name])
|
||||
self._removed_device_unapply_tuning(instance, device_name)
|
||||
self._call_device_script(instance, instance.script_pre, "unapply", [device_name])
|
||||
instance.processed_devices.remove(device_name)
|
||||
# This can be a bit racy (we can overcount),
|
||||
# but it shouldn't affect the boolean result
|
||||
instance.active = len(instance.processed_devices) \
|
||||
+ len(instance.assigned_devices) > 0
|
||||
self._assigned_devices.remove(device_name)
|
||||
return True
|
||||
return False
|
||||
|
||||
def _remove_device(self, device_name):
|
||||
"""Remove device from the instance
|
||||
|
||||
Parameters:
|
||||
device_name -- name of the device
|
||||
|
||||
"""
|
||||
if device_name not in (self._assigned_devices | self._free_devices):
|
||||
return
|
||||
|
||||
for instance in list(self._instances.values()):
|
||||
if device_name in instance.processed_devices:
|
||||
self._call_device_script(instance, instance.script_post, "unapply", [device_name])
|
||||
self._removed_device_unapply_tuning(instance, device_name)
|
||||
self._call_device_script(instance, instance.script_pre, "unapply", [device_name])
|
||||
instance.processed_devices.remove(device_name)
|
||||
# This can be a bit racy (we can overcount),
|
||||
# but it shouldn't affect the boolean result
|
||||
instance.active = len(instance.processed_devices) \
|
||||
+ len(instance.assigned_devices) > 0
|
||||
self._assigned_devices.remove(device_name)
|
||||
if self._remove_device_process(instance, device_name):
|
||||
break
|
||||
else:
|
||||
self._free_devices.remove(device_name)
|
||||
|
||||
def _remove_devices_nocheck(self, instance, device_names):
|
||||
"""
|
||||
Remove devices specified by the set from the instance, no check is performed.
|
||||
"""
|
||||
for dev in device_names:
|
||||
self._remove_device_process(instance, dev)
|
||||
|
||||
def _added_device_apply_tuning(self, instance, device_name):
|
||||
self._execute_all_device_commands(instance, [device_name])
|
||||
if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from . import base
|
||||
from . import hotplug
|
||||
from .decorators import *
|
||||
import tuned.logs
|
||||
from tuned.utils.commands import commands
|
||||
|
|
@ -10,7 +10,7 @@ import glob
|
|||
log = tuned.logs.get()
|
||||
cmd = commands()
|
||||
|
||||
class AudioPlugin(base.Plugin):
|
||||
class AudioPlugin(hotplug.Plugin):
|
||||
"""
|
||||
`audio`::
|
||||
|
||||
|
|
|
|||
|
|
@ -690,6 +690,8 @@ class BootloaderPlugin(base.Plugin):
|
|||
log.warn("requested changes to initrd will not be applied!")
|
||||
if len(self._cmdline_val) > 0:
|
||||
log.warn("requested changes to cmdline will not be applied!")
|
||||
# ensure that the desired cmdline is always written to BOOT_CMDLINE_FILE (/etc/tuned/bootcmdline)
|
||||
self._patch_bootcmdline({consts.BOOT_CMDLINE_TUNED_VAR : self._cmdline_val, consts.BOOT_CMDLINE_INITRD_ADD_VAR : self._initrd_val})
|
||||
elif enabling and self.update_grub2_cfg:
|
||||
if self._rpm_ostree:
|
||||
self._rpm_ostree_update()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from . import base
|
||||
from . import hotplug
|
||||
from .decorators import *
|
||||
import tuned.logs
|
||||
from tuned.utils.commands import commands
|
||||
|
|
@ -14,7 +14,7 @@ log = tuned.logs.get()
|
|||
|
||||
cpuidle_states_path = "/sys/devices/system/cpu/cpu0/cpuidle"
|
||||
|
||||
class CPULatencyPlugin(base.Plugin):
|
||||
class CPULatencyPlugin(hotplug.Plugin):
|
||||
"""
|
||||
`cpu`::
|
||||
|
||||
|
|
@ -65,7 +65,8 @@ class CPULatencyPlugin(base.Plugin):
|
|||
Bias (EPB) values are supported. The alternative values are separated
|
||||
using the '|' character. The following EPB values are supported
|
||||
starting with kernel 4.13: "performance", "balance-performance",
|
||||
"normal", "balance-power" and "power".
|
||||
"normal", "balance-power" and "power". On newer processors is value
|
||||
writen straight to file (see rhbz#2095829)
|
||||
+
|
||||
.Specifying alternative Energy Performance Bias values
|
||||
====
|
||||
|
|
@ -78,6 +79,26 @@ class CPULatencyPlugin(base.Plugin):
|
|||
try to set it to 'power'.
|
||||
====
|
||||
|
||||
`energy_performance_preference`:::
|
||||
[option]`energy_performance_preference` supports managing energy
|
||||
vs. performance hints on some newer Intel processors. 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
|
||||
directory in `sysfs`.
|
||||
in
|
||||
+
|
||||
.Specifying alternative Energy Performance Hints values
|
||||
====
|
||||
----
|
||||
[cpu]
|
||||
energy_performance_preference=balance_power|power
|
||||
----
|
||||
|
||||
*TuneD* will try to set EPP to 'balance_power'. If that fails, it will
|
||||
try to set it to 'power'.
|
||||
====
|
||||
|
||||
`latency_low, latency_high, load_threshold`:::
|
||||
+
|
||||
If the CPU load is lower than the value specified by
|
||||
|
|
@ -182,6 +203,8 @@ class CPULatencyPlugin(base.Plugin):
|
|||
self._governors_map = {}
|
||||
self._cmd = commands()
|
||||
|
||||
self._flags = None
|
||||
|
||||
def _init_devices(self):
|
||||
self._devices_supported = True
|
||||
self._free_devices = set()
|
||||
|
|
@ -208,6 +231,7 @@ class CPULatencyPlugin(base.Plugin):
|
|||
"max_perf_pct" : None,
|
||||
"no_turbo" : None,
|
||||
"pm_qos_resume_latency_us": None,
|
||||
"energy_performance_preference" : None,
|
||||
}
|
||||
|
||||
def _check_arch(self):
|
||||
|
|
@ -256,6 +280,11 @@ class CPULatencyPlugin(base.Plugin):
|
|||
if self._has_intel_pstate:
|
||||
log.info("intel_pstate detected")
|
||||
|
||||
def _get_cpuinfo_flags(self):
|
||||
if self._flags is None:
|
||||
self._flags = procfs.cpuinfo().tags.get("flags", [])
|
||||
return self._flags
|
||||
|
||||
def _is_cpu_online(self, device):
|
||||
sd = str(device)
|
||||
return self._cmd.is_cpu_online(str(device).replace("cpu", ""))
|
||||
|
|
@ -550,15 +579,43 @@ class CPULatencyPlugin(base.Plugin):
|
|||
return_err = True)
|
||||
return (retcode, err_msg)
|
||||
|
||||
def _intel_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):
|
||||
if not self._is_cpu_online(device):
|
||||
log.debug("%s is not online, skipping" % device)
|
||||
return None
|
||||
if self._has_energy_perf_bias:
|
||||
cpu_id = device.lstrip("cpu")
|
||||
vals = energy_perf_bias.split('|')
|
||||
|
||||
# It should be writen straight to sysfs energy_perf_bias file if requested on newer processors
|
||||
# see rhbz#2095829
|
||||
if consts.CFG_CPU_EPP_FLAG in self._get_cpuinfo_flags():
|
||||
energy_perf_bias_path = self._energy_perf_bias_path(cpu_id)
|
||||
if os.path.exists(energy_perf_bias_path):
|
||||
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
|
||||
else:
|
||||
log.error("Failed to set energy_perf_bias on cpu '%s'. Is the value in the profile correct?"
|
||||
% device)
|
||||
|
||||
return str(energy_perf_bias)
|
||||
else:
|
||||
log.error("Failed to set energy_perf_bias on cpu '%s' because energy_perf_bias file does not exist."
|
||||
% device)
|
||||
return None
|
||||
elif self._has_energy_perf_bias:
|
||||
if not sim:
|
||||
cpu_id = device.lstrip("cpu")
|
||||
vals = energy_perf_bias.split('|')
|
||||
for val in vals:
|
||||
val = val.strip()
|
||||
log.debug("Trying to set energy_perf_bias to '%s' on cpu '%s'"
|
||||
|
|
@ -612,8 +669,12 @@ class CPULatencyPlugin(base.Plugin):
|
|||
if not self._is_cpu_online(device):
|
||||
log.debug("%s is not online, skipping" % device)
|
||||
return None
|
||||
if self._has_energy_perf_bias:
|
||||
cpu_id = device.lstrip("cpu")
|
||||
cpu_id = device.lstrip("cpu")
|
||||
if consts.CFG_CPU_EPP_FLAG in self._get_cpuinfo_flags():
|
||||
energy_perf_bias_path = self._energy_perf_bias_path(cpu_id)
|
||||
if os.path.exists(energy_perf_bias_path):
|
||||
energy_perf_bias = self._energy_perf_policy_to_human_v2(self._cmd.read_file(energy_perf_bias_path))
|
||||
elif self._has_energy_perf_bias:
|
||||
retcode, lines = self._cmd.execute(["x86_energy_perf_policy", "-c", cpu_id, "-r"])
|
||||
if retcode == 0:
|
||||
for line in lines.splitlines():
|
||||
|
|
@ -656,3 +717,41 @@ class CPULatencyPlugin(base.Plugin):
|
|||
log.debug("%s is not online, skipping" % device)
|
||||
return None
|
||||
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):
|
||||
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)):
|
||||
vals = energy_performance_preference.split('|')
|
||||
if not sim:
|
||||
avail_vals = set(self._cmd.read_file(self._intel_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)
|
||||
log.info("Setting energy_performance_preference value '%s' for cpu '%s'" % (val, device))
|
||||
break
|
||||
else:
|
||||
log.warn("energy_performance_preference value '%s' unavailable for cpu '%s'" % (val, device))
|
||||
else:
|
||||
log.error("Failed to set energy_performance_preference on cpu '%s'. Is the value in the profile correct?"
|
||||
% 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.")
|
||||
return None
|
||||
|
||||
@command_get("energy_performance_preference")
|
||||
def _get_energy_performance_preference(self, device, ignore_missing=False):
|
||||
if not self._is_cpu_online(device):
|
||||
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()
|
||||
else:
|
||||
log.debug("energy_performance_available_preferences file missing, which can happen if the system is booted without the intel_pstate driver.")
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import errno
|
||||
from . import base
|
||||
from . import hotplug
|
||||
from .decorators import *
|
||||
import tuned.logs
|
||||
from tuned.utils.nettool import ethcard
|
||||
|
|
@ -11,7 +11,7 @@ log = tuned.logs.get()
|
|||
|
||||
WOL_VALUES = "pumbagsd"
|
||||
|
||||
class NetTuningPlugin(base.Plugin):
|
||||
class NetTuningPlugin(hotplug.Plugin):
|
||||
"""
|
||||
`net`::
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ class NetTuningPlugin(base.Plugin):
|
|||
# 0.6 is just a magical constant (empirical value): Typical workload on netcard won't exceed
|
||||
# that and if it does, then the code is smart enough to adapt it.
|
||||
# 1024 * 1024 as for MB -> B
|
||||
# speed / 7 Mb -> MB
|
||||
# speed / 8 Mb -> MB
|
||||
return (int) (0.6 * 1024 * 1024 * speed / 8)
|
||||
|
||||
# parse features/coalesce config parameters (those defined in profile configuration)
|
||||
|
|
|
|||
|
|
@ -526,7 +526,8 @@ class SchedulerPlugin(base.Plugin):
|
|||
instance._runtime_tuning = False
|
||||
|
||||
def _instance_cleanup(self, instance):
|
||||
pass
|
||||
for fd in instance._evlist.get_pollfd():
|
||||
os.close(fd.name)
|
||||
|
||||
@classmethod
|
||||
def _get_config_options(cls):
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class SysctlPlugin(base.Plugin):
|
|||
|
||||
if self._global_cfg.get_bool(consts.CFG_REAPPLY_SYSCTL, consts.CFG_DEF_REAPPLY_SYSCTL):
|
||||
log.info("reapplying system sysctl")
|
||||
_apply_system_sysctl()
|
||||
_apply_system_sysctl(instance._sysctl)
|
||||
|
||||
def _instance_verify_static(self, instance, ignore_missing, devices):
|
||||
ret = True
|
||||
|
|
@ -103,7 +103,7 @@ class SysctlPlugin(base.Plugin):
|
|||
_write_sysctl(option, value)
|
||||
|
||||
|
||||
def _apply_system_sysctl():
|
||||
def _apply_system_sysctl(instance_sysctl):
|
||||
files = {}
|
||||
for d in SYSCTL_CONFIG_DIRS:
|
||||
try:
|
||||
|
|
@ -119,15 +119,15 @@ def _apply_system_sysctl():
|
|||
for fname in sorted(files.keys()):
|
||||
d = files[fname]
|
||||
path = "%s/%s" % (d, fname)
|
||||
_apply_sysctl_config_file(path)
|
||||
_apply_sysctl_config_file("/etc/sysctl.conf")
|
||||
_apply_sysctl_config_file(path, instance_sysctl)
|
||||
_apply_sysctl_config_file("/etc/sysctl.conf", instance_sysctl)
|
||||
|
||||
def _apply_sysctl_config_file(path):
|
||||
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)
|
||||
_apply_sysctl_config_line(path, lineno, line, instance_sysctl)
|
||||
log.debug("Finished applying sysctl settings from file %s"
|
||||
% path)
|
||||
except (OSError, IOError) as e:
|
||||
|
|
@ -135,7 +135,7 @@ def _apply_sysctl_config_file(path):
|
|||
log.error("Error reading sysctl settings from file %s: %s"
|
||||
% (path, str(e)))
|
||||
|
||||
def _apply_sysctl_config_line(path, lineno, line):
|
||||
def _apply_sysctl_config_line(path, lineno, line, instance_sysctl):
|
||||
line = line.strip()
|
||||
if len(line) == 0 or line[0] == "#" or line[0] == ";":
|
||||
return
|
||||
|
|
@ -151,6 +151,10 @@ def _apply_sysctl_config_line(path, lineno, line):
|
|||
% (path, lineno))
|
||||
return
|
||||
value = value.strip()
|
||||
if option in instance_sysctl:
|
||||
log.info("Overriding sysctl parameter '%s' from '%s' to '%s'"
|
||||
% (option, instance_sysctl[option], value))
|
||||
|
||||
_write_sysctl(option, value, ignore_missing = True)
|
||||
|
||||
def _get_sysctl_path(option):
|
||||
|
|
|
|||
17
tuned/profiles/functions/function_cpulist2devs.py
Normal file
17
tuned/profiles/functions/function_cpulist2devs.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import tuned.logs
|
||||
from . import base
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
class cpulist2devs(base.Function):
|
||||
"""
|
||||
Conversion function: converts CPU list to device strings
|
||||
"""
|
||||
def __init__(self):
|
||||
# arbitrary number of arguments
|
||||
super(cpulist2devs, self).__init__("cpulist2devs", 0)
|
||||
|
||||
def execute(self, args):
|
||||
if not super(cpulist2devs, self).execute(args):
|
||||
return None
|
||||
return self._cmd.cpulist2string(self._cmd.cpulist_unpack(",".join(args)), prefix = "cpu")
|
||||
|
|
@ -96,11 +96,11 @@ class Loader(object):
|
|||
|
||||
def _load_config_data(self, file_name):
|
||||
try:
|
||||
config_obj = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
|
||||
config_obj = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
config_obj.optionxform=str
|
||||
with open(file_name) as f:
|
||||
config_obj.read_file(f, file_name)
|
||||
except Error as e:
|
||||
except Error.__bases__ as e:
|
||||
raise InvalidProfileException("Cannot parse '%s'." % file_name, e)
|
||||
|
||||
config = collections.OrderedDict()
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class Locator(object):
|
|||
if config_file is None:
|
||||
return None
|
||||
try:
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), allow_no_value=True)
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), allow_no_value=True, strict=False)
|
||||
config.optionxform = str
|
||||
with open(config_file) as f:
|
||||
config.read_string("[" + consts.MAGIC_HEADER_NAME + "]\n" + f.read())
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class Variables():
|
|||
log.error("unable to find variables_file: '%s'" % filename)
|
||||
return
|
||||
try:
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), allow_no_value=True)
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), allow_no_value=True, strict=False)
|
||||
config.optionxform = str
|
||||
with open(filename) as f:
|
||||
config.read_string("[" + consts.MAGIC_HEADER_NAME + "]\n" + f.read(), filename)
|
||||
|
|
|
|||
|
|
@ -414,8 +414,20 @@ class commands:
|
|||
m |= pow(2, v)
|
||||
return m
|
||||
|
||||
def cpulist2string(self, l):
|
||||
return ",".join(str(v) for v in l)
|
||||
def cpulist2string(self, l, prefix = ""):
|
||||
return ",".join((prefix + str(v)) for v in l)
|
||||
|
||||
# Converts string s consisting of "dev1,dev2,dev3,..." to list ["dev1", "dev2, "dev3", ...],
|
||||
# whitespaces are ignored, cpu lists are supported with the prefix "cpulist:", e.g.
|
||||
# "cpulist:0-2,4" is converted to ["cpu0", "cpu1", "cpu2", "cpu4"]. If device name starts
|
||||
# with "cpulist:" write it as "cpulist:cpulist:". Escape commas in name with the "\,".
|
||||
def devstr2devs(self, s):
|
||||
if s[0:8].lower() == "cpulist:":
|
||||
s = s[8:]
|
||||
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]
|
||||
|
||||
# Do not make balancing on patched Python 2 interpreter (rhbz#1028122).
|
||||
# It means less CPU usage on patchet interpreter. On non-patched interpreter
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ else:
|
|||
|
||||
class ConfigParser(cp.ConfigParser):
|
||||
|
||||
def __init__(self, delimiters=None, inline_comment_prefixes=None, strict=True, *args, **kwargs):
|
||||
def __init__(self, delimiters=None, inline_comment_prefixes=None, *args, **kwargs):
|
||||
delims = "".join(list(delimiters))
|
||||
# REs taken from the python-2.7 ConfigParser
|
||||
self.OPTCRE = re.compile(
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class GlobalConfig():
|
|||
"""
|
||||
log.debug("reading and parsing global configuration file '%s'" % file_name)
|
||||
try:
|
||||
config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
|
||||
config_parser = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
config_parser.optionxform = str
|
||||
with open(file_name) as f:
|
||||
config_parser.read_string("[" + consts.MAGIC_HEADER_NAME + "]\n" + f.read(), file_name)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class polkit():
|
|||
try:
|
||||
uid = self._bus.get_unix_user(sender)
|
||||
except dbus.exceptions.DBusException as e:
|
||||
log.error("error using falback authorization method: %s" % e)
|
||||
log.error("error using fallback authorization method: %s" % e)
|
||||
return -2
|
||||
if uid == 0:
|
||||
return 2
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class ProfileRecommender:
|
|||
try:
|
||||
if not os.path.isfile(fname):
|
||||
return None
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'))
|
||||
config = ConfigParser(delimiters=('='), inline_comment_prefixes=('#'), strict=False)
|
||||
config.optionxform = str
|
||||
with open(fname) as f:
|
||||
config.read_file(f, fname)
|
||||
|
|
|
|||
Loading…
Reference in a new issue