sync: add cross-subsystem event bus for config consistency
Add EventBus with loop guards to keep firewall, dnsmasq, wireguard, and network configs consistent. Handlers emit SyncEvent after mutations; subscribers compute diffs and write JSON without manual cascade loops.
This commit is contained in:
@@ -25,6 +25,7 @@ from daemon.iface import (
|
||||
)
|
||||
from daemon.server import NotFoundError, refresh_state, registry
|
||||
from lib.common import deep_merge, load_json, run, run_proc, save_json
|
||||
from lib.sync import SyncEvent, bus
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -126,7 +127,10 @@ def save_config_handler(_request: Any, body: dict[str, Any] | None) -> dict[str,
|
||||
if current_key:
|
||||
body.setdefault("interface", {})["private_key"] = current_key
|
||||
_save_config(body)
|
||||
refresh_state(["wireguard"])
|
||||
sync_result = bus.emit(
|
||||
SyncEvent("wireguard", "config_saved", {"action": "config_saved"})
|
||||
)
|
||||
refresh_state(["wireguard", *sync_result.affected_subsystems])
|
||||
return {"config_saved": True}
|
||||
|
||||
|
||||
@@ -146,7 +150,10 @@ def patch_config(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
|
||||
current = _get_config()
|
||||
merged = deep_merge(current, body)
|
||||
_save_config(merged)
|
||||
refresh_state(["wireguard"])
|
||||
sync_result = bus.emit(
|
||||
SyncEvent("wireguard", "config_saved", {"action": "config_patched"})
|
||||
)
|
||||
refresh_state(["wireguard", *sync_result.affected_subsystems])
|
||||
return {"config_saved": True}
|
||||
|
||||
|
||||
@@ -167,8 +174,11 @@ def apply(_request: Any, _body: Any) -> dict[str, Any]:
|
||||
local_tmp.unlink(missing_ok=True)
|
||||
run([WG_QUICK_BIN, "up", cfg["interface"]["name"]], sudo=True)
|
||||
logger.info("WireGuard tunnel '%s' brought up", cfg["interface"]["name"])
|
||||
refresh_state(["wireguard"])
|
||||
return {"applied": True}
|
||||
sync_result = bus.emit(
|
||||
SyncEvent("wireguard", "config_saved", {"action": "config_applied"})
|
||||
)
|
||||
refresh_state(["wireguard", *sync_result.affected_subsystems])
|
||||
return {"applied": True, "synced": sync_result.affected_subsystems}
|
||||
|
||||
|
||||
@registry.register(POST_WIREGUARD_DOWN)
|
||||
@@ -178,7 +188,10 @@ def down(_request: Any, _body: Any) -> dict[str, Any]:
|
||||
name = cfg["interface"]["name"]
|
||||
run([WG_QUICK_BIN, "down", name], sudo=True)
|
||||
logger.info("WireGuard tunnel '%s' brought down", name)
|
||||
refresh_state(["wireguard"])
|
||||
sync_result = bus.emit(
|
||||
SyncEvent("wireguard", "config_saved", {"action": "tunnel_down"})
|
||||
)
|
||||
refresh_state(["wireguard", *sync_result.affected_subsystems])
|
||||
return {"down": True}
|
||||
|
||||
|
||||
@@ -205,7 +218,10 @@ def initialize(_request: Any, _body: Any) -> dict[str, Any]:
|
||||
cfg["interface"]["public_key"] = public_key
|
||||
_save_config(cfg)
|
||||
logger.info("WireGuard initialised (pubkey=%s...)", public_key[:16])
|
||||
refresh_state(["wireguard"])
|
||||
sync_result = bus.emit(
|
||||
SyncEvent("wireguard", "config_saved", {"action": "initialized"})
|
||||
)
|
||||
refresh_state(["wireguard", *sync_result.affected_subsystems])
|
||||
safe = dict(cfg)
|
||||
safe["interface"] = dict(safe["interface"])
|
||||
safe["interface"].pop("private_key", None)
|
||||
@@ -235,6 +251,7 @@ def add_peer(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
|
||||
if body.get("preshared_key") is not None:
|
||||
peer["preshared_key"] = body["preshared_key"]
|
||||
logger.info("WireGuard peer '%s' updated", name)
|
||||
_peer_action = "peer_updated"
|
||||
else:
|
||||
res = run_proc([WG_BIN, "genkey"], sudo=True)
|
||||
priv = res.stdout.strip()
|
||||
@@ -249,8 +266,14 @@ def add_peer(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
|
||||
"preshared_key": body.get("preshared_key"),
|
||||
}
|
||||
logger.info("WireGuard peer '%s' added", name)
|
||||
_peer_action = "peer_added"
|
||||
_save_config(cfg)
|
||||
refresh_state(["wireguard"])
|
||||
sync_result = bus.emit(
|
||||
SyncEvent(
|
||||
"wireguard", "config_saved", {"action": _peer_action, "peer_name": name}
|
||||
)
|
||||
)
|
||||
refresh_state(["wireguard", *sync_result.affected_subsystems])
|
||||
peer_out = dict(peers[name])
|
||||
peer_out.pop("private_key", None)
|
||||
return peer_out
|
||||
@@ -276,7 +299,12 @@ def remove_peer(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
|
||||
del peers[name]
|
||||
_save_config(cfg)
|
||||
logger.info("WireGuard peer '%s' removed", name)
|
||||
refresh_state(["wireguard"])
|
||||
sync_result = bus.emit(
|
||||
SyncEvent(
|
||||
"wireguard", "config_saved", {"action": "peer_removed", "peer_name": name}
|
||||
)
|
||||
)
|
||||
refresh_state(["wireguard", *sync_result.affected_subsystems])
|
||||
return {"name": name}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user