From e3b3ec930967305e5fce314c0a4cf74151ad711c Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Wed, 13 Apr 2022 23:38:04 +0000 Subject: [PATCH] [DHCP] Break reference chain to any Exception object when resync In the DHCP agent, if an exception is raised during the driver call, "DhcpAgent.schedule_resync" is called. Before this patch, the exception instance was passed instead of a string. This instance reference was stored in the dictionary "needs_resync_reasons" and used in "_periodic_resync_helper" to resync the DHCP agent information. The call to "sync_state" passed the dictionary ".keys()" method. In python2.7 when that was implemented, this method was creating a list with the dictionary keys. In python3, this method is a generator that holds the dictionary content. This patch breaks this reference chain in two points (actually only one is needed): - "sync_state" now passes a list created from the mentioned generator. - The dictionary "needs_resync_reasons" now stores the exception strings only, instead of the exception instance. Closes-Bug: #1969270 Change-Id: I07e9818021283d321fc32066be7e0f8e2b81e639 --- neutron/agent/dhcp/agent.py | 4 ++-- neutron/tests/unit/agent/dhcp/test_agent.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/neutron/agent/dhcp/agent.py b/neutron/agent/dhcp/agent.py index a5718409867..2ecc0705ed4 100644 --- a/neutron/agent/dhcp/agent.py +++ b/neutron/agent/dhcp/agent.py @@ -237,7 +237,7 @@ class DhcpAgent(manager.Manager): # allocation failure. When the subnet is updated with a new # allocation pool or a port is deleted to free up an IP, this # will automatically be retried on the notification - self.schedule_resync(e, network.id) + self.schedule_resync(str(e), network.id) if (isinstance(e, oslo_messaging.RemoteError) and e.exc_type == 'NetworkNotFound' or isinstance(e, exceptions.NetworkNotFound)): @@ -362,7 +362,7 @@ class DhcpAgent(manager.Manager): net = "*" LOG.debug("resync (%(network)s): %(reason)s", {"reason": r, "network": net}) - self.sync_state(reasons.keys()) + self.sync_state(list(reasons.keys())) def periodic_resync(self): """Spawn a thread to periodically resync the dhcp state.""" diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index d56ca1579cf..6fa8b174955 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -672,7 +672,7 @@ class TestDhcpAgent(base.BaseTestCase): sync_state.side_effect = RuntimeError with testtools.ExpectedException(RuntimeError): dhcp._periodic_resync_helper() - sync_state.assert_called_once_with(resync_reasons.keys()) + sync_state.assert_called_once_with(list(resync_reasons.keys())) self.assertEqual(0, len(dhcp.needs_resync_reasons)) def test_periodic_resync_helper_with_event(self): @@ -680,7 +680,7 @@ class TestDhcpAgent(base.BaseTestCase): dhcp = dhcp_agent.DhcpAgent(HOSTNAME) dhcp.schedule_resync('reason1', 'a') dhcp.schedule_resync('reason1', 'b') - reasons = dhcp.needs_resync_reasons.keys() + reasons = list(dhcp.needs_resync_reasons.keys()) with mock.patch.object(dhcp, 'sync_state') as sync_state: sync_state.side_effect = RuntimeError with testtools.ExpectedException(RuntimeError):