mirror of
https://github.com/CHN-beta/nixpkgs.git
synced 2026-01-11 18:32:23 +08:00
[Backport release-25.05] tuned: init at 2.25.1 (#430398)
This commit is contained in:
@@ -222,6 +222,8 @@ Alongside many enhancements to NixOS modules and general system improvements, th
|
||||
|
||||
- [Docling Serve](https://github.com/docling-project/docling-serve) running [Docling](https://github.com/docling-project/docling) as an API service. Available as [services.docling-serve](#opt-services.docling-serve.enable).
|
||||
|
||||
- [TuneD](https://tuned-project.org/), a system tuning service for Linux. Available as [services.tuned](#opt-services.tuned.enable).
|
||||
|
||||
- [Pareto Security](https://paretosecurity.com/) is an alternative to corporate compliance solutions for companies that care about security but know it doesn't have to be invasive. Available as [services.paretosecurity](#opt-services.paretosecurity.enable).
|
||||
|
||||
- [GNU Rush](https://gnu.org/software/rush/) is a Restricted User Shell, designed for systems providing limited remote access to their resources. Available as [programs.rush](#opt-programs.rush.enable).
|
||||
|
||||
@@ -674,6 +674,7 @@
|
||||
./services/hardware/tlp.nix
|
||||
./services/hardware/trezord.nix
|
||||
./services/hardware/triggerhappy.nix
|
||||
./services/hardware/tuned.nix
|
||||
./services/hardware/tuxedo-rs.nix
|
||||
./services/hardware/udev.nix
|
||||
./services/hardware/udisks2.nix
|
||||
|
||||
257
nixos/modules/services/hardware/tuned.nix
Normal file
257
nixos/modules/services/hardware/tuned.nix
Normal file
@@ -0,0 +1,257 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.tuned;
|
||||
|
||||
moduleFromName = name: lib.getAttrFromPath (lib.splitString "." name) config;
|
||||
|
||||
settingsFormat = pkgs.formats.iniWithGlobalSection { };
|
||||
profileFormat = pkgs.formats.ini { };
|
||||
ppdSettingsFormat = pkgs.formats.ini { };
|
||||
|
||||
settingsSubmodule = {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options = {
|
||||
daemon = lib.mkEnableOption "the use of a daemon for TuneD" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
dynamic_tuning = lib.mkEnableOption "dynamic tuning";
|
||||
|
||||
sleep_interval = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 1;
|
||||
description = "Interval in which the TuneD daemon is waken up and checks for events (in seconds).";
|
||||
};
|
||||
|
||||
update_interval = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 10;
|
||||
description = "Update interval for dynamic tuning (in seconds).";
|
||||
};
|
||||
|
||||
recommend_command = lib.mkEnableOption "recommend functionality" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
reapply_sysctl =
|
||||
lib.mkEnableOption "the reapplying of global sysctls after TuneD sysctls are applied"
|
||||
// {
|
||||
default = true;
|
||||
};
|
||||
|
||||
default_instance_priority = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 0;
|
||||
description = "Default instance (unit) priority.";
|
||||
};
|
||||
|
||||
profile_dirs = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/etc/tuned/profiles";
|
||||
# Ensure we always have the vendored profiles available
|
||||
apply = dirs: "${cfg.package}/lib/tuned/profiles," + dirs;
|
||||
description = "Directories to search for profiles, separated by `,` or `;`.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ppdSettingsSubmodule = {
|
||||
freeformType = ppdSettingsFormat.type;
|
||||
|
||||
options = {
|
||||
main = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
default = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "balanced";
|
||||
description = "Default PPD profile.";
|
||||
example = "performance";
|
||||
};
|
||||
|
||||
battery_detection = lib.mkEnableOption "battery detection" // {
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = "Core configuration for power-profiles-daemon support.";
|
||||
};
|
||||
|
||||
profiles = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = {
|
||||
power-saver = "powersave";
|
||||
balanced = "balanced";
|
||||
performance = "throughput-performance";
|
||||
};
|
||||
description = "Map of PPD profiles to native TuneD profiles.";
|
||||
};
|
||||
|
||||
battery = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = {
|
||||
balanced = "balanced-battery";
|
||||
};
|
||||
description = "Map of PPD battery states to TuneD profiles.";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
options.services.tuned = {
|
||||
enable = lib.mkEnableOption "TuneD";
|
||||
|
||||
package = lib.mkPackageOption pkgs "tuned" { };
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule settingsSubmodule;
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for TuneD.
|
||||
See {manpage}`tuned-main.conf(5)`.
|
||||
'';
|
||||
};
|
||||
|
||||
profiles = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.submodule {
|
||||
freeformType = profileFormat.type;
|
||||
}
|
||||
);
|
||||
default = { };
|
||||
description = ''
|
||||
Profiles for TuneD.
|
||||
See {manpage}`tuned.conf(5)`.
|
||||
'';
|
||||
example = {
|
||||
my-cool-profile = {
|
||||
main.include = "my-other-cool-profile";
|
||||
|
||||
my_sysctl = {
|
||||
type = "sysctl";
|
||||
replace = true;
|
||||
|
||||
"net.core.rmem_default" = 262144;
|
||||
"net.core.wmem_default" = 262144;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ppdSupport = lib.mkEnableOption "translation of power-profiles-daemon API calls to TuneD" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
ppdSettings = lib.mkOption {
|
||||
type = lib.types.submodule ppdSettingsSubmodule;
|
||||
default = { };
|
||||
description = ''
|
||||
Settings for TuneD's power-profiles-daemon compatibility service.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
# From `tuned.service`
|
||||
{
|
||||
assertion = config.security.polkit.enable;
|
||||
message = "`services.tuned` requires `security.polkit` to be enabled.";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = cfg.settings.dynamic_tuning -> cfg.settings.daemon;
|
||||
message = "`services.tuned.settings.dynamic_tuning` requires `services.tuned.settings.daemon` to be `true`.";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = cfg.ppdSupport -> config.services.upower.enable;
|
||||
message = "`services.tuned.ppdSupport` requires `services.upower` to be enabled.";
|
||||
}
|
||||
]
|
||||
# Declare service conflicts, also sourced from `tuned.service`
|
||||
++
|
||||
map
|
||||
(name: {
|
||||
assertion = !(moduleFromName name).enable;
|
||||
message = "`services.tuned` conflicts with `${name}`.";
|
||||
})
|
||||
[
|
||||
"services.auto-cpufreq"
|
||||
"services.power-profiles-daemon"
|
||||
"services.tlp"
|
||||
];
|
||||
|
||||
environment = {
|
||||
etc = lib.mkMerge [
|
||||
{
|
||||
"tuned/tuned-main.conf".source = settingsFormat.generate "tuned-main.conf" {
|
||||
sections = { };
|
||||
globalSection = cfg.settings;
|
||||
};
|
||||
|
||||
"tuned/ppd.conf".source = lib.mkIf cfg.ppdSupport (
|
||||
ppdSettingsFormat.generate "ppd.conf" cfg.ppdSettings
|
||||
);
|
||||
}
|
||||
|
||||
(lib.mapAttrs' (
|
||||
name: value:
|
||||
lib.nameValuePair "tuned/profiles/${name}/tuned.conf" {
|
||||
source = profileFormat.generate "tuned.conf" value;
|
||||
}
|
||||
) cfg.profiles)
|
||||
];
|
||||
|
||||
systemPackages = [ cfg.package ];
|
||||
};
|
||||
|
||||
security.polkit.enable = lib.mkDefault true;
|
||||
|
||||
services = {
|
||||
dbus.packages = [ cfg.package ];
|
||||
|
||||
# Many DEs (like GNOME and KDE Plasma) enable PPD by default
|
||||
# Let's try to make it easier to transition by only enabling this module
|
||||
power-profiles-daemon.enable = false;
|
||||
|
||||
# NOTE: Required by `tuned-ppd` for handling power supply changes
|
||||
# (i.e., `services.tuned.ppdSettings.main.battery_detection`)
|
||||
# https://github.com/NixOS/nixpkgs/issues/431105
|
||||
upower.enable = lib.mkIf cfg.ppdSupport true;
|
||||
};
|
||||
|
||||
systemd = {
|
||||
packages = [ cfg.package ];
|
||||
|
||||
services = {
|
||||
tuned = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
tuned-ppd = lib.mkIf cfg.ppdSupport {
|
||||
wantedBy = [ "graphical.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
tmpfiles = {
|
||||
packages = [ cfg.package ];
|
||||
|
||||
# NOTE(@getchoo): `cfg.package` should contain a `tuned.conf` for tmpfiles.d already. Avoid a naming conflict!
|
||||
settings.tuned-profiles = {
|
||||
# Required for tuned-gui
|
||||
"/etc/tuned/profiles".d = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1408,6 +1408,7 @@ in
|
||||
ttyd = handleTest ./web-servers/ttyd.nix { };
|
||||
tt-rss = handleTest ./web-apps/tt-rss.nix { };
|
||||
txredisapi = handleTest ./txredisapi.nix { };
|
||||
tuned = runTest ./tuned.nix;
|
||||
tuptime = handleTest ./tuptime.nix { };
|
||||
turbovnc-headless-server = handleTest ./turbovnc-headless-server.nix { };
|
||||
turn-rs = handleTest ./turn-rs.nix { };
|
||||
|
||||
51
nixos/tests/tuned.nix
Normal file
51
nixos/tests/tuned.nix
Normal file
@@ -0,0 +1,51 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
name = "tuned";
|
||||
meta = { inherit (pkgs.tuned.meta) maintainers; };
|
||||
|
||||
nodes.machine = {
|
||||
imports = [ ./common/x11.nix ];
|
||||
|
||||
services.tuned = {
|
||||
enable = true;
|
||||
|
||||
profiles = {
|
||||
test-profile = {
|
||||
sysctls = {
|
||||
type = "sysctl";
|
||||
replace = true;
|
||||
|
||||
"net.core.rmem_default" = 262144;
|
||||
"net.core.wmem_default" = 262144;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
|
||||
testScript = ''
|
||||
with subtest("Wait for service startup"):
|
||||
machine.wait_for_x()
|
||||
machine.wait_for_unit("tuned.service")
|
||||
machine.wait_for_unit("tuned-ppd.service")
|
||||
|
||||
with subtest("Get service status"):
|
||||
machine.succeed("systemctl status tuned.service")
|
||||
|
||||
# NOTE(@getchoo): `pkgs.tuned` provides its own `tuned.conf` for tmpfiles.d
|
||||
# A naming conflict with it and a `systemd.tmpfiles.settings` entry appeared in the initial PR for this module
|
||||
# This breaks the GUI in some cases, and it was annoying to figure out. Make sure it doesn't happen again!
|
||||
with subtest("Ensure systemd-tmpfiles paths are configured"):
|
||||
machine.succeed("systemd-tmpfiles --cat-config | grep '/etc/tuned/profiles'")
|
||||
machine.succeed("systemd-tmpfiles --cat-config | grep '/run/tuned'")
|
||||
|
||||
with subtest("Test GUI"):
|
||||
machine.execute("tuned-gui >&2 &")
|
||||
machine.wait_for_window("tuned")
|
||||
machine.wait_for_text("Start TuneD Daemon")
|
||||
machine.screenshot("gui")
|
||||
'';
|
||||
}
|
||||
154
pkgs/by-name/tu/tuned/package.nix
Normal file
154
pkgs/by-name/tu/tuned/package.nix
Normal file
@@ -0,0 +1,154 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
asciidoctor,
|
||||
desktop-file-utils,
|
||||
dmidecode,
|
||||
ethtool,
|
||||
fetchFromGitHub,
|
||||
gawk,
|
||||
gobject-introspection,
|
||||
hdparm,
|
||||
iproute2,
|
||||
nix-update-script,
|
||||
nixosTests,
|
||||
pkg-config,
|
||||
powertop,
|
||||
python3Packages,
|
||||
tuna,
|
||||
util-linux,
|
||||
versionCheckHook,
|
||||
virt-what,
|
||||
wrapGAppsHook3,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "tuned";
|
||||
version = "2.25.1";
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
"doc"
|
||||
"man"
|
||||
];
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "redhat-performance";
|
||||
repo = "tuned";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-MMyYMgdvoAIeLCqUZMoQYsYYbgkXku47nZWq2aowPFg=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Some tests require a TTY to run
|
||||
./remove-tty-tests.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
patchShebangs .
|
||||
|
||||
substituteInPlace tuned-gui.py tuned.service tuned/ppd/tuned-ppd.service \
|
||||
--replace-warn "/usr/sbin/" "$out/bin/"
|
||||
|
||||
substituteInPlace tuned-gui.py \
|
||||
--replace-warn "/usr/share/" "$out/share/"
|
||||
|
||||
substituteInPlace tuned-gui.desktop \
|
||||
--replace-warn "/usr/sbin/tuned-gui" "tuned-gui"
|
||||
|
||||
substituteInPlace experiments/powertop2tuned.py \
|
||||
--replace-warn "/usr/sbin/powertop" "${lib.getExe powertop}"
|
||||
'';
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
asciidoctor
|
||||
desktop-file-utils
|
||||
gobject-introspection
|
||||
pkg-config
|
||||
wrapGAppsHook3
|
||||
python3Packages.wrapPython
|
||||
];
|
||||
|
||||
propagatedBuildInputs = with python3Packages; [
|
||||
dbus-python
|
||||
pygobject3
|
||||
pyinotify
|
||||
pyperf
|
||||
python-linux-procfs
|
||||
pyudev
|
||||
tuna
|
||||
];
|
||||
|
||||
makeFlags = [
|
||||
"PREFIX="
|
||||
|
||||
"DATADIR=/share"
|
||||
"DESTDIR=${placeholder "out"}"
|
||||
"KERNELINSTALLHOOKDIR=/lib/kernel/install.d"
|
||||
"PYTHON=${lib.getExe python3Packages.python}"
|
||||
"PYTHON_SITELIB=/${python3Packages.python.sitePackages}"
|
||||
"TMPFILESDIR=/lib/tmpfiles.d"
|
||||
"TUNED_PROFILESDIR=/lib/tuned/profile"
|
||||
"UNITDIR=/lib/systemd/system"
|
||||
];
|
||||
|
||||
installTargets = [
|
||||
"install"
|
||||
"install-ppd"
|
||||
];
|
||||
|
||||
dontWrapGApps = true;
|
||||
makeWrapperArgs = [
|
||||
"\${gappsWrapperArgs[@]}"
|
||||
"--prefix"
|
||||
"PATH"
|
||||
":"
|
||||
(lib.makeBinPath [
|
||||
dmidecode
|
||||
ethtool
|
||||
gawk
|
||||
hdparm
|
||||
iproute2
|
||||
util-linux
|
||||
virt-what
|
||||
])
|
||||
];
|
||||
|
||||
doCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
||||
checkTarget = "test";
|
||||
|
||||
doInstallCheck = true;
|
||||
nativeInstallCheckInputs = [
|
||||
python3Packages.pythonImportsCheckHook
|
||||
versionCheckHook
|
||||
];
|
||||
|
||||
pythonImportsCheck = [ "tuned" ];
|
||||
|
||||
postInstall = ''
|
||||
rm -rf $out/{run,var}
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
wrapPythonPrograms
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
tests = lib.optionalAttrs stdenv.hostPlatform.isLinux {
|
||||
nixos = nixosTests.tuned;
|
||||
};
|
||||
updateScript = nix-update-script { };
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Tuning Profile Delivery Mechanism for Linux";
|
||||
homepage = "https://tuned-project.org";
|
||||
changelog = "https://github.com/redhat-performance/tuned/releases/tag/v${finalAttrs.version}";
|
||||
license = lib.licenses.gpl2Only;
|
||||
maintainers = with lib.maintainers; [ getchoo ];
|
||||
mainProgram = "tuned";
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
})
|
||||
52
pkgs/by-name/tu/tuned/remove-tty-tests.patch
Normal file
52
pkgs/by-name/tu/tuned/remove-tty-tests.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
diff --git a/tests/unit/hardware/test_device_matcher_udev.py b/tests/unit/hardware/test_device_matcher_udev.py
|
||||
index 1903955..f973107 100644
|
||||
--- a/tests/unit/hardware/test_device_matcher_udev.py
|
||||
+++ b/tests/unit/hardware/test_device_matcher_udev.py
|
||||
@@ -10,27 +10,7 @@ class DeviceMatcherUdevTestCase(unittest.TestCase):
|
||||
cls.matcher = DeviceMatcherUdev()
|
||||
|
||||
def test_simple_search(self):
|
||||
- try:
|
||||
- device = pyudev.Devices.from_sys_path(self.udev_context,
|
||||
- "/sys/devices/virtual/tty/tty0")
|
||||
- except AttributeError:
|
||||
- device = pyudev.Device.from_sys_path(self.udev_context,
|
||||
- "/sys/devices/virtual/tty/tty0")
|
||||
- self.assertTrue(self.matcher.match("tty0", device))
|
||||
- try:
|
||||
- device = pyudev.Devices.from_sys_path(self.udev_context,
|
||||
- "/sys/devices/virtual/tty/tty1")
|
||||
- except AttributeError:
|
||||
- device = pyudev.Device.from_sys_path(self.udev_context,
|
||||
- "/sys/devices/virtual/tty/tty1")
|
||||
- self.assertFalse(self.matcher.match("tty0", device))
|
||||
+ return True
|
||||
|
||||
def test_regex_search(self):
|
||||
- try:
|
||||
- device = pyudev.Devices.from_sys_path(self.udev_context,
|
||||
- "/sys/devices/virtual/tty/tty0")
|
||||
- except AttributeError:
|
||||
- device = pyudev.Device.from_sys_path(self.udev_context,
|
||||
- "/sys/devices/virtual/tty/tty0")
|
||||
- self.assertTrue(self.matcher.match("tty.", device))
|
||||
- self.assertFalse(self.matcher.match("tty[1-9]", device))
|
||||
+ return True
|
||||
diff --git a/tests/unit/hardware/test_inventory.py b/tests/unit/hardware/test_inventory.py
|
||||
index 8490922..8bd004b 100644
|
||||
--- a/tests/unit/hardware/test_inventory.py
|
||||
+++ b/tests/unit/hardware/test_inventory.py
|
||||
@@ -18,12 +18,7 @@ class InventoryTestCase(unittest.TestCase):
|
||||
cls._dummier = DummyPlugin()
|
||||
|
||||
def test_get_device(self):
|
||||
- try:
|
||||
- device1 = pyudev.Devices.from_name(self._context, "tty", "tty0")
|
||||
- except AttributeError:
|
||||
- device1 = pyudev.Device.from_name(self._context, "tty", "tty0")
|
||||
- device2 = self._inventory.get_device("tty", "tty0")
|
||||
- self.assertEqual(device1,device2)
|
||||
+ return True
|
||||
|
||||
def test_get_devices(self):
|
||||
device_list1 = self._context.list_devices(subsystem = "tty")
|
||||
Reference in New Issue
Block a user