From bb1e89efbdbafed7275d01409bf3f55cbe187da5 Mon Sep 17 00:00:00 2001 From: Vivekanandan Narasimhan Date: Wed, 27 Aug 2014 02:07:37 -0700 Subject: [PATCH] Fix DVR to service DHCP Ports This fix ensures that DHCP Ports that are available on DVR routed subnets, are serviced by DVR neutron infrastructure. Here servicing by DVR means, creation of DVR namespaces on such nodes holding DHCP Ports and also applying DVR specific OVS Rules to the br-int and br-tun bridges on such nodes, to enable traffic to be routed via DVR to such DHCP Ports. Closes-Bug: #1358718 Change-Id: Ib6d5fbf883d6698f34f3a3b722e426e3285a5736 --- neutron/common/utils.py | 7 ++-- .../openvswitch/test_ovs_neutron_agent.py | 8 ++++ neutron/tests/unit/test_common_utils.py | 16 ++++++++ neutron/tests/unit/test_l3_schedulers.py | 40 +++++++++++++------ 4 files changed, 55 insertions(+), 16 deletions(-) diff --git a/neutron/common/utils.py b/neutron/common/utils.py index 006e3b7dc89..5b238e810d8 100644 --- a/neutron/common/utils.py +++ b/neutron/common/utils.py @@ -345,6 +345,7 @@ def is_dvr_serviced(device_owner): if they are required for DVR or any service directly or indirectly associated with DVR. """ - if (device_owner.startswith('compute:') or ( - q_const.DEVICE_OWNER_LOADBALANCER == device_owner)): - return True + dvr_serviced_device_owners = (q_const.DEVICE_OWNER_LOADBALANCER, + q_const.DEVICE_OWNER_DHCP) + return (device_owner.startswith('compute:') or + device_owner in dvr_serviced_device_owners) diff --git a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py index 91ed43d9e14..de272443717 100644 --- a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py @@ -291,6 +291,10 @@ class TestOvsNeutronAgent(base.BaseTestCase): self._test_port_bound_for_dvr( device_owner=n_const.DEVICE_OWNER_LOADBALANCER) + def test_port_bound_for_dvr_with_dhcp_ports(self): + self._test_port_bound_for_dvr( + device_owner=n_const.DEVICE_OWNER_DHCP) + def test_port_bound_for_dvr_with_csnat_ports(self, ofport=10): self._setup_for_dvr_test() with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.' @@ -434,6 +438,10 @@ class TestOvsNeutronAgent(base.BaseTestCase): self._test_treat_devices_removed_for_dvr( device_owner=n_const.DEVICE_OWNER_LOADBALANCER) + def test_treat_devices_removed_for_dvr_with_dhcp_ports(self): + self._test_treat_devices_removed_for_dvr( + device_owner=n_const.DEVICE_OWNER_DHCP) + def test_treat_devices_removed_for_dvr_csnat_port(self, ofport=10): self._setup_for_dvr_test() with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.' diff --git a/neutron/tests/unit/test_common_utils.py b/neutron/tests/unit/test_common_utils.py index d42ce4e9262..d3ee9110514 100644 --- a/neutron/tests/unit/test_common_utils.py +++ b/neutron/tests/unit/test_common_utils.py @@ -16,6 +16,7 @@ import eventlet import mock import testtools +from neutron.common import constants from neutron.common import exceptions as n_exc from neutron.common import utils from neutron.plugins.common import utils as plugin_utils @@ -464,3 +465,18 @@ class TestExceptionLogger(base.BaseTestCase): calls.assert_has_calls([mock.call(0), mock.call(1), mock.call(3)], any_order=True) self.assertTrue(logger.called) + + +class TestDvrServices(base.BaseTestCase): + + def _test_is_dvr_serviced(self, device_owner, expected): + self.assertEqual(expected, utils.is_dvr_serviced(device_owner)) + + def test_is_dvr_serviced_with_lb_port(self): + self._test_is_dvr_serviced(constants.DEVICE_OWNER_LOADBALANCER, True) + + def test_is_dvr_serviced_with_dhcp_port(self): + self._test_is_dvr_serviced(constants.DEVICE_OWNER_DHCP, True) + + def test_is_dvr_serviced_with_vm_port(self): + self._test_is_dvr_serviced('compute:', True) diff --git a/neutron/tests/unit/test_l3_schedulers.py b/neutron/tests/unit/test_l3_schedulers.py index 2a8890784bd..6f8d61a7dbc 100644 --- a/neutron/tests/unit/test_l3_schedulers.py +++ b/neutron/tests/unit/test_l3_schedulers.py @@ -827,7 +827,17 @@ class L3DvrSchedulerTestCase(testlib_api.SqlTestCase, sub_ids) self.assertFalse(result) - def test_check_dvr_serviced_port_exists_on_subnet(self): + def _test_dvr_serviced_port_exists_on_subnet(self, port): + with mock.patch('neutron.db.db_base_plugin_v2.NeutronDbPluginV2.' + 'get_ports', return_value=[port]): + result = self.dut.check_ports_active_on_host_and_subnet( + self.adminContext, + 'thisHost', + 'dvr1-intf-id', + 'my-subnet-id') + self.assertTrue(result) + + def test_dvr_serviced_vip_port_exists_on_subnet(self): vip_port = { 'id': 'lbaas-vip-port1', 'device_id': 'vip-pool-id', @@ -841,19 +851,23 @@ class L3DvrSchedulerTestCase(testlib_api.SqlTestCase, } ] } + self._test_dvr_serviced_port_exists_on_subnet(port=vip_port) - with contextlib.nested( - mock.patch('neutron.db.db_base_plugin_v2.NeutronDbPluginV2' - '.get_ports', return_value=[vip_port]), - mock.patch('neutron.common.utils.is_dvr_serviced', - return_value=True)) as (get_ports_fn, dvr_serv_fn): - result = self.dut.check_ports_active_on_host_and_subnet( - self.adminContext, - 'thisHost', - 'dvr1-intf-id', - 'my-subnet-id') - self.assertTrue(result) - self.assertEqual(dvr_serv_fn.call_count, 1) + def test_dvr_serviced_dhcp_port_exists_on_subnet(self): + dhcp_port = { + 'id': 'dhcp-port1', + 'device_id': 'dhcp-net-id', + 'status': 'ACTIVE', + 'binding:host_id': 'thisHost', + 'device_owner': constants.DEVICE_OWNER_DHCP, + 'fixed_ips': [ + { + 'subnet_id': 'my-subnet-id', + 'ip_address': '10.10.10.2' + } + ] + } + self._test_dvr_serviced_port_exists_on_subnet(port=dhcp_port) def _prepare_schedule_snat_tests(self): agent = agents_db.Agent()