Add extra router attributes for ECMP and BFD
* enable_default_route_ecmp * enable_default_route_bfd Partial-Bug: #2002687 Change-Id: I3fcd0458d20f20ce40378f90f073f37c41400865
This commit is contained in:
parent
656897f32e
commit
89702218db
36
neutron/conf/db/l3_extra_gws_db.py
Normal file
36
neutron/conf/db/l3_extra_gws_db.py
Normal file
@ -0,0 +1,36 @@
|
||||
# Copyright (c) 2023 Canonical Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron._i18n import _
|
||||
|
||||
|
||||
L3_EXTRA_GWS_OPTS = [
|
||||
cfg.BoolOpt('enable_default_route_ecmp',
|
||||
default=False,
|
||||
help=_("Define the default value for "
|
||||
"enable_default_route_ecmp if not specified on the "
|
||||
"router.")),
|
||||
cfg.BoolOpt('enable_default_route_bfd',
|
||||
default=False,
|
||||
help=_("Define the default value for "
|
||||
"enable_default_route_bfd if not specified on the "
|
||||
"router.")),
|
||||
]
|
||||
|
||||
|
||||
def register_db_l3_extragws_opts(conf=cfg.CONF):
|
||||
conf.register_opts(L3_EXTRA_GWS_OPTS)
|
@ -127,6 +127,22 @@ rules = [
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY)
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='create_router:enable_default_route_bfd',
|
||||
check_str=base.ADMIN,
|
||||
scope_types=['project'],
|
||||
description=('Specify ``enable_default_route_bfd`` attribute when'
|
||||
' creating a router'),
|
||||
operations=ACTION_POST,
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='create_router:enable_default_route_ecmp',
|
||||
check_str=base.ADMIN,
|
||||
scope_types=['project'],
|
||||
description=('Specify ``enable_default_route_ecmp`` attribute when'
|
||||
' creating a router'),
|
||||
operations=ACTION_POST,
|
||||
),
|
||||
|
||||
policy.DocumentedRuleDefault(
|
||||
name='get_router',
|
||||
@ -252,6 +268,22 @@ rules = [
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY)
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='update_router:enable_default_route_bfd',
|
||||
check_str=base.ADMIN,
|
||||
scope_types=['project'],
|
||||
description=('Specify ``enable_default_route_bfd`` attribute when '
|
||||
'updating a router'),
|
||||
operations=ACTION_POST,
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='update_router:enable_default_route_ecmp',
|
||||
check_str=base.ADMIN,
|
||||
scope_types=['project'],
|
||||
description=('Specify ``enable_default_route_ecmp`` attribute when '
|
||||
'updating a router'),
|
||||
operations=ACTION_POST,
|
||||
),
|
||||
|
||||
policy.DocumentedRuleDefault(
|
||||
name='delete_router',
|
||||
|
@ -18,9 +18,13 @@ from neutron_lib.db import resource_extend
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron._i18n import _
|
||||
from neutron.conf.db import l3_extra_gws_db
|
||||
from neutron.db.models import l3_attrs
|
||||
|
||||
|
||||
l3_extra_gws_db.register_db_l3_extragws_opts()
|
||||
|
||||
|
||||
def get_attr_info():
|
||||
"""Returns api visible attr names and their default values."""
|
||||
return {'distributed': {'default': cfg.CONF.router_distributed},
|
||||
@ -29,7 +33,11 @@ def get_attr_info():
|
||||
'availability_zone_hints': {
|
||||
'default': '[]',
|
||||
'transform_to_db': az_validator.convert_az_list_to_string,
|
||||
'transform_from_db': az_validator.convert_az_string_to_list}
|
||||
'transform_from_db': az_validator.convert_az_string_to_list},
|
||||
'enable_default_route_ecmp': {
|
||||
'default': cfg.CONF.enable_default_route_ecmp},
|
||||
'enable_default_route_bfd': {
|
||||
'default': cfg.CONF.enable_default_route_bfd},
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,6 +22,8 @@ from neutron.db import l3_gwmode_db
|
||||
from neutron.objects import ports as port_obj
|
||||
from neutron.objects import router as l3_obj
|
||||
from neutron_lib.api.definitions import l3 as l3_apidef
|
||||
from neutron_lib.api.definitions import l3_enable_default_route_bfd
|
||||
from neutron_lib.api.definitions import l3_enable_default_route_ecmp
|
||||
from neutron_lib.api.definitions import l3_ext_gw_multihoming
|
||||
from neutron_lib.api import extensions
|
||||
from neutron_lib.callbacks import events
|
||||
@ -75,6 +77,16 @@ class ExtraGatewaysDbOnlyMixin(l3_gwmode_db.L3_NAT_dbonly_mixin):
|
||||
trigger, payload):
|
||||
self._remove_all_gateways(payload.context, payload.resource_id)
|
||||
|
||||
@registry.receives(resources.ROUTER, [events.PRECOMMIT_CREATE])
|
||||
def _process_bfd_ecmp_request(self, resource, event, trigger, payload):
|
||||
router = payload.latest_state
|
||||
router_db = payload.metadata['router_db']
|
||||
for attr in (l3_enable_default_route_ecmp.ENABLE_DEFAULT_ROUTE_ECMP,
|
||||
l3_enable_default_route_bfd.ENABLE_DEFAULT_ROUTE_BFD):
|
||||
value = router.get(attr)
|
||||
if value is not None:
|
||||
self.set_extra_attr_value(router_db, attr, value)
|
||||
|
||||
def _add_external_gateways(
|
||||
self, context, router_id, gw_info_list, payload):
|
||||
"""Add external gateways to a router."""
|
||||
|
@ -0,0 +1,39 @@
|
||||
# Copyright 2023 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import sql
|
||||
|
||||
|
||||
"""Add ECMP and BFD router-level policy attributes
|
||||
Revision ID: 89c58a70ceba
|
||||
Revises: c33da356b165
|
||||
Create Date: 2023-02-22 21:08:33.593101
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '89c58a70ceba'
|
||||
down_revision = 'c33da356b165'
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('router_extra_attributes',
|
||||
sa.Column('enable_default_route_ecmp', sa.Boolean(),
|
||||
server_default=sql.false(), nullable=False))
|
||||
op.add_column('router_extra_attributes',
|
||||
sa.Column('enable_default_route_bfd', sa.Boolean(),
|
||||
server_default=sql.false(), nullable=False))
|
@ -1 +1 @@
|
||||
c33da356b165
|
||||
89c58a70ceba
|
||||
|
@ -40,6 +40,12 @@ class RouterExtraAttributes(model_base.BASEV2):
|
||||
ha_vr_id = sa.Column(sa.Integer())
|
||||
# Availability Zone support
|
||||
availability_zone_hints = sa.Column(sa.String(255))
|
||||
enable_default_route_ecmp = sa.Column(sa.Boolean, default=False,
|
||||
server_default=sa.sql.false(),
|
||||
nullable=False)
|
||||
enable_default_route_bfd = sa.Column(sa.Boolean, default=False,
|
||||
server_default=sa.sql.false(),
|
||||
nullable=False)
|
||||
|
||||
router = orm.relationship(
|
||||
'Router', load_on_pending=True,
|
||||
|
@ -71,7 +71,8 @@ class RouterRoute(base.NeutronDbObject):
|
||||
@base.NeutronObjectRegistry.register
|
||||
class RouterExtraAttributes(base.NeutronDbObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
# Version 1.1: Added ECMP and BFD attributes
|
||||
VERSION = '1.1'
|
||||
|
||||
db_model = l3_attrs.RouterExtraAttributes
|
||||
|
||||
@ -81,7 +82,10 @@ class RouterExtraAttributes(base.NeutronDbObject):
|
||||
'service_router': obj_fields.BooleanField(default=False),
|
||||
'ha': obj_fields.BooleanField(default=False),
|
||||
'ha_vr_id': obj_fields.IntegerField(nullable=True),
|
||||
'availability_zone_hints': obj_fields.ListOfStringsField(nullable=True)
|
||||
'availability_zone_hints': obj_fields.ListOfStringsField(
|
||||
nullable=True),
|
||||
'enable_default_route_bfd': obj_fields.BooleanField(default=False),
|
||||
'enable_default_route_ecmp': obj_fields.BooleanField(default=False),
|
||||
}
|
||||
|
||||
primary_keys = ['router_id']
|
||||
@ -130,6 +134,12 @@ class RouterExtraAttributes(base.NeutronDbObject):
|
||||
|
||||
return list(query)
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
_target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if _target_version < (1, 1):
|
||||
primitive.pop('enable_default_route_bfd', None)
|
||||
primitive.pop('enable_default_route_ecmp', None)
|
||||
|
||||
|
||||
@base.NeutronObjectRegistry.register
|
||||
class RouterPort(base.NeutronDbObject):
|
||||
|
@ -35,6 +35,7 @@ import neutron.conf.db.dvr_mac_db
|
||||
import neutron.conf.db.extraroute_db
|
||||
import neutron.conf.db.l3_agentschedulers_db
|
||||
import neutron.conf.db.l3_dvr_db
|
||||
import neutron.conf.db.l3_extra_gws_db
|
||||
import neutron.conf.db.l3_gwmode_db
|
||||
import neutron.conf.db.l3_hamode_db
|
||||
import neutron.conf.experimental
|
||||
@ -168,7 +169,8 @@ def list_db_opts():
|
||||
neutron.conf.db.dvr_mac_db.DVR_MAC_ADDRESS_OPTS,
|
||||
neutron.conf.db.l3_dvr_db.ROUTER_DISTRIBUTED_OPTS,
|
||||
neutron.conf.db.l3_agentschedulers_db.L3_AGENTS_SCHEDULER_OPTS,
|
||||
neutron.conf.db.l3_hamode_db.L3_HA_OPTS)
|
||||
neutron.conf.db.l3_hamode_db.L3_HA_OPTS,
|
||||
neutron.conf.db.l3_extra_gws_db.L3_EXTRA_GWS_OPTS)
|
||||
),
|
||||
('database',
|
||||
neutron.db.migration.cli.get_engine_config())
|
||||
|
@ -114,6 +114,30 @@ class SystemAdminTests(RouterAPITestCase):
|
||||
'create_router:external_gateway_info:external_fixed_ips',
|
||||
self.alt_target)
|
||||
|
||||
def test_create_router_enable_default_route_bfd(self):
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'create_router:enable_default_route_bfd',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'create_router:enable_default_route_bfd',
|
||||
self.alt_target)
|
||||
|
||||
def test_create_router_enable_default_route_ecmp(self):
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'create_router:enable_default_route_ecmp',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'create_router:enable_default_route_ecmp',
|
||||
self.alt_target)
|
||||
|
||||
def test_get_router(self):
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
@ -224,6 +248,30 @@ class SystemAdminTests(RouterAPITestCase):
|
||||
'update_router:external_gateway_info:external_fixed_ips',
|
||||
self.alt_target)
|
||||
|
||||
def test_update_router_enable_default_route_bfd(self):
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'update_router:enable_default_route_bfd',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'update_router:enable_default_route_bfd',
|
||||
self.alt_target)
|
||||
|
||||
def test_update_router_enable_default_route_ecmp(self):
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'update_router:enable_default_route_ecmp',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
policy.enforce,
|
||||
self.context, 'update_router:enable_default_route_ecmp',
|
||||
self.alt_target)
|
||||
|
||||
def test_delete_router(self):
|
||||
self.assertRaises(
|
||||
base_policy.InvalidScope,
|
||||
@ -337,6 +385,30 @@ class AdminTests(RouterAPITestCase):
|
||||
'create_router:external_gateway_info:external_fixed_ips',
|
||||
self.alt_target))
|
||||
|
||||
def test_update_router_enable_default_route_bfd(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(
|
||||
self.context,
|
||||
'update_router:enable_default_route_bfd',
|
||||
self.target))
|
||||
self.assertTrue(
|
||||
policy.enforce(
|
||||
self.context,
|
||||
'update_router:enable_default_route_bfd',
|
||||
self.alt_target))
|
||||
|
||||
def test_update_router_enable_default_route_ecmp(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(
|
||||
self.context,
|
||||
'update_router:enable_default_route_ecmp',
|
||||
self.target))
|
||||
self.assertTrue(
|
||||
policy.enforce(
|
||||
self.context,
|
||||
'update_router:enable_default_route_ecmp',
|
||||
self.alt_target))
|
||||
|
||||
def test_get_router(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context, 'get_router', self.target))
|
||||
@ -524,6 +596,34 @@ class ProjectMemberTests(AdminTests):
|
||||
'create_router:external_gateway_info:external_fixed_ips',
|
||||
self.alt_target)
|
||||
|
||||
def test_update_router_enable_default_route_bfd(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context,
|
||||
'update_router:enable_default_route_bfd',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context,
|
||||
'update_router:enable_default_route_bfd',
|
||||
self.alt_target)
|
||||
|
||||
def test_update_router_enable_default_route_ecmp(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context,
|
||||
'update_router:enable_default_route_ecmp',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context,
|
||||
'update_router:enable_default_route_ecmp',
|
||||
self.alt_target)
|
||||
|
||||
def test_get_router(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context, 'get_router', self.target))
|
||||
|
@ -657,9 +657,17 @@ class ExtraAttributesMixinTestCase(testlib_api.SqlTestCase):
|
||||
self.mixin.set_extra_attr_value(self.router,
|
||||
'availability_zone_hints',
|
||||
['x', 'y', 'z'])
|
||||
self.mixin.set_extra_attr_value(self.router,
|
||||
'enable_default_route_ecmp',
|
||||
True)
|
||||
self.mixin.set_extra_attr_value(self.router,
|
||||
'enable_default_route_bfd',
|
||||
True)
|
||||
expected = self._get_default_api_values()
|
||||
expected.update({'ha_vr_id': 99,
|
||||
'availability_zone_hints': ['x', 'y', 'z']})
|
||||
'availability_zone_hints': ['x', 'y', 'z'],
|
||||
'enable_default_route_ecmp': True,
|
||||
'enable_default_route_bfd': True})
|
||||
rdict = {}
|
||||
self.mixin._extend_extra_router_dict(rdict, self.router)
|
||||
self.assertEqual(expected, rdict)
|
||||
@ -667,7 +675,15 @@ class ExtraAttributesMixinTestCase(testlib_api.SqlTestCase):
|
||||
self.mixin.set_extra_attr_value(self.router,
|
||||
'availability_zone_hints',
|
||||
['z', 'y', 'z'])
|
||||
self.mixin.set_extra_attr_value(self.router,
|
||||
'enable_default_route_ecmp',
|
||||
False)
|
||||
self.mixin.set_extra_attr_value(self.router,
|
||||
'enable_default_route_bfd',
|
||||
False)
|
||||
expected['availability_zone_hints'] = ['z', 'y', 'z']
|
||||
expected['enable_default_route_ecmp'] = False
|
||||
expected['enable_default_route_bfd'] = False
|
||||
self.mixin._extend_extra_router_dict(rdict, self.router)
|
||||
self.assertEqual(expected, rdict)
|
||||
|
||||
|
@ -106,7 +106,7 @@ object_data = {
|
||||
'ResourceDelta': '1.0-a980b37e0a52618b5af8db29af18be76',
|
||||
'Route': '1.0-a9883a63b416126f9e345523ec09483b',
|
||||
'Router': '1.1-614fa16cc99c60e4fc19ac1b31a52291',
|
||||
'RouterExtraAttributes': '1.0-ef8d61ae2864f0ec9af0ab7939cab318',
|
||||
'RouterExtraAttributes': '1.1-19c45c32098d2aae8e1a22d18944a954',
|
||||
'RouterL3AgentBinding': '1.0-c5ba6c95e3a4c1236a55f490cd67da82',
|
||||
'RouterNDPProxyState': '1.0-4042e475bf173d1d8d17adb962eae1b2',
|
||||
'RouterPort': '1.0-c8c8f499bcdd59186fcd83f323106908',
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add ``enable_default_route_bfd`` and ``enable_default_route_ecmp``
|
||||
configuration options which control default behavior for enabling BFD and
|
||||
ECMP on default routes for newly created routers. Both configuration
|
||||
options have a default value of 'False' and are only supported with the
|
||||
OVN driver.
|
Loading…
Reference in New Issue
Block a user