]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Reload DHCP interface when its port is updated
authorKevin Benton <blak111@gmail.com>
Thu, 12 Mar 2015 09:06:47 +0000 (02:06 -0700)
committerKevin Benton <blak111@gmail.com>
Fri, 27 Mar 2015 07:53:51 +0000 (00:53 -0700)
When a DHCP port corresponding to a DHCP agent is updated,
trigger a reload on the namespace so it uses the latest port
attributes (e.g. IP address).

Closes-Bug: #1431248
Change-Id: I3d1d7b95a8baa4416f1ea3fbbf25a51b818c2c23

neutron/agent/dhcp/agent.py
neutron/tests/unit/test_dhcp_agent.py

index 8f0647c8992f817001d24d03aaaad849cb0331e6..f30dfd867ec9be65b58ebb711a385af576d2edb5 100644 (file)
@@ -316,8 +316,21 @@ class DhcpAgent(manager.Manager):
         updated_port = dhcp.DictModel(payload['port'])
         network = self.cache.get_network_by_id(updated_port.network_id)
         if network:
+            driver_action = 'reload_allocations'
+            if self._is_port_on_this_agent(updated_port):
+                orig = self.cache.get_port_by_id(updated_port['id'])
+                # assume IP change if not in cache
+                old_ips = {i['ip_address'] for i in orig['fixed_ips'] or []}
+                new_ips = {i['ip_address'] for i in updated_port['fixed_ips']}
+                if old_ips != new_ips:
+                    driver_action = 'restart'
             self.cache.put_port(updated_port)
-            self.call_driver('reload_allocations', network)
+            self.call_driver(driver_action, network)
+
+    def _is_port_on_this_agent(self, port):
+        thishost = utils.get_dhcp_agent_device_id(
+            port['network_id'], self.conf.host)
+        return port['device_id'] == thishost
 
     # Use the update handler for the port create event.
     port_create_end = port_update_end
index 2be9afe0049efd33f3493f497a0e89c8d95a4fbb..f0b6750b4eabd89009fa6988929209d3d0eba7a3 100644 (file)
@@ -33,6 +33,7 @@ from neutron.agent.linux import interface
 from neutron.common import config as common_config
 from neutron.common import constants as const
 from neutron.common import exceptions
+from neutron.common import utils
 from neutron import context
 from neutron.tests import base
 
@@ -102,6 +103,7 @@ fake_port1 = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
                             fixed_ips=[fake_fixed_ip1]))
 
 fake_port2 = dhcp.DictModel(dict(id='12345678-1234-aaaa-123456789000',
+                            device_id='dhcp-12345678-1234-aaaa-123456789000',
                             device_owner='',
                             mac_address='aa:bb:cc:dd:ee:99',
                             network_id='12345678-1234-5678-1234567890ab',
@@ -529,6 +531,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
         cfg.CONF.set_override('interface_driver',
                               'neutron.agent.linux.interface.NullDriver')
         cfg.CONF.register_opts(dhcp_config.DHCP_AGENT_OPTS)
+        cfg.CONF.register_opts(dhcp_config.DHCP_OPTS)
 
         self.plugin_p = mock.patch(DHCP_PLUGIN)
         plugin_cls = self.plugin_p.start()
@@ -914,6 +917,26 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
         self.call_driver.assert_has_calls(
             [mock.call.call_driver('reload_allocations', fake_network)])
 
+    def test_port_update_change_ip_on_dhcp_agents_port(self):
+        self.cache.get_network_by_id.return_value = fake_network
+        self.cache.get_port_by_id.return_value = fake_port1
+        payload = dict(port=copy.deepcopy(fake_port1))
+        device_id = utils.get_dhcp_agent_device_id(
+            payload['port']['network_id'], self.dhcp.conf.host)
+        payload['port']['fixed_ips'][0]['ip_address'] = '172.9.9.99'
+        payload['port']['device_id'] = device_id
+        self.dhcp.port_update_end(None, payload)
+        self.call_driver.assert_has_calls(
+            [mock.call.call_driver('restart', fake_network)])
+
+    def test_port_update_on_dhcp_agents_port_no_ip_change(self):
+        payload = dict(port=fake_port1)
+        self.cache.get_network_by_id.return_value = fake_network
+        self.cache.get_port_by_id.return_value = fake_port1
+        self.dhcp.port_update_end(None, payload)
+        self.call_driver.assert_has_calls(
+            [mock.call.call_driver('reload_allocations', fake_network)])
+
     def test_port_delete_end(self):
         payload = dict(port_id=fake_port2.id)
         self.cache.get_network_by_id.return_value = fake_network