Skip to content

Commit

Permalink
Delete sg rule which remote is the deleted sg
Browse files Browse the repository at this point in the history
Based on bug #2008712 if we have a security-group which
is the remote group of a 2nd security-group, the backend
never deletes the rule of the 2nd group which
remote_group_id is the original security-group.
By AFTER_DELETE event for each rule that has the
security_group_id as remote_group_id, we can make the
mech drivers do their work and delete these rules in the
backend.

One version of this fix was merged:
https://review.opendev.org/q/I207ecf7954b06507e03cb16b502ceb6e2807e0e7
and reverted due to #2019449:
https://review.opendev.org/q/I077fe87435f61bd29d5c1efc979c2adebca26181

This patch is based on
https://review.opendev.org/c/openstack/neutron/+/876716/1

Closes-Bug: #2008712
Related-Bug: #2019449
Change-Id: I9e8ddfa26c5402fefd573b0e2ea5f3a57983ca35
(cherry picked from commit 67a0b07)
  • Loading branch information
elajkat authored and katonalala committed Jul 4, 2023
1 parent b4f7c9d commit 4d09a6f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
7 changes: 7 additions & 0 deletions neutron/api/rpc/handlers/securitygroups_rpc.py
Expand Up @@ -303,6 +303,13 @@ def _clear_child_sg_rules(self, rtype, event, trigger, payload):
for rule in self.rcache.get_resources('SecurityGroupRule', filters):
self.rcache.record_resource_delete(context, 'SecurityGroupRule',
rule.id)
# If there's a rule which remote is the deleted sg, remove that also.
rules = self.rcache.match_resources_with_func(
'SecurityGroupRule',
lambda sg_rule: sg_rule.remote_group_id == existing.id)
for rule in rules:
self.rcache.record_resource_delete(context, 'SecurityGroupRule',
rule.id)

def _handle_sg_rule_delete(self, rtype, event, trigger, payload):
existing = payload.states[0]
Expand Down
50 changes: 49 additions & 1 deletion neutron/tests/unit/api/rpc/handlers/test_securitygroups_rpc.py
Expand Up @@ -15,6 +15,7 @@
from unittest import mock

import netaddr
from neutron_lib.callbacks import events
from neutron_lib import context
from oslo_utils import uuidutils

Expand Down Expand Up @@ -120,13 +121,14 @@ def _make_address_group_ovo(self, *args, **kwargs):
return_value=False)
def _make_security_group_ovo(self, *args, **kwargs):
attrs = {'id': uuidutils.generate_uuid(), 'revision_number': 1}
r_group = kwargs.get('remote_group_id') or attrs['id']
sg_rule = securitygroup.SecurityGroupRule(
id=uuidutils.generate_uuid(),
security_group_id=attrs['id'],
direction='ingress',
ethertype='IPv4', protocol='tcp',
port_range_min=400,
remote_group_id=attrs['id'],
remote_group_id=r_group,
revision_number=1,
remote_address_group_id=kwargs.get('remote_address_group_id',
None),
Expand Down Expand Up @@ -198,6 +200,52 @@ def test_sg_member_update_events(self):
self.sg_agent.security_groups_member_updated.assert_called_with(
{s1.id})

def test_sg_delete_events_with_remote(self):
s1 = self._make_security_group_ovo(remote_group_id='')
s2 = self._make_security_group_ovo(remote_group_id=s1.id)
rules = self.rcache.get_resources(
'SecurityGroupRule',
filters={'security_group_id': (s1.id, s2.id)})
self.assertEqual(2, len(rules))
self.assertEqual(s1.id, rules[0].remote_group_id)

self.shim._clear_child_sg_rules(
'SecurityGroup', 'after_delete', '',
events.DBEventPayload(
context=self.ctx,
states=[s1]
)
)
rules = self.rcache.get_resources(
'SecurityGroupRule',
filters={'security_group_id': (s1.id, s2.id)})
self.assertEqual(0, len(rules))

def test_sg_delete_events_without_remote(self):
s1 = self._make_security_group_ovo()
s2 = self._make_security_group_ovo()
rules = self.rcache.get_resources(
'SecurityGroupRule',
filters={'security_group_id': (s1.id, s2.id)})
self.assertEqual(2, len(rules))
self.assertEqual(s1.id, rules[0].remote_group_id)

self.shim._clear_child_sg_rules(
'SecurityGroup', 'after_delete', '',
events.DBEventPayload(
context=self.ctx,
states=[s1]
)
)
s1_rules = self.rcache.get_resources(
'SecurityGroupRule',
filters={'security_group_id': (s1.id, )})
self.assertEqual(0, len(s1_rules))
s2_rules = self.rcache.get_resources(
'SecurityGroupRule',
filters={'security_group_id': (s2.id, )})
self.assertEqual(1, len(s2_rules))

def test_get_secgroup_ids_for_address_group(self):
ag = self._make_address_group_ovo()
sg1 = self._make_security_group_ovo(remote_address_group_id=ag.id)
Expand Down

0 comments on commit 4d09a6f

Please sign in to comment.