Skip to content

Commit 37abd72

Browse files
committed
[OVN] DB sync host/physnet - filter on agent_type
When syncing hostname and physical networks, filter neutron hosts on agent_type. Only segmenthostmappings for hosts with agent 'OVN Controller agent' should be cleaned up. Since change: I935186b6ee95f0cae8dc05869d9742c8fb3353c3 there is de-duplication of segmenthostmapping updates from agents. If the OVN DB sync clears/deletes mappings for hosts owned by other agents/plugins the mappings are never re-created. Closes-Bug: #2040172 Change-Id: Iaf15e560e1b1ec31618b2ebc6206a938463c1094 Signed-off-by: Harald Jensås <[email protected]> (cherry picked from commit 71d69cf6277ba553354512209a2bff61c013f8ea) (cherry picked from commit 4eb234a)
1 parent 7d8ea71 commit 37abd72

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1344,7 +1344,8 @@ def sync_hostname_and_physical_networks(self, ctx):
13441344
LOG.debug('OVN-SB Sync hostname and physical networks started')
13451345
host_phynets_map = self.ovn_api.get_chassis_hostname_and_physnets()
13461346
current_hosts = set(host_phynets_map)
1347-
previous_hosts = segments_db.get_hosts_mapped_with_segments(ctx)
1347+
previous_hosts = segments_db.get_hosts_mapped_with_segments(
1348+
ctx, include_agent_types={ovn_const.OVN_CONTROLLER_AGENT})
13481349

13491350
stale_hosts = previous_hosts - current_hosts
13501351
for host in stale_hosts:

neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,6 +1794,22 @@ def setUp(self):
17941794
def _sync_resources(self):
17951795
self.sb_synchronizer.sync_hostname_and_physical_networks(self.ctx)
17961796

1797+
def create_agent(self, host, bridge_mappings=None, agent_type=None):
1798+
if agent_type is None:
1799+
agent_type = ovn_const.OVN_CONTROLLER_AGENT
1800+
if bridge_mappings is None:
1801+
bridge_mappings = {}
1802+
agent = {
1803+
'host': host,
1804+
'agent_type': agent_type,
1805+
'binary': '/bin/test',
1806+
'topic': 'test_topic',
1807+
'configurations': {'bridge_mappings': bridge_mappings}
1808+
}
1809+
_, status = self.plugin.create_or_update_agent(self.context, agent)
1810+
1811+
return status['id']
1812+
17971813
def create_segment(self, network_id, physical_network, segmentation_id):
17981814
segment_data = {'network_id': network_id,
17991815
'physical_network': physical_network,
@@ -1834,6 +1850,7 @@ def test_ovn_sb_sync_delete_stale_host(self):
18341850
segment = self.create_segment(network_id, 'physnet1', 50)
18351851
segments_db.update_segment_host_mapping(
18361852
self.ctx, 'host1', {segment['id']})
1853+
_ = self.create_agent('host1', bridge_mappings={'physnet1': 'eth0'})
18371854
segment_hosts = segments_db.get_hosts_mapped_with_segments(self.ctx)
18381855
self.assertEqual({'host1'}, segment_hosts)
18391856
# Since there is no chassis in the sb DB, host1 is the stale host
@@ -1842,6 +1859,36 @@ def test_ovn_sb_sync_delete_stale_host(self):
18421859
segment_hosts = segments_db.get_hosts_mapped_with_segments(self.ctx)
18431860
self.assertFalse(segment_hosts)
18441861

1862+
def test_ovn_sb_sync_host_with_no_agent_not_deleted(self):
1863+
with self.network() as network:
1864+
network_id = network['network']['id']
1865+
segment = self.create_segment(network_id, 'physnet1', 50)
1866+
segments_db.update_segment_host_mapping(
1867+
self.ctx, 'host1', {segment['id']})
1868+
_ = self.create_agent('host1', bridge_mappings={'physnet1': 'eth0'},
1869+
agent_type="Not OVN Agent")
1870+
segment_hosts = segments_db.get_hosts_mapped_with_segments(self.ctx)
1871+
self.assertEqual({'host1'}, segment_hosts)
1872+
# There is no chassis in the sb DB, host1 does not have an agent
1873+
# so it is not deleted.
1874+
self._sync_resources()
1875+
segment_hosts = segments_db.get_hosts_mapped_with_segments(self.ctx)
1876+
self.assertEqual({'host1'}, segment_hosts)
1877+
1878+
def test_ovn_sb_sync_host_with_other_agent_type_not_deleted(self):
1879+
with self.network() as network:
1880+
network_id = network['network']['id']
1881+
segment = self.create_segment(network_id, 'physnet1', 50)
1882+
segments_db.update_segment_host_mapping(
1883+
self.ctx, 'host1', {segment['id']})
1884+
segment_hosts = segments_db.get_hosts_mapped_with_segments(self.ctx)
1885+
self.assertEqual({'host1'}, segment_hosts)
1886+
# There is no chassis in the sb DB, host1 does not have an agent
1887+
# so it is not deleted.
1888+
self._sync_resources()
1889+
segment_hosts = segments_db.get_hosts_mapped_with_segments(self.ctx)
1890+
self.assertEqual({'host1'}, segment_hosts)
1891+
18451892
def test_ovn_sb_sync(self):
18461893
with self.network() as network:
18471894
network_id = network['network']['id']
@@ -1854,6 +1901,9 @@ def test_ovn_sb_sync(self):
18541901
segments_db.update_segment_host_mapping(
18551902
self.ctx, 'host3', {seg1['id']})
18561903
segment_hosts = segments_db.get_hosts_mapped_with_segments(self.ctx)
1904+
_ = self.create_agent('host1')
1905+
_ = self.create_agent('host2', bridge_mappings={'physnet2': 'eth0'})
1906+
_ = self.create_agent('host3', bridge_mappings={'physnet3': 'eth0'})
18571907
self.assertEqual({'host1', 'host2', 'host3'}, segment_hosts)
18581908
self.add_fake_chassis('host2', ['physnet2'])
18591909
self.add_fake_chassis('host3', ['physnet3'])

neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1169,8 +1169,10 @@ def test_ovn_sb_sync(self):
11691169

11701170
with mock.patch.object(ovn_db_sync.segments_db,
11711171
'get_hosts_mapped_with_segments',
1172-
return_value=hosts_in_neutron):
1172+
return_value=hosts_in_neutron) as mock_ghmws:
11731173
ovn_sb_synchronizer.sync_hostname_and_physical_networks(mock.ANY)
1174+
mock_ghmws.assert_called_once_with(
1175+
mock.ANY, include_agent_types={ovn_const.OVN_CONTROLLER_AGENT})
11741176
all_hosts = set(hostname_with_physnets.keys()) | hosts_in_neutron
11751177
self.assertEqual(
11761178
len(all_hosts),
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
fixes:
3+
- |
4+
When synchronizing the OVN databases, either when running the migration
5+
command or during startup, the code responsible for synchronization will
6+
only clean up segment-to-host mappings for hosts with agent_type
7+
``OVN Controller agent``. Before, the synchronization would clean up
8+
(delete) segment-to-host mappings for non-OVN hosts. Fixes bug:
9+
`2040172 <https://bugs.launchpad.net/neutron/+bug/2040172>`_.
10+

0 commit comments

Comments
 (0)