Browse Source

Merge "Metadata agent: fetch ovn-bridge from OVSDB and not from config" into stable/queens

changes/70/693270/9
Zuul 2 months ago
parent
commit
dc9da4e8d8
3 changed files with 59 additions and 5 deletions
  1. +37
    -3
      networking_ovn/agent/metadata/agent.py
  2. +12
    -0
      networking_ovn/releasenotes/notes/ignore-ovs-integration-bridge-from-metadata-agent-2752193adbbdeec9.yaml
  3. +10
    -2
      networking_ovn/tests/unit/agent/metadata/test_agent.py

+ 37
- 3
networking_ovn/agent/metadata/agent.py View File

@@ -21,6 +21,7 @@ from neutron.common import utils
from neutron_lib import constants as n_const
from oslo_concurrency import lockutils
from oslo_log import log
from oslo_utils import excutils
from ovsdbapp.backend.ovs_idl import event as row_event
from ovsdbapp.backend.ovs_idl import vlog
import six
@@ -139,6 +140,7 @@ class MetadataAgent(object):
# Open the connection to OVS database
self.ovs_idl = ovsdb.MetadataAgentOvsIdl().start()
self.chassis = self._get_own_chassis_name()
self.ovn_bridge = self._get_ovn_bridge()

# Open the connection to OVN SB database.
self.sb_idl = ovsdb.MetadataAgentOvnSbIdl(
@@ -159,6 +161,22 @@ class MetadataAgent(object):
'Open_vSwitch', '.', 'external_ids').execute()
return ext_ids['system-id']

def _get_ovn_bridge(self):
"""Return the external_ids:ovn-bridge value of the Open_vSwitch table.

This is the OVS bridge used to plug the metadata ports to.
If the key doesn't exist, this method will return 'br-int' as default.
"""
ext_ids = self.ovs_idl.db_get(
'Open_vSwitch', '.', 'external_ids').execute()
try:
ovn_bridge = ext_ids['ovn-bridge']
except KeyError:
LOG.warning("Can't read ovn-bridge external-id from OVSDB. Using "
"br-int instead.")
return 'br-int'
return ovn_bridge

@_sync_lock
def sync(self):
"""Agent sync.
@@ -208,8 +226,7 @@ class MetadataAgent(object):
self._process_monitor, datapath, self.conf, namespace)

veth_name = self._get_veth_name(datapath)
self.ovs_idl.del_port(
veth_name[0], bridge=self.conf.ovs_integration_bridge).execute()
self.ovs_idl.del_port(veth_name[0]).execute()
if ip_lib.device_exists(veth_name[0]):
ip_lib.IPWrapper().del_veth(veth_name[0])

@@ -316,9 +333,26 @@ class MetadataAgent(object):
if utils.get_ip_version(ipaddr) == 4:
ip2.addr.add(ipaddr)

# Check that this port is not attached to any other OVS bridge. This
# can happen when the OVN bridge changes (for example, during a
# migration from ML2/OVS).
ovs_bridges = set(self.ovs_idl.list_br().execute())
try:
ovs_bridges.remove(self.ovn_bridge)
except KeyError:
with excutils.save_and_reraise_exception():
LOG.exception("Configured OVN bridge %s cannot be found in "
"the system.", self.ovn_bridge)

if ovs_bridges:
with self.ovs_idl.transaction() as txn:
for br in ovs_bridges:
txn.add(self.ovs_idl.del_port(veth_name[0], bridge=br,
if_exists=True))

# Configure the OVS port and add external_ids:iface-id so that it
# can be tracked by OVN.
self.ovs_idl.add_port(self.conf.ovs_integration_bridge,
self.ovs_idl.add_port(self.ovn_bridge,
veth_name[0]).execute()
self.ovs_idl.db_set(
'Interface', veth_name[0],

+ 12
- 0
networking_ovn/releasenotes/notes/ignore-ovs-integration-bridge-from-metadata-agent-2752193adbbdeec9.yaml View File

@@ -0,0 +1,12 @@
---
fixes:
- |
The configuration option ``ovs_integration_bridge`` used by networking-ovn
metadata agent can only lead to problems as the bridge used by
``ovn-controller`` to install the flows is stored in OVSDB.
The metadata agent will now use OVSDB instead of the configuration option
to plug its ports, as a mismatch between both will break metadata.
There is no real use case for this option to exist and systems currently
using it will *not* be impacted by this change.
For more information see bug `1799216
<https://bugs.launchpad.net/networking-ovn/+bug/1799216>`_.

+ 10
- 2
networking_ovn/tests/unit/agent/metadata/test_agent.py View File

@@ -63,7 +63,9 @@ class TestMetadataAgent(base.BaseTestCase):
self.agent = agent.MetadataAgent(self.fake_conf)
self.agent.sb_idl = mock.Mock()
self.agent.ovs_idl = mock.Mock()
self.agent.ovs_idl.transaction = mock.MagicMock()
self.agent.chassis = 'chassis'
self.agent.ovn_bridge = 'br-int'

def test_sync(self):
with mock.patch.object(
@@ -181,8 +183,7 @@ class TestMetadataAgent(base.BaseTestCase):
self.agent.teardown_datapath('1')

destroy_mdp.assert_called_once()
self.agent.ovs_idl.del_port.assert_called_once_with(
'veth_0', bridge='br-int')
self.agent.ovs_idl.del_port.assert_called_once_with('veth_0')
del_veth.assert_called_once_with('veth_0')
garbage_collect.assert_called_once()

@@ -224,8 +225,15 @@ class TestMetadataAgent(base.BaseTestCase):
driver.MetadataDriver,
'spawn_monitored_metadata_proxy') as spawn_mdp:

# Simulate that the VETH pair was already present in 'br-fake'.
# We need to assert that it was deleted first.
self.agent.ovs_idl.list_br.return_value.execute.return_value = (
['br-int', 'br-fake'])
self.agent.provision_datapath('1')

# Check that the port was deleted from br-fake
self.agent.ovs_idl.del_port.assert_called_once_with(
'veth_0', bridge='br-fake', if_exists=True)
# Check that the VETH pair is created
add_veth.assert_called_once_with('veth_0', 'veth_1', 'namespace')
# Make sure that the two ends of the VETH pair have been set as up.

Loading…
Cancel
Save