refactor: rename package directory fabledscryer → roundtable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
"""Generate NUT (Network UPS Tools) configuration files.
|
||||
|
||||
Called by entrypoint.sh before the NUT daemons start. Reads config either from
|
||||
environment variables (legacy NUT_MANAGED=1 path) or from a JSON file written
|
||||
by the FabledScryer settings page (/data/nut_managed.json).
|
||||
|
||||
Environment variables (used when no --from-file is given):
|
||||
NUT_DRIVER NUT driver (default: snmp-ups)
|
||||
snmp-ups — any UPS with SNMP management card (APC, Eaton,
|
||||
CyberPower, Tripp Lite, Liebert, ...)
|
||||
netxml-ups — Eaton Network Management Card (XML/HTTP)
|
||||
NUT_UPS_NAME Name exposed by upsd (default: ups)
|
||||
Must match 'ups_name' in the UPS plugin settings.
|
||||
NUT_UPS_HOST IP address or hostname of the UPS management card (required)
|
||||
NUT_SNMP_COMMUNITY SNMP community string (default: public) [snmp-ups only]
|
||||
NUT_SNMP_VERSION SNMP version: v1, v2c (default: v1) [snmp-ups only]
|
||||
NUT_USERNAME Optional upsd username for authenticated access
|
||||
NUT_PASSWORD Optional upsd password
|
||||
|
||||
JSON file format (--from-file path):
|
||||
{
|
||||
"ups_host": "192.168.1.x", // required
|
||||
"driver": "snmp-ups",
|
||||
"ups_name": "ups",
|
||||
"snmp_community": "public",
|
||||
"snmp_version": "v1",
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
NUT_CONF_DIR = Path("/etc/nut")
|
||||
NUT_MANAGED_JSON = Path("/data/nut_managed.json")
|
||||
|
||||
|
||||
def _env(key: str, default: str = "") -> str:
|
||||
return os.environ.get(key, default).strip()
|
||||
|
||||
|
||||
def write_configs(cfg: dict | None = None) -> None:
|
||||
"""Write NUT config files. If cfg is given, use it; otherwise fall back to env vars."""
|
||||
NUT_CONF_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if cfg is not None:
|
||||
driver = cfg.get("driver", "snmp-ups").strip()
|
||||
ups_name = cfg.get("ups_name", "ups").strip()
|
||||
ups_host = cfg.get("ups_host", "").strip()
|
||||
community = cfg.get("snmp_community", "public").strip()
|
||||
snmp_ver = cfg.get("snmp_version", "v1").strip()
|
||||
username = cfg.get("username", "").strip()
|
||||
password = cfg.get("password", "").strip()
|
||||
else:
|
||||
driver = _env("NUT_DRIVER", "snmp-ups")
|
||||
ups_name = _env("NUT_UPS_NAME", "ups")
|
||||
ups_host = _env("NUT_UPS_HOST")
|
||||
community = _env("NUT_SNMP_COMMUNITY", "public")
|
||||
snmp_ver = _env("NUT_SNMP_VERSION", "v1")
|
||||
username = _env("NUT_USERNAME")
|
||||
password = _env("NUT_PASSWORD")
|
||||
|
||||
if not ups_host:
|
||||
print("[nut_setup] ERROR: NUT_UPS_HOST is required", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# ── nut.conf ───────────────────────────────────────────────────────────────
|
||||
(NUT_CONF_DIR / "nut.conf").write_text("MODE=standalone\n")
|
||||
|
||||
# ── ups.conf ───────────────────────────────────────────────────────────────
|
||||
ups_block = [f"[{ups_name}]"]
|
||||
ups_block.append(f" driver = {driver}")
|
||||
|
||||
if driver == "netxml-ups":
|
||||
# Eaton: port is a URL
|
||||
ups_block.append(f" port = http://{ups_host}")
|
||||
else:
|
||||
# snmp-ups and others: port is the IP/hostname
|
||||
ups_block.append(f" port = {ups_host}")
|
||||
if driver == "snmp-ups":
|
||||
ups_block.append(f" community = {community}")
|
||||
ups_block.append(f" snmp_version = {snmp_ver}")
|
||||
|
||||
ups_block.append(f' desc = "Network UPS at {ups_host}"')
|
||||
(NUT_CONF_DIR / "ups.conf").write_text("\n".join(ups_block) + "\n")
|
||||
|
||||
# ── upsd.conf ──────────────────────────────────────────────────────────────
|
||||
(NUT_CONF_DIR / "upsd.conf").write_text("LISTEN 127.0.0.1 3493\n")
|
||||
|
||||
# ── upsd.users ─────────────────────────────────────────────────────────────
|
||||
if username and password:
|
||||
users_content = (
|
||||
f"[{username}]\n"
|
||||
f" password = {password}\n"
|
||||
f" upsmon primary\n"
|
||||
)
|
||||
else:
|
||||
users_content = "# No users configured — unauthenticated access\n"
|
||||
users_path = NUT_CONF_DIR / "upsd.users"
|
||||
users_path.write_text(users_content)
|
||||
users_path.chmod(0o640)
|
||||
|
||||
print(
|
||||
f"[nut_setup] Config written: driver={driver} host={ups_host} ups_name={ups_name}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
cfg = None
|
||||
if "--from-file" in sys.argv:
|
||||
idx = sys.argv.index("--from-file")
|
||||
json_path = Path(sys.argv[idx + 1])
|
||||
with json_path.open() as f:
|
||||
cfg = json.load(f)
|
||||
write_configs(cfg)
|
||||
except Exception as exc:
|
||||
print(f"[nut_setup] ERROR: {exc}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user