feat(topology): add compose generator and deployer integration

Adds per-topology compose generation (one Docker bridge network per
LAN, multi-homed bridge deckies, ip_forward sysctl for L3 forwarders)
plus async deploy_topology/teardown_topology in the engine. Leaf-first
teardown via BFS-named LAN reverse sort; partial-state safe on failure.
This commit is contained in:
2026-04-20 16:54:40 -04:00
parent 33f139ecfa
commit 2a030bf3a9
4 changed files with 394 additions and 0 deletions

View File

@@ -227,6 +227,60 @@ def remove_macvlan_network(client: docker.DockerClient) -> None:
n.remove()
# ---------------------------------------------------------------------------
# Plain Docker bridge networks (MazeNET topologies — one per LAN)
# ---------------------------------------------------------------------------
def create_bridge_network(
client: docker.DockerClient,
name: str,
subnet: str,
*,
internal: bool = False,
) -> str:
"""Create (or reuse) a plain Docker bridge network and return its id.
``internal=True`` blocks outbound routing via the host — used for
non-DMZ MazeNET LANs so deckies can only reach what the bridge
deckies let them reach.
"""
for net in client.networks.list(names=[name]):
pools = (net.attrs.get("IPAM") or {}).get("Config") or []
cur = pools[0] if pools else {}
if net.attrs.get("Driver") == "bridge" and cur.get("Subnet") == subnet:
return net.id
for cid in (net.attrs.get("Containers") or {}):
try:
net.disconnect(cid, force=True)
except docker.errors.APIError:
pass
net.remove()
net = client.networks.create(
name=name,
driver="bridge",
internal=internal,
ipam=docker.types.IPAMConfig(
driver="default",
pool_configs=[docker.types.IPAMPool(subnet=subnet)],
),
)
return net.id
def remove_bridge_network(client: docker.DockerClient, name: str) -> None:
for net in client.networks.list(names=[name]):
for cid in (net.attrs.get("Containers") or {}):
try:
net.disconnect(cid, force=True)
except docker.errors.APIError:
pass
try:
net.remove()
except docker.errors.APIError:
pass
# ---------------------------------------------------------------------------
# Host-side macvlan interface (hairpin fix)
# ---------------------------------------------------------------------------