commit 6fe5d14f588956dfff89716f81b8101c7a94cd6d Author: nyanloutre Date: Wed Nov 3 20:05:41 2021 +0100 init diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ab2c639 --- /dev/null +++ b/flake.lock @@ -0,0 +1,26 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1635844945, + "narHash": "sha256-tZcL307dj28jgEU1Wdn+zwG9neyW0H2+ZjdVhvJxh9g=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b67e752c29f18a0ca5534a07661366d6a2c2e649", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..0c96812 --- /dev/null +++ b/flake.nix @@ -0,0 +1,49 @@ +{ + description = "IPMI HDD temp fan control"; + + inputs.nixpkgs.url = "nixpkgs/nixos-unstable"; + + outputs = { self, nixpkgs }: let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + python_pkgs = nixpkgs.legacyPackages.${system}.python3.pkgs; + packageName = "ipmihddtemp"; + app = python_pkgs.buildPythonApplication rec { + pname = packageName; + + version = builtins.substring 0 8 self.lastModifiedDate; + + src = ./.; + + postPatch = '' + substituteInPlace ipmihddtemp.py \ + --replace "ipmitool" "${pkgs.ipmitool}/bin/ipmitool" + ''; + + doCheck = false; + + propagatedBuildInputs = with python_pkgs; [ + pysmart + ]; + }; + module = ({ config, lib, pkgs, ... }: let + cfg = config.${packageName}; + in { + options.${packageName} = with lib.options; { + enable = mkEnableOption packageName; + }; + + config = lib.mkIf cfg.enable { + systemd.services.ipmihddtemp = { + wantedBy = [ "multi-user.target" ]; + script = "${app}/bin/ipmihddtemp"; + enable = true; + }; + }; + }); + in { + defaultPackage.${system} = app; + nixosModules.${packageName} = module; + nixosModule = self.nixosModules.${packageName}; + }; +} diff --git a/ipmihddtemp.py b/ipmihddtemp.py new file mode 100644 index 0000000..d96d596 --- /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"]) + +def main(): + 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) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1ecc944 --- /dev/null +++ b/setup.py @@ -0,0 +1,20 @@ +from setuptools import setup + +setup( + name='ipmihddtemp', + py_modules=['ipmihddtemp'], + version='1.0', + description='IPMI HDD temp fan control', + author='Paul TREHIOU', + author_email='paul@nyanlout.re', + url='https://gitea.nyanlout.re/nyanloutre/ipmihddtemp', + license='MIT', + entry_points={ + 'console_scripts': [ + 'ipmihddtemp=ipmihddtemp:main' + ] + }, + install_requires=[ + 'pysmart' + ] +)