]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Teach DHCP Agent about DVR router interfaces
authorBrian Haley <brian.haley@hp.com>
Fri, 3 Oct 2014 21:32:01 +0000 (17:32 -0400)
committerBrian Haley <brian.haley@hp.com>
Tue, 7 Oct 2014 19:22:55 +0000 (15:22 -0400)
When DVR is enabled and enable_isolated_metadata=True,
the DHCP agent should only inject a metadata host route
when there is no port with the gateway IP address configured
on the subnet.  Add a check for DEVICE_OWNER_DVR_INTERFACE
when we look at each port's device_owner field, otherwise
it will always add this route to the opts file when DVR
is enabled.

Change-Id: I3ff3bb85105b8215b36535983016d8c0ff3d8cb7
Closes-bug: #1377307

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

index aba75af571621b3bc3f97eb2c5c6fdb716069edd..51e89913d48b254e90cea7d1251f83cb05ccadcb 100644 (file)
@@ -730,7 +730,8 @@ class Dnsmasq(DhcpLocalProcess):
         subnets = dict((subnet.id, subnet) for subnet in network.subnets)
 
         for port in network.ports:
-            if port.device_owner != constants.DEVICE_OWNER_ROUTER_INTF:
+            if port.device_owner not in (constants.DEVICE_OWNER_ROUTER_INTF,
+                                         constants.DEVICE_OWNER_DVR_INTERFACE):
                 continue
             for alloc in port.fixed_ips:
                 if subnets[alloc.subnet_id].gateway_ip == alloc.ip_address:
index c6f98643fe8e309f1fbb20bc2aa4e0e90d1c4ea0..cae87c692b5eb80b0b89bcdf51f715534fc2c4e6 100644 (file)
@@ -72,6 +72,8 @@ fake_meta_subnet = dhcp.DictModel(dict(id='bbbbbbbb-1111-2222-bbbbbbbbbbbb',
 
 fake_fixed_ip1 = dhcp.DictModel(dict(id='', subnet_id=fake_subnet1.id,
                                 ip_address='172.9.9.9'))
+fake_fixed_ip2 = dhcp.DictModel(dict(id='', subnet_id=fake_subnet1.id,
+                                ip_address='172.9.9.10'))
 fake_meta_fixed_ip = dhcp.DictModel(dict(id='', subnet=fake_meta_subnet,
                                     ip_address='169.254.169.254'))
 fake_allocation_pool_subnet1 = dhcp.DictModel(dict(id='', start='172.9.9.2',
@@ -89,7 +91,7 @@ fake_port2 = dhcp.DictModel(dict(id='12345678-1234-aaaa-123456789000',
                             device_owner='',
                             mac_address='aa:bb:cc:dd:ee:99',
                             network_id='12345678-1234-5678-1234567890ab',
-                            fixed_ips=[]))
+                            fixed_ips=[fake_fixed_ip2]))
 
 fake_meta_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
                                 mac_address='aa:bb:cc:dd:ee:ff',
@@ -98,6 +100,13 @@ fake_meta_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
                                 device_id='forzanapoli',
                                 fixed_ips=[fake_meta_fixed_ip]))
 
+fake_dist_port = dhcp.DictModel(dict(id='12345678-1234-aaaa-1234567890ab',
+                                mac_address='aa:bb:cc:dd:ee:ff',
+                                network_id='12345678-1234-5678-1234567890ab',
+                                device_owner=const.DEVICE_OWNER_DVR_INTERFACE,
+                                device_id='forzanapoli',
+                                fixed_ips=[fake_meta_fixed_ip]))
+
 fake_network = dhcp.NetModel(True, dict(id='12345678-1234-5678-1234567890ab',
                              tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
                              admin_state_up=True,
@@ -112,6 +121,14 @@ isolated_network = dhcp.NetModel(
         subnets=[fake_subnet1],
         ports=[fake_port1]))
 
+nonisolated_dist_network = dhcp.NetModel(
+    True, dict(
+        id='12345678-1234-5678-1234567890ab',
+        tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
+        admin_state_up=True,
+        subnets=[fake_subnet1],
+        ports=[fake_port1, fake_port2]))
+
 empty_network = dhcp.NetModel(
     True, dict(
         id='12345678-1234-5678-1234567890ab',
@@ -127,6 +144,13 @@ fake_meta_network = dhcp.NetModel(
                subnets=[fake_meta_subnet],
                ports=[fake_meta_port]))
 
+fake_dist_network = dhcp.NetModel(
+    True, dict(id='12345678-1234-5678-1234567890ab',
+               tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
+               admin_state_up=True,
+               subnets=[fake_meta_subnet],
+               ports=[fake_meta_port, fake_dist_port]))
+
 fake_down_network = dhcp.NetModel(
     True, dict(id='12345678-dddd-dddd-1234567890ab',
                tenant_id='aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa',
@@ -540,13 +564,26 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
 
     def test_enable_dhcp_helper_enable_metadata_nonisolated_network(self):
         nonisolated_network = copy.deepcopy(isolated_network)
-        nonisolated_network.ports[0].device_owner = "network:router_interface"
+        nonisolated_network.ports[0].device_owner = (
+            const.DEVICE_OWNER_ROUTER_INTF)
         nonisolated_network.ports[0].fixed_ips[0].ip_address = '172.9.9.1'
 
         self._enable_dhcp_helper(nonisolated_network,
                                  enable_isolated_metadata=True,
                                  is_isolated_network=False)
 
+    def test_enable_dhcp_helper_enable_metadata_nonisolated_dist_network(self):
+        nonisolated_dist_network.ports[0].device_owner = (
+            const.DEVICE_OWNER_ROUTER_INTF)
+        nonisolated_dist_network.ports[0].fixed_ips[0].ip_address = '172.9.9.1'
+        nonisolated_dist_network.ports[1].device_owner = (
+            const.DEVICE_OWNER_DVR_INTERFACE)
+        nonisolated_dist_network.ports[1].fixed_ips[0].ip_address = '172.9.9.1'
+
+        self._enable_dhcp_helper(nonisolated_dist_network,
+                                 enable_isolated_metadata=True,
+                                 is_isolated_network=False)
+
     def test_enable_dhcp_helper_enable_metadata_empty_network(self):
         self._enable_dhcp_helper(empty_network,
                                  enable_isolated_metadata=True,
@@ -685,7 +722,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
                 mock.call().disable()
             ])
 
-    def test_enable_isolated_metadata_proxy_with_metadata_network(self):
+    def _test_metadata_network(self, network):
         cfg.CONF.set_override('enable_metadata_network', True)
         cfg.CONF.set_override('debug', True)
         cfg.CONF.set_override('verbose', False)
@@ -695,7 +732,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
         # Ensure the mock is restored if this test fail
         try:
             with mock.patch(class_path) as ip_wrapper:
-                self.dhcp.enable_isolated_metadata_proxy(fake_meta_network)
+                self.dhcp.enable_isolated_metadata_proxy(network)
                 ip_wrapper.assert_has_calls([mock.call(
                     'sudo',
                     'qdhcp-12345678-1234-5678-1234567890ab'),
@@ -708,11 +745,17 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
                         mock.ANY,
                         '--debug',
                         ('--log-file=neutron-ns-metadata-proxy-%s.log' %
-                         fake_meta_network.id)], addl_env=None)
+                         network.id)], addl_env=None)
                 ])
         finally:
             self.external_process_p.start()
 
+    def test_enable_isolated_metadata_proxy_with_metadata_network(self):
+        self._test_metadata_network(fake_meta_network)
+
+    def test_enable_isolated_metadata_proxy_with_dist_network(self):
+        self._test_metadata_network(fake_dist_network)
+
     def test_network_create_end(self):
         payload = dict(network=dict(id=fake_network.id))
 
index b3090e1b57535d4e9529bfa31696f02f7969d636..a0187369b82a271b1f96fdc7fb5ea4530c7e19a4 100644 (file)
@@ -130,8 +130,9 @@ class FakeRouterPort:
                                   'dddddddd-dddd-dddd-dddd-dddddddddddd')]
     mac_address = '00:00:0f:rr:rr:rr'
 
-    def __init__(self):
+    def __init__(self, dev_owner=constants.DEVICE_OWNER_ROUTER_INTF):
         self.extra_dhcp_opts = []
+        self.device_owner = dev_owner
 
 
 class FakePortMultipleAgents1:
@@ -341,6 +342,13 @@ class FakeV4NetworkNoRouter:
     ports = [FakePort1()]
 
 
+class FakeV4NetworkDistRouter:
+    id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
+    subnets = [FakeV4Subnet()]
+    ports = [FakePort1(),
+             FakeRouterPort(dev_owner=constants.DEVICE_OWNER_DVR_INTERFACE)]
+
+
 class FakeDualV4Pxe3Ports:
     id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
     subnets = [FakeV4Subnet(), FakeV4SubnetNoDHCP()]
@@ -962,6 +970,26 @@ tag:tag0,option:router""".lstrip()
 
         self.safe.assert_called_once_with('/foo/opts', expected)
 
+    def test_output_opts_file_dist_neutron_router_on_subnet(self):
+        expected = (
+            'tag:tag0,option:dns-server,8.8.8.8\n'
+            'tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1,'
+            '0.0.0.0/0,192.168.0.1\n'
+            'tag:tag0,249,20.0.0.1/24,20.0.0.1,0.0.0.0/0,192.168.0.1\n'
+            'tag:tag0,option:router,192.168.0.1').lstrip()
+
+        with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
+            conf_fn.return_value = '/foo/opts'
+            dm = dhcp.Dnsmasq(self.conf, FakeV4NetworkDistRouter(),
+                              version=dhcp.Dnsmasq.MINIMUM_VERSION)
+            with mock.patch.object(dm, '_make_subnet_interface_ip_map') as ipm:
+                ipm.return_value = {FakeV4Subnet.id: '192.168.0.1'}
+
+                dm._output_opts_file()
+                self.assertTrue(ipm.called)
+
+        self.safe.assert_called_once_with('/foo/opts', expected)
+
     def test_output_opts_file_pxe_2port_1net(self):
         expected = (
             'tag:tag0,option:dns-server,8.8.8.8\n'