manage fans

Felix Barbalet
2020-03-02T10:19:31Z

ipmitemp.py

| from pySMART import Device, DeviceList
| import subprocess, datetime, time, logging, sys
|
| #below this triggers an alert and fans spin up
| MIN_FAN = 10
| MAX_FAN = 64
| IPMI_SLEEP_DELAY = 2
|
| SYS_FAN_THRESH = [55, 50, 45, 00]
| SYS_FAN_SPEEDS = [64, 48, 30, MIN_FAN]
|
| CPU_FAN_THRESH = [65, 60, 55, 00]
| CPU_FAN_SPEEDS = [64, 48, 32, MIN_FAN]
|
| summary_temps = lambda temps: '{:.0f}/{:.0f}'.format(sum(temps) / len(temps), max(temps))
|
| def get_hdd_temps(devs):
| """SMART attribute 194 is temperature"""
| return [int(d.attributes[194].raw) for d in devs]
|
|
| def get_temp_from_sysctl(sl):
| return [float(_.split(':')[1].strip().replace('C','')) for _ in sl]
|
| def get_system_temps(sysctl_list):
| return filter(lambda _:_.startswith('hw.acpi.thermal.') and 'temperature' in _, sysctl_list)
|
| def get_cpu_temps(sysctl_list):
| return filter(lambda _:_.startswith('dev.cpu.') and 'temperature' in _, sysctl_list)
|
|
| #ipmitool raw 0x30 0x45 0x00
|
| def ipmi(extra):
| result = subprocess.check_output(['/usr/local/bin/ipmitool', 'raw', '0x30'] + extra)
| time.sleep(IPMI_SLEEP_DELAY)
| return result.decode('ascii')
|
| def thresholds():
| for fan in ['FAN1', 'FAN2', 'FAN3', 'FAN4', 'FANA']:
| 'ipmitool sensor thresh {} lower 100 100 100'
|
| def setup_fans():
| ipmi(['0x45','0x01', '0x01'])
|
| def fans_fullspeed():
| result = ipmi([
| '0x45',
| '0x00'
| ])
|
| return result.strip() == '01'
|
| def set_fan(fan, speed):
| ipmi(['0x70','0x66', '0x01', fan, '0x{}'.format(int(min(MAX_FAN, speed)))])
|
| def set_cpu_fan(speed):
| set_fan('0x01', speed)
| return speed
|
| def set_system_fan(speed):
| set_fan('0x00', speed)
| return speed
|
| def apply_temp_policy(TEMP, SPEEDS, THRESH, FAN, adj=0):
|
| for i, temp in enumerate(THRESH):
|
| if TEMP >= temp:
| return FAN(SPEEDS[i]+adj)
|
| return FAN(SPEEDS[-1]+adj)
|
|
| def setup_logging(debug=False):
|
| log = logging.getLogger('ipmitemp')
| log.setLevel(logging.DEBUG if debug else logging.INFO)
|
| formatter = logging.Formatter('%(asctime)s %(name)s - %(levelname)s - %(message)s')
|
| sh = logging.StreamHandler(stream=sys.stdout)
| sh.setFormatter(formatter)
| log.addHandler(sh)
|
| return log
|
|
| import time
| log = setup_logging(False)
|
| def doit():
|
| summary = []
|
| hdd_temps = get_hdd_temps(DeviceList().devices)
|
| sysctl_list = str(subprocess.check_output(['/sbin/sysctl', '-a'])).split('\\n')
|
| sys_temps = [_ for _ in get_temp_from_sysctl(get_system_temps(sysctl_list))]
| cpu_temps = [_ for _ in get_temp_from_sysctl(get_cpu_temps(sysctl_list))]
|
| summary.append('HDD:{}'.format(summary_temps(hdd_temps)))
| summary.append('SYS:{}'.format(summary_temps(sys_temps)))
| summary.append('CPU:{}'.format(summary_temps(cpu_temps)))
|
| if not fans_fullspeed():
| summary.append('FANS-SETUP')
| setup_fans()
|
| SYS = max(sys_temps + hdd_temps)
| CPU = int(sum(cpu_temps)/len(cpu_temps))
|
| cpu_speed = apply_temp_policy(CPU, CPU_FAN_SPEEDS, CPU_FAN_THRESH, set_cpu_fan)
| sys_speed = apply_temp_policy(SYS, SYS_FAN_SPEEDS, SYS_FAN_THRESH, set_system_fan, adj=max(0,float(cpu_speed-10)*0.50))
| summary.append('FAN_CPU:{:.0f}'.format(cpu_speed))
| summary.append('FAN_SYS:{:.0f}'.format(sys_speed))
|
| log.info(' '.join(sorted(summary)))
|
| if __name__ == '__main__':
| while True:
| doit()
| time.sleep(30)