Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix readme and adjust column headers in output #1

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions .github/workflows/build_and_publish_docker_image.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Docker image CI

on:
workflow_dispatch:
push:
branches: [ master ]
paths-ignore:
Expand All @@ -12,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Remove "_Docker" suffix from GitHub repository name to use it as image name
uses: mad9000/actions-find-and-replace-string@3
Expand All @@ -32,26 +33,20 @@ jobs:
tags: type=raw,value=latest

- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3

- name: Build and publish Docker image
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: bradbarnhill/dell_idrac_fan_controller:latest
labels: ${{ steps.meta.outputs.labels }}
102 changes: 89 additions & 13 deletions Dell_iDRAC_fan_controller.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ function apply_user_fan_control_profile () {
CURRENT_FAN_CONTROL_PROFILE="User static fan control profile ($DECIMAL_FAN_SPEED%)"
}

function apply_line_interpolation_fan_control_profile () {
ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x00 > /dev/null
ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x02 0xff $HEXADECIMAL_CURRENT_FAN_SPEED > /dev/null
CURRENT_FAN_CONTROL_PROFILE="Interpolated fan control profile ($CURRENT_FAN_SPEED%)"
}

# Retrieve temperature sensors data using ipmitool
# Usage : retrieve_temperatures $IS_EXHAUST_TEMPERATURE_SENSOR_PRESENT $IS_CPU2_TEMPERATURE_SENSOR_PRESENT
function retrieve_temperatures () {
Expand Down Expand Up @@ -97,7 +103,12 @@ trap 'gracefull_exit' SIGQUIT SIGKILL SIGTERM

# readonly DELL_FRESH_AIR_COMPLIANCE=45

# Check if FAN_SPEED variable is in hexadecimal format. If not, convert it to hexadecimal
# Convert current fan value to hexadecimal
function convert_current_fan_value_to_hexadecimal_format () {
HEXADECIMAL_CURRENT_FAN_SPEED=$(printf '0x%02x' $CURRENT_FAN_SPEED)
}

# Check if FAN_SPEED and HIGH_FAN_SPEED variable is in hexadecimal format. If not, convert it to hexadecimal
if [[ $FAN_SPEED == 0x* ]]
then
DECIMAL_FAN_SPEED=$(printf '%d' $FAN_SPEED)
Expand All @@ -107,6 +118,18 @@ else
HEXADECIMAL_FAN_SPEED=$(printf '0x%02x' $FAN_SPEED)
fi

if $ENABLE_LINE_INTERPOLATION
then
if [[ $HIGH_FAN_SPEED == 0x* ]]
then
DECIMAL_HIGH_FAN_SPEED=$(printf '%d' $HIGH_FAN_SPEED)
HEXADECIMAL_HIGH_FAN_SPEED=$HIGH_FAN_SPEED
else
DECIMAL_HIGH_FAN_SPEED=$HIGH_FAN_SPEED
HEXADECIMAL_HIGH_FAN_SPEED=$(printf '0x%02x' $HIGH_FAN_SPEED)
fi
fi

# Log main informations given to the container
echo "iDRAC/IPMI host: $IDRAC_HOST"

Expand All @@ -126,10 +149,21 @@ else
fi

# Log the fan speed objective, CPU temperature threshold and check interval
echo "Fan speed objective: $DECIMAL_FAN_SPEED%"
echo "CPU temperature threshold: $CPU_TEMPERATURE_THRESHOLD°C"
echo "Check interval: ${CHECK_INTERVAL}s"
echo ""
echo "Line interpolation enable: $ENABLE_LINE_INTERPOLATION"
if $ENABLE_LINE_INTERPOLATION
then
echo "Fan speed lower value: $DECIMAL_FAN_SPEED%"
echo "Fan speed higher value: $DECIMAL_HIGH_FAN_SPEED%"
echo "CPU lower temperature threshold: $CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION°C"
echo "CPU higher temperature threshold: $CPU_TEMPERATURE_THRESHOLD°C"
echo "Check interval: ${CHECK_INTERVAL}s"
echo ""
else
echo "Fan speed objective: $DECIMAL_FAN_SPEED%"
echo "CPU temperature threshold: $CPU_TEMPERATURE_THRESHOLD°C"
echo "Check interval: ${CHECK_INTERVAL}s"
echo ""
fi

# Define the interval for printing
readonly TABLE_HEADER_PRINT_INTERVAL=10
Expand Down Expand Up @@ -203,13 +237,55 @@ while true; do
COMMENT="CPU 2 temperature is too high, Dell default dynamic fan control profile applied for safety"
fi
else
apply_user_fan_control_profile

# 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."
if $ENABLE_LINE_INTERPOLATION
then
CURRENT_FAN_SPEED=$DECIMAL_FAN_SPEED

CPU_HIGHER_TEMP=$CPU1_TEMPERATURE
if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT
then
if [ $CPU2_TEMPERATURE -gt $CPU1_TEMPERATURE ];
then
CPU_HIGHER_TEMP=$CPU2_TEMPERATURE
fi
fi

if [ $CPU_HIGHER_TEMP -gt $CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION ];
then
#
# F1 - lower fan speed
# F2 - higher fan speed
# T_CPU - higher temperature from both CPUs (if only one exist that will be CPU1 temp value)
# T1 - lower temperature threshold
# T2 - higher temperature threshold
# Fan speed = F1 + ( ( F2 - F1 ) * ( T_CPU - T1 ) / ( T2 - T1 ) )
#
# Difference between higher and lower temperature
TEMP_WINDOW="$((CPU_TEMPERATURE_THRESHOLD - CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION))"
# Temperature above lower value
TEMPERATURE_ABOVE_LOWER_THRESHOLD="$((CPU_HIGHER_TEMP - CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION))"
# Difference between higher and lower fan speed
FAN_WINDOW="$((DECIMAL_HIGH_FAN_SPEED - DECIMAL_FAN_SPEED))"
FAN_VALUE_TO_ADD=0
# Check if TEMP_WINDOW is grater than 0
if [ $TEMP_WINDOW -gt $FAN_VALUE_TO_ADD ];
then
FAN_VALUE_TO_ADD="$((FAN_WINDOW * TEMPERATURE_ABOVE_LOWER_THRESHOLD / TEMP_WINDOW))"
fi
CURRENT_FAN_SPEED="$((DECIMAL_FAN_SPEED + FAN_VALUE_TO_ADD))"
fi
# Convert decimal to hexadecimal value of fan speed
convert_current_fan_value_to_hexadecimal_format
apply_line_interpolation_fan_control_profile
else
apply_user_fan_control_profile

# 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
fi

Expand All @@ -228,7 +304,7 @@ while true; do
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"
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"
Expand Down
14 changes: 8 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
FROM ubuntu:latest

LABEL org.opencontainers.image.authors="tigerblue77"
FROM ubuntu:24.04
LABEL org.opencontainers.image.authors="bradbarnhill"

RUN apt-get update

Expand All @@ -15,9 +14,12 @@ RUN chmod 0777 /Dell_iDRAC_fan_controller.sh
ENV IDRAC_HOST local
#ENV IDRAC_USERNAME root
#ENV IDRAC_PASSWORD calvin
ENV FAN_SPEED 5
ENV CPU_TEMPERATURE_THRESHOLD 50
ENV CHECK_INTERVAL 60
ENV FAN_SPEED 15
ENV HIGH_FAN_SPEED 45
ENV CPU_TEMPERATURE_THRESHOLD 70
ENV CHECK_INTERVAL 3
ENV CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION 50
ENV ENABLE_LINE_INTERPOLATION true
ENV DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE false

CMD ["/Dell_iDRAC_fan_controller.sh"]
47 changes: 39 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

# Dell iDRAC fan controller Docker image
Download Docker image from :
- [Docker Hub](https://hub.docker.com/r/tigerblue77/dell_idrac_fan_controller)
- [GitHub Containers Repository](https://github.com/tigerblue77/Dell_iDRAC_fan_controller_Docker/pkgs/container/dell_idrac_fan_controller)
- [Docker Hub](https://hub.docker.com/r/7adrian/dell_idrac_fan_controller_with_line_interpolation)
- [GitHub Containers Repository](https://github.com/7Adrian/Dell_iDRAC_fan_controller_Docker_with_line_interpolation)

<!-- TABLE OF CONTENTS -->
<details>
Expand Down Expand Up @@ -71,8 +71,11 @@ docker run -d \
-e CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold> \
-e CHECK_INTERVAL=<seconds between each check> \
-e DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false> \
-e ENABLE_LINE_INTERPOLATION=<true or false> \
-e CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, olny when interpolation enabled> \
-e HIGH_FAN_SPEED=<decimal or hexadecimal fan speed, only when interpolation enabled> \
--device=/dev/ipmi0:/dev/ipmi0:rw \
tigerblue77/dell_idrac_fan_controller:latest
7adrian/dell_idrac_fan_controller_with_line_interpolation:latest
```

2. with LAN iDRAC:
Expand All @@ -88,9 +91,11 @@ docker run -d \
-e CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold> \
-e CHECK_INTERVAL=<seconds between each check> \
-e DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false> \
tigerblue77/dell_idrac_fan_controller:latest
-e ENABLE_LINE_INTERPOLATION=<true or false> \
-e CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled> \
-e HIGH_FAN_SPEED=<decimal or hexadecimal fan speed, only when interpolation enabled> \
7adrian/dell_idrac_fan_controller_with_line_interpolation:latest
```

`docker-compose.yml` examples:

1. to use with local iDRAC:
Expand All @@ -100,7 +105,7 @@ version: '3'

services:
Dell_iDRAC_fan_controller:
image: tigerblue77/dell_idrac_fan_controller:latest
image: 7adrian/dell_idrac_fan_controller_with_line_interpolation:latest
container_name: Dell_iDRAC_fan_controller
restart: unless-stopped
environment:
Expand All @@ -109,6 +114,9 @@ services:
- CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold>
- CHECK_INTERVAL=<seconds between each check>
- DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false>
- ENABLE_LINE_INTERPOLATION=<true or false>
- CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled>
- HIGH_FAN_SPEED=<decimal or hexadecimal fan speed when interpolation enabled>
devices:
- /dev/ipmi0:/dev/ipmi0:rw
```
Expand All @@ -120,7 +128,7 @@ version: '3'

services:
Dell_iDRAC_fan_controller:
image: tigerblue77/dell_idrac_fan_controller:latest
image: 7adrian/dell_idrac_fan_controller_with_line_interpolation:latest
container_name: Dell_iDRAC_fan_controller
restart: unless-stopped
environment:
Expand All @@ -131,6 +139,9 @@ services:
- CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold>
- CHECK_INTERVAL=<seconds between each check>
- DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false>
- ENABLE_LINE_INTERPOLATION=<true or false>
- CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled>
- HIGH_FAN_SPEED=<decimal or hexadecimal fan speed when interpolation enabled>
```

<p align="right">(<a href="#top">back to top</a>)</p>
Expand All @@ -147,6 +158,26 @@ All parameters are optional as they have default values (including default iDRAC
- `CPU_TEMPERATURE_THRESHOLD` parameter is the T°junction (junction temperature) threshold beyond which the Dell fan mode defined in your BIOS will become active again (to protect the server hardware against overheat). **Default** value is 50(°C).
- `CHECK_INTERVAL` parameter is the time (in seconds) between each temperature check and potential profile change. **Default** value is 60(s).
- `DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE` parameter is a boolean that allows to disable third-party PCIe card Dell default cooling response. **Default** value is false.
- `ENABLE_LINE_INTERPOLATION` parameter is a boolean that allows to enable line interpolation. If temperature value going above **CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION** they will proportionally increase fan speed to **HIGH_FAN_SPEED** when **CPU_TEMPERATURE_THRESHOLD** will reached. **Default** value is false.
- `CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION` parameter is only necessary if you're using line interpolation. Must be lower than **CPU_TEMPERATURE_THRESHOLD**. **Default** value is 40(°C).
- `HIGH_FAN_SPEED` parameter is only necessary if you're using line interpolation. It defines maximum fan speed before swiching to dell temperature control. **Default** value is 45(%).

Example of how interpolation work:
- `FAN_SPEED` = 10
- `HIGH_FAN_SPEED` = 50
- `CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION` = 30
- `CPU_TEMPERATURE_THRESHOLD` = 70

| CPU Temperature | Fan Speed |
| ------------- | ------------- |
| 15 °C | 10 % |
| 30 °C | 10 % |
| 35 °C | 15 % |
| 50 °C | 30 % |
| 69 °C | 49 % |
| 70 °C | Dell fan control |

When using line interpolation it's recommended to lower **CHECK_INTERVAL** to value such as 3 seconds.

<p align="right">(<a href="#top">back to top</a>)</p>

Expand All @@ -155,7 +186,7 @@ All parameters are optional as they have default values (including default iDRAC

If your server frequently switches back to the default Dell fan mode:
1. Check `Tcase` (case temperature) of your CPU on Intel Ark website and then set `CPU_TEMPERATURE_THRESHOLD` to a slightly lower value. Example with my CPUs ([Intel Xeon E5-2630L v2](https://www.intel.com/content/www/us/en/products/sku/75791/intel-xeon-processor-e52630l-v2-15m-cache-2-40-ghz/specifications.html)) : Tcase = 63°C, I set `CPU_TEMPERATURE_THRESHOLD` to 60(°C).
2. If it's already good, adapt your `FAN_SPEED` value to increase the airflow and thus further decrease the temperature of your CPU(s)
2. If it's already good, adapt your `FAN_SPEED` value to increase the airflow and thus further decrease the temperature of your CPU(s) or enable and experiment with line interpolation
3. If neither increasing the fan speed nor increasing the threshold solves your problem, then it may be time to replace your thermal paste

<p align="right">(<a href="#top">back to top</a>)</p>
Expand Down