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 <sahid.ferdjaoui@industrialdiscipline.com>
Change-Id: Icd57570004055903c6817a75d814ed65db3fa53c
This commit is contained in:
Sahid Orentino Ferdjaoui 2022-02-14 13:52:10 +01:00 committed by Sahid Orentino Ferdjaoui
parent fc3d3cc824
commit b5b519a4fa
2 changed files with 22 additions and 6 deletions

View File

@ -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'])

View File

@ -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()