@@ -31,6 +31,7 @@ import (
31
31
"k8s.io/apimachinery/pkg/util/wait"
32
32
utilsnet "k8s.io/utils/net"
33
33
"k8s.io/utils/ptr"
34
+ ctrl "sigs.k8s.io/controller-runtime"
34
35
35
36
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
36
37
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
@@ -41,12 +42,16 @@ import (
41
42
)
42
43
43
44
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
47
49
)
48
50
49
- const loadBalancerProvisioningStatusActive = "ACTIVE"
51
+ const (
52
+ loadBalancerProvisioningStatusActive = "ACTIVE"
53
+ loadBalancerProvisioningStatusPendingDelete = "PENDING_DELETE"
54
+ )
50
55
51
56
// We wrap the LookupHost function in a variable to allow overriding it in unit tests.
52
57
//
@@ -658,32 +663,40 @@ func (s *Service) ReconcileLoadBalancerMember(openStackCluster *infrav1.OpenStac
658
663
return nil
659
664
}
660
665
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 ) {
662
667
loadBalancerName := getLoadBalancerName (clusterResourceName )
663
668
lb , err := s .checkIfLbExists (loadBalancerName )
664
669
if err != nil {
665
- return err
670
+ return nil , err
666
671
}
667
672
668
673
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
670
683
}
671
684
672
685
if lb .VipPortID != "" {
673
686
fip , err := s .networkingService .GetFloatingIPByPortID (lb .VipPortID )
674
687
if err != nil {
675
- return err
688
+ return nil , err
676
689
}
677
690
678
691
if fip != nil && fip .FloatingIP != "" {
679
692
if err = s .networkingService .DisassociateFloatingIP (openStackCluster , fip .FloatingIP ); err != nil {
680
- return err
693
+ return nil , err
681
694
}
682
695
683
696
// If the floating is user-provider (BYO floating IP), don't delete it.
684
697
if openStackCluster .Spec .APIServerFloatingIP == nil || * openStackCluster .Spec .APIServerFloatingIP != fip .FloatingIP {
685
698
if err = s .networkingService .DeleteFloatingIP (openStackCluster , fip .FloatingIP ); err != nil {
686
- return err
699
+ return nil , err
687
700
}
688
701
} else {
689
702
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,
698
711
err = s .loadbalancerClient .DeleteLoadBalancer (lb .ID , deleteOpts )
699
712
if err != nil && ! capoerrors .IsNotFound (err ) {
700
713
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
702
715
}
703
716
704
717
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
706
722
}
707
723
708
724
func (s * Service ) DeleteLoadBalancerMember (openStackCluster * infrav1.OpenStackCluster , openStackMachine * infrav1.OpenStackMachine , clusterResourceName string ) error {
0 commit comments