From f0e8356d04d04600c072a1c0f0bdf274ff19ab8c Mon Sep 17 00:00:00 2001 From: sridhargaddam Date: Mon, 27 Jul 2015 03:46:48 +0000 Subject: [PATCH] Update dhcp agent cache for network:dhcp ports When a network with a dhcp_enabled subnet is scheduled on a dhcp agent, dhcp driver creates the network:dhcp port for the subnet. However, the port info is not updated in dhcp agents internal cache. Subsequently if the user deletes the network:dhcp port, the port is properly deleted on the server side (i.e., in the database) and when the port_delete_end notification is sent to the dhcp agent, it simply ignores it as the port entry would be missing in the cache. This patch fixes this issue by updating the dhcp agents cache when dhcp driver creates the network:dhcp port for the subnets. Closes-Bug: #1478426 Change-Id: I69f5834dd964a4320c606c4e0aa2cdba70416943 --- neutron/agent/linux/dhcp.py | 9 ++++++++ neutron/tests/unit/agent/dhcp/test_agent.py | 25 +++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index e7159893b..efdf12fa3 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -1056,9 +1056,18 @@ class DeviceManager(object): return dhcp_port + def _update_dhcp_port(self, network, port): + for index in range(len(network.ports)): + if network.ports[index].id == port.id: + network.ports[index] = port + break + else: + network.ports.append(port) + def setup(self, network): """Create and initialize a device for network's DHCP on this host.""" port = self.setup_dhcp_port(network) + self._update_dhcp_port(network, port) interface_name = self.get_interface_name(network, port) if ip_lib.ensure_device_is_ready(interface_name, diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index a64e98387..d1c7226d8 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -102,6 +102,14 @@ fake_port1 = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab', network_id='12345678-1234-5678-1234567890ab', fixed_ips=[fake_fixed_ip1])) +fake_dhcp_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-123456789022', + device_id='dhcp-12345678-1234-aaaa-123456789022', + device_owner='network:dhcp', + allocation_pools=fake_subnet1_allocation_pools, + mac_address='aa:bb:cc:dd:ee:22', + network_id='12345678-1234-5678-1234567890ab', + fixed_ips=[fake_fixed_ip2])) + fake_port2 = dhcp.DictModel(dict(id='12345678-1234-aaaa-123456789000', device_id='dhcp-12345678-1234-aaaa-123456789000', device_owner='', @@ -1254,6 +1262,23 @@ class TestDeviceManager(base.BaseTestCase): expected = [mock.call.add_rule('POSTROUTING', rule)] self.mangle_inst.assert_has_calls(expected) + def test_setup_create_dhcp_port(self): + plugin = mock.Mock() + net = copy.deepcopy(fake_network) + plugin.create_dhcp_port.return_value = fake_dhcp_port + dh = dhcp.DeviceManager(cfg.CONF, plugin) + dh.setup(net) + + plugin.assert_has_calls([ + mock.call.create_dhcp_port( + {'port': {'name': '', 'admin_state_up': True, + 'network_id': net.id, + 'tenant_id': net.tenant_id, + 'fixed_ips': [{'subnet_id': + fake_dhcp_port.fixed_ips[0].subnet_id}], + 'device_id': mock.ANY}})]) + self.assertIn(fake_dhcp_port, net.ports) + def test_setup_ipv6(self): self._test_setup_helper(True, net=fake_network_ipv6, port=fake_ipv6_port) -- 2.45.2