That actually did it!
I had to come to some conclusions myself, such as having to enclose multi-word service names within double brackets, but besides that, it went positively smoothly.
If anyone wishes to implement the exact same fringe case as me, enclosed is the full code that I put under ~/local/bin in accordance with the linked documentation.
pdu_status_check.py
#!/usr/bin/env python3
import requests
import xml.etree.ElementTree as ET
from bs4 import BeautifulSoup
# === Config ===
PDU_HOST = "http://192.168.1.41" # Change to your PDU IP
AUTH = ("username", "password") # Credentials for control_outlet.htm
# === Fetch XML status ===
def fetch_status_xml():
try:
response = requests.get(f"{PDU_HOST}/status.xml", timeout=2)
response.raise_for_status()
return ET.fromstring(response.content)
except Exception as e:
print(f"2 PDU_Status - Error fetching status.xml: {e}")
exit(1)
# === Fetch outlet names from control_outlet.htm ===
def fetch_outlet_names():
try:
response = requests.get(f"{PDU_HOST}/control_outlet.htm", auth=AUTH, timeout=2)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
names = [td.text.strip() for td in soup.find_all('td')[::3]][1:] # Skip header
return {f"outletStat{i}": names[i] for i in range(len(names))}
except Exception as e:
print(f"2 PDU_Outlets - Error fetching outlet names: {e}")
return {}
# === Check Logic ===
def parse_services(status_xml, outlet_name_map):
services = []
# Load
current = status_xml.findtext("curBan")
if current is not None:
current = float(current)
state = 0 if current <= 9.0 else 1 if current <= 9.5 else 2
services.append((state, f'"PDU Load" - Current Load: {current} A'))
# Temperature
temp = status_xml.findtext("tempBan")
if temp is not None:
temp = int(temp)
state = 0 if temp < 35 else 1 if temp <= 45 else 2
services.append((state, f'"PDU Temperature" - Temperature: {temp} °C'))
# Humidity
hum = status_xml.findtext("humBan")
if hum is not None:
hum = int(hum)
state = 0 if hum < 70 else 1 if hum < 85 else 2
services.append((state, f'"PDU Humidity" - Humidity: {hum}%'))
# Outlets
for i in range(8):
key = f"outletStat{i}"
val = status_xml.findtext(key)
name = outlet_name_map.get(key, f"Outlet {i}")
state = 0 if val == "on" else 2
if state == 0:
msg = f'"PDU Outlet {i}" - OK - [{name}], ({val.upper()})'
elif state == 2:
msg = f'"PDU Outlet {i}" - CRIT - [{name}], ({val.upper()})'
services.append((state, msg))
return services
# === Main ===
if __name__ == "__main__":
xml_root = fetch_status_xml()
outlet_names = fetch_outlet_names()
results = parse_services(xml_root, outlet_names)
print('<<<local>>>')
for state, msg in results:
print(f'{state} {msg}')
status.xml file fetched from PDU, to work with
root@Srv01-SANDBOX:~# cat status.xml
<response>
<cur0>0.0</cur0>
<stat0>normal</stat0>
<curBan>0.0</curBan>
<tempBan>31</tempBan>
<humBan>19</humBan>
<statBan>normal</statBan>
<outletStat0>on</outletStat0>
<outletStat1>on</outletStat1>
<outletStat2>on</outletStat2>
<outletStat3>on</outletStat3>
<outletStat4>on</outletStat4>
<outletStat5>on</outletStat5>
<outletStat6>on</outletStat6>
<outletStat7>on</outletStat7>
<userVerifyRes>0</userVerifyRes>
</response>
Result:
OMD[mischief]:~/local/bin$ cmk -d MischiefPDU01
<<<local>>>
0 "PDU Load" - Current Load: 0.0 A
0 "PDU Temperature" - Temperature: 31 °C
0 "PDU Humidity" - Humidity: 19%
0 "PDU Outlet 0" - OK - [MschfAS01], (ON)
0 "PDU Outlet 1" - OK - [MschfFS01], (ON)
0 "PDU Outlet 2" - OK - [MschfFan0], (ON)
0 "PDU Outlet 3" - OK - [MschfSrv0], (ON)
0 "PDU Outlet 4" - OK - [BestaFans], (ON)
0 "PDU Outlet 5" - OK - [outlet6], (ON)
0 "PDU Outlet 6" - OK - [outlet7], (ON)
0 "PDU Outlet 7" - OK - [PS5_TV], (ON)

Thanks again for the quick help, I learned a lot!