feat(enroll): opt-in IPvlan per-agent for Wi-Fi-bridged VMs

Wi-Fi APs bind one MAC per associated station, so VirtualBox/VMware
guests bridged over Wi-Fi rotate the VM's DHCP lease when Docker's
macvlan starts emitting container-MAC frames through the vNIC. Adds a
`use_ipvlan` toggle on the Agent Enrollment tab (mirrors the updater
daemon checkbox): flips the flag on SwarmHost, bakes `ipvlan=true` into
the agent's decnet.ini, and `_worker_config` forces ipvlan=True on the
per-host shard at dispatch. Safe no-op on wired/bare-metal agents.
This commit is contained in:
2026-04-19 17:57:45 -04:00
parent 6d7567b6bb
commit 5df995fda1
6 changed files with 109 additions and 6 deletions

View File

@@ -43,8 +43,18 @@ def _shard_by_host(config: DecnetConfig) -> dict[str, list[DeckyConfig]]:
return buckets
def _worker_config(base: DecnetConfig, shard: list[DeckyConfig]) -> DecnetConfig:
return base.model_copy(update={"deckies": shard})
def _worker_config(
base: DecnetConfig,
shard: list[DeckyConfig],
host: dict[str, Any],
) -> DecnetConfig:
updates: dict[str, Any] = {"deckies": shard}
# Per-host driver opt-in (Wi-Fi-bridged VMs can't use macvlan — see
# SwarmHost.use_ipvlan). Never downgrade: if the operator picked ipvlan
# at the deploy level, keep it regardless of the per-host flag.
if host.get("use_ipvlan"):
updates["ipvlan"] = True
return base.model_copy(update=updates)
async def dispatch_decnet_config(
@@ -69,7 +79,7 @@ async def dispatch_decnet_config(
async def _dispatch(host_uuid: str, shard: list[DeckyConfig]) -> SwarmHostResult:
host = hosts[host_uuid]
cfg = _worker_config(config, shard)
cfg = _worker_config(config, shard, host)
try:
async with AgentClient(host=host) as agent:
body = await agent.deploy(cfg, dry_run=dry_run, no_cache=no_cache)