Skip to content

vpc: release public IPs whose network went away while VPC firewall rules held them - #19

Open
calvix wants to merge 3 commits into
integration/all-fixes-4.23.0.0from
fix/vpc-network-delete-unbinds-ips-4.23
Open

calvix wants to merge 3 commits into
integration/all-fixes-4.23.0.0from
fix/vpc-network-delete-unbinds-ips-4.23

Conversation

@calvix

@calvix calvix commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Deleting a VPC fails with a NullPointerException after one of its networks has been deleted while a public IP of the VPC still had a firewall rule. Since 4.23 a VPC public IP can carry firewall rules that belong to the VPC rather than to a network (vpc_id set, network_id NULL). isIpAllocatedToVpc, which decides both whether a VPC IP stays associated with its network and whether it stays plugged on the router, counted those rules, so the IP stayed associated with a network that was then removed, and deleteVPC later passed a null network to applyIpAssociations.

Only static NAT and rules that belong to a network now keep a VPC IP in use; VPC firewall rules need neither the association nor the IP on the router, so the IP is unbound and unplugged together. unassignIPFromVpcNetwork decides under the IP's lock, so a rule being created on the IP cannot lose its network association to a concurrent removal of the IP's last rule. disassociatePublicIpAddress handles an IP that still points at a removed network: when its rules were cleaned up it releases the IP like an unassociated one, so VPCs already stuck in this state can be deleted, and otherwise keeps it out of the pool. Unit tests cover these cases.

…les held them

Since VPC public IPs can carry firewall rules (apache#12706), such a rule has a
VPC but no network. unassignIPFromVpcNetwork() kept a VPC IP bound to its
network while the IP had any firewall_rules row, and deleting the network
never revokes these rules, because they belong to no network. The IP then
stayed bound to the removed network. deleteVPC removed the firewall rule,
looked the network up, got null, and failed with a NullPointerException in
applyIpAssociations(), leaving the IP in Releasing and the VPC undeletable.

Repro: VPC offering with the Firewall service, one network, a VM, a public
IP with a port forwarding rule and a firewall rule; destroy the VM, delete
the network, delete the VPC.

- Only static NAT and rules that belong to a network keep a VPC IP bound to
  its network; VPC firewall rules are applied through the VPC.
  isIpAllocatedToVpc(), which also decides whether the IP stays plugged on
  the router, is unchanged.
- disassociatePublicIpAddress() releases an IP whose associated network was
  removed as an unassociated IP instead of applying IP associations on a
  null network, so VPCs already stuck this way can be deleted.
@github-actions

Copy link
Copy Markdown

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

…lace on the router

The previous change stopped VPC firewall rules from holding a VPC IP's network
association, but isIpAllocatedToVpc(), which decides whether the IP stays
plugged on the router, still counted them. An IP left with only such a rule
was then unbound but stayed on the router, and nothing would ever take it off,
since a rule without a network triggers no IP association. Both now follow the
same rule: only static NAT and rules of a network keep a VPC IP in use.

- unassignIPFromVpcNetwork() locks the IP and decides on its locked state, so
  a rule being created on the IP cannot lose its network association to a
  concurrent removal of the IP's last rule.
- disassociatePublicIpAddress() frees an IP still associated with a removed
  network only when its rules were cleaned up, so no rules stay behind on an
  IP that goes back to the pool.
A VPC IP leaves the router after its rules are applied only when all of
them are revoked (checkIfIpAssocRequired) and the IP is then used for no
purpose (getIpToServices). Both counted VPC firewall rules, so deleting the
last port forwarding or load balancing rule of an IP that also had a
firewall rule left the IP configured on the router, although it was no
longer associated with a network; nothing would ever remove it, as a rule
without a network triggers no IP association, and a later release would
free the IP while the router still answered for it.

For a VPC IP both now count only rules that belong to a network, like
isIpAllocatedToVpc(), so the IP leaves the router together with its network
association. Verified on a VPC router: with a port forwarding and a
firewall rule on an IP, deleting the port forwarding rule left the IP on
the router before, the same as an IP whose only rule is deleted after.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant