diff --git a/pkg/openstack/loadbalancer.go b/pkg/openstack/loadbalancer.go index a753920018..feb72c0157 100644 --- a/pkg/openstack/loadbalancer.go +++ b/pkg/openstack/loadbalancer.go @@ -33,6 +33,7 @@ import ( "github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/loadbalancers" v2monitors "github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/monitors" v2pools "github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/pools" + "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/attributestags" "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/layer3/floatingips" "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets" corev1 "k8s.io/api/core/v1" @@ -618,6 +619,43 @@ func (lbaas *LbaasV2) updateFloatingIP(ctx context.Context, floatingip *floating return floatingip, nil } +func (lbaas *LbaasV2) updateFloatingIPTag(ctx context.Context, fip *floatingips.FloatingIP, Tag string, del bool) error { + if enabled, ok := lbaas.netExtensions["standard-attr-tag"]; !ok || !enabled { + return nil + } + if Tag == "" { + return fmt.Errorf("Error input tag argument ") + } + tags, err := attributestags.List(ctx, lbaas.network, "floatingips", fip.ID).Extract() + if err != nil { + klog.V(3).Infof("Cannot get floatIP tags for floating %s", fip.ID) + return err + } + + found := slices.Contains(tags, Tag) + + if (found && !del) || (!found && del) { + return nil + } + + if found && del { + err = attributestags.Delete(ctx, lbaas.network, "floatingips", fip.ID, Tag).ExtractErr() + if err != nil { + klog.V(2).ErrorS(err, "Cannot update floating IP tag %s for floating %s", Tag, fip.ID) + } + return err + } + + if !found && !del { + err = attributestags.Add(ctx, lbaas.network, "floatingips", fip.ID, Tag).ExtractErr() + if err != nil { + klog.V(2).ErrorS(err, "Cannot update floating IP tag %s for floating %s", Tag, fip.ID) + } + return err + } + return nil +} + // ensureFloatingIP manages a FIP for a Service and returns the address that should be advertised in the // .Status.LoadBalancer. In particular it will: // 1. Lookup if any FIP is already attached to the VIP port of the LB. @@ -663,6 +701,7 @@ func (lbaas *LbaasV2) ensureFloatingIP(ctx context.Context, clusterName string, if err != nil { return "", err } + _ = lbaas.updateFloatingIPTag(ctx, floatIP, svcConf.lbName, true) } } return lb.VipAddress, nil @@ -762,6 +801,7 @@ func (lbaas *LbaasV2) ensureFloatingIP(ctx context.Context, clusterName string, } if floatIP != nil { + _ = lbaas.updateFloatingIPTag(ctx, floatIP, svcConf.lbName, false) return floatIP.FloatingIP, nil } @@ -1760,6 +1800,13 @@ func (lbaas *LbaasV2) ensureOctaviaLoadBalancer(ctx context.Context, clusterName if err != nil { return nil, err } + extensions, err := openstackutil.GetNetworkExtensions(ctx, lbaas.network) + if err == nil { + klog.V(2).ErrorS(err, "cannot get network extensions") + lbaas.netExtensions = extensions + } else { + lbaas.netExtensions = map[string]bool{} + } klog.V(4).InfoS("Load balancer ensured", "lbID", loadbalancer.ID, "isLBOwner", isLBOwner, "createNewLB", createNewLB) diff --git a/pkg/openstack/openstack.go b/pkg/openstack/openstack.go index ef1a7bc57b..e0a14533c0 100644 --- a/pkg/openstack/openstack.go +++ b/pkg/openstack/openstack.go @@ -91,6 +91,7 @@ type LoadBalancer struct { opts LoadBalancerOpts kclient kubernetes.Interface eventRecorder record.EventRecorder + netExtensions map[string]bool } // LoadBalancerOpts have the options to talk to Neutron LBaaSV2 or Octavia @@ -375,7 +376,7 @@ func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) { klog.V(1).Info("Claiming to support LoadBalancer") - return &LbaasV2{LoadBalancer{secret, network, lb, os.lbOpts, os.kclient, os.eventRecorder}}, true + return &LbaasV2{LoadBalancer{secret, network, lb, os.lbOpts, os.kclient, os.eventRecorder, map[string]bool{}}}, true } // Zones indicates that we support zones