WireGuard access classes, firewall nftables fixes, network sync event refactor

- WireGuard: refactor to multi-interface 'access classes' model; extract config
  generation and helpers into lib/wireguard.py; add per-class up/down endpoints
  and API routes; update UI with class management pages and QR code component
- Firewall: fix zone creation with --new-zone before --set-target; skip
  masquerade on public zone; add masquerade propagation for nftables backend
  so NAT works when internal zones exit via public
- Network: rename sync event subsystem 'network' -> 'networkd'; always stamp
  config hash even when deployment fails (fixes pending-changes detection)
- DHCP: add new API endpoint and update frontend page
- State/Sync: update state collectors and sync buses for new subsystems
- Docs: update API and config documentation for new endpoints and schemas
This commit is contained in:
2026-07-20 03:57:16 +00:00
parent dadabd7954
commit 04417cf05c
19 changed files with 2688 additions and 455 deletions
+16
View File
@@ -160,10 +160,14 @@ class TestApplyAll:
}
)
runtime_dir = tmp_network / "run" / "vacuum-wall"
runtime_dir.mkdir(parents=True)
with (
patch("daemon.handlers.network.generate_network_files") as mock_gen,
patch("daemon.handlers.network.run") as mock_run,
patch("daemon.handlers.network.collect_upstream_dns", return_value=[]),
patch("daemon.handlers.network.RUNTIME_DIR", runtime_dir),
):
mock_gen.return_value = {
"generated": [_net.DATA_DIR / "99-eth0.network"],
@@ -188,11 +192,15 @@ class TestApplyAll:
}
)
runtime_dir = tmp_network / "run" / "vacuum-wall"
runtime_dir.mkdir(parents=True)
with (
patch("daemon.handlers.network.generate_network_files") as mock_gen,
patch("daemon.handlers.network.run") as mock_run,
patch("daemon.handlers.network.set_upstreams") as mock_set_upstreams,
patch("daemon.handlers.network.collect_upstream_dns") as mock_collect,
patch("daemon.handlers.network.RUNTIME_DIR", runtime_dir),
):
mock_gen.return_value = {
"generated": [_net.DATA_DIR / "99-eth0.network"],
@@ -208,6 +216,9 @@ class TestApplyAll:
def test_apply_all_handles_dns_sync_failure(self, tmp_network):
_net.save_config({"interfaces": {"eth0": {"dns": ["8.8.8.8"]}}})
runtime_dir = tmp_network / "run" / "vacuum-wall"
runtime_dir.mkdir(parents=True)
with (
patch("daemon.handlers.network.generate_network_files") as mock_gen,
patch("daemon.handlers.network.run") as mock_run,
@@ -216,6 +227,7 @@ class TestApplyAll:
side_effect=RuntimeError("fail"),
),
patch("daemon.handlers.network.collect_upstream_dns") as mock_collect,
patch("daemon.handlers.network.RUNTIME_DIR", runtime_dir),
):
mock_gen.return_value = {
"generated": [_net.DATA_DIR / "99-eth0.network"],
@@ -233,10 +245,14 @@ class TestApplyAll:
sys_dir.mkdir(parents=True)
(sys_dir / "stale-file.network").write_text("[Match]\nName=old\n")
runtime_dir = tmp_network / "run" / "vacuum-wall"
runtime_dir.mkdir(parents=True)
with (
patch("daemon.handlers.network.generate_network_files") as mock_gen,
patch("daemon.handlers.network.run") as mock_run,
patch("daemon.handlers.network.collect_upstream_dns", return_value=[]),
patch("daemon.handlers.network.RUNTIME_DIR", runtime_dir),
):
mock_gen.return_value = {
"generated": [_net.DATA_DIR / "99-eth0.network"],