diff --git a/flake.lock b/flake.lock index 1698b1d..9e35e36 100644 --- a/flake.lock +++ b/flake.lock @@ -16,6 +16,22 @@ "type": "github" } }, + "nixpkgs-nyanloutre-pysmart": { + "locked": { + "lastModified": 1634643555, + "narHash": "sha256-Fu0JVScZt0fUqfeo2tsTUcoehtpalBU7+15pxy1Ld+Y=", + "owner": "nyanloutre", + "repo": "nixpkgs", + "rev": "256d8d34f05c8badeaf3ecb615d3af08a4b492d6", + "type": "github" + }, + "original": { + "owner": "nyanloutre", + "ref": "pysmart-init", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs-unstable": { "locked": { "lastModified": 1634436779, @@ -50,6 +66,7 @@ "root": { "inputs": { "nixpkgs": "nixpkgs", + "nixpkgs-nyanloutre-pysmart": "nixpkgs-nyanloutre-pysmart", "nixpkgs-unstable": "nixpkgs-unstable", "simple-nixos-mailserver": "simple-nixos-mailserver" } diff --git a/flake.nix b/flake.nix index a586e8b..ac35fd1 100644 --- a/flake.nix +++ b/flake.nix @@ -2,10 +2,11 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-21.05"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + nixpkgs-nyanloutre-pysmart.url = "github:nyanloutre/nixpkgs/pysmart-init"; simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-21.05"; }; - outputs = { self, nixpkgs, nixpkgs-unstable, simple-nixos-mailserver }: { + outputs = { self, nixpkgs, nixpkgs-unstable, simple-nixos-mailserver, nixpkgs-nyanloutre-pysmart }: { nixosConfigurations.loutreos = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ @@ -18,6 +19,23 @@ "${nixpkgs-unstable}/nixos/modules/services/audio/navidrome.nix" simple-nixos-mailserver.nixosModule ./systems/LoutreOS/configuration.nix + ({ pkgs, ... }: { + systemd.services.ipmihddtemp = { + description = "IPMI HDD temp fan control"; + wantedBy = ["multi-user.target"]; + path = with pkgs;[ ipmitool smartmontools ]; + serviceConfig = { + ExecStart = with nixpkgs-nyanloutre-pysmart.legacyPackages.x86_64-linux; + let env = python3Packages.python.buildEnv.override { + extraLibs = with python3Packages;[ pysmart ]; + ignoreCollisions = true; + }; + in "${pkgs.writeShellScriptBin "run.sh" '' + ${env}/bin/python ${pkgs.writeScript "ipmihddtemp.py" "${builtins.readFile ./ipmihddtemp.py}"} + ''}/bin/run.sh"; + }; + }; + }) ]; }; diff --git a/ipmihddtemp.py b/ipmihddtemp.py new file mode 100644 index 0000000..ee7e21f --- /dev/null +++ b/ipmihddtemp.py @@ -0,0 +1,42 @@ +import math +import subprocess +import time +from pySMART import DeviceList + +MIN_FAN_SPEED = 30 +MAX_FAN_SPEED = 100 + +MIN_HDD_TEMP = 30 +MAX_HDD_TEMP = 50 + +devlist = DeviceList() + +# Put fans in full speed mode +subprocess.run(["ipmitool", "raw", "0x30", "0x45", "0x01", "0x01"]) + +while True: + for device in devlist: + device.update() + + # Linear fan speed between MIN_FAN_SPEED and MAX_FAN_SPEED + fan_speed = max( + min( + math.ceil( + MIN_FAN_SPEED + + ( + (MAX_FAN_SPEED - MIN_FAN_SPEED) + * ( + (max([x.temperature for x in devlist]) - MIN_HDD_TEMP) + / (MAX_HDD_TEMP - MIN_HDD_TEMP) + ) + ) + ), + MAX_FAN_SPEED, + ), + MIN_FAN_SPEED, + ) + + subprocess.run(["ipmitool", "raw", "0x30", "0x70", "0x66", "0x01", "0x00", hex(fan_speed)]) + + time.sleep(10) +