libnet/cnmallocator: don't fail OnGetNetwork if unallocated - #53325
Conversation
OnGetNetwork errored when the network was absent from the allocator's map of allocated networks, which its own interface contract forbids: // The network may not have been allocated at the time of the call. // Calling OnGetNetwork with an unallocated network should not be an // error. That state is not hypothetical. A network is in the store but unallocated whenever the allocator has yet to restore it - allocateNetworks() skips networks with no driver state or IPAM during init, so as not to hand out resources another network already holds - and whenever its allocation failed, which only logs and parks the network for a later retry. The consequence reached well past the one network. Cluster.GetNetworks requests every Swarm network with no filters, deliberately: the Engine API's filter semantics are richer than swarmkit's, so the matching has to happen client-side. Swarmkit runs the hook per network over that unfiltered listing, so one unallocated network failed the whole response. The network inspect route falls back to that listing to resolve a name and reports a failed lookup as "no such network", which made inspecting a perfectly healthy Swarm network by name 404 because an unrelated network could not report status. Report no status instead. An absent Status is already how "no status available" is expressed - it is what a manager whose IPAM driver does not implement PoolStatuser returns - and the unallocated condition stays visible in what the allocator never filled in: an empty IPAM config and no VNI. Only requests which ask for status reach the hook, so this was limited to API v1.52 and later. Listing networks was unaffected either way; it does not request status. Signed-off-by: Cory Snider <csnider@mirantis.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
50c46fa to
1b7bdd0
Compare
Haven't looked what filters would be relevant here, but is that something that could be added to swarmkit? Would it be useful / improve performance? @corhere |
It would improve performance on a cluster with a large number of networks when the Engine API request is received on a non-leader manager as the whole unfiltered Swarmkit API response has to traverse the network. But it's still just |
Good question; not sure; mostly considering if it's easy / not much work to add a filter, it could simplify things? |
Summary
cnmNetworkAllocator.OnGetNetworkreturned an error when the network was not in the allocator's map of allocated networks. Its own interface contract forbids that:A network is in the store but unallocated in two ordinary situations:
allocateNetworks()deliberately skips networks with no driver state or IPAM during manager init, so as not to hand out resources another network already holds.allocateNetwork()parks the network inunallocatedNetworksfor a later retry anddoNetworkAlloc()only logsFailed allocation for network %s. A VNI collision gets you here: pin acom.docker.network.driver.overlay.vxlanid_listthat another network already holds and the overlay manager returnscould not assign vxlan id. Allocation happens after the spec is committed to Raft, sonetwork createhas already returned success.The consequence reached well past the one network.
Cluster.GetNetworksrequests every Swarm network with no filters, deliberately — the Engine API's filter semantics are richer than swarmkit's, so the matching has to happen client-side — and swarmkit runs the hook per network over that unfiltered listing. One unallocated network therefore failed the whole response. Thenetwork inspectroute falls back to that listing to resolve a name and reports a failed lookup asErrNoSuchNetwork, so:...for a network that is perfectly healthy, because an unrelated one could not report status.
Report no status instead. An absent
Statusis already how "no status available" is expressed — it is what a manager whose IPAM driver does not implementPoolStatuserreturns — and the unallocated condition stays visible in what the allocator never filled in: an empty IPAM config and no VNI echoed back.Scope
Only requests that ask for status reach the hook, so this affected API v1.52 and later only. Within that, the reachable paths are:
network inspect <name>, no scope filternetwork inspect <unallocated>network inspect <full-id>/--scope=swarmnetwork lsTesting
TestOnGetNetworkUnallocatedcovers the contract directly, withTestOnGetNetworkAllocatedas a positive control so it cannot pass by status reporting having stopped working altogether.Release notes (optional)
A picture of a cute animal (not mandatory but encouraged)
Created with: Claude Opus 5