Development

This commit is contained in:
Matthew Grotke 2026-06-01 22:12:11 -04:00
parent 9f1b4a9119
commit 8eec61a1df
8 changed files with 697 additions and 56 deletions

View file

@ -114,9 +114,9 @@ SYSTEMD_DIR = Path("/etc/systemd/system")
BLIST_TIMER_NAME = f"{PRODUCT_NAME}-dns-blocklist-update"
BLIST_TIMER_FILE = SYSTEMD_DIR / f"{BLIST_TIMER_NAME}.timer"
BLIST_TIMER_SVC_FILE = SYSTEMD_DIR / f"{BLIST_TIMER_NAME}.service"
DDNS_TIMER_NAME = f"{PRODUCT_NAME}-ddns-update"
DDNS_TIMER_FILE = SYSTEMD_DIR / f"{DDNS_TIMER_NAME}.timer"
DDNS_TIMER_SVC_FILE = SYSTEMD_DIR / f"{DDNS_TIMER_NAME}.service"
MAINT_TIMER_NAME = f"{PRODUCT_NAME}-maintenance"
MAINT_TIMER_FILE = SYSTEMD_DIR / f"{MAINT_TIMER_NAME}.timer"
MAINT_TIMER_SVC_FILE = SYSTEMD_DIR / f"{MAINT_TIMER_NAME}.service"
HEALTH_TIMER_NAME = f"{PRODUCT_NAME}-health-check"
HEALTH_TIMER_FILE = SYSTEMD_DIR / f"{HEALTH_TIMER_NAME}.timer"
HEALTH_TIMER_SVC_FILE = SYSTEMD_DIR / f"{HEALTH_TIMER_NAME}.service"
@ -1143,10 +1143,10 @@ def _parse_ddns_interval(interval_str):
raise ValueError(f"Invalid timer_interval format: '{s}'. Use e.g. 5m, 2h, 1d.")
def install_ddns_timer(data):
def install_maint_timer(data):
ddns = data.get("ddns", {})
interval = ddns.get("general", {}).get("timer_interval", "10m")
script_path = SCRIPT_DIR / "ddns.py"
script_path = SCRIPT_DIR / "maintenance.py"
try:
systemd_unit = _parse_ddns_interval(interval)
except ValueError as e:
@ -1182,19 +1182,19 @@ def install_ddns_timer(data):
"WantedBy=timers.target",
"",
])
for path, content in ((DDNS_TIMER_SVC_FILE, service_content), (DDNS_TIMER_FILE, timer_content)):
for path, content in ((MAINT_TIMER_SVC_FILE, service_content), (MAINT_TIMER_FILE, timer_content)):
if not path.exists() or path.read_text() != content:
path.write_text(content)
print(f"Written: {path}")
subprocess.run(["systemctl", "daemon-reload"], capture_output=True, text=True)
active = subprocess.run(
["systemctl", "is-active", f"{DDNS_TIMER_NAME}.timer"],
["systemctl", "is-active", f"{MAINT_TIMER_NAME}.timer"],
capture_output=True, text=True
).stdout.strip() == "active"
verb = "restart" if active else "enable --now"
subprocess.run(["systemctl"] + verb.split() + [f"{DDNS_TIMER_NAME}.timer"],
subprocess.run(["systemctl"] + verb.split() + [f"{MAINT_TIMER_NAME}.timer"],
capture_output=True, text=True)
print(f"Timer {DDNS_TIMER_NAME}.timer enabled (runs every {interval}).")
print(f"Timer {MAINT_TIMER_NAME}.timer enabled (runs every {interval}).")
# ===================================================================
# banned_ips expansion
@ -1898,7 +1898,7 @@ def build_radius_users(data):
Generate freeradius users file.
Each MAC reservation across all VLANs gets an entry mapping it to its VLAN ID.
Unknown MACs fall through to DEFAULT which returns the radius_default VLAN.
MAC format and DEFAULT rule scope are read from free_radius.options in config.
MAC format and DEFAULT rule scope are read from radius.options in config.
"""
default_vlan = next(
(v for v in data["vlans"] if v.get("radius_default") is True), None
@ -1906,7 +1906,7 @@ def build_radius_users(data):
if default_vlan is None:
die("No VLAN has radius_default: true. Cannot generate RADIUS users file.")
fr_opts = data.get('free_radius', {}).get('options', {})
fr_opts = data.get('radius', {}).get('options', {})
mac_fmt = fr_opts.get('mac_format', 'aabbccddeeff')
apply_to = fr_opts.get('apply_to', 'all')
@ -1979,7 +1979,7 @@ def apply_radius(data):
clients_content = build_radius_clients_conf(data, secret)
users_content = build_radius_users(data)
logging = data.get('free_radius', {}).get('general', {}).get('logging', False)
logging = data.get('radius', {}).get('general', {}).get('logging', False)
changed = _set_freeradius_log(logging)
for path, content in [(RADIUS_CLIENTS_CONF, clients_content),
@ -2449,9 +2449,9 @@ def show_metrics(data):
def stop_instances(data):
"""Remove timers and stop all per-VLAN instances (config files preserved)."""
_remove_timers(
names=[BLIST_TIMER_NAME, HEALTH_TIMER_NAME, DDNS_TIMER_NAME],
timer_files=[BLIST_TIMER_FILE, HEALTH_TIMER_FILE, DDNS_TIMER_FILE],
svc_files=[BLIST_TIMER_SVC_FILE, HEALTH_TIMER_SVC_FILE, DDNS_TIMER_SVC_FILE],
names=[BLIST_TIMER_NAME, HEALTH_TIMER_NAME, MAINT_TIMER_NAME],
timer_files=[BLIST_TIMER_FILE, HEALTH_TIMER_FILE, MAINT_TIMER_FILE],
svc_files=[BLIST_TIMER_SVC_FILE, HEALTH_TIMER_SVC_FILE, MAINT_TIMER_SVC_FILE],
daemon_reload=True,
)
print()
@ -3051,9 +3051,9 @@ def cmd_apply(data, dry_run=False):
print("DDNS timer ==========================================================")
enabled_ddns = [p for p in data.get("ddns", {}).get("providers", []) if p.get("enabled")]
if enabled_ddns:
install_ddns_timer(data)
install_maint_timer(data)
else:
_remove_timers([DDNS_TIMER_NAME], [DDNS_TIMER_FILE], [DDNS_TIMER_SVC_FILE])
_remove_timers([MAINT_TIMER_NAME], [MAINT_TIMER_FILE], [MAINT_TIMER_SVC_FILE])
print("No enabled DDNS providers — timer not installed.")
print()