Introduce ovn_nb_global config section
The patch introduces a new config section ovn_nb_global. All options from this section are passed to OVN Northbound NB_Global table to configure Northbound OVN. First option is ignore_lsp_down to override OVN default configuration. This option was changed in OVN to `true` [1] but for Neutron it's better to not answer ARP packets when ports are in DOWN status. [1] https://www.mail-archive.com/ovs-dev@openvswitch.org/msg60064.html Change-Id: I478249cae483fd2540a7ff3ab714e3d9c3e13f17 Signed-off-by: Jakub Libosvar <libosvar@redhat.com>
This commit is contained in:
parent
c3ba36bc83
commit
4e566b11d0
@ -28,6 +28,8 @@ VLOG_LEVELS = {'CRITICAL': vlog.CRITICAL, 'ERROR': vlog.ERROR, 'WARNING':
|
|||||||
|
|
||||||
MIGRATE_MODE = "migrate"
|
MIGRATE_MODE = "migrate"
|
||||||
|
|
||||||
|
OVN_NB_GLOBAL = "ovn_nb_global"
|
||||||
|
|
||||||
ovn_opts = [
|
ovn_opts = [
|
||||||
cfg.StrOpt('ovn_nb_connection',
|
cfg.StrOpt('ovn_nb_connection',
|
||||||
default='tcp:127.0.0.1:6641',
|
default='tcp:127.0.0.1:6641',
|
||||||
@ -226,16 +228,33 @@ ovn_opts = [
|
|||||||
'newer.')),
|
'newer.')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
nb_global_opts = [
|
||||||
|
cfg.BoolOpt('ignore_lsp_down',
|
||||||
|
default=False,
|
||||||
|
help=_('If set to False, ARP/ND reply flows for logical '
|
||||||
|
'switch ports will be installed only if the port is '
|
||||||
|
'UP, i.e. claimed by a Chassis. If set to True, these '
|
||||||
|
'flows are installed regardless of the status of the '
|
||||||
|
'port, which can result in a situation that an ARP '
|
||||||
|
'request to an IP is resolved even before the relevant '
|
||||||
|
'VM/container is running. For environments where this '
|
||||||
|
'is not an issue, setting it to True can reduce '
|
||||||
|
'the load and latency of the control plane. '
|
||||||
|
'The default value is False.')),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def register_opts():
|
def register_opts():
|
||||||
cfg.CONF.register_opts(ovn_opts, group='ovn')
|
cfg.CONF.register_opts(ovn_opts, group='ovn')
|
||||||
ovs_conf.register_ovs_agent_opts()
|
ovs_conf.register_ovs_agent_opts()
|
||||||
|
cfg.CONF.register_opts(nb_global_opts, group=OVN_NB_GLOBAL)
|
||||||
|
|
||||||
|
|
||||||
def list_opts():
|
def list_opts():
|
||||||
return [
|
return [
|
||||||
('ovn', ovn_opts),
|
('ovn', ovn_opts),
|
||||||
('ovs', ovs_conf.OPTS)
|
('ovs', ovs_conf.OPTS),
|
||||||
|
(OVN_NB_GLOBAL, nb_global_opts),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -623,6 +623,10 @@ class API(api.API, metaclass=abc.ABCMeta):
|
|||||||
:returns: The NAT rule row or Load_Balancer row or None
|
:returns: The NAT rule row or Load_Balancer row or None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def set_nb_global_options(self, key, value):
|
||||||
|
"""Set NB_Global options configuration"""
|
||||||
|
|
||||||
|
|
||||||
class SbAPI(api.API, metaclass=abc.ABCMeta):
|
class SbAPI(api.API, metaclass=abc.ABCMeta):
|
||||||
|
|
||||||
|
@ -848,6 +848,10 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
|
|||||||
def update_lb_external_ids(self, lb_name, values, if_exists=True):
|
def update_lb_external_ids(self, lb_name, values, if_exists=True):
|
||||||
return cmd.UpdateLbExternalIds(self, lb_name, values, if_exists)
|
return cmd.UpdateLbExternalIds(self, lb_name, values, if_exists)
|
||||||
|
|
||||||
|
def set_nb_global_options(self, **options):
|
||||||
|
LOG.debug("Setting NB_Global options: %s", options)
|
||||||
|
return self.db_set("NB_Global", ".", options=options)
|
||||||
|
|
||||||
|
|
||||||
class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
|
class OvsdbSbOvnIdl(sb_impl_idl.OvnSbApiIdlImpl, Backend):
|
||||||
def __init__(self, connection):
|
def __init__(self, connection):
|
||||||
|
@ -1079,6 +1079,22 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase):
|
|||||||
context = n_context.get_admin_context()
|
context = n_context.get_admin_context()
|
||||||
hash_ring_db.cleanup_old_nodes(context, days=5)
|
hash_ring_db.cleanup_old_nodes(context, days=5)
|
||||||
|
|
||||||
|
@has_lock_periodic(spacing=86400, run_immediately=True)
|
||||||
|
def configure_nb_global(self):
|
||||||
|
"""Configure Northbound OVN NB_Global options
|
||||||
|
|
||||||
|
The method goes over all config options from ovn_nb_global config
|
||||||
|
sections and configures same key/value pairs to the NB_Global:options
|
||||||
|
column.
|
||||||
|
"""
|
||||||
|
options = {opt.name: str(cfg.CONF.ovn_nb_global.get(opt.name)).lower()
|
||||||
|
for opt in ovn_conf.nb_global_opts}
|
||||||
|
|
||||||
|
self._nb_idl.set_nb_global_options(**options).execute(
|
||||||
|
check_error=True)
|
||||||
|
|
||||||
|
raise periodics.NeverAgain()
|
||||||
|
|
||||||
|
|
||||||
class HashRingHealthCheckPeriodics(object):
|
class HashRingHealthCheckPeriodics(object):
|
||||||
|
|
||||||
|
@ -1032,6 +1032,39 @@ class TestMaintenance(_TestMaintenanceHelper):
|
|||||||
# "Chassis_Private" register was missing.
|
# "Chassis_Private" register was missing.
|
||||||
self.assertEqual(2, len(chassis_result))
|
self.assertEqual(2, len(chassis_result))
|
||||||
|
|
||||||
|
def test_configure_nb_global(self):
|
||||||
|
def options_intersect(options1, options2):
|
||||||
|
return bool(set(
|
||||||
|
new_nb_global_options.keys()).intersection(nb_options.keys()))
|
||||||
|
|
||||||
|
new_nb_global_options = {
|
||||||
|
'foo': 'bar',
|
||||||
|
'baz': 'qux',
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_nb_global_options = [
|
||||||
|
ovn_config.cfg.StrOpt(key) for key in new_nb_global_options
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_opt(key):
|
||||||
|
return new_nb_global_options[key]
|
||||||
|
|
||||||
|
nb_options = self.nb_api.db_get('NB_Global', '.', 'options').execute(
|
||||||
|
check_error=True, log_errors=True)
|
||||||
|
self.assertFalse(options_intersect(new_nb_global_options, nb_options))
|
||||||
|
|
||||||
|
with mock.patch.object(
|
||||||
|
ovn_config, 'nb_global_opts', cfg_nb_global_options), \
|
||||||
|
mock.patch.object(
|
||||||
|
ovn_config.cfg.CONF.ovn_nb_global, 'get',
|
||||||
|
side_effect=get_opt):
|
||||||
|
self.assertRaises(periodics.NeverAgain,
|
||||||
|
self.maint.configure_nb_global)
|
||||||
|
|
||||||
|
nb_options = self.nb_api.db_get('NB_Global', '.', 'options').execute(
|
||||||
|
check_error=True, log_errors=True)
|
||||||
|
self.assertTrue(options_intersect(new_nb_global_options, nb_options))
|
||||||
|
|
||||||
|
|
||||||
class TestLogMaintenance(_TestMaintenanceHelper,
|
class TestLogMaintenance(_TestMaintenanceHelper,
|
||||||
test_log_driver.LogApiTestCaseBase):
|
test_log_driver.LogApiTestCaseBase):
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Starting with OVN version v21.12.0, OVN replies to ARP requests for ports
|
||||||
|
that are in a DOWN status. It does not reply in versions older than
|
||||||
|
v21.12.0. In order to keep the same behavior in Neutron, the default OVN
|
||||||
|
behavior is overridden by Neutron and Neutron ports will no longer reply to
|
||||||
|
ARP packets if the ports are in a DOWN state. If it is required to reply to
|
||||||
|
ARP for such ports, the config option ``ignore_lsp_down`` from
|
||||||
|
``[ovn_nb_global]`` section can be set to True in the Neutron config. It is
|
||||||
|
set to False by default.
|
Loading…
Reference in New Issue
Block a user