Skip to content

Commit 7ef114b

Browse files
committed
Wait and requeue if LB is in PENDING_DELETE
If the LB that is being deleted when a cluster is deleted, it'll go through the PENDING_DELETE state and at this stage there is nothing we can do but wait for the LB to be actually deleted. If the LB is in that state during the deletion, let's just return no error but request a reconcile after some time.
1 parent 218212a commit 7ef114b

File tree

2 files changed

+35
-14
lines changed

2 files changed

+35
-14
lines changed

controllers/openstackcluster_controller.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ import (
5959
)
6060

6161
const (
62-
waitForBastionToReconcile = 15 * time.Second
62+
waitForBastionToReconcile = 15 * time.Second
63+
waitForOctaviaPortsCleanup = 15 * time.Second
6364
)
6465

6566
// OpenStackClusterReconciler reconciles a OpenStackCluster object.
@@ -183,10 +184,14 @@ func (r *OpenStackClusterReconciler) reconcileDelete(ctx context.Context, scope
183184
return reconcile.Result{}, err
184185
}
185186

186-
if err = loadBalancerService.DeleteLoadBalancer(openStackCluster, clusterResourceName); err != nil {
187+
result, err := loadBalancerService.DeleteLoadBalancer(openStackCluster, clusterResourceName)
188+
if err != nil {
187189
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to delete load balancer: %w", err), false)
188190
return reconcile.Result{}, fmt.Errorf("failed to delete load balancer: %w", err)
189191
}
192+
if result != nil {
193+
return *result, nil
194+
}
190195
}
191196

192197
// if ManagedSubnets was not set, no network was created.

pkg/cloud/services/loadbalancer/loadbalancer.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"k8s.io/apimachinery/pkg/util/wait"
3232
utilsnet "k8s.io/utils/net"
3333
"k8s.io/utils/ptr"
34+
ctrl "sigs.k8s.io/controller-runtime"
3435

3536
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
3637
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -41,12 +42,16 @@ import (
4142
)
4243

4344
const (
44-
networkPrefix string = "k8s-clusterapi"
45-
kubeapiLBSuffix string = "kubeapi"
46-
resolvedMsg string = "ControlPlaneEndpoint.Host is not an IP address, using the first resolved IP address"
45+
networkPrefix string = "k8s-clusterapi"
46+
kubeapiLBSuffix string = "kubeapi"
47+
resolvedMsg string = "ControlPlaneEndpoint.Host is not an IP address, using the first resolved IP address"
48+
waitForOctaviaLBCleanup = 15 * time.Second
4749
)
4850

49-
const loadBalancerProvisioningStatusActive = "ACTIVE"
51+
const (
52+
loadBalancerProvisioningStatusActive = "ACTIVE"
53+
loadBalancerProvisioningStatusPendingDelete = "PENDING_DELETE"
54+
)
5055

5156
// We wrap the LookupHost function in a variable to allow overriding it in unit tests.
5257
//
@@ -658,32 +663,40 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
658663
return nil
659664
}
660665

661-
func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
666+
func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) (result *ctrl.Result, reterr error) {
662667
loadBalancerName := getLoadBalancerName(clusterResourceName)
663668
lb, err := s.checkIfLbExists(loadBalancerName)
664669
if err != nil {
665-
return err
670+
return nil, err
666671
}
667672

668673
if lb == nil {
669-
return nil
674+
return nil, nil
675+
}
676+
677+
// If the load balancer is already in PENDING_DELETE state, we don't need to do anything.
678+
// However we should still wait for the load balancer to be deleted which is why we
679+
// request a new reconcile after a certain amount of time.
680+
if lb.ProvisioningStatus == loadBalancerProvisioningStatusPendingDelete {
681+
s.scope.Logger().Info("Load balancer is already in PENDING_DELETE state", "name", loadBalancerName)
682+
return &ctrl.Result{RequeueAfter: waitForOctaviaLBCleanup}, nil
670683
}
671684

672685
if lb.VipPortID != "" {
673686
fip, err := s.networkingService.GetFloatingIPByPortID(lb.VipPortID)
674687
if err != nil {
675-
return err
688+
return nil, err
676689
}
677690

678691
if fip != nil && fip.FloatingIP != "" {
679692
if err = s.networkingService.DisassociateFloatingIP(openStackCluster, fip.FloatingIP); err != nil {
680-
return err
693+
return nil, err
681694
}
682695

683696
// If the floating is user-provider (BYO floating IP), don't delete it.
684697
if openStackCluster.Spec.APIServerFloatingIP == nil || *openStackCluster.Spec.APIServerFloatingIP != fip.FloatingIP {
685698
if err = s.networkingService.DeleteFloatingIP(openStackCluster, fip.FloatingIP); err != nil {
686-
return err
699+
return nil, err
687700
}
688701
} else {
689702
s.scope.Logger().Info("Skipping load balancer floating IP deletion as it's a user-provided resource", "name", loadBalancerName, "fip", fip.FloatingIP)
@@ -698,11 +711,14 @@ func (s *Service) DeleteLoadBalancer(openStackCluster *infrav1.OpenStackCluster,
698711
err = s.loadbalancerClient.DeleteLoadBalancer(lb.ID, deleteOpts)
699712
if err != nil && !capoerrors.IsNotFound(err) {
700713
record.Warnf(openStackCluster, "FailedDeleteLoadBalancer", "Failed to delete load balancer %s with id %s: %v", lb.Name, lb.ID, err)
701-
return err
714+
return nil, err
702715
}
703716

704717
record.Eventf(openStackCluster, "SuccessfulDeleteLoadBalancer", "Deleted load balancer %s with id %s", lb.Name, lb.ID)
705-
return nil
718+
719+
// If we have reached this point, that means that the load balancer wasn't initially deleted but the request to delete it didn't return an error.
720+
// So we want to requeue until the load balancer and its associated ports are actually deleted.
721+
return &ctrl.Result{RequeueAfter: waitForOctaviaLBCleanup}, nil
706722
}
707723

708724
func (s *Service) DeleteLoadBalancerMember(openStackCluster *infrav1.OpenStackCluster, openStackMachine *infrav1.OpenStackMachine, clusterResourceName string) error {

0 commit comments

Comments
 (0)