From a155ae74c33db8998237eb5b24c44f5f8a574511 Mon Sep 17 00:00:00 2001 From: zhagenguth Date: Wed, 20 Dec 2023 11:11:43 +0100 Subject: [PATCH] Anexia Provider: Add field `IPProvisioningExpires` to status Adds field to check if a IP reservation is still valid, if the IP is no longer valid a new one is requested. This fixes a bug where we use an IP that expired already for a VM, if the VM provisioning failed, which then leads to a race condition. In which we wait for the VM provisioning to finish, but it can't due the IP being no longer useable, but we also never request a new IP in that case. Signed-off-by: Zofia hagenguth --- pkg/cloudprovider/provider/anexia/provider.go | 3 ++- .../provider/anexia/provider_test.go | 1 + .../provider/anexia/types/types.go | 23 ++++++++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pkg/cloudprovider/provider/anexia/provider.go b/pkg/cloudprovider/provider/anexia/provider.go index b036d9149..75fffa230 100644 --- a/pkg/cloudprovider/provider/anexia/provider.go +++ b/pkg/cloudprovider/provider/anexia/provider.go @@ -214,7 +214,7 @@ func getIPAddress(ctx context.Context, client anxclient.Client) (string, error) status := reconcileContext.Status // only use IP if it is still unbound - if status.ReservedIP != "" && status.IPState == anxtypes.IPStateUnbound { + if status.ReservedIP != "" && status.IPState == anxtypes.IPStateUnbound && (!status.IPProvisioningExpires.IsZero() && status.IPProvisioningExpires.After(time.Now())) { klog.Infof("reusing already provisioned ip %q", status.ReservedIP) return status.ReservedIP, nil } @@ -240,6 +240,7 @@ func getIPAddress(ctx context.Context, client anxclient.Client) (string, error) ip := res.Data[0].Address status.ReservedIP = ip status.IPState = anxtypes.IPStateUnbound + status.IPProvisioningExpires = time.Now().Add(anxtypes.IPProvisioningExpires) return ip, nil } diff --git a/pkg/cloudprovider/provider/anexia/provider_test.go b/pkg/cloudprovider/provider/anexia/provider_test.go index 4bda59f26..b87a9a6b7 100644 --- a/pkg/cloudprovider/provider/anexia/provider_test.go +++ b/pkg/cloudprovider/provider/anexia/provider_test.go @@ -270,6 +270,7 @@ func TestAnexiaProvider(t *testing.T) { expectedIP := "8.8.8.8" providerStatus.ReservedIP = expectedIP providerStatus.IPState = anxtypes.IPStateUnbound + providerStatus.IPProvisioningExpires = time.Now().Add(anxtypes.IPProvisioningExpires) reservedIP, err := getIPAddress(ctx, client) testhelper.AssertNoErr(t, err) testhelper.AssertEquals(t, expectedIP, reservedIP) diff --git a/pkg/cloudprovider/provider/anexia/types/types.go b/pkg/cloudprovider/provider/anexia/types/types.go index e6d8e9f22..c0564a48f 100644 --- a/pkg/cloudprovider/provider/anexia/types/types.go +++ b/pkg/cloudprovider/provider/anexia/types/types.go @@ -34,11 +34,11 @@ const ( GetRequestTimeout = 1 * time.Minute DeleteRequestTimeout = 1 * time.Minute - IPStateBound = "Bound" - IPStateUnbound = "Unbound" - - VmxNet3NIC = "vmxnet3" - MachinePoweredOn = "poweredOn" + IPStateBound = "Bound" + IPStateUnbound = "Unbound" + IPProvisioningExpires = 1800 * time.Second + VmxNet3NIC = "vmxnet3" + MachinePoweredOn = "poweredOn" ) var StatusUpdateFailed = cloudprovidererrors.TerminalError{ @@ -72,12 +72,13 @@ type RawConfig struct { } type ProviderStatus struct { - InstanceID string `json:"instanceID"` - ProvisioningID string `json:"provisioningID"` - DeprovisioningID string `json:"deprovisioningID"` - ReservedIP string `json:"reservedIP"` - IPState string `json:"ipState"` - Conditions []v1.Condition `json:"conditions,omitempty"` + InstanceID string `json:"instanceID"` + ProvisioningID string `json:"provisioningID"` + DeprovisioningID string `json:"deprovisioningID"` + ReservedIP string `json:"reservedIP"` + IPState string `json:"ipState"` + IPProvisioningExpires time.Time `json:"ipProvisioningExpires"` + Conditions []v1.Condition `json:"conditions,omitempty"` } func GetConfig(pconfig providerconfigtypes.Config) (*RawConfig, error) {