diff --git a/neutron/agent/dhcp/agent.py b/neutron/agent/dhcp/agent.py index b2f14df2d7a..44fa3686885 100644 --- a/neutron/agent/dhcp/agent.py +++ b/neutron/agent/dhcp/agent.py @@ -245,6 +245,12 @@ class DhcpAgent(manager.Manager): if subnet.ip_version == 4 and subnet.enable_dhcp: self.enable_isolated_metadata_proxy(network) break + elif (self.conf.use_namespaces and not self.conf.force_metadata and + not self.conf.enable_isolated_metadata): + # In the case that the dhcp agent ran with metadata enabled, + # and dhcp agent now starts with metadata disabled, check and + # delete any metadata_proxy. + self.disable_isolated_metadata_proxy(network) def disable_dhcp_helper(self, network_id): """Disable DHCP for a network known to the agent.""" diff --git a/neutron/tests/functional/agent/test_dhcp_agent.py b/neutron/tests/functional/agent/test_dhcp_agent.py index 40238a8c826..984b61c66cf 100644 --- a/neutron/tests/functional/agent/test_dhcp_agent.py +++ b/neutron/tests/functional/agent/test_dhcp_agent.py @@ -27,6 +27,7 @@ from neutron.agent.common import ovs_lib from neutron.agent.dhcp import agent from neutron.agent import dhcp_agent from neutron.agent.linux import dhcp +from neutron.agent.linux import external_process from neutron.agent.linux import interface from neutron.agent.linux import ip_lib from neutron.agent.linux import utils @@ -80,6 +81,8 @@ class DHCPAgentOVSTestFramework(base.BaseSudoTestCase): self.ovs_driver = interface.OVSInterfaceDriver(self.conf) + self.conf.set_override('check_child_processes_interval', 1, 'AGENT') + def network_dict_for_dhcp(self, dhcp_enabled=True, ip_version=4): net_id = uuidutils.generate_uuid() subnet_dict = self.create_subnet_dict( @@ -232,6 +235,12 @@ class DHCPAgentOVSTestFramework(base.BaseSudoTestCase): self.addCleanup(proc.wait) self.addCleanup(proc.kill) + def _get_metadata_proxy_process(self, network): + return external_process.ProcessManager( + self.conf, + network.id, + network.namespace) + class DHCPAgentOVSTestCase(DHCPAgentOVSTestFramework): @@ -260,3 +269,38 @@ class DHCPAgentOVSTestCase(DHCPAgentOVSTestFramework): port.mac_address = str(bad_mac_address) self._plug_port_for_dhcp_request(network, port) self.assert_bad_allocation_for_port(network, port) + + def _spawn_network_metadata_proxy(self): + network = self.network_dict_for_dhcp() + self.conf.set_override('enable_isolated_metadata', True) + self.addCleanup(self.agent.disable_isolated_metadata_proxy, network) + self.configure_dhcp_for_network(network=network) + pm = self._get_metadata_proxy_process(network) + utils.wait_until_true( + lambda: pm.active, + timeout=5, + sleep=0.01, + exception=RuntimeError("Metadata proxy didn't spawn")) + return (pm, network) + + def test_metadata_proxy_respawned(self): + pm, network = self._spawn_network_metadata_proxy() + old_pid = pm.pid + + utils.execute(['kill', '-9', old_pid], run_as_root=True) + utils.wait_until_true( + lambda: pm.active and pm.pid != old_pid, + timeout=5, + sleep=0.1, + exception=RuntimeError("Metadata proxy didn't respawn")) + + def test_stale_metadata_proxy_killed(self): + pm, network = self._spawn_network_metadata_proxy() + + self.conf.set_override('enable_isolated_metadata', False) + self.configure_dhcp_for_network(network=network) + utils.wait_until_true( + lambda: not pm.active, + timeout=5, + sleep=0.1, + exception=RuntimeError("Stale metadata proxy didn't get killed")) diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index a1953f462d2..b55204b0627 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -617,11 +617,14 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): mock.call.get_network_info(network.id)]) self.call_driver.assert_called_once_with('enable', network) self.cache.assert_has_calls([mock.call.put(network)]) - if is_isolated_network: + if is_isolated_network and enable_isolated_metadata: self.external_process.assert_has_calls([ self._process_manager_constructor_call(), - mock.call().enable() - ]) + mock.call().enable()]) + elif not enable_isolated_metadata: + self.external_process.assert_has_calls([ + self._process_manager_constructor_call(ns=None), + mock.call().disable()]) else: self.assertFalse(self.external_process.call_count) @@ -723,6 +726,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase): def test_enable_dhcp_helper_driver_failure(self): self.plugin.get_network_info.return_value = fake_network self.call_driver.return_value = False + cfg.CONF.set_override('enable_isolated_metadata', True) self.dhcp.enable_dhcp_helper(fake_network.id) self.plugin.assert_has_calls( [mock.call.get_network_info(fake_network.id)])