From 8cf394b896e3644ff51edf6a0d462501fb6e6843 Mon Sep 17 00:00:00 2001 From: Stephen Ma Date: Sun, 27 Oct 2013 08:14:21 -0700 Subject: [PATCH] Delete DHCP port without DHCP server on a net node A DHCP-network was deleted from one host using neutron dhcp-agent-network-remove and then added to another host using neutron dhcp-agent-network-add command. While the dhcp-agent-network-remove command was in progress, the host crashed. As a result, the removal of the DHCP-network was partially done. The network was disassociated from the agent in mysql. However, the agent never made the release_dhcp_port RPC call to delete the port -- even after the agent restarted. The end result is that there are two DHCP ports for the same network. One of these is found on the host that is no longer hosting the dhcp-server. This fix make the DHCP agent invoke the release_dhcp_port RPC call on a stale network whose dnsmasq process is not running (not active). Before this change, the RPC call is made on a stale network only when the dnsmasq process is running. Closes-Bug: #1244860 Change-Id: Ie0bafdac698810b5455550c306c6a75ddf91d9bb --- neutron/agent/linux/dhcp.py | 18 ++++++++++-------- neutron/tests/unit/test_linux_dhcp.py | 8 ++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index 3a26dc263..42dd7c295 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -173,15 +173,17 @@ class DhcpLocalProcess(DhcpBase): """Disable DHCP for this network by killing the local process.""" pid = self.pid - if self.active: - cmd = ['kill', '-9', pid] - utils.execute(cmd, self.root_helper) + if pid: + if self.active: + cmd = ['kill', '-9', pid] + utils.execute(cmd, self.root_helper) + else: + LOG.debug(_('DHCP for %(net_id)s is stale, pid %(pid)d ' + 'does not exist, performing cleanup'), + {'net_id': self.network.id, 'pid': pid}) if not retain_port: - self.device_manager.destroy(self.network, self.interface_name) - - elif pid: - LOG.debug(_('DHCP for %(net_id)s pid %(pid)d is stale, ignoring ' - 'command'), {'net_id': self.network.id, 'pid': pid}) + self.device_manager.destroy(self.network, + self.interface_name) else: LOG.debug(_('No DHCP started for %s'), self.network.id) diff --git a/neutron/tests/unit/test_linux_dhcp.py b/neutron/tests/unit/test_linux_dhcp.py index 1a6723d04..e3c060763 100644 --- a/neutron/tests/unit/test_linux_dhcp.py +++ b/neutron/tests/unit/test_linux_dhcp.py @@ -539,10 +539,14 @@ class TestDhcpLocalProcess(TestBase): mocks['pid'].__get__ = mock.Mock(return_value=5) mocks['interface_name'].__get__ = mock.Mock(return_value='tap0') with mock.patch.object(dhcp.LOG, 'debug') as log: - lp = LocalChild(self.conf, FakeDualNetwork()) + network = FakeDualNetwork() + lp = LocalChild(self.conf, network) + lp.device_manager = mock.Mock() lp.disable() msg = log.call_args[0][0] - self.assertIn('stale', msg) + self.assertIn('does not exist', msg) + lp.device_manager.destroy.assert_called_once_with( + network, 'tap0') def test_disable_unknown_network(self): attrs_to_mock = dict([(a, mock.DEFAULT) for a in -- 2.45.2