diff --git a/spinifex/daemon/vm_adapters.go b/spinifex/daemon/vm_adapters.go index 6c5eca68c..5596ac5b6 100644 --- a/spinifex/daemon/vm_adapters.go +++ b/spinifex/daemon/vm_adapters.go @@ -412,6 +412,29 @@ func (d *Daemon) onInstanceUpHook() func(*vm.VM) error { } } } + + // Republish vpc.add-nat so vpcd re-establishes the dnat_and_snat + // rule on host-reboot recovery. The OVN NB entry doesn't always + // survive the reboot, and vpcd's reconcile loop only re-creates + // EIP-allocated NATs (reconcile.go:391) — direct-add NATs from + // LaunchInstance / LaunchSystemInstance are otherwise unrecoverable. + // Idempotent: vpcd's handler deletes-then-adds (topology.go:1297), + // so this is a no-op on fresh launches where the initial publish + // already fired. + if d.natsConn != nil && instance.PublicIP != "" && instance.ENIId != "" && instance.Instance != nil { + vpcID := "" + privateIP := "" + if instance.Instance.VpcId != nil { + vpcID = *instance.Instance.VpcId + } + if instance.Instance.PrivateIpAddress != nil { + privateIP = *instance.Instance.PrivateIpAddress + } + if vpcID != "" && privateIP != "" { + portName := "port-" + instance.ENIId + utils.PublishNATEvent(d.natsConn, "vpc.add-nat", vpcID, instance.PublicIP, privateIP, portName, instance.ENIMac) + } + } return nil } }