ovn: Clean up code to handle old versions with no stateless acl support

It's reasonable to expect ovn 21.06+ used with master neutron.

Change-Id: I421d702f38d483e498bc65e968d40ed5fae4640e
This commit is contained in:
Ihar Hrachyshka 2024-08-30 13:52:47 -04:00
parent d10e469cea
commit 3abce4c6d8
7 changed files with 61 additions and 122 deletions

View File

@ -261,15 +261,12 @@ def _acl_columns_name_severity_supported(nb_idl):
return ('name' in columns) and ('severity' in columns)
def is_sg_stateful(sg, stateless_supported):
if stateless_supported:
return sg.get("stateful", True)
return True
def is_sg_stateful(sg):
return sg.get("stateful", True)
def add_acls_for_sg_port_group(ovn, security_group, txn,
stateless_supported=True):
stateful = is_sg_stateful(security_group, stateless_supported)
def add_acls_for_sg_port_group(ovn, security_group, txn):
stateful = is_sg_stateful(security_group)
for r in security_group['security_group_rules']:
acl = _add_sg_rule_acl_for_port_group(
utils.ovn_port_group_name(security_group['id']), stateful, r)
@ -281,8 +278,7 @@ def update_acls_for_security_group(plugin,
ovn,
security_group_id,
security_group_rule,
is_add_acl=True,
stateless_supported=True):
is_add_acl=True):
# Skip ACLs if security groups aren't enabled
if not is_sg_enabled():
@ -292,7 +288,7 @@ def update_acls_for_security_group(plugin,
keep_name_severity = _acl_columns_name_severity_supported(ovn)
sg = plugin.get_security_group(admin_context, security_group_id)
stateful = is_sg_stateful(sg, stateless_supported)
stateful = is_sg_stateful(sg)
acl = _add_sg_rule_acl_for_port_group(
utils.ovn_port_group_name(security_group_id),

View File

@ -194,15 +194,6 @@ ovn_opts = [
'provisioning over IPv6 this option should be set '
'to "True" and neutron-dhcp-agent should be used '
'instead. Defaults to "False".')),
cfg.BoolOpt('allow_stateless_action_supported',
default=True,
deprecated_for_removal=True,
deprecated_since="2023.1",
help=_('If OVN older than 21.06 is used together with '
'Neutron, this option should be set to ``False`` in '
'order to disable the ``stateful-security-group`` API '
'extension as ``allow-stateless`` keyword is only '
'supported by OVN >= 21.06.')),
cfg.BoolOpt('localnet_learn_fdb',
default=False,
help=_('If enabled it will allow localnet ports to learn MAC '

View File

@ -26,7 +26,6 @@ import uuid
from neutron_lib.api.definitions import portbindings
from neutron_lib.api.definitions import provider_net
from neutron_lib.api.definitions import segment as segment_def
from neutron_lib.api.definitions import stateful_security_group
from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
@ -230,10 +229,7 @@ class OVNMechanismDriver(api.MechanismDriver):
return portbindings.CONNECTIVITY_L2
def supported_extensions(self, extensions):
supported_extensions = set(ovn_extensions.ML2_SUPPORTED_API_EXTENSIONS)
if not cfg.CONF.ovn.allow_stateless_action_supported:
supported_extensions.discard(stateful_security_group.ALIAS)
return set(supported_extensions) & extensions
return set(ovn_extensions.ML2_SUPPORTED_API_EXTENSIONS) & extensions
@staticmethod
def provider_network_attribute_updates_supported():
@ -430,13 +426,8 @@ class OVNMechanismDriver(api.MechanismDriver):
security_group = payload.latest_state
old_state, new_state = payload.states
is_allow_stateless_supported = (
self._ovn_client.is_allow_stateless_supported()
)
old_stateful = ovn_acl.is_sg_stateful(
old_state, is_allow_stateless_supported)
new_stateful = ovn_acl.is_sg_stateful(
new_state, is_allow_stateless_supported)
old_stateful = ovn_acl.is_sg_stateful(old_state)
new_stateful = ovn_acl.is_sg_stateful(new_state)
if old_stateful != new_stateful:
for rule in self._plugin.get_security_group_rules(
context, {'security_group_id': [security_group['id']]}):

View File

@ -142,11 +142,6 @@ class OVNClient(object):
return self._nb_idl.is_col_present(
'Logical_Switch_Port', 'ha_chassis_group')
# TODO(ihrachys) remove when min OVN version >= 21.06
def is_allow_stateless_supported(self):
return self._nb_idl.is_col_supports_value('ACL', 'action',
'allow-stateless')
def _get_allowed_addresses_from_port(self, port):
if not port.get(psec.PORTSECURITY):
return [], []
@ -2539,8 +2534,7 @@ class OVNClient(object):
# When a SG is created, it comes with some default rules,
# so we'll apply them to the Port Group.
ovn_acl.add_acls_for_sg_port_group(
self._nb_idl, security_group, txn,
self.is_allow_stateless_supported())
self._nb_idl, security_group, txn)
db_rev.bump_revision(
context, security_group, ovn_const.TYPE_SECURITY_GROUPS)
@ -2565,8 +2559,7 @@ class OVNClient(object):
ovn_acl.update_acls_for_security_group(
self._plugin, admin_context, self._nb_idl,
rule['security_group_id'], rule,
is_add_acl=is_add_acl,
stateless_supported=self.is_allow_stateless_supported())
is_add_acl=is_add_acl)
def create_security_group_rule(self, context, rule):
self._process_security_group_rule(rule)

View File

@ -260,24 +260,17 @@ class OvnNbSynchronizer(OvnDbSynchronizer):
LOG.debug('OVN-NB Sync ACLs started @ %s', str(datetime.now()))
neutron_acls = []
# if allow-stateless supported, we have to fetch groups to determine if
# stateful is set
if self._ovn_client.is_allow_stateless_supported():
for sg in self.core_plugin.get_security_groups(ctx):
stateful = sg.get("stateful", True)
pg_name = utils.ovn_port_group_name(sg['id'])
for sgr in self.core_plugin.get_security_group_rules(
ctx, {'security_group_id': sg['id']}):
neutron_acls.append(
acl_utils._add_sg_rule_acl_for_port_group(
pg_name, stateful, sgr)
)
else:
# TODO(ihrachys) remove when min OVN version >= 21.06
for sgr in self.core_plugin.get_security_group_rules(ctx):
pg_name = utils.ovn_port_group_name(sgr['security_group_id'])
neutron_acls.append(acl_utils._add_sg_rule_acl_for_port_group(
pg_name, True, sgr))
# we have to fetch groups to determine if stateful is set
for sg in self.core_plugin.get_security_groups(ctx):
stateful = sg.get("stateful", True)
pg_name = utils.ovn_port_group_name(sg['id'])
for sgr in self.core_plugin.get_security_group_rules(
ctx, {'security_group_id': sg['id']}):
neutron_acls.append(
acl_utils._add_sg_rule_acl_for_port_group(
pg_name, stateful, sgr)
)
# Sort the acls in the Neutron database according to the security
# group rule ID for easy comparison in the future.
neutron_acls.sort(key=lambda x: x[ovn_const.OVN_SG_RULE_EXT_ID_KEY])

View File

@ -270,23 +270,19 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
self._test__validate_network_segments_id_succeed, 300)
@mock.patch.object(ovn_revision_numbers_db, 'bump_revision')
def _test__create_security_group(
self, stateful, stateless_supported, mock_bump):
def _test__create_security_group(self, stateful, mock_bump):
self.fake_sg["stateful"] = stateful
with mock.patch.object(self.mech_driver._ovn_client,
'is_allow_stateless_supported',
return_value=stateless_supported):
self.mech_driver._create_security_group(
resources.SECURITY_GROUP, events.AFTER_CREATE, {},
payload=events.DBEventPayload(
self.context, states=(self.fake_sg,)))
self.mech_driver._create_security_group(
resources.SECURITY_GROUP, events.AFTER_CREATE, {},
payload=events.DBEventPayload(
self.context, states=(self.fake_sg,)))
external_ids = {ovn_const.OVN_SG_EXT_ID_KEY: self.fake_sg['id']}
pg_name = ovn_utils.ovn_port_group_name(self.fake_sg['id'])
self.nb_ovn.pg_add.assert_called_once_with(
name=pg_name, acls=[], external_ids=external_ids)
if stateful or not stateless_supported:
if stateful:
expected = ovn_const.ACL_ACTION_ALLOW_RELATED
else:
expected = ovn_const.ACL_ACTION_ALLOW_STATELESS
@ -296,17 +292,11 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
mock_bump.assert_called_once_with(
mock.ANY, self.fake_sg, ovn_const.TYPE_SECURITY_GROUPS)
def test__create_security_group_stateful_supported(self):
self._test__create_security_group(True, True)
def test__create_security_group_stateful(self):
self._test__create_security_group(True)
def test__create_security_group_stateful_not_supported(self):
self._test__create_security_group(True, False)
def test__create_security_group_stateless_supported(self):
self._test__create_security_group(False, True)
def test__create_security_group_stateless_not_supported(self):
self._test__create_security_group(False, False)
def test__create_security_group_stateless(self):
self._test__create_security_group(False)
@mock.patch.object(ovn_revision_numbers_db, 'delete_revision')
def test__delete_security_group(self, mock_del_rev):
@ -326,16 +316,12 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
@mock.patch.object(ovn_revision_numbers_db, 'bump_revision')
@mock.patch.object(ovn_revision_numbers_db, 'delete_revision')
def _test__update_security_group(
self, stateful, stateless_supported, mock_del, mock_bump):
def _test__update_security_group(self, stateful, mock_del, mock_bump):
self.fake_sg['stateful'] = stateful
fake_sg_update = copy.deepcopy(self.fake_sg)
fake_sg_update['stateful'] = not stateful
rule = fake_sg_update['security_group_rules'][0]
with mock.patch.object(self.mech_driver._ovn_client,
'is_allow_stateless_supported',
return_value=stateless_supported), \
mock.patch.object(securitygroups_db.SecurityGroupDbMixin,
with mock.patch.object(securitygroups_db.SecurityGroupDbMixin,
'get_security_group_rules',
return_value=[rule]), \
mock.patch.object(
@ -347,42 +333,28 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
states=(self.fake_sg, fake_sg_update),
resource_id=self.fake_sg['id']))
# When stateless is supported we will update the SG rules,
# otherwise will just bump the revision on the SG.
bump_calls = []
if stateless_supported:
acl_calls = [
mock.call(mock.ANY, mock.ANY, mock.ANY,
rule['security_group_id'], rule, is_add_acl=False,
stateless_supported=stateless_supported),
mock.call(mock.ANY, mock.ANY, mock.ANY,
rule['security_group_id'], rule, is_add_acl=True,
stateless_supported=stateless_supported)]
ovn_acl_up.assert_has_calls(acl_calls)
# we will update the SG rules
ovn_acl_up.assert_has_calls([
mock.call(mock.ANY, mock.ANY, mock.ANY,
rule['security_group_id'], rule, is_add_acl=False),
mock.call(mock.ANY, mock.ANY, mock.ANY,
rule['security_group_id'], rule, is_add_acl=True)
])
mock_del.assert_called_once_with(
mock.ANY, rule['id'], ovn_const.TYPE_SECURITY_GROUP_RULES)
mock_del.assert_called_once_with(
mock.ANY, rule['id'], ovn_const.TYPE_SECURITY_GROUP_RULES)
bump_calls.extend([
mock.call(mock.ANY, rule,
ovn_const.TYPE_SECURITY_GROUP_RULES)])
mock_bump.assert_has_calls([
mock.call(mock.ANY, rule, ovn_const.TYPE_SECURITY_GROUP_RULES),
mock.call(mock.ANY, fake_sg_update,
ovn_const.TYPE_SECURITY_GROUPS),
])
bump_calls.extend([
mock.call(mock.ANY, fake_sg_update,
ovn_const.TYPE_SECURITY_GROUPS)])
mock_bump.assert_has_calls(bump_calls)
def test__update_security_group_stateful(self):
self._test__update_security_group(True)
def test__update_security_group_stateful_supported(self):
self._test__update_security_group(True, True)
def test__update_security_group_stateful_not_supported(self):
self._test__update_security_group(True, False)
def test__update_security_group_stateless_supported(self):
self._test__update_security_group(False, True)
def test__update_security_group_stateless_not_supported(self):
self._test__update_security_group(False, False)
def test__update_security_group_stateless(self):
self._test__update_security_group(False)
@mock.patch.object(ovn_revision_numbers_db, 'bump_revision')
def test__process_sg_rule_notifications_sgr_create(self, mock_bump):
@ -398,8 +370,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
self.context, states=(rule,)))
has_same_rules.assert_not_called()
ovn_acl_up.assert_called_once_with(
mock.ANY, mock.ANY, mock.ANY,
'sg_id', rule, is_add_acl=True, stateless_supported=False)
mock.ANY, mock.ANY, mock.ANY, 'sg_id', rule, is_add_acl=True)
mock_bump.assert_called_once_with(
mock.ANY, rule, ovn_const.TYPE_SECURITY_GROUP_RULES)
@ -419,8 +390,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
self.context, states=(rule,)))
has_same_rules.assert_not_called()
ovn_acl_up.assert_called_once_with(
mock.ANY, mock.ANY, mock.ANY,
'sg_id', rule, is_add_acl=True, stateless_supported=False)
mock.ANY, mock.ANY, mock.ANY, 'sg_id', rule, is_add_acl=True)
mock_bump.assert_called_once_with(
mock.ANY, rule, ovn_const.TYPE_SECURITY_GROUP_RULES)
@ -437,8 +407,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
payload=events.DBEventPayload(
self.context, states=(rule,)))
ovn_acl_up.assert_called_once_with(
mock.ANY, mock.ANY, mock.ANY,
'sg_id', rule, is_add_acl=False, stateless_supported=False)
mock.ANY, mock.ANY, mock.ANY, 'sg_id', rule, is_add_acl=False)
mock_delrev.assert_called_once_with(
mock.ANY, rule['id'], ovn_const.TYPE_SECURITY_GROUP_RULES)

View File

@ -0,0 +1,6 @@
---
upgrade:
- |
The ``allow_stateless_action_supported`` configuration option for OVN is
removed. The ``stateful-security-group`` API is now unconditionally
enabled. Please upgrade OVN to 21.06.0 or a later version.