Skip to content

Commit 3b3b8eb

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "[OVN] Remove ACLs with remote SG during deletion of SG" into stable/yoga
2 parents 4966df1 + 0cccea3 commit 3b3b8eb

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ def subscribe(self):
254254
registry.subscribe(self._create_security_group,
255255
resources.SECURITY_GROUP,
256256
events.AFTER_CREATE)
257+
registry.subscribe(self._delete_security_group_precommit,
258+
resources.SECURITY_GROUP,
259+
events.PRECOMMIT_DELETE)
257260
registry.subscribe(self._delete_security_group,
258261
resources.SECURITY_GROUP,
259262
events.AFTER_DELETE)
@@ -424,6 +427,14 @@ def _create_security_group(self, resource, event, trigger, payload):
424427
self._ovn_client.create_security_group(context,
425428
security_group)
426429

430+
def _delete_security_group_precommit(self, resource, event, trigger,
431+
payload):
432+
context = n_context.get_admin_context()
433+
security_group_id = payload.resource_id
434+
for sg_rule in self._plugin.get_security_group_rules(
435+
context, filters={'remote_group_id': [security_group_id]}):
436+
self._ovn_client.delete_security_group_rule(context, sg_rule)
437+
427438
def _delete_security_group(self, resource, event, trigger, payload):
428439
context = payload.context
429440
security_group_id = payload.resource_id

neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,12 @@ def setUp(self):
784784
super(TestSecurityGroup, self).setUp()
785785
self._ovn_client = self.mech_driver._ovn_client
786786
self.plugin = self.mech_driver._plugin
787+
self.sg_data = {
788+
'name': 'testsg',
789+
'description': 'Test Security Group',
790+
'tenant_id': self._tenant_id,
791+
'is_default': True,
792+
}
787793

788794
def _find_acls_for_sg(self, sg_id):
789795
rows = self.nb_api.db_find_rows('ACL').execute(check_error=True)
@@ -800,28 +806,29 @@ def get_api_id(r):
800806
return [r for r in rows if get_api_id(r) in rule_ids]
801807
return []
802808

809+
def _find_acl_remote_sg(self, remote_sg_id):
810+
# NOTE: the ACL to be found has ethertype=IPv4 and protocol=ICMP.
811+
sg_match = '$pg_' + remote_sg_id.replace('-', '_') + '_ip4 && icmp4'
812+
for row in self.nb_api.db_find_rows('ACL').execute(check_error=True):
813+
if sg_match in row.match:
814+
return row
815+
803816
def test_sg_stateful_toggle_updates_ovn_acls(self):
804817
def check_acl_actions(sg_id, expected):
805818
self.assertEqual(
806819
{expected},
807820
set(a.action for a in self._find_acls_for_sg(sg_id))
808821
)
809822

810-
sg_data = {
811-
'name': 'testsg',
812-
'description': 'Test Security Group',
813-
'tenant_id': self._tenant_id,
814-
'is_default': True,
815-
}
816823
sg = self.plugin.create_security_group(
817-
self.context, security_group={'security_group': sg_data})
824+
self.context, security_group={'security_group': self.sg_data})
818825
check_acl_actions(sg['id'], 'allow-related')
819826

820827
def update_sg(stateful):
821-
sg_data['stateful'] = stateful
828+
self.sg_data['stateful'] = stateful
822829
self.plugin.update_security_group(
823830
self.context, sg['id'],
824-
security_group={'security_group': sg_data})
831+
security_group={'security_group': self.sg_data})
825832

826833
update_sg(False)
827834
check_acl_actions(sg['id'], 'allow-stateless')
@@ -832,6 +839,35 @@ def update_sg(stateful):
832839
update_sg(False)
833840
check_acl_actions(sg['id'], 'allow-stateless')
834841

842+
def test_remove_sg_with_related_rule_remote_sg(self):
843+
self.sg_data['is_default'] = False
844+
sg1 = self.plugin.create_security_group(
845+
self.context, security_group={'security_group': self.sg_data})
846+
sg2 = self.plugin.create_security_group(
847+
self.context, security_group={'security_group': self.sg_data})
848+
rule_data = {'direction': constants.INGRESS_DIRECTION,
849+
'ethertype': constants.IPv4,
850+
'protocol': constants.PROTO_NAME_ICMP,
851+
'port_range_max': None,
852+
'port_range_min': None,
853+
'remote_ip_prefix': None,
854+
'tenant_id': sg1['project_id'],
855+
'remote_address_group_id': None,
856+
'security_group_id': sg1['id'],
857+
'remote_group_id': sg2['id']}
858+
sg_rule = {'security_group_rule': rule_data}
859+
rule = self.plugin.create_security_group_rule(self.context, sg_rule)
860+
acl = self._find_acl_remote_sg(sg2['id'])
861+
self.assertEqual(rule['id'],
862+
acl.external_ids[ovn_const.OVN_SG_RULE_EXT_ID_KEY])
863+
acls = self._find_acls_for_sg(sg1['id'])
864+
self.assertEqual(3, len(acls))
865+
866+
self.plugin.delete_security_group(self.context, sg2['id'])
867+
self.assertIsNone(self._find_acl_remote_sg(sg2['id']))
868+
acls = self._find_acls_for_sg(sg1['id'])
869+
self.assertEqual(2, len(acls))
870+
835871

836872
class TestProvnetPorts(base.TestOVNFunctionalBase):
837873

0 commit comments

Comments
 (0)