Skip to content

Commit 28cccb9

Browse files
authored
Merge pull request #2122 from shiftstack/lb
🐛 Wait and requeue if LB not deleted
2 parents 218212a + 7ef114b commit 28cccb9

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)