Disable DHCP on agent port removal

The previous logic was just ripping the interface out without
stopping dnsmasq. This would lead to a file handle remaining to the
interface which would cause OVS to completely freak out and assign
the same ofport to multiple ports.

This preserves the behavior introduced in
I40b85033d075562c43ce4d0e68296211b3241197 but just fully disables
DHCP rather than relying on an exception generation to cause the
resync.

Closes-bug: #1624701
Change-Id: Icdd9ac136eeb3707c912853b134dbb58109e6940
This commit is contained in:
Kevin Benton 2016-09-15 14:10:20 -07:00
parent 27928c0ddf
commit 251922f5de
4 changed files with 19 additions and 11 deletions

View File

@ -409,7 +409,14 @@ class DhcpAgent(manager.Manager):
if port:
network = self.cache.get_network_by_id(port.network_id)
self.cache.remove_port(port)
self.call_driver('reload_allocations', network)
if self._is_port_on_this_agent(port):
# the agent's port has been deleted. disable the service
# and add the network to the resync list to create
# (or acquire a reserved) port.
self.call_driver('disable', network)
self.schedule_resync("Agent port was deleted", port.network_id)
else:
self.call_driver('reload_allocations', network)
def enable_isolated_metadata_proxy(self, network):

View File

@ -793,15 +793,10 @@ class Dnsmasq(DhcpLocalProcess):
# here is dhcpv6 stuff needed to craft dhcpv6 packet
v6_leases = self._read_v6_leases_file_leases(leases_filename)
new_leases = set()
dhcp_port_exists = False
dhcp_port_on_this_host = self.device_manager.get_device_id(
self.network)
for port in self.network.ports:
client_id = self._get_client_id(port)
for alloc in port.fixed_ips:
new_leases.add((alloc.ip_address, port.mac_address, client_id))
if port.device_id == dhcp_port_on_this_host:
dhcp_port_exists = True
for ip, mac, client_id in old_leases - new_leases:
entry = v6_leases.get(ip, None)
@ -816,9 +811,6 @@ class Dnsmasq(DhcpLocalProcess):
elif version == constants.IP_VERSION_4:
self._release_lease(mac, ip, client_id)
if not dhcp_port_exists:
self.device_manager.unplug(self.interface_name, self.network)
def _output_addn_hosts_file(self):
"""Writes a dnsmasq compatible additional hosts file.

View File

@ -1098,6 +1098,17 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
self.cache.assert_has_calls([mock.call.get_port_by_id('unknown')])
self.assertEqual(self.call_driver.call_count, 0)
def test_port_delete_end_agents_port(self):
port = dhcp.DictModel(copy.deepcopy(fake_port1))
device_id = utils.get_dhcp_agent_device_id(
port.network_id, self.dhcp.conf.host)
port['device_id'] = device_id
self.cache.get_network_by_id.return_value = fake_network
self.cache.get_port_by_id.return_value = port
self.dhcp.port_delete_end(None, {'port_id': port.id})
self.call_driver.assert_has_calls(
[mock.call.call_driver('disable', fake_network)])
class TestDhcpPluginApiProxy(base.BaseTestCase):
def _test_dhcp_api(self, method, **kwargs):

View File

@ -1675,8 +1675,6 @@ class TestDnsmasq(TestBase):
0xff),
],
any_order=True)
dnsmasq.device_manager.unplug.assert_has_calls(
[mock.call(dnsmasq.interface_name, dnsmasq.network)])
def test_release_for_ipv6_lease(self):
dnsmasq = self._get_dnsmasq(FakeDualNetwork())