From b5b519a4faa52677d5b9d5553217ed40aac70483 Mon Sep 17 00:00:00 2001 From: Sahid Orentino Ferdjaoui Date: Mon, 14 Feb 2022 13:52:10 +0100 Subject: [PATCH] segments: fix scheduling duplicate segments It has been reported by bug #1959750 that for a given network the agent is scheduling all segments reported by agent. This commit is fixing the issue by ensuring scheduling segments per network that they belong to only. A test has been updated to demonstract the fact that for a given network we only schedule the related segments. Closes-bug: #1959750 Signed-off-by: Sahid Orentino Ferdjaoui Change-Id: Icd57570004055903c6817a75d814ed65db3fa53c --- neutron/db/agentschedulers_db.py | 7 ++++++- .../tests/unit/db/test_agentschedulers_db.py | 21 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/neutron/db/agentschedulers_db.py b/neutron/db/agentschedulers_db.py index 52af486e7cc..e43befd89fb 100644 --- a/neutron/db/agentschedulers_db.py +++ b/neutron/db/agentschedulers_db.py @@ -500,8 +500,13 @@ class DhcpAgentSchedulerDbMixin(dhcpagentscheduler subnets = subnet_obj.Subnet.get_objects( payload.context, segment_id=segment_ids) network_ids = {s.network_id for s in subnets} + + # pre-compute net-id per segments. + netsegs = {} + [netsegs.setdefault(s['network_id'], []).append(s) + for s in segments if 'network_id' in s] for network_id in network_ids: - for segment in segments: + for segment in netsegs.get(network_id, []): self._schedule_network( payload.context, network_id, dhcp_notifier, candidate_hosts=segment['hosts']) diff --git a/neutron/tests/unit/db/test_agentschedulers_db.py b/neutron/tests/unit/db/test_agentschedulers_db.py index 729f6f87a8b..09b4e70870e 100644 --- a/neutron/tests/unit/db/test_agentschedulers_db.py +++ b/neutron/tests/unit/db/test_agentschedulers_db.py @@ -1595,10 +1595,16 @@ class OvsDhcpAgentNotifierTestCase(test_agent.AgentDBTestMixIn, payload = events.DBEventPayload( ctx, metadata={'host': 'HOST A', - 'current_segment_ids': set(['segment-1'])}) + 'current_segment_ids': set([ + 'segment-1', 'segment-2', 'segment-3'])}) segments_plugin = mock.Mock() segments_plugin.get_segments.return_value = [ - {'id': 'segment-1', 'hosts': ['HOST A']}] + {'id': 'segment-1', 'hosts': ['HOST A'], + 'network_id': 'net-1'}, + {'id': 'segment-2', 'hosts': ['HOST A', 'HOST B'], + 'network_id': 'net-1'}, + {'id': 'segment-3', 'hosts': ['HOST A', 'HOST C'], + 'network_id': 'net-2'}] dhcp_notifier = mock.Mock() dhcp_mixin = agentschedulers_db.DhcpAgentSchedulerDbMixin() with mock.patch( @@ -1618,9 +1624,14 @@ class OvsDhcpAgentNotifierTestCase(test_agent.AgentDBTestMixIn, resources.SEGMENT_HOST_MAPPING, events.AFTER_CREATE, ctx, payload) if subnet_on_segment: - schedule_network.assert_called_once_with( - ctx, subnet_on_segment.network_id, - dhcp_notifier, candidate_hosts=['HOST A']) + self.assertEqual(schedule_network.mock_calls, [ + mock.call( + ctx, subnet_on_segment.network_id, + dhcp_notifier, candidate_hosts=['HOST A']), + mock.call( + ctx, subnet_on_segment.network_id, + dhcp_notifier, candidate_hosts=['HOST A', 'HOST B']) + ]) else: schedule_network.assert_not_called()