Development
This commit is contained in:
parent
4150c6ef6e
commit
63cf7dc2c4
2 changed files with 88 additions and 34 deletions
|
|
@ -118,20 +118,11 @@ BLIST_TIMER_SVC_FILE = SYSTEMD_DIR / f"{BLIST_TIMER_NAME}.service"
|
||||||
DDNS_TIMER_NAME = f"{PRODUCT_NAME}-ddns-update"
|
DDNS_TIMER_NAME = f"{PRODUCT_NAME}-ddns-update"
|
||||||
DDNS_TIMER_FILE = SYSTEMD_DIR / f"{DDNS_TIMER_NAME}.timer"
|
DDNS_TIMER_FILE = SYSTEMD_DIR / f"{DDNS_TIMER_NAME}.timer"
|
||||||
DDNS_TIMER_SVC_FILE = SYSTEMD_DIR / f"{DDNS_TIMER_NAME}.service"
|
DDNS_TIMER_SVC_FILE = SYSTEMD_DIR / f"{DDNS_TIMER_NAME}.service"
|
||||||
DASHB_TIMER_NAME = f"{PRODUCT_NAME}-dashboard-queue"
|
|
||||||
DASHB_TIMER_FILE = SYSTEMD_DIR / f"{DASHB_TIMER_NAME}.timer"
|
|
||||||
DASHB_TIMER_SVC_FILE = SYSTEMD_DIR / f"{DASHB_TIMER_NAME}.service"
|
|
||||||
DASHB_TIMER_INTERVAL_SEC = 60
|
|
||||||
DASHB_QUEUE_FILE = SCRIPT_DIR / ".dashboard-queue"
|
|
||||||
HEALTH_TIMER_NAME = f"{PRODUCT_NAME}-health-check"
|
HEALTH_TIMER_NAME = f"{PRODUCT_NAME}-health-check"
|
||||||
HEALTH_TIMER_FILE = SYSTEMD_DIR / f"{HEALTH_TIMER_NAME}.timer"
|
HEALTH_TIMER_FILE = SYSTEMD_DIR / f"{HEALTH_TIMER_NAME}.timer"
|
||||||
HEALTH_TIMER_SVC_FILE = SYSTEMD_DIR / f"{HEALTH_TIMER_NAME}.service"
|
HEALTH_TIMER_SVC_FILE = SYSTEMD_DIR / f"{HEALTH_TIMER_NAME}.service"
|
||||||
HEALTH_TIMER_INTERVAL_SEC = 300
|
HEALTH_TIMER_INTERVAL_SEC = 300
|
||||||
HEALTH_FILE = SCRIPT_DIR / ".health"
|
HEALTH_FILE = SCRIPT_DIR / ".health"
|
||||||
DASHB_DONE_FILE = SCRIPT_DIR / ".dashboard-done"
|
|
||||||
DASHB_LAST_RUN_FILE = SCRIPT_DIR / ".dashboard-last-run"
|
|
||||||
DASHB_LOCK_FILE = SCRIPT_DIR / ".dashboard-lock"
|
|
||||||
DASHB_SCRIPT_FILE = SCRIPT_DIR / "do_dashboard_queue.sh"
|
|
||||||
RESOLV_CONF = Path("/etc/resolv.conf")
|
RESOLV_CONF = Path("/etc/resolv.conf")
|
||||||
NAT_SERVICE_NAME = f"{PRODUCT_NAME}-nat"
|
NAT_SERVICE_NAME = f"{PRODUCT_NAME}-nat"
|
||||||
NAT_SERVICE_FILE = SYSTEMD_DIR / f"{NAT_SERVICE_NAME}.service"
|
NAT_SERVICE_FILE = SYSTEMD_DIR / f"{NAT_SERVICE_NAME}.service"
|
||||||
|
|
@ -2384,9 +2375,9 @@ def show_metrics(data):
|
||||||
def stop_instances(data):
|
def stop_instances(data):
|
||||||
"""Remove timers and stop all per-VLAN instances (config files preserved)."""
|
"""Remove timers and stop all per-VLAN instances (config files preserved)."""
|
||||||
_remove_timers(
|
_remove_timers(
|
||||||
names=[BLIST_TIMER_NAME, DASHB_TIMER_NAME, HEALTH_TIMER_NAME, DDNS_TIMER_NAME],
|
names=[BLIST_TIMER_NAME, HEALTH_TIMER_NAME, DDNS_TIMER_NAME],
|
||||||
timer_files=[BLIST_TIMER_FILE, DASHB_TIMER_FILE, HEALTH_TIMER_FILE, DDNS_TIMER_FILE],
|
timer_files=[BLIST_TIMER_FILE, HEALTH_TIMER_FILE, DDNS_TIMER_FILE],
|
||||||
svc_files=[BLIST_TIMER_SVC_FILE, DASHB_TIMER_SVC_FILE, HEALTH_TIMER_SVC_FILE, DDNS_TIMER_SVC_FILE],
|
svc_files=[BLIST_TIMER_SVC_FILE, HEALTH_TIMER_SVC_FILE, DDNS_TIMER_SVC_FILE],
|
||||||
daemon_reload=True,
|
daemon_reload=True,
|
||||||
)
|
)
|
||||||
print()
|
print()
|
||||||
|
|
@ -2980,21 +2971,14 @@ def cmd_apply(data, dry_run=False):
|
||||||
print()
|
print()
|
||||||
|
|
||||||
print("Interval timers =====================================================")
|
print("Interval timers =====================================================")
|
||||||
# build parallel lists; dashboard timer only installed when queue file exists
|
_install_interval_timers(
|
||||||
t_names = [HEALTH_TIMER_NAME]
|
names=[HEALTH_TIMER_NAME],
|
||||||
t_files = [HEALTH_TIMER_FILE]
|
timer_files=[HEALTH_TIMER_FILE],
|
||||||
s_files = [HEALTH_TIMER_SVC_FILE]
|
svc_files=[HEALTH_TIMER_SVC_FILE],
|
||||||
t_descs = ["Router status health check"]
|
descriptions=["Router status health check"],
|
||||||
t_execs = [f"/usr/bin/python3 {SCRIPT_DIR / 'health.py'}"]
|
exec_starts=[f"/usr/bin/python3 {SCRIPT_DIR / 'health.py'}"],
|
||||||
t_intervals = [HEALTH_TIMER_INTERVAL_SEC]
|
interval_secs=[HEALTH_TIMER_INTERVAL_SEC],
|
||||||
if DASHB_QUEUE_FILE.exists():
|
)
|
||||||
t_names += [DASHB_TIMER_NAME]
|
|
||||||
t_files += [DASHB_TIMER_FILE]
|
|
||||||
s_files += [DASHB_TIMER_SVC_FILE]
|
|
||||||
t_descs += ["Router dashboard pending-update processor"]
|
|
||||||
t_execs += [f"/bin/bash {DASHB_SCRIPT_FILE}"]
|
|
||||||
t_intervals += [DASHB_TIMER_INTERVAL_SEC]
|
|
||||||
_install_interval_timers(t_names, t_files, s_files, t_descs, t_execs, t_intervals)
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
print("DDNS timer ==========================================================")
|
print("DDNS timer ==========================================================")
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,23 @@ SCRIPT_DIR = Path(__file__).parent.resolve()
|
||||||
COMPOSE_FILE = SCRIPT_DIR.parent / "docker" / "routlin-dash" / "docker-compose.yml"
|
COMPOSE_FILE = SCRIPT_DIR.parent / "docker" / "routlin-dash" / "docker-compose.yml"
|
||||||
CADDYFILE = Path("/etc/caddy/Caddyfile")
|
CADDYFILE = Path("/etc/caddy/Caddyfile")
|
||||||
FLASK_PORT = 25327
|
FLASK_PORT = 25327
|
||||||
|
PRODUCT_NAME = os.environ.get('PRODUCT_NAME', 'routlin')
|
||||||
|
SYSTEMD_DIR = Path("/etc/systemd/system")
|
||||||
|
|
||||||
# Per-VLAN dnsmasq dotfiles (parallel to core.py constants)
|
# Dashboard dotfiles
|
||||||
DASHB_QUEUE_FILE = SCRIPT_DIR / ".dashboard-queue"
|
DASHB_QUEUE_FILE = SCRIPT_DIR / ".dashboard-queue"
|
||||||
DASHB_DONE_FILE = SCRIPT_DIR / ".dashboard-done"
|
DASHB_DONE_FILE = SCRIPT_DIR / ".dashboard-done"
|
||||||
DASHB_LAST_RUN_FILE = SCRIPT_DIR / ".dashboard-last-run"
|
DASHB_LAST_RUN_FILE = SCRIPT_DIR / ".dashboard-last-run"
|
||||||
DASHB_LOCK_FILE = SCRIPT_DIR / ".dashboard-lock"
|
DASHB_LOCK_FILE = SCRIPT_DIR / ".dashboard-lock"
|
||||||
DASHB_PENDING_FILE = SCRIPT_DIR / ".dashboard-pending"
|
DASHB_PENDING_FILE = SCRIPT_DIR / ".dashboard-pending"
|
||||||
HEALTH_FILE = SCRIPT_DIR / ".health"
|
DASHB_SCRIPT_FILE = SCRIPT_DIR / "do_dashboard_queue.sh"
|
||||||
|
HEALTH_FILE = SCRIPT_DIR / ".health"
|
||||||
|
|
||||||
|
# Dashboard systemd timer
|
||||||
|
DASHB_TIMER_NAME = f"{PRODUCT_NAME}-dashboard-queue"
|
||||||
|
DASHB_TIMER_FILE = SYSTEMD_DIR / f"{DASHB_TIMER_NAME}.timer"
|
||||||
|
DASHB_TIMER_SVC_FILE = SYSTEMD_DIR / f"{DASHB_TIMER_NAME}.service"
|
||||||
|
DASHB_TIMER_INTERVAL_SEC = 60
|
||||||
|
|
||||||
|
|
||||||
# ===================================================================
|
# ===================================================================
|
||||||
|
|
@ -339,6 +348,62 @@ def create_dotfiles():
|
||||||
os.chown(f, stat.st_uid, stat.st_gid)
|
os.chown(f, stat.st_uid, stat.st_gid)
|
||||||
|
|
||||||
|
|
||||||
|
# ===================================================================
|
||||||
|
# Dashboard systemd timer
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
def install_dashboard_timer():
|
||||||
|
description = "Routlin dashboard pending-update processor"
|
||||||
|
timer_content = "\n".join([
|
||||||
|
"# Generated by install.py -- do not edit manually.",
|
||||||
|
"",
|
||||||
|
"[Unit]",
|
||||||
|
f"Description={description}",
|
||||||
|
"",
|
||||||
|
"[Timer]",
|
||||||
|
f"OnActiveSec={DASHB_TIMER_INTERVAL_SEC}s",
|
||||||
|
f"OnUnitActiveSec={DASHB_TIMER_INTERVAL_SEC}s",
|
||||||
|
"AccuracySec=10s",
|
||||||
|
"",
|
||||||
|
"[Install]",
|
||||||
|
"WantedBy=timers.target",
|
||||||
|
"",
|
||||||
|
])
|
||||||
|
service_content = "\n".join([
|
||||||
|
"# Generated by install.py -- do not edit manually.",
|
||||||
|
"",
|
||||||
|
"[Unit]",
|
||||||
|
f"Description={description}",
|
||||||
|
"",
|
||||||
|
"[Service]",
|
||||||
|
"Type=oneshot",
|
||||||
|
f"ExecStart=/bin/bash {DASHB_SCRIPT_FILE}",
|
||||||
|
"",
|
||||||
|
])
|
||||||
|
for path, content in ((DASHB_TIMER_FILE, timer_content), (DASHB_TIMER_SVC_FILE, service_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"{DASHB_TIMER_NAME}.timer"],
|
||||||
|
capture_output=True, text=True,
|
||||||
|
).stdout.strip() == "active"
|
||||||
|
subprocess.run(["systemctl", "enable", f"{DASHB_TIMER_NAME}.timer"], capture_output=True, text=True)
|
||||||
|
subprocess.run(["systemctl", "restart" if active else "start", f"{DASHB_TIMER_NAME}.timer"],
|
||||||
|
capture_output=True, text=True)
|
||||||
|
print(f" Timer {DASHB_TIMER_NAME}.timer enabled (runs every {DASHB_TIMER_INTERVAL_SEC}s).")
|
||||||
|
|
||||||
|
|
||||||
|
def remove_dashboard_timer():
|
||||||
|
subprocess.run(["systemctl", "disable", "--now", f"{DASHB_TIMER_NAME}.timer"],
|
||||||
|
capture_output=True, text=True)
|
||||||
|
for f in (DASHB_TIMER_FILE, DASHB_TIMER_SVC_FILE):
|
||||||
|
if f.exists():
|
||||||
|
f.unlink()
|
||||||
|
print(f" Removed: {f}")
|
||||||
|
subprocess.run(["systemctl", "daemon-reload"], capture_output=True, text=True)
|
||||||
|
|
||||||
|
|
||||||
# ===================================================================
|
# ===================================================================
|
||||||
# Caddy
|
# Caddy
|
||||||
# ===================================================================
|
# ===================================================================
|
||||||
|
|
@ -518,6 +583,7 @@ def main():
|
||||||
if not want_dashboard:
|
if not want_dashboard:
|
||||||
print()
|
print()
|
||||||
print(" Skipping dashboard setup.")
|
print(" Skipping dashboard setup.")
|
||||||
|
remove_dashboard_timer()
|
||||||
print()
|
print()
|
||||||
print("Done.")
|
print("Done.")
|
||||||
print(next_step)
|
print(next_step)
|
||||||
|
|
@ -543,6 +609,10 @@ def main():
|
||||||
setup_docker_compose(reuse_config=reuse_config)
|
setup_docker_compose(reuse_config=reuse_config)
|
||||||
create_dotfiles()
|
create_dotfiles()
|
||||||
|
|
||||||
|
# -- Dashboard timer -------------------------------------------
|
||||||
|
header("Dashboard Timer")
|
||||||
|
install_dashboard_timer()
|
||||||
|
|
||||||
# -- External access -------------------------------------------
|
# -- External access -------------------------------------------
|
||||||
header("External Access (optional)")
|
header("External Access (optional)")
|
||||||
ext_domain = _external_access_domain()
|
ext_domain = _external_access_domain()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue