Initial import: monitoring, power-management, maintenance, web scripts

This commit is contained in:
2026-08-05 12:26:50 +02:00
commit 1936ded08f
10 changed files with 1306 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env python3
"""Wrapper: power on pve2 (DL380p Gen8) via iLO4 Redfish API.
Fire-and-forget — sends power-on, does NOT wait for boot.
Used by cron job server-start (no_agent mode, 120s timeout)."""
import os, sys, json, subprocess
ENV_FILE = os.path.expanduser("~/.hermes/.env")
def get_env(key):
try:
with open(ENV_FILE) as f:
for line in f:
if line.startswith(key + "="):
return line.strip().split("=", 1)[1]
except FileNotFoundError:
pass
return None
def ilo_token():
url = get_env("ILO4_URL")
user = get_env("ILO4_USER")
pwd = get_env("ILO4_PASSWORD")
payload = '{"UserName":"%s","Password":"%s"}' % (user, pwd)
cmd = ["curl", "-s", "-k", "--max-time", "10",
"-D", "/dev/stderr", "-X", "POST",
"-H", "Content-Type: application/json",
"-d", payload,
url + "/redfish/v1/SessionService/Sessions/"]
r = subprocess.run(cmd, capture_output=True, timeout=15)
stderr = r.stderr.decode("utf-8", errors="replace")
for line in stderr.split("\n"):
if "X-Auth-Token" in line:
return line.split(":")[1].strip()
return None
url = get_env("ILO4_URL")
token = ilo_token()
if not token:
print("FAIL: iLO auth failed")
sys.exit(1)
hdr = "X-Auth-Token: " + token
r = subprocess.run([
"curl", "-s", "-k", "--max-time", "15",
"-X", "POST",
"-H", hdr,
"-H", "Content-Type: application/json",
"-d", '{"ResetType":"On"}',
url + "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset/"
], capture_output=True, timeout=20)
# Check curl exit code
if r.returncode != 0:
print(f"FAIL: curl returned {r.returncode}")
sys.exit(1)
# Parse iLO response - check for actual error messages
# iLO wraps success in "ExtendedError" type with "Success" MessageID
stdout = r.stdout.decode("utf-8", errors="replace")
if stdout.strip():
try:
resp = json.loads(stdout)
msgs = resp.get("Messages", []) or (resp.get("error", {}) or {}).get("@Message.ExtendedInfo", [])
for m in msgs:
mid = m.get("MessageID", "")
if mid and "Success" not in mid and "OK" not in mid:
print(f"FAIL: iLO error: {mid}")
sys.exit(1)
except json.JSONDecodeError:
pass
print("Power-on command sent via iLO")
sys.exit(0)
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env python3
"""Wrapper: graceful shutdown of pve2 (DL380p Gen8) via Proxmox API.
Silent on success, sends email on failure.
Used by cron job server-stop (no_agent mode)."""
import sys, os
script = os.path.join(os.path.dirname(__file__), "host-power.py")
os.execvp(sys.executable, [sys.executable, script, "stop"])