95f132bdf8
- Implemented set_fanspeed.py for dynamic fan speed control based on temperature. - Created ilo_poweroff.py and ilo_poweron.py for iLO power management. - Added ipmi_poweroff.py and ipmi_poweron.py for IPMI power control. - Developed vm_start.py, vm_stop.py, vm_restart.py, and vm_shutdown.py for VM and LXC management. - Introduced wrapper scripts (start_wrapper.sh, stop_wrapper.sh) for simplified execution. - Removed deprecated shell scripts for power control.
86 lines
3.0 KiB
Python
86 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
import subprocess
|
|
import re
|
|
import sys
|
|
import datetime
|
|
import argparse
|
|
|
|
# IPMI settings
|
|
IPMIUSER = "<username>"
|
|
IPMIPW = "<password>"
|
|
IPMIEK = "0000000000000000000000000000000000000000"
|
|
|
|
# Fan / temperature settings
|
|
FANSPEED = 20 # percent
|
|
MAXTEMP = 37 # Celsius
|
|
|
|
def run_ipmi(args):
|
|
base = ["ipmitool", "-I", "lanplus", "-H", IPMIHOST, "-U", IPMIUSER, "-P", IPMIPW, "-y", IPMIEK]
|
|
cmd = base + args
|
|
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
if p.returncode != 0:
|
|
raise RuntimeError(f"ipmitool failed: {' '.join(cmd)}\n{p.stderr.strip()}")
|
|
return p.stdout
|
|
|
|
def log_systemd(tag, msg):
|
|
try:
|
|
subprocess.run(["systemd-cat", "-t", tag], input=msg + "\n", text=True, check=True)
|
|
except Exception:
|
|
# fallback to stdout
|
|
ts_print(msg)
|
|
|
|
def ts_print(msg):
|
|
"""ts_print message prefixed with a timestamp (YYYY-MM-DD HH:MM:SS)."""
|
|
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
print(f"{now} {msg}")
|
|
|
|
def get_ambient_temp():
|
|
out = run_ipmi(["sdr", "type", "temperature"])
|
|
# find lines like "Exhuat Temp | 29 degrees C"
|
|
lines = [l for l in out.splitlines() if "Exhaust" in l and "degrees" in l]
|
|
if not lines:
|
|
raise RuntimeError("Exhaust temperature line not found in ipmitool output")
|
|
# Extract last number found in the last matching line (like the original)
|
|
field = lines[-1].split("|")[4]
|
|
#ts_print("Debug: field =", field)
|
|
m = re.search(r"(\d{1,3})", field)
|
|
if not m:
|
|
raise RuntimeError("Could not parse temperature from line: " + lines[-1])
|
|
return int(m.group(1))
|
|
|
|
def main():
|
|
# parse CLI args (IPMI host can be overridden with -H/--host)
|
|
parser = argparse.ArgumentParser(description="Set fan speed via IPMI")
|
|
parser.add_argument("-H", "--host", default="127.0.0.1", help="IPMI host/IP (default: %(default)s)")
|
|
args = parser.parse_args()
|
|
|
|
global IPMIHOST
|
|
# set global IPMIHOST so run_ipmi() uses the provided host
|
|
IPMIHOST = args.host
|
|
|
|
ts_print(f"{IPMIHOST}: Fan speed check for host {IPMIHOST}")
|
|
try:
|
|
temp = get_ambient_temp()
|
|
ts_print(f"{IPMIHOST}: Exhaust temperature: {temp} C")
|
|
except Exception as e:
|
|
ts_print(f"{IPMIHOST}: Error reading temperature: {e}")
|
|
sys.exit(1)
|
|
|
|
speed_hex = format(FANSPEED, "x")
|
|
|
|
if temp > MAXTEMP:
|
|
msg = f"{IPMIHOST}:Warning: Temperature is too high! Activating dynamic fan control! ({temp} C)"
|
|
log_systemd("R710-IPMI-TEMP", msg)
|
|
ts_print(msg)
|
|
run_ipmi(["raw", "0x30", "0x30", "0x01", "0x01"])
|
|
else:
|
|
okmsg = f"{IPMIHOST}: Temperature is OK ({temp} C)"
|
|
log_systemd("R710-IPMI-TEMP", okmsg)
|
|
ts_print(okmsg)
|
|
ts_print(f"{IPMIHOST}: Activating manual fan speeds! (requested %d%%)" % FANSPEED)
|
|
run_ipmi(["raw", "0x30", "0x30", "0x01", "0x00"])
|
|
run_ipmi(["raw", "0x30", "0x30", "0x02", "0xff", "0x" + speed_hex])
|
|
|
|
if __name__ == "__main__":
|
|
main()
|