From ced296a296104f650eaed2193ee4acc8577ea4ae Mon Sep 17 00:00:00 2001 From: Benoit Date: Sun, 31 Aug 2025 11:00:00 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20version=20LXC=20et=20restructuration=20?= =?UTF-8?q?compl=C3=A8te=20du=20projet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🚀 NOUVELLES FONCTIONNALITÉS : - Version LXC complĂšte pour Proxmox avec installation automatisĂ©e - Script d'installation LXC avec interface colorĂ©e et vĂ©rifications - Service systemd avec configuration sĂ©curisĂ©e - Script de dĂ©sinstallation avec sauvegarde de config 📁 RESTRUCTURATION : - SĂ©paration Docker/LXC dans des dossiers dĂ©diĂ©s - Documentation spĂ©cialisĂ©e pour chaque version - Guide d'installation unifiĂ© (INSTALL.md) - README principal avec comparaison des versions 🐳 AMÉLIORATIONS DOCKER : - docker-compose.yml optimisĂ© avec healthcheck - Documentation Docker dĂ©taillĂ©e - Configuration par variables d'environnement clarifiĂ©e 📩 FONCTIONNALITÉS LXC : - Installation en une commande - IntĂ©gration systemd native - Gestion des permissions et sĂ©curitĂ© - Logs intĂ©grĂ©s avec journalctl - Configuration via fichier d'environnement 🔧 OUTILS INCLUS : - Scripts d'installation/dĂ©sinstallation - Healthchecks pour les deux versions - Documentation de dĂ©pannage - Comparatif des deux approches đŸ€– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- INSTALL.md | 69 ++++++++++ README.md | 87 +++++++++---- docker/Dell_iDRAC_fan_controller.sh | 167 ++++++++++++++++++++++++ Dockerfile => docker/Dockerfile | 0 docker/README-DOCKER.md | 173 +++++++++++++++++++++++++ docker/docker-compose.yml | 53 ++++++++ docker/functions.sh | 105 +++++++++++++++ docker/healthcheck.sh | 24 ++++ lxc/Dell_iDRAC_fan_controller.sh | 167 ++++++++++++++++++++++++ lxc/README-LXC.md | 193 ++++++++++++++++++++++++++++ lxc/functions.sh | 105 +++++++++++++++ lxc/healthcheck.sh | 24 ++++ lxc/idrac-fan-controller.service | 39 ++++++ lxc/install-lxc.sh | 125 ++++++++++++++++++ lxc/uninstall-lxc.sh | 105 +++++++++++++++ 15 files changed, 1410 insertions(+), 26 deletions(-) create mode 100644 INSTALL.md create mode 100755 docker/Dell_iDRAC_fan_controller.sh rename Dockerfile => docker/Dockerfile (100%) create mode 100644 docker/README-DOCKER.md create mode 100644 docker/docker-compose.yml create mode 100755 docker/functions.sh create mode 100755 docker/healthcheck.sh create mode 100755 lxc/Dell_iDRAC_fan_controller.sh create mode 100644 lxc/README-LXC.md create mode 100755 lxc/functions.sh create mode 100755 lxc/healthcheck.sh create mode 100644 lxc/idrac-fan-controller.service create mode 100755 lxc/install-lxc.sh create mode 100755 lxc/uninstall-lxc.sh diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..7f12874 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,69 @@ +# Guide d'installation + +Choisissez votre mĂ©thode d'installation prĂ©fĂ©rĂ©e : + +## 🐳 Version Docker + +**Avantages :** +- Installation simple avec Docker Compose +- Environment isolĂ© et reproductible +- Gestion des versions via images Docker +- IntĂ©gration facile avec d'autres services + +**→ [Guide Docker complet](docker/README-DOCKER.md)** + +### Installation rapide Docker + +```bash +# Cloner le repo +git clone +cd Dell_iDRAC_fan_controller/docker + +# Configurer +cp docker-compose.yml docker-compose.local.yml +nano docker-compose.local.yml + +# Lancer +docker-compose -f docker-compose.local.yml up -d +``` + +--- + +## 📩 Version LXC (Proxmox) + +**Avantages :** +- Performance native (pas d'overhead Docker) +- IntĂ©gration parfaite avec Proxmox +- AccĂšs hardware direct +- Gestion avec systemd + +**→ [Guide LXC complet](lxc/README-LXC.md)** + +### Installation rapide LXC + +```bash +# Dans un container LXC Ubuntu +wget -O - https://github.com//archive/main.tar.gz | tar -xz +cd Dell_iDRAC_fan_controller-main/lxc +chmod +x install-lxc.sh +./install-lxc.sh +``` + +--- + +## Comparaison rapide + +| CritĂšre | Docker | LXC | +|---------|--------|-----| +| **FacilitĂ©** | ⭐⭐⭐ | ⭐⭐ | +| **Performance** | ⭐⭐ | ⭐⭐⭐ | +| **Isolation** | ⭐⭐⭐ | ⭐⭐ | +| **Maintenance** | ⭐⭐⭐ | ⭐⭐ | +| **Proxmox** | ⭐⭐ | ⭐⭐⭐ | +| **Ressources** | ⭐⭐ | ⭐⭐⭐ | + +## Support + +- **Issues** : [GitHub Issues](https://github.com//issues) +- **Discussions** : [GitHub Discussions](https://github.com//discussions) +- **Original** : [Projet source](https://github.com/tigerblue77/Dell_iDRAC_fan_controller_Docker) \ No newline at end of file diff --git a/README.md b/README.md index 576cfcf..e8d2b2c 100644 --- a/README.md +++ b/README.md @@ -10,46 +10,81 @@ Fork de : https://github.com/tigerblue77/Dell_iDRAC_fan_controller_Docker.git - Configuration de 4 seuils de tempĂ©rature avec vitesses correspondantes - Gestion progressive de la vitesse des ventilateurs selon la tempĂ©rature du CPU +## 🚀 Deux versions disponibles + +| **Version Docker** | **Version LXC Proxmox** | +|-------------------|------------------------| +| 🐳 Container Docker classique | 📩 Container LXC natif | +| Images versionnĂ©es | Installation directe | +| `docker-compose` | `systemctl` | +| Isolation forte | Performance native | +| → [Documentation Docker](docker/) | → [Documentation LXC](lxc/) | +
- Table of Contents + Table des matiĂšres
    -
  1. Container console log example
  2. -
  3. Supported architectures
  4. -
  5. Usage
  6. -
  7. Parameters
  8. -
  9. Troubleshooting
  10. -
  11. Contributing
  12. +
  13. 🚀 Deux versions disponibles
  14. +
  15. Prérequis
  16. +
  17. Installation rapide
  18. +
  19. ParamĂštres
  20. +
  21. Dépannage
  22. +
  23. Exemple de logs
+## Installation rapide + +### 🐳 Version Docker + +```bash +# TĂ©lĂ©charger la configuration +wget https://raw.githubusercontent.com/votre-repo/main/docker/docker-compose.yml + +# Modifier la configuration selon vos besoins +nano docker-compose.yml + +# Lancer le container +docker-compose up -d +``` + +### 📩 Version LXC (Proxmox) + +```bash +# Dans le container LXC Ubuntu +wget -O - https://github.com/votre-repo/archive/main.tar.gz | tar -xz +cd Dell_iDRAC_fan_controller-main/lxc +chmod +x install-lxc.sh +./install-lxc.sh +``` + +

(back to top)

+ +## Prérequis + +### Serveur Dell +- Dell PowerEdge avec iDRAC +- Support des commandes IPMI +- iDRAC 9 firmware < 3.30.30.30 (pour IPMI) + +### Environnement +- **Docker** : Docker + Docker Compose +- **LXC** : Proxmox avec container privilégié + +

(back to top)

+ ## Container console log example ![image](https://user-images.githubusercontent.com/37409593/216442212-d2ad7ff7-0d6f-443f-b8ac-c67b5f613b83.png)

(back to top)

- -## Prerequisites -### iDRAC version + +## Configuration dĂ©taillĂ©e -This Docker container only works on Dell PowerEdge servers that support IPMI commands, i.e. < iDRAC 9 firmware 3.30.30.30. +### 🐳 Version Docker -

(back to top)

- - -## Supported architectures - -This Docker container is currently built and available for the following CPU architectures : -- AMD64 -- ARM64 - -

(back to top)

- - -## Usage - -1. with local iDRAC: +**1. Utilisation avec iDRAC local :** ```bash docker run -d \ diff --git a/docker/Dell_iDRAC_fan_controller.sh b/docker/Dell_iDRAC_fan_controller.sh new file mode 100755 index 0000000..3d34347 --- /dev/null +++ b/docker/Dell_iDRAC_fan_controller.sh @@ -0,0 +1,167 @@ +#!/bin/bash + +# Enable strict bash mode to stop the script if an uninitialized variable is used, if a command fails, or if a command with a pipe fails +# Not working in some setups : https://github.com/tigerblue77/Dell_iDRAC_fan_controller/issues/48 +# set -euo pipefail + +source functions.sh + +# Trap the signals for container exit and run gracefull_exit function +trap 'gracefull_exit' SIGQUIT SIGKILL SIGTERM + +# Prepare, format and define initial variables + +# readonly DELL_FRESH_AIR_COMPLIANCE=45 + +# Define the temperature thresholds and corresponding fan speeds +TEMP_THRESHOLDS=($CPU_TEMPERATURE_1 $CPU_TEMPERATURE_2 $CPU_TEMPERATURE_3 $CPU_TEMPERATURE_4) +FAN_SPEEDS=($FAN_SPEED_1 $FAN_SPEED_2 $FAN_SPEED_3 $FAN_SPEED_4 100) # Correspond aux seuils + vitesse max + +# Check if the iDRAC host is set to 'local' or not then set the IDRAC_LOGIN_STRING accordingly +if [[ $IDRAC_HOST == "local" ]] +then + # Check that the Docker host IPMI device (the iDRAC) has been exposed to the Docker container + if [ ! -e "/dev/ipmi0" ] && [ ! -e "/dev/ipmi/0" ] && [ ! -e "/dev/ipmidev/0" ]; then + echo "/!\ Could not open device at /dev/ipmi0 or /dev/ipmi/0 or /dev/ipmidev/0, check that you added the device to your Docker container or stop using local mode. Exiting." >&2 + exit 1 + fi + IDRAC_LOGIN_STRING='open' +else + echo "iDRAC/IPMI username: $IDRAC_USERNAME" + echo "iDRAC/IPMI password: $IDRAC_PASSWORD" + IDRAC_LOGIN_STRING="lanplus -H $IDRAC_HOST -U $IDRAC_USERNAME -P $IDRAC_PASSWORD" +fi + +get_Dell_server_model + +if [[ ! $SERVER_MANUFACTURER == "DELL" ]] +then + echo "/!\ Your server isn't a Dell product. Exiting." >&2 + exit 1 +fi + +# Log main informations +echo "Server model: $SERVER_MANUFACTURER $SERVER_MODEL" +echo "iDRAC/IPMI host: $IDRAC_HOST" + +# Log the check interval +echo "Check interval: ${CHECK_INTERVAL}s" +echo "" + +# Define the interval for printing +readonly TABLE_HEADER_PRINT_INTERVAL=10 +i=$TABLE_HEADER_PRINT_INTERVAL +# Set the flag used to check if the active fan control profile has changed +IS_DELL_FAN_CONTROL_PROFILE_APPLIED=true + +# Check present sensors +IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT=true +IS_CPU2_TEMPERATURE_SENSOR_PRESENT=true +retrieve_temperatures $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT $IS_CPU2_TEMPERATURE_SENSOR_PRESENT +if [ -z "$EXHAUST_TEMPERATURE" ] +then + echo "No exhaust temperature sensor detected." + IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT=false +fi +if [ -z "$CPU2_TEMPERATURE" ] +then + echo "No CPU2 temperature sensor detected." + IS_CPU2_TEMPERATURE_SENSOR_PRESENT=false +fi +# Output new line to beautify output if one of the previous conditions have echoed +if ! $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT || ! $IS_CPU2_TEMPERATURE_SENSOR_PRESENT +then + echo "" +fi + + +# Start monitoring +while true; do + # Sleep for the specified interval before taking another reading + sleep $CHECK_INTERVAL & + SLEEP_PROCESS_PID=$! + + retrieve_temperatures $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT $IS_CPU2_TEMPERATURE_SENSOR_PRESENT + + # Define functions to check if CPU 1 and CPU 2 temperatures are above the threshold + function CPU1_OVERHEAT () { [ $CPU1_TEMPERATURE -gt $CPU_TEMPERATURE_THRESHOLD ]; } + if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT + then + function CPU2_OVERHEAT () { [ $CPU2_TEMPERATURE -gt $CPU_TEMPERATURE_THRESHOLD ]; } + fi + + # Initialize a variable to store the comments displayed when the fan control profile changed + COMMENT=" -" + # Check if CPU 1 is overheating then apply Dell default dynamic fan control profile if true + if CPU1_OVERHEAT + then + apply_Dell_fan_control_profile + + if ! $IS_DELL_FAN_CONTROL_PROFILE_APPLIED + then + IS_DELL_FAN_CONTROL_PROFILE_APPLIED=true + + # If CPU 2 temperature sensor is present, check if it is overheating too. + # Do not apply Dell default dynamic fan control profile as it has already been applied before + if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT && CPU2_OVERHEAT + then + COMMENT="CPU 1 and CPU 2 temperatures are too high, Dell default dynamic fan control profile applied for safety" + else + COMMENT="CPU 1 temperature is too high, Dell default dynamic fan control profile applied for safety" + fi + fi + # If CPU 2 temperature sensor is present, check if it is overheating then apply Dell default dynamic fan control profile if true + elif $IS_CPU2_TEMPERATURE_SENSOR_PRESENT && CPU2_OVERHEAT + then + apply_Dell_fan_control_profile + + if ! $IS_DELL_FAN_CONTROL_PROFILE_APPLIED + then + IS_DELL_FAN_CONTROL_PROFILE_APPLIED=true + COMMENT="CPU 2 temperature is too high, Dell default dynamic fan control profile applied for safety" + fi + else + # Adjust fan speed based on temperature thresholds + for i in ${!TEMP_THRESHOLDS[@]}; do + if [ $CPU1_TEMPERATURE -le ${TEMP_THRESHOLDS[$i]} ]; then + set_fan_speed ${FAN_SPEEDS[$i]} + break + fi + done + + # Si la tempĂ©rature est supĂ©rieure Ă  tous les seuils, dĂ©finir la vitesse maximale + if [ $CPU1_TEMPERATURE -gt ${TEMP_THRESHOLDS[-1]} ]; then + set_fan_speed ${FAN_SPEEDS[-1]} + fi + + + # Check if user fan control profile is applied then apply it if not + if $IS_DELL_FAN_CONTROL_PROFILE_APPLIED + then + IS_DELL_FAN_CONTROL_PROFILE_APPLIED=false + COMMENT="CPU temperature decreased and is now OK (<= $CPU_TEMPERATURE_THRESHOLD°C), user's fan control profile applied." + fi + fi + + # Enable or disable, depending on the user's choice, third-party PCIe card Dell default cooling response + # No comment will be displayed on the change of this parameter since it is not related to the temperature of any device (CPU, GPU, etc...) but only to the settings made by the user when launching this Docker container + if $DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE + then + disable_third_party_PCIe_card_Dell_default_cooling_response + THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE_STATUS="Disabled" + else + enable_third_party_PCIe_card_Dell_default_cooling_response + THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE_STATUS="Enabled" + fi + + # Print temperatures, active fan control profile and comment if any change happened during last time interval + if [ $i -eq $TABLE_HEADER_PRINT_INTERVAL ] + then + echo " ------- Temperatures -------" + echo " Date & time Inlet CPU 1 CPU 2 Exhaust Active fan speed profile Third-party PCIe card Dell default cooling response Comment" + i=0 + fi + printf "%19s %3d°C %3d°C %3s°C %5s°C %40s %51s %s\n" "$(date +"%d-%m-%Y %T")" $INLET_TEMPERATURE $CPU1_TEMPERATURE "$CPU2_TEMPERATURE" "$EXHAUST_TEMPERATURE" "$CURRENT_FAN_CONTROL_PROFILE" "$THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE_STATUS" "$COMMENT" + ((i++)) + wait $SLEEP_PROCESS_PID +done \ No newline at end of file diff --git a/Dockerfile b/docker/Dockerfile similarity index 100% rename from Dockerfile rename to docker/Dockerfile diff --git a/docker/README-DOCKER.md b/docker/README-DOCKER.md new file mode 100644 index 0000000..1f6f72d --- /dev/null +++ b/docker/README-DOCKER.md @@ -0,0 +1,173 @@ +# Version Docker + +Documentation spĂ©cifique pour l'installation et l'utilisation avec Docker. + +## Fichiers inclus + +- `Dockerfile` : Image Docker +- `Dell_iDRAC_fan_controller.sh` : Script principal +- `functions.sh` : Fonctions utilitaires +- `healthcheck.sh` : VĂ©rification de santĂ© + +## Installation Docker + +### 1. Construction de l'image + +```bash +cd docker/ +docker build -t idrac-fan-controller . +``` + +### 2. Utilisation avec Docker Compose (recommandĂ©) + +**CrĂ©er `docker-compose.yml` :** + +```yml +version: '3.8' + +services: + idrac_fan_controller: + build: . + container_name: idrac_fan_controller + restart: unless-stopped + environment: + # Connexion iDRAC + - IDRAC_HOST=local # ou IP pour distant + - IDRAC_USERNAME=root # si distant + - IDRAC_PASSWORD=calvin # si distant + + # Seuils de tempĂ©rature (°C) + - CPU_TEMPERATURE_1=30 + - CPU_TEMPERATURE_2=40 + - CPU_TEMPERATURE_3=50 + - CPU_TEMPERATURE_4=60 + + # Vitesses correspondantes (%) + - FAN_SPEED_1=10 + - FAN_SPEED_2=30 + - FAN_SPEED_3=60 + - FAN_SPEED_4=80 + + # Seuil de sĂ©curitĂ© + - CPU_TEMPERATURE_THRESHOLD=70 + + # Autres paramĂštres + - CHECK_INTERVAL=60 + - DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=false + + devices: + - /dev/ipmi0:/dev/ipmi0:rw # Pour iDRAC local + + # Optionnel : logs persistants + volumes: + - ./logs:/var/log/idrac +``` + +### 3. Lancement + +```bash +# DĂ©marrer +docker-compose up -d + +# Voir les logs +docker-compose logs -f + +# ArrĂȘter +docker-compose down +``` + +## Configuration par variables d'environnement + +Toutes les variables peuvent ĂȘtre configurĂ©es via l'environnement : + +```bash +# Exemple pour iDRAC distant +docker run -d \ + --name idrac_fan_controller \ + --restart unless-stopped \ + -e IDRAC_HOST=192.168.1.100 \ + -e IDRAC_USERNAME=root \ + -e IDRAC_PASSWORD=calvin \ + -e CPU_TEMPERATURE_1=30 \ + -e CPU_TEMPERATURE_2=40 \ + -e CPU_TEMPERATURE_3=50 \ + -e CPU_TEMPERATURE_4=60 \ + -e FAN_SPEED_1=10 \ + -e FAN_SPEED_2=30 \ + -e FAN_SPEED_3=60 \ + -e FAN_SPEED_4=80 \ + -e CPU_TEMPERATURE_THRESHOLD=70 \ + -e CHECK_INTERVAL=60 \ + idrac-fan-controller +``` + +## Gestion + +### Commandes utiles + +```bash +# État du container +docker-compose ps + +# Logs en temps rĂ©el +docker-compose logs -f idrac_fan_controller + +# RedĂ©marrer +docker-compose restart idrac_fan_controller + +# Shell dans le container +docker-compose exec idrac_fan_controller bash + +# Test de santĂ© +docker-compose exec idrac_fan_controller ./healthcheck.sh +``` + +### Mise Ă  jour + +```bash +# Reconstruire l'image +docker-compose build + +# RedĂ©marrer avec la nouvelle image +docker-compose up -d +``` + +## DĂ©pannage Docker + +### VĂ©rification de l'accĂšs IPMI + +```bash +# Dans le container +docker-compose exec idrac_fan_controller ls -la /dev/ipmi* + +# Test ipmitool +docker-compose exec idrac_fan_controller ipmitool fru +``` + +### Erreurs communes + +**"Could not open device at /dev/ipmi0"** +```bash +# VĂ©rifier sur l'hĂŽte +ls -la /dev/ipmi* + +# VĂ©rifier les permissions +docker-compose exec idrac_fan_controller ls -la /dev/ipmi* +``` + +**Container qui s'arrĂȘte** +```bash +# Voir les logs +docker-compose logs idrac_fan_controller + +# Mode debug +docker-compose run --rm idrac_fan_controller bash +``` + +## Avantages Docker + +- **Isolation** : Environment isolĂ© +- **ReproductibilitĂ©** : MĂȘme environnement partout +- **Versioning** : Images versionnĂ©es +- **Rollback** : Retour en arriĂšre facile +- **Orchestration** : IntĂ©gration avec autres services \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..03e3d32 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,53 @@ +version: '3.8' + +services: + idrac_fan_controller: + build: . + container_name: idrac_fan_controller + restart: unless-stopped + + environment: + # Connexion iDRAC + - IDRAC_HOST=local # "local" ou IP pour distant (ex: 192.168.1.100) + - IDRAC_USERNAME=root # Requis seulement si IDRAC_HOST != "local" + - IDRAC_PASSWORD=calvin # Requis seulement si IDRAC_HOST != "local" + + # === Seuils de tempĂ©rature (°C) === + # TempĂ©rature <= CPU_TEMPERATURE_1 → vitesse FAN_SPEED_1 + - CPU_TEMPERATURE_1=30 + # TempĂ©rature <= CPU_TEMPERATURE_2 → vitesse FAN_SPEED_2 + - CPU_TEMPERATURE_2=40 + # TempĂ©rature <= CPU_TEMPERATURE_3 → vitesse FAN_SPEED_3 + - CPU_TEMPERATURE_3=50 + # TempĂ©rature <= CPU_TEMPERATURE_4 → vitesse FAN_SPEED_4 + - CPU_TEMPERATURE_4=60 + + # === Vitesses des ventilateurs (%) === + - FAN_SPEED_1=10 # Vitesse minimale + - FAN_SPEED_2=30 + - FAN_SPEED_3=60 + - FAN_SPEED_4=80 # Si > CPU_TEMPERATURE_4 → 100% + + # === Seuil de sĂ©curitĂ© === + # Si tempĂ©rature > CPU_TEMPERATURE_THRESHOLD → mode Dell par dĂ©faut + - CPU_TEMPERATURE_THRESHOLD=70 + + # === Autres paramĂštres === + - CHECK_INTERVAL=60 # Secondes entre chaque vĂ©rification + - DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=false + + # AccĂšs au pĂ©riphĂ©rique IPMI (requis pour IDRAC_HOST=local) + devices: + - /dev/ipmi0:/dev/ipmi0:rw + + # Logs persistants (optionnel) + volumes: + - ./logs:/var/log/idrac + + # Healthcheck intĂ©grĂ© + healthcheck: + test: ["CMD", "/app/healthcheck.sh"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s \ No newline at end of file diff --git a/docker/functions.sh b/docker/functions.sh new file mode 100755 index 0000000..e5c6b67 --- /dev/null +++ b/docker/functions.sh @@ -0,0 +1,105 @@ +# This function applies Dell's default dynamic fan control profile +function apply_Dell_fan_control_profile () { + # Use ipmitool to send the raw command to set fan control to Dell default + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x01 > /dev/null + CURRENT_FAN_CONTROL_PROFILE="Dell default dynamic fan control profile" +} + +# This function applies a user-specified static fan control profile +function apply_user_fan_control_profile () { + # Use ipmitool to send the raw command to set fan control to user-specified value + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x00 > /dev/null + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x02 0xff $HEXADECIMAL_FAN_SPEED > /dev/null + CURRENT_FAN_CONTROL_PROFILE="User static fan control profile ($DECIMAL_FAN_SPEED%)" +} + +# This function sets the fan speed to a specified value +# Usage: set_fan_speed +function set_fan_speed () { + local SPEED=$1 + local HEX_SPEED=$(convert_decimal_value_to_hexadecimal $SPEED) + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x00 > /dev/null + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x02 0xff $HEX_SPEED > /dev/null + CURRENT_FAN_CONTROL_PROFILE="User static fan control profile ($SPEED%)" +} + +# Convert first parameter given ($DECIMAL_NUMBER) to hexadecimal +# Usage : convert_decimal_value_to_hexadecimal $DECIMAL_NUMBER +# Returns : hexadecimal value of DECIMAL_NUMBER +function convert_decimal_value_to_hexadecimal () { + local DECIMAL_NUMBER=$1 + local HEXADECIMAL_NUMBER=$(printf '0x%02x' $DECIMAL_NUMBER) + echo $HEXADECIMAL_NUMBER +} + +# Retrieve temperature sensors data using ipmitool +# Usage : retrieve_temperatures $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT $IS_CPU2_TEMPERATURE_SENSOR_PRESENT +function retrieve_temperatures () { + if (( $# != 2 )) + then + printf "Illegal number of parameters.\nUsage: retrieve_temperatures \$IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT \$IS_CPU2_TEMPERATURE_SENSOR_PRESENT" >&2 + return 1 + fi + local IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT=$1 + local IS_CPU2_TEMPERATURE_SENSOR_PRESENT=$2 + + local DATA=$(ipmitool -I $IDRAC_LOGIN_STRING sdr type temperature | grep degrees) + + # Parse CPU data + local CPU_DATA=$(echo "$DATA" | grep "3\." | grep -Po '\d{2}') + CPU1_TEMPERATURE=$(echo $CPU_DATA | awk '{print $1;}') + if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT + then + CPU2_TEMPERATURE=$(echo $CPU_DATA | awk '{print $2;}') + else + CPU2_TEMPERATURE="-" + fi + + # Parse inlet temperature data + INLET_TEMPERATURE=$(echo "$DATA" | grep Inlet | grep -Po '\d{2}' | tail -1) + + # If exhaust temperature sensor is present, parse its temperature data + if $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT + then + EXHAUST_TEMPERATURE=$(echo "$DATA" | grep Exhaust | grep -Po '\d{2}' | tail -1) + else + EXHAUST_TEMPERATURE="-" + fi +} + +function enable_third_party_PCIe_card_Dell_default_cooling_response () { + # We could check the current cooling response before applying but it's not very useful so let's skip the test and apply directly + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0xce 0x00 0x16 0x05 0x00 0x00 0x00 0x05 0x00 0x00 0x00 0x00 > /dev/null +} + +function disable_third_party_PCIe_card_Dell_default_cooling_response () { + # We could check the current cooling response before applying but it's not very useful so let's skip the test and apply directly + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0xce 0x00 0x16 0x05 0x00 0x00 0x00 0x05 0x00 0x01 0x00 0x00 > /dev/null +} + + +# Prepare traps in case of container exit +function gracefull_exit () { + apply_Dell_fan_control_profile + enable_third_party_PCIe_card_Dell_default_cooling_response + echo "/!\ WARNING /!\ Container stopped, Dell default dynamic fan control profile applied for safety." + exit 0 +} + +# Helps debugging when people are posting their output +function get_Dell_server_model () { + IPMI_FRU_content=$(ipmitool -I $IDRAC_LOGIN_STRING fru 2>/dev/null) # FRU stands for "Field Replaceable Unit" + + SERVER_MANUFACTURER=$(echo "$IPMI_FRU_content" | grep "Product Manufacturer" | awk -F ': ' '{print $2}') + SERVER_MODEL=$(echo "$IPMI_FRU_content" | grep "Product Name" | awk -F ': ' '{print $2}') + + # Check if SERVER_MANUFACTURER is empty, if yes, assign value based on "Board Mfg" + if [ -z "$SERVER_MANUFACTURER" ]; then + SERVER_MANUFACTURER=$(echo "$IPMI_FRU_content" | tr -s ' ' | grep "Board Mfg :" | awk -F ': ' '{print $2}') + fi + + # Check if SERVER_MODEL is empty, if yes, assign value based on "Board Product" + if [ -z "$SERVER_MODEL" ]; then + SERVER_MODEL=$(echo "$IPMI_FRU_content" | tr -s ' ' | grep "Board Product :" | awk -F ': ' '{print $2}') + fi +} diff --git a/docker/healthcheck.sh b/docker/healthcheck.sh new file mode 100755 index 0000000..0bdbe12 --- /dev/null +++ b/docker/healthcheck.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Enable strict bash mode to stop the script if an uninitialized variable is used, if a command fails, or if a command with a pipe fails +# Not working in some setups : https://github.com/tigerblue77/Dell_iDRAC_fan_controller/issues/48 +# set -euo pipefail + +source functions.sh + +# Check if the iDRAC host is set to 'local' or not then set the IDRAC_LOGIN_STRING accordingly +if [[ $IDRAC_HOST == "local" ]] +then + # Check that the Docker host IPMI device (the iDRAC) has been exposed to the Docker container + if [ ! -e "/dev/ipmi0" ] && [ ! -e "/dev/ipmi/0" ] && [ ! -e "/dev/ipmidev/0" ]; then + echo "/!\ Could not open device at /dev/ipmi0 or /dev/ipmi/0 or /dev/ipmidev/0, check that you added the device to your Docker container or stop using local mode. Exiting." >&2 + exit 1 + fi + IDRAC_LOGIN_STRING='open' +else + echo "iDRAC/IPMI username: $IDRAC_USERNAME" + echo "iDRAC/IPMI password: $IDRAC_PASSWORD" + IDRAC_LOGIN_STRING="lanplus -H $IDRAC_HOST -U $IDRAC_USERNAME -P $IDRAC_PASSWORD" +fi + +ipmitool -I $IDRAC_LOGIN_STRING sdr type temperature diff --git a/lxc/Dell_iDRAC_fan_controller.sh b/lxc/Dell_iDRAC_fan_controller.sh new file mode 100755 index 0000000..3d34347 --- /dev/null +++ b/lxc/Dell_iDRAC_fan_controller.sh @@ -0,0 +1,167 @@ +#!/bin/bash + +# Enable strict bash mode to stop the script if an uninitialized variable is used, if a command fails, or if a command with a pipe fails +# Not working in some setups : https://github.com/tigerblue77/Dell_iDRAC_fan_controller/issues/48 +# set -euo pipefail + +source functions.sh + +# Trap the signals for container exit and run gracefull_exit function +trap 'gracefull_exit' SIGQUIT SIGKILL SIGTERM + +# Prepare, format and define initial variables + +# readonly DELL_FRESH_AIR_COMPLIANCE=45 + +# Define the temperature thresholds and corresponding fan speeds +TEMP_THRESHOLDS=($CPU_TEMPERATURE_1 $CPU_TEMPERATURE_2 $CPU_TEMPERATURE_3 $CPU_TEMPERATURE_4) +FAN_SPEEDS=($FAN_SPEED_1 $FAN_SPEED_2 $FAN_SPEED_3 $FAN_SPEED_4 100) # Correspond aux seuils + vitesse max + +# Check if the iDRAC host is set to 'local' or not then set the IDRAC_LOGIN_STRING accordingly +if [[ $IDRAC_HOST == "local" ]] +then + # Check that the Docker host IPMI device (the iDRAC) has been exposed to the Docker container + if [ ! -e "/dev/ipmi0" ] && [ ! -e "/dev/ipmi/0" ] && [ ! -e "/dev/ipmidev/0" ]; then + echo "/!\ Could not open device at /dev/ipmi0 or /dev/ipmi/0 or /dev/ipmidev/0, check that you added the device to your Docker container or stop using local mode. Exiting." >&2 + exit 1 + fi + IDRAC_LOGIN_STRING='open' +else + echo "iDRAC/IPMI username: $IDRAC_USERNAME" + echo "iDRAC/IPMI password: $IDRAC_PASSWORD" + IDRAC_LOGIN_STRING="lanplus -H $IDRAC_HOST -U $IDRAC_USERNAME -P $IDRAC_PASSWORD" +fi + +get_Dell_server_model + +if [[ ! $SERVER_MANUFACTURER == "DELL" ]] +then + echo "/!\ Your server isn't a Dell product. Exiting." >&2 + exit 1 +fi + +# Log main informations +echo "Server model: $SERVER_MANUFACTURER $SERVER_MODEL" +echo "iDRAC/IPMI host: $IDRAC_HOST" + +# Log the check interval +echo "Check interval: ${CHECK_INTERVAL}s" +echo "" + +# Define the interval for printing +readonly TABLE_HEADER_PRINT_INTERVAL=10 +i=$TABLE_HEADER_PRINT_INTERVAL +# Set the flag used to check if the active fan control profile has changed +IS_DELL_FAN_CONTROL_PROFILE_APPLIED=true + +# Check present sensors +IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT=true +IS_CPU2_TEMPERATURE_SENSOR_PRESENT=true +retrieve_temperatures $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT $IS_CPU2_TEMPERATURE_SENSOR_PRESENT +if [ -z "$EXHAUST_TEMPERATURE" ] +then + echo "No exhaust temperature sensor detected." + IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT=false +fi +if [ -z "$CPU2_TEMPERATURE" ] +then + echo "No CPU2 temperature sensor detected." + IS_CPU2_TEMPERATURE_SENSOR_PRESENT=false +fi +# Output new line to beautify output if one of the previous conditions have echoed +if ! $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT || ! $IS_CPU2_TEMPERATURE_SENSOR_PRESENT +then + echo "" +fi + + +# Start monitoring +while true; do + # Sleep for the specified interval before taking another reading + sleep $CHECK_INTERVAL & + SLEEP_PROCESS_PID=$! + + retrieve_temperatures $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT $IS_CPU2_TEMPERATURE_SENSOR_PRESENT + + # Define functions to check if CPU 1 and CPU 2 temperatures are above the threshold + function CPU1_OVERHEAT () { [ $CPU1_TEMPERATURE -gt $CPU_TEMPERATURE_THRESHOLD ]; } + if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT + then + function CPU2_OVERHEAT () { [ $CPU2_TEMPERATURE -gt $CPU_TEMPERATURE_THRESHOLD ]; } + fi + + # Initialize a variable to store the comments displayed when the fan control profile changed + COMMENT=" -" + # Check if CPU 1 is overheating then apply Dell default dynamic fan control profile if true + if CPU1_OVERHEAT + then + apply_Dell_fan_control_profile + + if ! $IS_DELL_FAN_CONTROL_PROFILE_APPLIED + then + IS_DELL_FAN_CONTROL_PROFILE_APPLIED=true + + # If CPU 2 temperature sensor is present, check if it is overheating too. + # Do not apply Dell default dynamic fan control profile as it has already been applied before + if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT && CPU2_OVERHEAT + then + COMMENT="CPU 1 and CPU 2 temperatures are too high, Dell default dynamic fan control profile applied for safety" + else + COMMENT="CPU 1 temperature is too high, Dell default dynamic fan control profile applied for safety" + fi + fi + # If CPU 2 temperature sensor is present, check if it is overheating then apply Dell default dynamic fan control profile if true + elif $IS_CPU2_TEMPERATURE_SENSOR_PRESENT && CPU2_OVERHEAT + then + apply_Dell_fan_control_profile + + if ! $IS_DELL_FAN_CONTROL_PROFILE_APPLIED + then + IS_DELL_FAN_CONTROL_PROFILE_APPLIED=true + COMMENT="CPU 2 temperature is too high, Dell default dynamic fan control profile applied for safety" + fi + else + # Adjust fan speed based on temperature thresholds + for i in ${!TEMP_THRESHOLDS[@]}; do + if [ $CPU1_TEMPERATURE -le ${TEMP_THRESHOLDS[$i]} ]; then + set_fan_speed ${FAN_SPEEDS[$i]} + break + fi + done + + # Si la tempĂ©rature est supĂ©rieure Ă  tous les seuils, dĂ©finir la vitesse maximale + if [ $CPU1_TEMPERATURE -gt ${TEMP_THRESHOLDS[-1]} ]; then + set_fan_speed ${FAN_SPEEDS[-1]} + fi + + + # Check if user fan control profile is applied then apply it if not + if $IS_DELL_FAN_CONTROL_PROFILE_APPLIED + then + IS_DELL_FAN_CONTROL_PROFILE_APPLIED=false + COMMENT="CPU temperature decreased and is now OK (<= $CPU_TEMPERATURE_THRESHOLD°C), user's fan control profile applied." + fi + fi + + # Enable or disable, depending on the user's choice, third-party PCIe card Dell default cooling response + # No comment will be displayed on the change of this parameter since it is not related to the temperature of any device (CPU, GPU, etc...) but only to the settings made by the user when launching this Docker container + if $DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE + then + disable_third_party_PCIe_card_Dell_default_cooling_response + THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE_STATUS="Disabled" + else + enable_third_party_PCIe_card_Dell_default_cooling_response + THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE_STATUS="Enabled" + fi + + # Print temperatures, active fan control profile and comment if any change happened during last time interval + if [ $i -eq $TABLE_HEADER_PRINT_INTERVAL ] + then + echo " ------- Temperatures -------" + echo " Date & time Inlet CPU 1 CPU 2 Exhaust Active fan speed profile Third-party PCIe card Dell default cooling response Comment" + i=0 + fi + printf "%19s %3d°C %3d°C %3s°C %5s°C %40s %51s %s\n" "$(date +"%d-%m-%Y %T")" $INLET_TEMPERATURE $CPU1_TEMPERATURE "$CPU2_TEMPERATURE" "$EXHAUST_TEMPERATURE" "$CURRENT_FAN_CONTROL_PROFILE" "$THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE_STATUS" "$COMMENT" + ((i++)) + wait $SLEEP_PROCESS_PID +done \ No newline at end of file diff --git a/lxc/README-LXC.md b/lxc/README-LXC.md new file mode 100644 index 0000000..1e0ae5b --- /dev/null +++ b/lxc/README-LXC.md @@ -0,0 +1,193 @@ +# Installation LXC pour Proxmox + +Ce guide vous explique comment installer le contrĂŽleur de ventilateurs Dell iDRAC dans un container LXC Proxmox. + +## PrĂ©requis + +### 1. Container LXC Proxmox + +- Template Ubuntu 22.04 LTS +- Container **privilĂ©giĂ©** (requis pour l'accĂšs IPMI) +- AccĂšs rĂ©seau configurĂ© + +### 2. Configuration Proxmox + +Dans l'interface Proxmox ou en ligne de commande : + +```bash +# Rendre le container privilĂ©giĂ© +pct set -privilege 1 + +# Activer nesting si nĂ©cessaire +pct set -features nesting=1 + +# Configuration des ressources (exemple) +pct set -memory 512 -cores 1 +``` + +### 3. AccĂšs IPMI + +**Option A - iDRAC local (dans le container sur l'hĂŽte physique) :** +```bash +# Ajouter l'accĂšs au pĂ©riphĂ©rique IPMI dans la configuration LXC +echo "lxc.cgroup2.devices.allow: c 10:* rwm" >> /etc/pve/lxc/.conf +echo "lxc.mount.entry: /dev/ipmi0 dev/ipmi0 none bind,optional,create=file" >> /etc/pve/lxc/.conf +``` + +**Option B - iDRAC distant :** +Aucune configuration matĂ©rielle supplĂ©mentaire requise. + +## Installation + +### 1. TĂ©lĂ©chargement + +```bash +# Dans le container LXC +cd /tmp +wget -O - https://github.com/votre-repo/archive/main.tar.gz | tar -xz +cd Dell_iDRAC_fan_controller-main/lxc +``` + +### 2. Installation automatique + +```bash +chmod +x install-lxc.sh +./install-lxc.sh +``` + +Le script va : +- Installer ipmitool +- CrĂ©er la structure de rĂ©pertoires +- Copier les fichiers +- Configurer le service systemd +- CrĂ©er le fichier de configuration + +## Configuration + +### 1. Édition de la configuration + +```bash +nano /opt/idrac-fan-controller/config/environment +``` + +### 2. ParamĂštres principaux + +```bash +# Connexion iDRAC +IDRAC_HOST=local # ou IP pour iDRAC distant +IDRAC_USERNAME=root # si iDRAC distant +IDRAC_PASSWORD=calvin # si iDRAC distant + +# Seuils de tempĂ©rature (°C) +CPU_TEMPERATURE_1=30 +CPU_TEMPERATURE_2=40 +CPU_TEMPERATURE_3=50 +CPU_TEMPERATURE_4=60 + +# Vitesses correspondantes (%) +FAN_SPEED_1=10 +FAN_SPEED_2=30 +FAN_SPEED_3=60 +FAN_SPEED_4=80 + +# Seuil de sĂ©curitĂ© +CPU_TEMPERATURE_THRESHOLD=70 +``` + +## Utilisation + +### Gestion du service + +```bash +# DĂ©marrer +systemctl start idrac-fan-controller + +# ArrĂȘter +systemctl stop idrac-fan-controller + +# RedĂ©marrer +systemctl restart idrac-fan-controller + +# Statut +systemctl status idrac-fan-controller + +# Activer au dĂ©marrage (dĂ©jĂ  fait par l'installation) +systemctl enable idrac-fan-controller +``` + +### Surveillance + +```bash +# Logs en temps rĂ©el +journalctl -u idrac-fan-controller -f + +# Logs rĂ©cents +journalctl -u idrac-fan-controller -n 50 + +# Test de santĂ© +/opt/idrac-fan-controller/healthcheck.sh +``` + +## DĂ©pannage + +### VĂ©rification IPMI + +```bash +# Test de base +ipmitool fru + +# Si erreur "Could not open device" +ls -la /dev/ipmi* +# Doit montrer /dev/ipmi0 ou similaire + +# VĂ©rifier les permissions +id +# Doit ĂȘtre root dans le container +``` + +### Erreurs communes + +**"Could not open device at /dev/ipmi0"** +- VĂ©rifier que le container est privilĂ©giĂ© +- S'assurer que l'accĂšs IPMI est configurĂ© dans Proxmox +- RedĂ©marrer le container aprĂšs les changements + +**Service qui ne dĂ©marre pas** +```bash +# VĂ©rifier la syntaxe du fichier de configuration +systemctl status idrac-fan-controller + +# Tester manuellement +cd /opt/idrac-fan-controller +sudo -u root bash Dell_iDRAC_fan_controller.sh +``` + +## DĂ©sinstallation + +```bash +cd /tmp/Dell_iDRAC_fan_controller-main/lxc +chmod +x uninstall-lxc.sh +./uninstall-lxc.sh +``` + +## Comparaison Docker vs LXC + +| Aspect | Docker | LXC | +|--------|---------|-----| +| **Installation** | Pull image | Script d'installation | +| **Configuration** | Variables ENV | Fichier de config | +| **Gestion** | docker-compose | systemctl | +| **Logs** | docker logs | journalctl | +| **Ressources** | Container isolĂ© | Container systĂšme | +| **AccĂšs hardware** | Device mapping | AccĂšs direct | +| **Maintenance** | Image updates | Package updates | +| **Backup** | Image + volumes | Snapshot LXC | + +## Avantages LXC + +- **Performance** : Pas d'overhead Docker +- **IntĂ©gration** : Gestion native avec Proxmox +- **AccĂšs hardware** : Plus direct et simple +- **Ressources** : Utilisation optimale +- **Logs** : IntĂ©grĂ©s avec systemd +- **Maintenance** : Mise Ă  jour avec le systĂšme \ No newline at end of file diff --git a/lxc/functions.sh b/lxc/functions.sh new file mode 100755 index 0000000..e5c6b67 --- /dev/null +++ b/lxc/functions.sh @@ -0,0 +1,105 @@ +# This function applies Dell's default dynamic fan control profile +function apply_Dell_fan_control_profile () { + # Use ipmitool to send the raw command to set fan control to Dell default + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x01 > /dev/null + CURRENT_FAN_CONTROL_PROFILE="Dell default dynamic fan control profile" +} + +# This function applies a user-specified static fan control profile +function apply_user_fan_control_profile () { + # Use ipmitool to send the raw command to set fan control to user-specified value + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x00 > /dev/null + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x02 0xff $HEXADECIMAL_FAN_SPEED > /dev/null + CURRENT_FAN_CONTROL_PROFILE="User static fan control profile ($DECIMAL_FAN_SPEED%)" +} + +# This function sets the fan speed to a specified value +# Usage: set_fan_speed +function set_fan_speed () { + local SPEED=$1 + local HEX_SPEED=$(convert_decimal_value_to_hexadecimal $SPEED) + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x00 > /dev/null + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x02 0xff $HEX_SPEED > /dev/null + CURRENT_FAN_CONTROL_PROFILE="User static fan control profile ($SPEED%)" +} + +# Convert first parameter given ($DECIMAL_NUMBER) to hexadecimal +# Usage : convert_decimal_value_to_hexadecimal $DECIMAL_NUMBER +# Returns : hexadecimal value of DECIMAL_NUMBER +function convert_decimal_value_to_hexadecimal () { + local DECIMAL_NUMBER=$1 + local HEXADECIMAL_NUMBER=$(printf '0x%02x' $DECIMAL_NUMBER) + echo $HEXADECIMAL_NUMBER +} + +# Retrieve temperature sensors data using ipmitool +# Usage : retrieve_temperatures $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT $IS_CPU2_TEMPERATURE_SENSOR_PRESENT +function retrieve_temperatures () { + if (( $# != 2 )) + then + printf "Illegal number of parameters.\nUsage: retrieve_temperatures \$IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT \$IS_CPU2_TEMPERATURE_SENSOR_PRESENT" >&2 + return 1 + fi + local IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT=$1 + local IS_CPU2_TEMPERATURE_SENSOR_PRESENT=$2 + + local DATA=$(ipmitool -I $IDRAC_LOGIN_STRING sdr type temperature | grep degrees) + + # Parse CPU data + local CPU_DATA=$(echo "$DATA" | grep "3\." | grep -Po '\d{2}') + CPU1_TEMPERATURE=$(echo $CPU_DATA | awk '{print $1;}') + if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT + then + CPU2_TEMPERATURE=$(echo $CPU_DATA | awk '{print $2;}') + else + CPU2_TEMPERATURE="-" + fi + + # Parse inlet temperature data + INLET_TEMPERATURE=$(echo "$DATA" | grep Inlet | grep -Po '\d{2}' | tail -1) + + # If exhaust temperature sensor is present, parse its temperature data + if $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT + then + EXHAUST_TEMPERATURE=$(echo "$DATA" | grep Exhaust | grep -Po '\d{2}' | tail -1) + else + EXHAUST_TEMPERATURE="-" + fi +} + +function enable_third_party_PCIe_card_Dell_default_cooling_response () { + # We could check the current cooling response before applying but it's not very useful so let's skip the test and apply directly + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0xce 0x00 0x16 0x05 0x00 0x00 0x00 0x05 0x00 0x00 0x00 0x00 > /dev/null +} + +function disable_third_party_PCIe_card_Dell_default_cooling_response () { + # We could check the current cooling response before applying but it's not very useful so let's skip the test and apply directly + ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0xce 0x00 0x16 0x05 0x00 0x00 0x00 0x05 0x00 0x01 0x00 0x00 > /dev/null +} + + +# Prepare traps in case of container exit +function gracefull_exit () { + apply_Dell_fan_control_profile + enable_third_party_PCIe_card_Dell_default_cooling_response + echo "/!\ WARNING /!\ Container stopped, Dell default dynamic fan control profile applied for safety." + exit 0 +} + +# Helps debugging when people are posting their output +function get_Dell_server_model () { + IPMI_FRU_content=$(ipmitool -I $IDRAC_LOGIN_STRING fru 2>/dev/null) # FRU stands for "Field Replaceable Unit" + + SERVER_MANUFACTURER=$(echo "$IPMI_FRU_content" | grep "Product Manufacturer" | awk -F ': ' '{print $2}') + SERVER_MODEL=$(echo "$IPMI_FRU_content" | grep "Product Name" | awk -F ': ' '{print $2}') + + # Check if SERVER_MANUFACTURER is empty, if yes, assign value based on "Board Mfg" + if [ -z "$SERVER_MANUFACTURER" ]; then + SERVER_MANUFACTURER=$(echo "$IPMI_FRU_content" | tr -s ' ' | grep "Board Mfg :" | awk -F ': ' '{print $2}') + fi + + # Check if SERVER_MODEL is empty, if yes, assign value based on "Board Product" + if [ -z "$SERVER_MODEL" ]; then + SERVER_MODEL=$(echo "$IPMI_FRU_content" | tr -s ' ' | grep "Board Product :" | awk -F ': ' '{print $2}') + fi +} diff --git a/lxc/healthcheck.sh b/lxc/healthcheck.sh new file mode 100755 index 0000000..0bdbe12 --- /dev/null +++ b/lxc/healthcheck.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Enable strict bash mode to stop the script if an uninitialized variable is used, if a command fails, or if a command with a pipe fails +# Not working in some setups : https://github.com/tigerblue77/Dell_iDRAC_fan_controller/issues/48 +# set -euo pipefail + +source functions.sh + +# Check if the iDRAC host is set to 'local' or not then set the IDRAC_LOGIN_STRING accordingly +if [[ $IDRAC_HOST == "local" ]] +then + # Check that the Docker host IPMI device (the iDRAC) has been exposed to the Docker container + if [ ! -e "/dev/ipmi0" ] && [ ! -e "/dev/ipmi/0" ] && [ ! -e "/dev/ipmidev/0" ]; then + echo "/!\ Could not open device at /dev/ipmi0 or /dev/ipmi/0 or /dev/ipmidev/0, check that you added the device to your Docker container or stop using local mode. Exiting." >&2 + exit 1 + fi + IDRAC_LOGIN_STRING='open' +else + echo "iDRAC/IPMI username: $IDRAC_USERNAME" + echo "iDRAC/IPMI password: $IDRAC_PASSWORD" + IDRAC_LOGIN_STRING="lanplus -H $IDRAC_HOST -U $IDRAC_USERNAME -P $IDRAC_PASSWORD" +fi + +ipmitool -I $IDRAC_LOGIN_STRING sdr type temperature diff --git a/lxc/idrac-fan-controller.service b/lxc/idrac-fan-controller.service new file mode 100644 index 0000000..8e3f17f --- /dev/null +++ b/lxc/idrac-fan-controller.service @@ -0,0 +1,39 @@ +[Unit] +Description=Dell iDRAC Fan Controller +Documentation=https://github.com/tigerblue77/Dell_iDRAC_fan_controller_Docker +After=network.target +Wants=network.target + +[Service] +Type=simple +User=root +Group=root +WorkingDirectory=/opt/idrac-fan-controller +EnvironmentFile=/opt/idrac-fan-controller/config/environment +ExecStart=/opt/idrac-fan-controller/Dell_iDRAC_fan_controller.sh +ExecReload=/bin/kill -HUP $MAINPID +Restart=always +RestartSec=10 +KillMode=mixed +TimeoutStopSec=30 + +# Logging +StandardOutput=journal +StandardError=journal +SyslogIdentifier=idrac-fan-controller + +# Security settings +NoNewPrivileges=false +PrivateTmp=true +ProtectHome=true +ProtectSystem=strict +ReadWritePaths=/var/log/idrac-fan-controller +ReadOnlyPaths=/opt/idrac-fan-controller + +# Hardware access required for IPMI +DeviceAllow=/dev/ipmi0 rw +DeviceAllow=/dev/ipmi/0 rw +DeviceAllow=/dev/ipmidev/0 rw + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/lxc/install-lxc.sh b/lxc/install-lxc.sh new file mode 100755 index 0000000..b1bc94a --- /dev/null +++ b/lxc/install-lxc.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +# Script d'installation du contrĂŽleur de ventilateurs Dell iDRAC pour LXC/Proxmox +# Usage: ./install-lxc.sh + +set -euo pipefail + +# Couleurs pour l'affichage +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +INSTALL_DIR="/opt/idrac-fan-controller" +SERVICE_NAME="idrac-fan-controller" +CONFIG_FILE="$INSTALL_DIR/config/environment" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +echo -e "${BLUE}=== Installation du contrĂŽleur de ventilateurs Dell iDRAC ===${NC}" +echo + +# VĂ©rifier les privilĂšges root +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}Erreur: Ce script doit ĂȘtre exĂ©cutĂ© en tant que root${NC}" + exit 1 +fi + +# VĂ©rifier si on est dans un container LXC +if ! systemd-detect-virt --container >/dev/null 2>&1; then + echo -e "${YELLOW}Attention: Ce script est conçu pour un container LXC Proxmox${NC}" + read -p "Continuer quand mĂȘme ? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 0 + fi +fi + +echo -e "${BLUE}1. Mise Ă  jour du systĂšme...${NC}" +apt-get update -qq + +echo -e "${BLUE}2. Installation des dĂ©pendances...${NC}" +apt-get install -y ipmitool + +echo -e "${BLUE}3. VĂ©rification de l'accĂšs IPMI...${NC}" +if [ ! -e "/dev/ipmi0" ] && [ ! -e "/dev/ipmi/0" ] && [ ! -e "/dev/ipmidev/0" ]; then + echo -e "${YELLOW}Attention: Aucun pĂ©riphĂ©rique IPMI dĂ©tectĂ©${NC}" + echo -e "${YELLOW}Assurez-vous que le container LXC est configurĂ© avec l'accĂšs au hardware IPMI${NC}" + echo -e "${YELLOW}Configuration Proxmox requise:${NC}" + echo -e "${YELLOW} - Container privilĂ©giĂ© (privilege: 1)${NC}" + echo -e "${YELLOW} - AccĂšs au pĂ©riphĂ©rique IPMI configurĂ©${NC}" + echo +fi + +echo -e "${BLUE}4. CrĂ©ation de la structure de rĂ©pertoires...${NC}" +mkdir -p "$INSTALL_DIR/config" +mkdir -p "/var/log/$SERVICE_NAME" + +echo -e "${BLUE}5. Copie des fichiers de l'application...${NC}" +cp "$SCRIPT_DIR/../Dell_iDRAC_fan_controller.sh" "$INSTALL_DIR/" +cp "$SCRIPT_DIR/../functions.sh" "$INSTALL_DIR/" +cp "$SCRIPT_DIR/../healthcheck.sh" "$INSTALL_DIR/" +cp "$SCRIPT_DIR/idrac-fan-controller.service" "/etc/systemd/system/" + +# Rendre les scripts exĂ©cutables +chmod +x "$INSTALL_DIR"/*.sh + +echo -e "${BLUE}6. Configuration des variables d'environnement...${NC}" +if [ ! -f "$CONFIG_FILE" ]; then + cat > "$CONFIG_FILE" << 'EOF' +# Configuration du contrĂŽleur de ventilateurs Dell iDRAC +# Modifiez ces valeurs selon votre environnement + +# Connexion iDRAC +IDRAC_HOST=local +IDRAC_USERNAME=root +IDRAC_PASSWORD=calvin + +# ContrĂŽle dynamique des ventilateurs +CPU_TEMPERATURE_1=30 +CPU_TEMPERATURE_2=40 +CPU_TEMPERATURE_3=50 +CPU_TEMPERATURE_4=60 +FAN_SPEED_1=10 +FAN_SPEED_2=30 +FAN_SPEED_3=60 +FAN_SPEED_4=80 + +# Seuil de sĂ©curitĂ© +CPU_TEMPERATURE_THRESHOLD=70 + +# Autres paramĂštres +CHECK_INTERVAL=60 +DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=false +EOF + echo -e "${GREEN}Fichier de configuration créé: $CONFIG_FILE${NC}" +else + echo -e "${YELLOW}Fichier de configuration existant conservĂ©: $CONFIG_FILE${NC}" +fi + +echo -e "${BLUE}7. Configuration du service systemd...${NC}" +systemctl daemon-reload +systemctl enable "$SERVICE_NAME" + +echo -e "${GREEN}=== Installation terminĂ©e avec succĂšs ! ===${NC}" +echo +echo -e "${BLUE}Prochaines Ă©tapes:${NC}" +echo "1. Éditez la configuration: nano $CONFIG_FILE" +echo "2. DĂ©marrez le service: systemctl start $SERVICE_NAME" +echo "3. VĂ©rifiez le statut: systemctl status $SERVICE_NAME" +echo "4. Consultez les logs: journalctl -u $SERVICE_NAME -f" +echo +echo -e "${BLUE}Commandes utiles:${NC}" +echo "‱ DĂ©marrer: systemctl start $SERVICE_NAME" +echo "‱ ArrĂȘter: systemctl stop $SERVICE_NAME" +echo "‱ RedĂ©marrer: systemctl restart $SERVICE_NAME" +echo "‱ Statut: systemctl status $SERVICE_NAME" +echo "‱ Logs: journalctl -u $SERVICE_NAME -f" +echo "‱ Test: $INSTALL_DIR/healthcheck.sh" +echo +echo -e "${YELLOW}N'oubliez pas de configurer votre container LXC Proxmox avec:${NC}" +echo "‱ pct set -privilege 1" +echo "‱ pct set -features nesting=1" +echo "‱ Configuration de l'accĂšs IPMI selon votre setup" \ No newline at end of file diff --git a/lxc/uninstall-lxc.sh b/lxc/uninstall-lxc.sh new file mode 100755 index 0000000..0dc49a7 --- /dev/null +++ b/lxc/uninstall-lxc.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# Script de dĂ©sinstallation du contrĂŽleur de ventilateurs Dell iDRAC pour LXC +# Usage: ./uninstall-lxc.sh + +set -euo pipefail + +# Couleurs pour l'affichage +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +INSTALL_DIR="/opt/idrac-fan-controller" +SERVICE_NAME="idrac-fan-controller" +CONFIG_FILE="$INSTALL_DIR/config/environment" + +echo -e "${RED}=== DĂ©sinstallation du contrĂŽleur de ventilateurs Dell iDRAC ===${NC}" +echo + +# VĂ©rifier les privilĂšges root +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}Erreur: Ce script doit ĂȘtre exĂ©cutĂ© en tant que root${NC}" + exit 1 +fi + +# Confirmation +echo -e "${YELLOW}Cette opĂ©ration va :${NC}" +echo "‱ ArrĂȘter et dĂ©sactiver le service $SERVICE_NAME" +echo "‱ Supprimer tous les fichiers dans $INSTALL_DIR" +echo "‱ Supprimer le service systemd" +echo "‱ Supprimer les logs" +echo +echo -e "${RED}ATTENTION: Cette action est irrĂ©versible !${NC}" +read -p "Êtes-vous sĂ»r de vouloir continuer ? (yes/NO): " -r +if [[ ! $REPLY =~ ^yes$ ]]; then + echo -e "${GREEN}DĂ©sinstallation annulĂ©e.${NC}" + exit 0 +fi +echo + +echo -e "${BLUE}1. ArrĂȘt du service...${NC}" +if systemctl is-active --quiet "$SERVICE_NAME"; then + systemctl stop "$SERVICE_NAME" + echo -e "${GREEN}Service arrĂȘtĂ©${NC}" +else + echo -e "${YELLOW}Service dĂ©jĂ  arrĂȘtĂ©${NC}" +fi + +echo -e "${BLUE}2. DĂ©sactivation du service...${NC}" +if systemctl is-enabled --quiet "$SERVICE_NAME" 2>/dev/null; then + systemctl disable "$SERVICE_NAME" + echo -e "${GREEN}Service dĂ©sactivĂ©${NC}" +else + echo -e "${YELLOW}Service dĂ©jĂ  dĂ©sactivĂ©${NC}" +fi + +echo -e "${BLUE}3. Suppression du fichier de service systemd...${NC}" +if [ -f "/etc/systemd/system/$SERVICE_NAME.service" ]; then + rm -f "/etc/systemd/system/$SERVICE_NAME.service" + systemctl daemon-reload + echo -e "${GREEN}Fichier de service supprimĂ©${NC}" +else + echo -e "${YELLOW}Fichier de service non trouvĂ©${NC}" +fi + +echo -e "${BLUE}4. Sauvegarde de la configuration...${NC}" +if [ -f "$CONFIG_FILE" ]; then + BACKUP_FILE="/tmp/idrac-fan-controller-config-backup-$(date +%Y%m%d-%H%M%S)" + cp "$CONFIG_FILE" "$BACKUP_FILE" + echo -e "${GREEN}Configuration sauvegardĂ©e dans: $BACKUP_FILE${NC}" +fi + +echo -e "${BLUE}5. Suppression des fichiers d'installation...${NC}" +if [ -d "$INSTALL_DIR" ]; then + rm -rf "$INSTALL_DIR" + echo -e "${GREEN}RĂ©pertoire d'installation supprimĂ©${NC}" +else + echo -e "${YELLOW}RĂ©pertoire d'installation non trouvĂ©${NC}" +fi + +echo -e "${BLUE}6. Suppression des logs...${NC}" +if [ -d "/var/log/$SERVICE_NAME" ]; then + rm -rf "/var/log/$SERVICE_NAME" + echo -e "${GREEN}Logs supprimĂ©s${NC}" +else + echo -e "${YELLOW}RĂ©pertoire de logs non trouvĂ©${NC}" +fi + +echo -e "${BLUE}7. Nettoyage des logs systemd...${NC}" +journalctl --vacuum-time=1d --quiet || true + +echo -e "${GREEN}=== DĂ©sinstallation terminĂ©e avec succĂšs ! ===${NC}" +echo +echo -e "${BLUE}Actions effectuĂ©es:${NC}" +echo "‱ Service $SERVICE_NAME arrĂȘtĂ© et dĂ©sactivĂ©" +echo "‱ Fichiers d'application supprimĂ©s" +echo "‱ Logs nettoyĂ©s" +if [ -f "$BACKUP_FILE" ]; then + echo -e "${YELLOW}‱ Configuration sauvegardĂ©e: $BACKUP_FILE${NC}" +fi +echo +echo -e "${YELLOW}Note: Les ventilateurs sont maintenant contrĂŽlĂ©s par le systĂšme Dell par dĂ©faut${NC}" \ No newline at end of file