From 5b0ea0320236d05bc3af0cb338e03f3c3cde040a Mon Sep 17 00:00:00 2001 From: Hong Hui Xiao Date: Wed, 8 Jun 2016 12:18:53 +0000 Subject: [PATCH] Mark port as ready after enabling dhcp at agent When subnet is created and network is scheduled to dhcp agent, the dhcp agent will request neutron server to create dhcp port. Neutron server will create and mark port as BUILD and wait for the ready signal from dhcp agent. dhcp agent will create 'real' dhcp port after getting response from neutron server. But after that, dhcp agent will not tell neutron server that the dhcp port is ready. So, the reported bug can be observed. If ports are created before dhcp is enabled for network, dhcp agent will not mark ports as 'ready' as there is no network cache. This patch also marks all ports in network as ready, in case that happens. Change-Id: I363d8727f7ef6e6e08be4b0022c6464d51692b85 Closes-bug: #1588906 --- neutron/agent/dhcp/agent.py | 4 ++++ .../tests/functional/agent/test_dhcp_agent.py | 18 ++++++++++++++++++ neutron/tests/unit/agent/dhcp/test_agent.py | 6 ++++++ 3 files changed, 28 insertions(+) diff --git a/neutron/agent/dhcp/agent.py b/neutron/agent/dhcp/agent.py index 4602a3c4c53..c4b38885656 100644 --- a/neutron/agent/dhcp/agent.py +++ b/neutron/agent/dhcp/agent.py @@ -277,6 +277,10 @@ class DhcpAgent(manager.Manager): if self.call_driver('enable', network): dhcp_network_enabled = True self.cache.put(network) + # After enabling dhcp for network, mark all existing + # ports as ready. So that the status of ports which are + # created before enabling dhcp can be updated. + self.dhcp_ready_ports |= {p.id for p in network.ports} break if enable_metadata and dhcp_network_enabled: diff --git a/neutron/tests/functional/agent/test_dhcp_agent.py b/neutron/tests/functional/agent/test_dhcp_agent.py index 041367c6c5b..383102d2d6b 100644 --- a/neutron/tests/functional/agent/test_dhcp_agent.py +++ b/neutron/tests/functional/agent/test_dhcp_agent.py @@ -19,6 +19,7 @@ import eventlet import fixtures import mock import netaddr +from neutron_lib import constants as lib_const from oslo_config import fixture as fixture_config from oslo_utils import uuidutils @@ -313,3 +314,20 @@ class DHCPAgentOVSTestCase(DHCPAgentOVSTestFramework): timeout=5, sleep=0.1, exception=RuntimeError("Stale metadata proxy didn't get killed")) + + def test_notify_port_ready_after_enable_dhcp(self): + network = self.network_dict_for_dhcp() + dhcp_port = self.create_port_dict( + network.id, network.subnets[0].id, + '24:77:03:7d:00:4d', ip_address='192.168.10.11') + dhcp_port.device_owner = lib_const.DEVICE_OWNER_DHCP + network.ports.append(dhcp_port) + self.agent.start_ready_ports_loop() + self.configure_dhcp_for_network(network) + ports_to_send = {p.id for p in network.ports} + utils.wait_until_true( + lambda: self.mock_plugin_api.dhcp_ready_on_ports.called, + timeout=1, + sleep=0.1, + exception=RuntimeError("'dhcp_ready_on_ports' not be called")) + self.mock_plugin_api.dhcp_ready_on_ports.assert_called_with(ports_to_send) diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index 0cd5bb84157..4911df332df 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -467,6 +467,12 @@ class TestDhcpAgent(base.BaseTestCase): # should have been called with all ports again after the failure ready.assert_has_calls([mock.call(set(range(4)))] * 2) + def test_dhcp_ready_ports_updates_after_enable_dhcp(self): + dhcp = dhcp_agent.DhcpAgent(HOSTNAME) + self.assertEqual(set(), dhcp.dhcp_ready_ports) + dhcp.configure_dhcp_for_network(fake_network) + self.assertEqual({fake_port1.id}, dhcp.dhcp_ready_ports) + def test_report_state_revival_logic(self): dhcp = dhcp_agent.DhcpAgentWithStateReport(HOSTNAME) with mock.patch.object(dhcp.state_rpc,