Make the local chassis ID configurable

ovn-controller can be configured with a system-id override file or
-n option to use any suffix for OVSDB options. Currently ovn-bgp-agent
just uses a constant "bgp" for this and there is no way to change it.

48db2a7a35

Let's allow this suffix to be set via a config option instead.

Change-Id: Ida30b46e16ddcdc2d82af980546876f72a845c1d
This commit is contained in:
Dmitrii Shcherbakov 2024-06-27 17:17:37 +03:00
parent a4e307e6f5
commit e3cb1b4a47
6 changed files with 83 additions and 9 deletions

View File

@ -69,12 +69,15 @@ The OVN routing architecture proposes the following mapping:
(``br-osp``). (``br-osp``).
- ``br-osp`` does not have any physical resources attached, just patch - ``br-osp`` does not have any physical resources attached, just patch
ports connecting them to ``br-int`` and ``br-bgp``. ports connecting them to ``br-int`` and ``br-bgp``. The name of this bridge can
be arbitrary so long as ovn-bridge-mappings for both OVN clusters (the primary and
the extra node-local one) are set accordingly.
- ``br-bgp`` is the integration bridge managed by the extra OVN cluster - ``br-bgp`` is the integration bridge managed by the extra OVN cluster
deployed per node. This is where the virtual OVN resources are be created deployed per node. This is where the virtual OVN resources are be created
(routers and switches). It creates mappings to ``br-osp`` and ``br-ex`` (routers and switches). OVN creates patch ports between ``br-osp`` and ``br-ex``
(patch ports). based on ovn-bridge-mappings set for the extra OVN cluster. The name of this bridge
is configurable and can be changed by setting a relevant instance-specific OVSDB option.
- ``br-ex`` keeps being the external bridge, where the physical NICs are - ``br-ex`` keeps being the external bridge, where the physical NICs are
attached (as in default environments without BGP). But instead of being attached (as in default environments without BGP). But instead of being
@ -236,6 +239,71 @@ range for the provider networks to expose/handle:
external_nics=eth1,eth2 external_nics=eth1,eth2
peer_ips=100.64.1.5,100.65.1.5 peer_ips=100.64.1.5,100.65.1.5
provider_networks_pool_prefixes=172.16.0.0/16 provider_networks_pool_prefixes=172.16.0.0/16
# This will be used as a suffix for options relevant to the node-local OVN.
bgp_chassis_id = bgp
Multiple OVN Controllers
++++++++++++++++++++++++
This mode relies on running two ovn-controllers on the same host. However, a single
OVSDB is shared for both controllers. To achieve that, OVN supports having option
suffixes for options stored in OVSDB that look like this: ``<option>-<system-id>``.
One of the ``ovn-controller`` instances will need to have ``-n <system-id-override>``
passed in via command-line arguments to the daemon. Alternatively, if the second
ovn-controller is run in a container, ``/etc/<ovn-config-dir>/system-id-override``
can be provided to override the system-id.
``ovn-bgp-agent`` itself needs to parse bridge-mappings related to the local OVN instance
and by default uses ``bgp_chassis_id`` config option set to `bgp` making it look for
bridge mappings in the ``ovn-bridge-mappings-bgp`` option. Make sure to set this option
correctly, otherwise, ``ovn-bgp-agent`` will not create the necessary local ``ovn-nb`` state
and, as a result, no patch ports will be created between ``br-bgp`` and ``br-ex``.
An example of how to set relevant OVSDB options for both ``ovn-controller``s via ``ovs-vsctl``:
.. code-block:: bash
# Set the hostname that will be used by both ovn-controllers.
ovs-vsctl set open . external-ids:hostname=<desired-hostname>
# This is optional as it matches the default integration bridge
# name in OVN but present here to clarify the difference with the
# extra OVN cluster config.
ovs-vsctl set open . external-ids:ovn-bridge=br-int
# Bridge mappings for the primary OVN cluster's ovn-controller.
ovs-vsctl set open . external-ids:ovn-bridge-mappings=provider:br-osp
# Set the IP to be used for a tunnel endpoint.
ovs-vsctl set open . external-ids:ovn-encap-ip=<desired-vtep-ip>
# Set the desired encapsulation (will apply to both ovn-controllers as there's no
# suffixed override):
ovs-vsctl set open . external-ids:ovn-encap-type=geneve
# Assuming the primary OVN deployment has a clustered ovn-sb setup with 3 IPs
# and listening on port 6642:
ovs-vsctl set open . external-ids:ovn-remote="ssl:<primary-ovn-sb-ip-1>:6642,ssl:<primary-ovn-sb-ip-2>:6642,ssl:<primary-ovn-sb-ip-3>:6642"
# Set the integation bridge name for the extra OVN deployment
# (this overrides the default br-int):
ovs-vsctl set open . external-ids:ovn-bridge-bgp=br-bgp
# Set the bridge mappings for the extra OVN's ovn-controller instance. Note that
# there will be localnet ports on both the northbound and southbound side of br-bgp
# as a result.
ovs-vsctl set open . external-ids:ovn-bridge-mappings-bgp=dcfabric:br-ex,local:br-osp
# Make sure that the local ovn-controller speaks to the local ovn-sb.
ovs-vsctl set open . external-ids:ovn-remote-bgp=unix:/var/run/ovn/ovnsb_db.sock
# Have to set both ovn-encap-ip (taken from the option without suffix) and ovn-encap-ip
# in order for ovn-controller to start successfully.
# Since we only use localnet ports for the extra cluster, we can set this IP to the localhost IP.
ovs-vsctl set open . external-ids:ovn-encap-ip-bgp=127.0.0.1
# Enable hardware offload if your hardware supports it which will apply to the state created
# by both ovn-controllers.
ovs-vsctl set open . other-config:hw-offload=true
Limitations Limitations

View File

@ -231,6 +231,13 @@ local_ovn_cluster_opts = [
cfg.ListOpt('provider_networks_pool_prefixes', cfg.ListOpt('provider_networks_pool_prefixes',
default=['192.168.0.0/16'], default=['192.168.0.0/16'],
help='List of prefixes for provider networks'), help='List of prefixes for provider networks'),
cfg.ListOpt('bgp_chassis_id',
default='bgp',
help='The chassis_id used for the ovn-controller instance'
' related to the node-local OVN instance. Used as a'
' suffix for getting instance-specific options'
' from OVSDB. This option has effect only when the OVN'
' NB driver is used.'),
] ]
CONF = cfg.CONF CONF = cfg.CONF

View File

@ -133,7 +133,6 @@ ADVERTISEMENT_METHOD_HOST = 'host'
ADVERTISEMENT_METHOD_SUBNET = 'subnet' ADVERTISEMENT_METHOD_SUBNET = 'subnet'
# OVN Cluster related constants # OVN Cluster related constants
OVN_CLUSTER_BRIDGE = 'bgp'
OVN_CLUSTER_ROUTER = 'bgp-router' OVN_CLUSTER_ROUTER = 'bgp-router'
OVN_CLUSTER_ROUTER_INTERNAL_MAC = '40:44:00:00:00:06' OVN_CLUSTER_ROUTER_INTERNAL_MAC = '40:44:00:00:00:06'

View File

@ -239,7 +239,7 @@ def _ensure_base_wiring_config_ovn(ovs_idl, ovn_idl):
# LS # LS
bgp_bridge_mappings = ovs_idl.get_ovn_bridge_mappings( bgp_bridge_mappings = ovs_idl.get_ovn_bridge_mappings(
bridge=constants.OVN_CLUSTER_BRIDGE) bridge=CONF.local_ovn_cluster.bgp_chassis_id)
for bridge_mapping in bgp_bridge_mappings: for bridge_mapping in bgp_bridge_mappings:
network, bridge = helpers.parse_bridge_mapping(bridge_mapping) network, bridge = helpers.parse_bridge_mapping(bridge_mapping)
if not network: if not network:
@ -347,7 +347,7 @@ def _ensure_ovn_network_link(ovn_idl, switch_name, direction,
# bind to local chassis # bind to local chassis
# ovn-nbctl lrp-set-gateway-chassis bgp-router-public bgp 1 # ovn-nbctl lrp-set-gateway-chassis bgp-router-public bgp 1
cmds.append(ovn_idl.lrp_set_gateway_chassis( cmds.append(ovn_idl.lrp_set_gateway_chassis(
r_port_name, constants.OVN_CLUSTER_BRIDGE, 1)) r_port_name, CONF.local_ovn_cluster.bgp_chassis_id, 1))
else: # direction == 'external' else: # direction == 'external'
# Connect BGP router to the external logical switch # Connect BGP router to the external logical switch
r_port_name = "{}-{}".format(constants.OVN_CLUSTER_ROUTER, switch_name) r_port_name = "{}-{}".format(constants.OVN_CLUSTER_ROUTER, switch_name)

View File

@ -180,7 +180,7 @@ class TestWire(test_base.TestCase):
m_ensure_lsp.assert_called_once_with( m_ensure_lsp.assert_called_once_with(
self.nb_idl, mock.ANY, switch_name, 'router', 'router', **options) self.nb_idl, mock.ANY, switch_name, 'router', 'router', **options)
self.nb_idl.lrp_set_gateway_chassis.assert_called_once_with( self.nb_idl.lrp_set_gateway_chassis.assert_called_once_with(
r_port_name, constants.OVN_CLUSTER_BRIDGE, 1) r_port_name, CONF.local_ovn_cluster.bgp_chassis_id, 1)
@mock.patch.object(wire, '_execute_commands') @mock.patch.object(wire, '_execute_commands')
@mock.patch.object(wire, '_ensure_lsp_cmds') @mock.patch.object(wire, '_ensure_lsp_cmds')
@ -205,7 +205,7 @@ class TestWire(test_base.TestCase):
m_ensure_lsp.assert_called_once_with( m_ensure_lsp.assert_called_once_with(
self.nb_idl, mock.ANY, switch_name, 'router', 'router', **options) self.nb_idl, mock.ANY, switch_name, 'router', 'router', **options)
self.nb_idl.lrp_set_gateway_chassis.assert_called_once_with( self.nb_idl.lrp_set_gateway_chassis.assert_called_once_with(
r_port_name, constants.OVN_CLUSTER_BRIDGE, 1) r_port_name, CONF.local_ovn_cluster.bgp_chassis_id, 1)
@mock.patch.object(wire, '_ensure_lsp_cmds') @mock.patch.object(wire, '_ensure_lsp_cmds')
def test__ensure_ovn_network_link_external(self, m_ensure_lsp): def test__ensure_ovn_network_link_external(self, m_ensure_lsp):

View File

@ -179,7 +179,7 @@ def ensure_anycast_mac_for_interface(intf, offset):
# Also update the 'scope link' address on the interface. # Also update the 'scope link' address on the interface.
ll = lladdr.replace(':', '') ll = lladdr.replace(':', '')
ll_ip_address = ipaddress.IPv6Address( ll_ip_address = ipaddress.IPv6Address(
f'fe80::{ll[0:4]}:{ll[4:8]}:{ll[8:12]}') f'fe80::{ll[0:4]}:{ll[4:8]}:{ll[8:12]}') # noqa: E231
ll_net = ipaddress.IPv6Network('fe80::/10') ll_net = ipaddress.IPv6Network('fe80::/10')
# Fetch all ipv6 addresses and check if we already configured the # Fetch all ipv6 addresses and check if we already configured the