From 4faac331682d517bf8ad4ef97414632d0ab44d6b Mon Sep 17 00:00:00 2001 From: Daniel Alvarez Date: Mon, 5 Mar 2018 18:05:54 +0100 Subject: [PATCH] Spawn/stop metadata proxies upon adding/deleting router interfaces When a network becomes isolated and isolated_metadata_enabled=True, the DHCP agent won't spawn the required metadata proxy instance unless the agent gets restarted. Similarly, it won't stop them when the network is no longer isolated. This patch fixes it by updating the isolated metadata proxy on port_update_end and port_delete_end methods which are invoked every time a router interface port is added, updated or deleted. Change-Id: I5c197a5755135357c6465dfe4803019a2ad52c14 Closes-Bug: #1753540 Signed-off-by: Daniel Alvarez (cherry picked from 9362d4f1f21df2a27c818bb0c2918241eb67e3d0) (cherry picked from commit b07aa19deb82604b954f323a76c70cc623601ca7) --- neutron/agent/dhcp/agent.py | 2 + neutron/tests/unit/agent/dhcp/test_agent.py | 51 ++++++++++++--------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/neutron/agent/dhcp/agent.py b/neutron/agent/dhcp/agent.py index 6c093496e0f..4722e0fd5c3 100644 --- a/neutron/agent/dhcp/agent.py +++ b/neutron/agent/dhcp/agent.py @@ -438,6 +438,7 @@ class DhcpAgent(manager.Manager): self.cache.put_port(updated_port) self.call_driver(driver_action, network) self.dhcp_ready_ports.add(updated_port.id) + self.update_isolated_metadata_proxy(network) def _is_port_on_this_agent(self, port): thishost = utils.get_dhcp_agent_device_id( @@ -468,6 +469,7 @@ class DhcpAgent(manager.Manager): self.schedule_resync("Agent port was deleted", port.network_id) else: self.call_driver('reload_allocations', network) + self.update_isolated_metadata_proxy(network) def update_isolated_metadata_proxy(self, network): """Spawn or kill metadata proxy. diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index e4d197c3861..4cb1c26bcd0 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -1013,12 +1013,15 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): payload = dict(port=fake_port2) self.cache.get_network_by_id.return_value = fake_network self.cache.get_port_by_id.return_value = fake_port2 - self.dhcp.port_update_end(None, payload) - self.cache.assert_has_calls( - [mock.call.get_network_by_id(fake_port2.network_id), - mock.call.put_port(mock.ANY)]) - self.call_driver.assert_called_once_with('reload_allocations', - fake_network) + with mock.patch.object( + self.dhcp, 'update_isolated_metadata_proxy') as ump: + self.dhcp.port_update_end(None, payload) + self.cache.assert_has_calls( + [mock.call.get_network_by_id(fake_port2.network_id), + mock.call.put_port(mock.ANY)]) + self.call_driver.assert_called_once_with('reload_allocations', + fake_network) + self.assertTrue(ump.called) def test_port_update_end_grabs_lock(self): payload = dict(port=fake_port2) @@ -1034,12 +1037,15 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): updated_fake_port1 = copy.deepcopy(fake_port1) updated_fake_port1.fixed_ips[0].ip_address = '172.9.9.99' self.cache.get_port_by_id.return_value = updated_fake_port1 - self.dhcp.port_update_end(None, payload) - self.cache.assert_has_calls( - [mock.call.get_network_by_id(fake_port1.network_id), - mock.call.put_port(mock.ANY)]) - self.call_driver.assert_has_calls( - [mock.call.call_driver('reload_allocations', fake_network)]) + with mock.patch.object( + self.dhcp, 'update_isolated_metadata_proxy') as ump: + self.dhcp.port_update_end(None, payload) + self.cache.assert_has_calls( + [mock.call.get_network_by_id(fake_port1.network_id), + mock.call.put_port(mock.ANY)]) + self.call_driver.assert_has_calls( + [mock.call.call_driver('reload_allocations', fake_network)]) + self.assertTrue(ump.called) def test_port_update_change_subnet_on_dhcp_agents_port(self): self.cache.get_network_by_id.return_value = fake_network @@ -1092,15 +1098,18 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): self.cache.get_network_by_id.return_value = fake_network self.cache.get_port_by_id.return_value = fake_port2 - self.dhcp.port_delete_end(None, payload) - self.cache.assert_has_calls( - [mock.call.get_port_by_id(fake_port2.id), - mock.call.deleted_ports.add(fake_port2.id), - mock.call.get_port_by_id(fake_port2.id), - mock.call.get_network_by_id(fake_network.id), - mock.call.remove_port(fake_port2)]) - self.call_driver.assert_has_calls( - [mock.call.call_driver('reload_allocations', fake_network)]) + with mock.patch.object( + self.dhcp, 'update_isolated_metadata_proxy') as ump: + self.dhcp.port_delete_end(None, payload) + self.cache.assert_has_calls( + [mock.call.get_port_by_id(fake_port2.id), + mock.call.deleted_ports.add(fake_port2.id), + mock.call.get_port_by_id(fake_port2.id), + mock.call.get_network_by_id(fake_network.id), + mock.call.remove_port(fake_port2)]) + self.call_driver.assert_has_calls( + [mock.call.call_driver('reload_allocations', fake_network)]) + self.assertTrue(ump.called) def test_port_delete_end_unknown_port(self): payload = dict(port_id='unknown')