From 4b17c5b77af9634f11e0f755cb846fda85a5c7d2 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Mon, 21 Oct 2024 11:18:14 -0400 Subject: [PATCH] Remove SGs from non-existent nodes ports on Update --- pkg/openstack/loadbalancer_sg.go | 76 ++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/pkg/openstack/loadbalancer_sg.go b/pkg/openstack/loadbalancer_sg.go index 875de31e32..ad3b9691ec 100644 --- a/pkg/openstack/loadbalancer_sg.go +++ b/pkg/openstack/loadbalancer_sg.go @@ -63,7 +63,7 @@ func applyNodeSecurityGroupIDForLB(network *gophercloud.ServiceClient, svcConf * continue } - listOpts := neutronports.ListOpts{DeviceID: serverID} + listOpts := neutronports.ListOpts{} allPorts, err := openstackutil.GetPorts[PortWithPortSecurity](network, listOpts) if err != nil { return err @@ -75,6 +75,23 @@ func applyNodeSecurityGroupIDForLB(network *gophercloud.ServiceClient, svcConf * continue } + if port.DeviceID != serverID { + sgFound := false + for _, portSG := range port.SecurityGroups { + if portSG == sg { + sgFound = true + break + } + } + if sgFound { + err := removeSecurityGroupFromPort(network, port.Port, sg) + if err != nil { + return err + } + continue + } + } + // If the Security Group is already present on the port, skip it. if slices.Contains(port.SecurityGroups, sg) { continue @@ -97,6 +114,7 @@ func applyNodeSecurityGroupIDForLB(network *gophercloud.ServiceClient, svcConf * return fmt.Errorf("failed to update security group for port %s: %v", port.ID, res.Err) } } + } return nil @@ -113,31 +131,41 @@ func disassociateSecurityGroupForLB(network *gophercloud.ServiceClient, sg strin // Disassocate security group and remove the tag. for _, port := range allPorts { - existingSGs := sets.NewString() - for _, sgID := range port.SecurityGroups { - existingSGs.Insert(sgID) - } - existingSGs.Delete(sg) - - // Update port security groups - newSGs := existingSGs.List() - // TODO(dulek): This should be done using Neutron's revision_number to make sure - // we don't trigger a lost update issue. - updateOpts := neutronports.UpdateOpts{SecurityGroups: &newSGs} - mc := metrics.NewMetricContext("port", "update") - res := neutronports.Update(context.TODO(), network, port.ID, updateOpts) - if mc.ObserveRequest(res.Err) != nil { - return fmt.Errorf("failed to update security group for port %s: %v", port.ID, res.Err) + err := removeSecurityGroupFromPort(network, port, sg) + if err != nil { + return err } + } - // Remove the security group ID tag from the port. Please note we don't tag ports with SG IDs anymore, - // so this stays for backward compatibility. It's reasonable to delete it in the future. 404s are ignored. - if slices.Contains(port.Tags, sg) { - mc = metrics.NewMetricContext("port_tag", "delete") - err := neutrontags.Delete(context.TODO(), network, "ports", port.ID, sg).ExtractErr() - if mc.ObserveRequest(err) != nil { - return fmt.Errorf("failed to remove tag %s to port %s: %v", sg, port.ID, res.Err) - } + return nil +} + +// removeSecurityGroupFromPort removes the given security group from the port +func removeSecurityGroupFromPort(network *gophercloud.ServiceClient, port neutronports.Port, sg string) error { + existingSGs := sets.NewString() + for _, sgID := range port.SecurityGroups { + existingSGs.Insert(sgID) + } + existingSGs.Delete(sg) + + // Update port security groups + newSGs := existingSGs.List() + // TODO(dulek): This should be done using Neutron's revision_number to make sure + // we don't trigger a lost update issue. + updateOpts := neutronports.UpdateOpts{SecurityGroups: &newSGs} + mc := metrics.NewMetricContext("port", "update") + res := neutronports.Update(context.TODO(), network, port.ID, updateOpts) + if mc.ObserveRequest(res.Err) != nil { + return fmt.Errorf("failed to update security group for port %s: %v", port.ID, res.Err) + } + + // Remove the security group ID tag from the port. Please note we don't tag ports with SG IDs anymore, + // so this stays for backward compatibility. It's reasonable to delete it in the future. 404s are ignored. + if slices.Contains(port.Tags, sg) { + mc = metrics.NewMetricContext("port_tag", "delete") + err := neutrontags.Delete(context.TODO(), network, "ports", port.ID, sg).ExtractErr() + if mc.ObserveRequest(err) != nil { + return fmt.Errorf("failed to remove tag %s to port %s: %v", sg, port.ID, res.Err) } }