From: Maru Newby Date: Mon, 6 Apr 2015 21:51:23 +0000 (+0000) Subject: Merge open source plugin test code modules X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=5bdcacad62ba468de1bd339cad44428c2374d973;p=openstack-build%2Fneutron-build.git Merge open source plugin test code modules The unit test reorg is about moving files around so a test module is clearly associated with the code module it targets, but the test modules in this change needed to be manually merged because they both targeted the same module. Change-Id: I80f4b97fadd318896e7fa4e7e7e939f924127b2a Partial-Bug: #1440834 --- diff --git a/neutron/tests/unit/plugins/ml2/db/test_ml2_db.py b/neutron/tests/unit/plugins/ml2/db/test_ml2_db.py index a3890690f..10042e8b9 100644 --- a/neutron/tests/unit/plugins/ml2/db/test_ml2_db.py +++ b/neutron/tests/unit/plugins/ml2/db/test_ml2_db.py @@ -13,8 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +import mock + +from sqlalchemy.orm import query + from neutron import context from neutron.db import db_base_plugin_v2 +from neutron.db import l3_db from neutron.db import models_v2 from neutron.extensions import portbindings from neutron.openstack.common import uuidutils @@ -220,3 +225,137 @@ class Ml2DBTestCase(testlib_api.SqlTestCase): port_id) self.assertIsNone(port) self.assertIsNone(binding) + + +class Ml2DvrDBTestCase(testlib_api.SqlTestCase): + + def setUp(self): + super(Ml2DvrDBTestCase, self).setUp() + self.ctx = context.get_admin_context() + + def _setup_neutron_network(self, network_id, port_ids): + with self.ctx.session.begin(subtransactions=True): + self.ctx.session.add(models_v2.Network(id=network_id)) + ports = [] + for port_id in port_ids: + mac_address = (db_base_plugin_v2.NeutronDbPluginV2. + _generate_mac()) + port = models_v2.Port(id=port_id, + network_id=network_id, + mac_address=mac_address, + admin_state_up=True, + status='ACTIVE', + device_id='', + device_owner='') + self.ctx.session.add(port) + ports.append(port) + return ports + + def _setup_neutron_router(self): + with self.ctx.session.begin(subtransactions=True): + router = l3_db.Router() + self.ctx.session.add(router) + return router + + def _setup_dvr_binding(self, network_id, port_id, router_id, host_id): + with self.ctx.session.begin(subtransactions=True): + record = models.DVRPortBinding( + port_id=port_id, + host=host_id, + router_id=router_id, + vif_type=portbindings.VIF_TYPE_UNBOUND, + vnic_type=portbindings.VNIC_NORMAL, + status='DOWN') + self.ctx.session.add(record) + return record + + def test_ensure_dvr_port_binding_deals_with_db_duplicate(self): + network_id = 'foo_network_id' + port_id = 'foo_port_id' + router_id = 'foo_router_id' + host_id = 'foo_host_id' + self._setup_neutron_network(network_id, [port_id]) + self._setup_dvr_binding(network_id, port_id, router_id, host_id) + with mock.patch.object(query.Query, 'first') as query_first: + query_first.return_value = [] + with mock.patch.object(ml2_db.LOG, 'debug') as log_trace: + binding = ml2_db.ensure_dvr_port_binding( + self.ctx.session, port_id, host_id, router_id) + self.assertTrue(query_first.called) + self.assertTrue(log_trace.called) + self.assertEqual(port_id, binding.port_id) + + def test_ensure_dvr_port_binding(self): + network_id = 'foo_network_id' + port_id = 'foo_port_id' + self._setup_neutron_network(network_id, [port_id]) + router = self._setup_neutron_router() + ml2_db.ensure_dvr_port_binding( + self.ctx.session, port_id, 'foo_host', router.id) + expected = (self.ctx.session.query(models.DVRPortBinding). + filter_by(port_id=port_id).one()) + self.assertEqual(expected.port_id, port_id) + + def test_ensure_dvr_port_binding_multiple_bindings(self): + network_id = 'foo_network_id' + port_id = 'foo_port_id' + self._setup_neutron_network(network_id, [port_id]) + router = self._setup_neutron_router() + ml2_db.ensure_dvr_port_binding( + self.ctx.session, port_id, 'foo_host_1', router.id) + ml2_db.ensure_dvr_port_binding( + self.ctx.session, port_id, 'foo_host_2', router.id) + bindings = (self.ctx.session.query(models.DVRPortBinding). + filter_by(port_id=port_id).all()) + self.assertEqual(2, len(bindings)) + + def test_delete_dvr_port_binding(self): + network_id = 'foo_network_id' + port_id = 'foo_port_id' + self._setup_neutron_network(network_id, [port_id]) + router = self._setup_neutron_router() + binding = self._setup_dvr_binding( + network_id, port_id, router.id, 'foo_host_id') + ml2_db.delete_dvr_port_binding( + self.ctx.session, port_id, 'foo_host_id') + count = (self.ctx.session.query(models.DVRPortBinding). + filter_by(port_id=binding.port_id).count()) + self.assertFalse(count) + + def test_delete_dvr_port_binding_not_found(self): + ml2_db.delete_dvr_port_binding( + self.ctx.session, 'foo_port_id', 'foo_host') + + def test_delete_dvr_port_binding_if_stale(self): + network_id = 'foo_network_id' + port_id = 'foo_port_id' + self._setup_neutron_network(network_id, [port_id]) + binding = self._setup_dvr_binding( + network_id, port_id, None, 'foo_host_id') + + ml2_db.delete_dvr_port_binding_if_stale(self.ctx.session, binding) + count = (self.ctx.session.query(models.DVRPortBinding). + filter_by(port_id=binding.port_id).count()) + self.assertFalse(count) + + def test_get_dvr_port_binding_by_host_not_found(self): + port = ml2_db.get_dvr_port_binding_by_host( + self.ctx.session, 'foo_port_id', 'foo_host_id') + self.assertIsNone(port) + + def test_get_dvr_port_bindings_not_found(self): + port = ml2_db.get_dvr_port_bindings(self.ctx.session, 'foo_port_id') + self.assertFalse(len(port)) + + def test_get_dvr_port_bindings(self): + network_id = 'foo_network_id' + port_id_1 = 'foo_port_id_1' + port_id_2 = 'foo_port_id_2' + self._setup_neutron_network(network_id, [port_id_1, port_id_2]) + router = self._setup_neutron_router() + self._setup_dvr_binding( + network_id, port_id_1, router.id, 'foo_host_id_1') + self._setup_dvr_binding( + network_id, port_id_1, router.id, 'foo_host_id_2') + ports = ml2_db.get_dvr_port_bindings(self.ctx.session, 'foo_port_id') + self.assertEqual(2, len(ports)) diff --git a/neutron/tests/unit/plugins/ml2/db/test_ml2_dvr_db.py b/neutron/tests/unit/plugins/ml2/db/test_ml2_dvr_db.py deleted file mode 100644 index 455d70dde..000000000 --- a/neutron/tests/unit/plugins/ml2/db/test_ml2_dvr_db.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright (c) 2014 OpenStack Foundation, all rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock - -from sqlalchemy.orm import query - -from neutron import context -from neutron.db import db_base_plugin_v2 -from neutron.db import l3_db -from neutron.db import models_v2 -from neutron.extensions import portbindings -from neutron.plugins.ml2 import db as ml2_db -from neutron.plugins.ml2 import models as ml2_models -from neutron.tests.unit import testlib_api - - -class Ml2DvrDBTestCase(testlib_api.SqlTestCase): - - def setUp(self): - super(Ml2DvrDBTestCase, self).setUp() - self.ctx = context.get_admin_context() - - def _setup_neutron_network(self, network_id, port_ids): - with self.ctx.session.begin(subtransactions=True): - self.ctx.session.add(models_v2.Network(id=network_id)) - ports = [] - for port_id in port_ids: - mac_address = (db_base_plugin_v2.NeutronDbPluginV2. - _generate_mac()) - port = models_v2.Port(id=port_id, - network_id=network_id, - mac_address=mac_address, - admin_state_up=True, - status='ACTIVE', - device_id='', - device_owner='') - self.ctx.session.add(port) - ports.append(port) - return ports - - def _setup_neutron_router(self): - with self.ctx.session.begin(subtransactions=True): - router = l3_db.Router() - self.ctx.session.add(router) - return router - - def _setup_dvr_binding(self, network_id, port_id, router_id, host_id): - with self.ctx.session.begin(subtransactions=True): - record = ml2_models.DVRPortBinding( - port_id=port_id, - host=host_id, - router_id=router_id, - vif_type=portbindings.VIF_TYPE_UNBOUND, - vnic_type=portbindings.VNIC_NORMAL, - status='DOWN') - self.ctx.session.add(record) - return record - - def test_ensure_dvr_port_binding_deals_with_db_duplicate(self): - network_id = 'foo_network_id' - port_id = 'foo_port_id' - router_id = 'foo_router_id' - host_id = 'foo_host_id' - self._setup_neutron_network(network_id, [port_id]) - self._setup_dvr_binding(network_id, port_id, router_id, host_id) - with mock.patch.object(query.Query, 'first') as query_first: - query_first.return_value = [] - with mock.patch.object(ml2_db.LOG, 'debug') as log_trace: - binding = ml2_db.ensure_dvr_port_binding( - self.ctx.session, port_id, host_id, router_id) - self.assertTrue(query_first.called) - self.assertTrue(log_trace.called) - self.assertEqual(port_id, binding.port_id) - - def test_ensure_dvr_port_binding(self): - network_id = 'foo_network_id' - port_id = 'foo_port_id' - self._setup_neutron_network(network_id, [port_id]) - router = self._setup_neutron_router() - ml2_db.ensure_dvr_port_binding( - self.ctx.session, port_id, 'foo_host', router.id) - expected = (self.ctx.session.query(ml2_models.DVRPortBinding). - filter_by(port_id=port_id).one()) - self.assertEqual(expected.port_id, port_id) - - def test_ensure_dvr_port_binding_multiple_bindings(self): - network_id = 'foo_network_id' - port_id = 'foo_port_id' - self._setup_neutron_network(network_id, [port_id]) - router = self._setup_neutron_router() - ml2_db.ensure_dvr_port_binding( - self.ctx.session, port_id, 'foo_host_1', router.id) - ml2_db.ensure_dvr_port_binding( - self.ctx.session, port_id, 'foo_host_2', router.id) - bindings = (self.ctx.session.query(ml2_models.DVRPortBinding). - filter_by(port_id=port_id).all()) - self.assertEqual(2, len(bindings)) - - def test_delete_dvr_port_binding(self): - network_id = 'foo_network_id' - port_id = 'foo_port_id' - self._setup_neutron_network(network_id, [port_id]) - router = self._setup_neutron_router() - binding = self._setup_dvr_binding( - network_id, port_id, router.id, 'foo_host_id') - ml2_db.delete_dvr_port_binding( - self.ctx.session, port_id, 'foo_host_id') - count = (self.ctx.session.query(ml2_models.DVRPortBinding). - filter_by(port_id=binding.port_id).count()) - self.assertFalse(count) - - def test_delete_dvr_port_binding_not_found(self): - ml2_db.delete_dvr_port_binding( - self.ctx.session, 'foo_port_id', 'foo_host') - - def test_delete_dvr_port_binding_if_stale(self): - network_id = 'foo_network_id' - port_id = 'foo_port_id' - self._setup_neutron_network(network_id, [port_id]) - binding = self._setup_dvr_binding( - network_id, port_id, None, 'foo_host_id') - - ml2_db.delete_dvr_port_binding_if_stale(self.ctx.session, binding) - count = (self.ctx.session.query(ml2_models.DVRPortBinding). - filter_by(port_id=binding.port_id).count()) - self.assertFalse(count) - - def test_get_dvr_port_binding_by_host_not_found(self): - port = ml2_db.get_dvr_port_binding_by_host( - self.ctx.session, 'foo_port_id', 'foo_host_id') - self.assertIsNone(port) - - def test_get_dvr_port_bindings_not_found(self): - port = ml2_db.get_dvr_port_bindings(self.ctx.session, 'foo_port_id') - self.assertFalse(len(port)) - - def test_get_dvr_port_bindings(self): - network_id = 'foo_network_id' - port_id_1 = 'foo_port_id_1' - port_id_2 = 'foo_port_id_2' - self._setup_neutron_network(network_id, [port_id_1, port_id_2]) - router = self._setup_neutron_router() - self._setup_dvr_binding( - network_id, port_id_1, router.id, 'foo_host_id_1') - self._setup_dvr_binding( - network_id, port_id_1, router.id, 'foo_host_id_2') - ports = ml2_db.get_dvr_port_bindings(self.ctx.session, 'foo_port_id') - self.assertEqual(2, len(ports)) diff --git a/neutron/tests/unit/plugins/openvswitch/test_ovs_dvr_neutron_agent.py b/neutron/tests/unit/plugins/openvswitch/test_ovs_dvr_neutron_agent.py deleted file mode 100644 index b17f44df6..000000000 --- a/neutron/tests/unit/plugins/openvswitch/test_ovs_dvr_neutron_agent.py +++ /dev/null @@ -1,828 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import contextlib - -import mock -from oslo_config import cfg -import oslo_messaging - -from neutron.agent.common import utils -from neutron.common import constants as n_const -from neutron.plugins.common import constants as p_const -from neutron.plugins.openvswitch.agent import ovs_neutron_agent -from neutron.plugins.openvswitch.common import constants -from neutron.tests import base - - -NOTIFIER = 'neutron.plugins.ml2.rpc.AgentNotifierApi' -OVS_LINUX_KERN_VERS_WITHOUT_VXLAN = "3.12.0" - -FAKE_MAC = '00:11:22:33:44:55' -FAKE_IP1 = '10.0.0.1' -FAKE_IP2 = '10.0.0.2' - - -class TestOvsDvrNeutronAgent(base.BaseTestCase): - - def setUp(self): - super(TestOvsDvrNeutronAgent, self).setUp() - notifier_p = mock.patch(NOTIFIER) - notifier_cls = notifier_p.start() - self.notifier = mock.Mock() - notifier_cls.return_value = self.notifier - cfg.CONF.set_default('firewall_driver', - 'neutron.agent.firewall.NoopFirewallDriver', - group='SECURITYGROUP') - kwargs = ovs_neutron_agent.create_agent_config_map(cfg.CONF) - - class MockFixedIntervalLoopingCall(object): - def __init__(self, f): - self.f = f - - def start(self, interval=0): - self.f() - - with contextlib.nested( - mock.patch('neutron.plugins.openvswitch.agent.ovs_neutron_agent.' - 'OVSNeutronAgent.setup_integration_br'), - mock.patch('neutron.plugins.openvswitch.agent.ovs_neutron_agent.' - 'OVSNeutronAgent.setup_ancillary_bridges', - return_value=[]), - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'create'), - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'set_secure_mode'), - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'get_local_port_mac', - return_value='00:00:00:00:00:01'), - mock.patch('neutron.agent.linux.utils.get_interface_mac', - return_value='00:00:00:00:00:01'), - mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges'), - mock.patch('neutron.openstack.common.loopingcall.' - 'FixedIntervalLoopingCall', - new=MockFixedIntervalLoopingCall)): - self.agent = ovs_neutron_agent.OVSNeutronAgent(**kwargs) - # set back to true because initial report state will succeed due - # to mocked out RPC calls - self.agent.use_call = True - self.agent.tun_br = mock.Mock() - self.agent.sg_agent = mock.Mock() - - def _setup_for_dvr_test(self, ofport=10): - self._port = mock.Mock() - self._port.ofport = ofport - self._port.vif_id = "1234-5678-90" - self._physical_network = 'physeth1' - self._old_local_vlan = None - self._segmentation_id = 2001 - self.agent.enable_distributed_routing = True - self.agent.enable_tunneling = True - self.agent.patch_tun_ofport = 1 - self.agent.patch_int_ofport = 2 - self.agent.dvr_agent.local_ports = {} - self.agent.local_vlan_map = {} - self.agent.dvr_agent.enable_distributed_routing = True - self.agent.dvr_agent.enable_tunneling = True - self.agent.dvr_agent.patch_tun_ofport = 1 - self.agent.dvr_agent.patch_int_ofport = 2 - self.agent.dvr_agent.tun_br = mock.Mock() - self.agent.dvr_agent.phys_brs[self._physical_network] = mock.Mock() - self.agent.dvr_agent.bridge_mappings = {self._physical_network: - 'br-eth1'} - self.agent.dvr_agent.int_ofports[self._physical_network] = 30 - self.agent.dvr_agent.phys_ofports[self._physical_network] = 40 - self.agent.dvr_agent.local_dvr_map = {} - self.agent.dvr_agent.registered_dvr_macs = set() - self.agent.dvr_agent.dvr_mac_address = 'aa:22:33:44:55:66' - self._net_uuid = 'my-net-uuid' - self._fixed_ips = [{'subnet_id': 'my-subnet-uuid', - 'ip_address': '1.1.1.1'}] - self._compute_port = mock.Mock() - self._compute_port.ofport = 20 - self._compute_port.vif_id = "1234-5678-91" - self._compute_fixed_ips = [{'subnet_id': 'my-subnet-uuid', - 'ip_address': '1.1.1.3'}] - - def _test_port_bound_for_dvr_on_vlan_network(self, device_owner, - ip_version=4): - self._setup_for_dvr_test() - if ip_version == 4: - gateway_ip = '1.1.1.1' - cidr = '1.1.1.0/24' - else: - gateway_ip = '2001:100::1' - cidr = '2001:100::0/64' - self._port.vif_mac = gateway_mac = 'aa:bb:cc:11:22:33' - self._compute_port.vif_mac = '77:88:99:00:11:22' - physical_network = self._physical_network - segmentation_id = self._segmentation_id - network_type = p_const.TYPE_VLAN - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'set_db_attribute', - return_value=True): - with contextlib.nested( - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'db_get_val', - return_value=self._old_local_vlan), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_subnet_for_dvr', - return_value={ - 'gateway_ip': gateway_ip, - 'cidr': cidr, - 'ip_version': ip_version, - 'gateway_mac': gateway_mac}), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_ports_on_host_by_subnet', - return_value=[]), - mock.patch.object(self.agent.dvr_agent.int_br, - 'get_vif_port_by_id', - return_value=self._port), - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'), - mock.patch.object( - self.agent.dvr_agent.phys_brs[physical_network], - 'add_flow'), - mock.patch.object( - self.agent.dvr_agent.phys_brs[physical_network], - 'delete_flows') - ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, - get_vif_fn, add_flow_int_fn, delete_flows_int_fn, - add_flow_tun_fn, delete_flows_tun_fn, add_flow_phys_fn, - delete_flows_phys_fn): - self.agent.port_bound( - self._port, self._net_uuid, network_type, - physical_network, segmentation_id, self._fixed_ips, - n_const.DEVICE_OWNER_DVR_INTERFACE, False) - lvm = self.agent.local_vlan_map[self._net_uuid] - phy_ofp = self.agent.dvr_agent.phys_ofports[physical_network] - int_ofp = self.agent.dvr_agent.int_ofports[physical_network] - expected_on_phys_br = [ - mock.call(table=constants.LOCAL_VLAN_TRANSLATION, - priority=4, - in_port=phy_ofp, - dl_vlan=lvm.vlan, - actions="mod_vlan_vid:%s,normal" % - (lvm.segmentation_id)), - mock.call(table=constants.DVR_PROCESS_VLAN, - priority=2, - dl_vlan=lvm.vlan, - dl_dst=self._port.vif_mac, - actions="drop"), - mock.call(table=constants.DVR_PROCESS_VLAN, - priority=1, - dl_vlan=lvm.vlan, - dl_src=self._port.vif_mac, - actions="mod_dl_src:%s,resubmit(,%s)" % - (self.agent.dvr_agent.dvr_mac_address, - constants.LOCAL_VLAN_TRANSLATION)) - ] - if ip_version == 4: - expected_on_phys_br.insert(1, mock.call( - proto='arp', - nw_dst=gateway_ip, actions='drop', - priority=3, table=constants.DVR_PROCESS_VLAN, - dl_vlan=lvm.vlan)) - else: - expected_on_phys_br.insert(1, mock.call( - icmp_type=n_const.ICMPV6_TYPE_RA, proto='icmp6', - dl_src=self._port.vif_mac, actions='drop', - priority=3, table=constants.DVR_PROCESS_VLAN, - dl_vlan=lvm.vlan)) - self.assertEqual(expected_on_phys_br, - add_flow_phys_fn.call_args_list) - self.agent.port_bound(self._compute_port, self._net_uuid, - network_type, physical_network, - segmentation_id, - self._compute_fixed_ips, - device_owner, False) - expected_on_int_br = [ - mock.call(priority=3, - in_port=int_ofp, - dl_vlan=lvm.segmentation_id, - actions="mod_vlan_vid:%s,normal" % lvm.vlan), - mock.call(table=constants.DVR_TO_SRC_MAC_VLAN, - priority=4, - dl_dst=self._compute_port.vif_mac, - dl_vlan=lvm.segmentation_id, - actions="strip_vlan,mod_dl_src:%s," - "output:%s" % - (gateway_mac, - self._compute_port.ofport)) - ] - self.assertEqual(expected_on_int_br, - add_flow_int_fn.call_args_list) - expected_on_int_br = [ - mock.call(in_port=self._port.ofport), - mock.call(in_port=self._compute_port.ofport) - ] - self.assertEqual(expected_on_int_br, - delete_flows_int_fn.call_args_list) - self.assertFalse(add_flow_tun_fn.called) - self.assertFalse(delete_flows_tun_fn.called) - self.assertFalse(delete_flows_phys_fn.called) - - def _test_port_bound_for_dvr_on_vxlan_network(self, device_owner, - ip_version=4): - self._setup_for_dvr_test() - if ip_version == 4: - gateway_ip = '1.1.1.1' - cidr = '1.1.1.0/24' - else: - gateway_ip = '2001:100::1' - cidr = '2001:100::0/64' - network_type = p_const.TYPE_VXLAN - self._port.vif_mac = gateway_mac = 'aa:bb:cc:11:22:33' - self._compute_port.vif_mac = '77:88:99:00:11:22' - physical_network = self._physical_network - segmentation_id = self._segmentation_id - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'set_db_attribute', - return_value=True): - with contextlib.nested( - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'db_get_val', - return_value=self._old_local_vlan), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_subnet_for_dvr', - return_value={ - 'gateway_ip': gateway_ip, - 'cidr': cidr, - 'ip_version': ip_version, - 'gateway_mac': gateway_mac}), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_ports_on_host_by_subnet', - return_value=[]), - mock.patch.object(self.agent.dvr_agent.int_br, - 'get_vif_port_by_id', - return_value=self._port), - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'), - mock.patch.object( - self.agent.dvr_agent.phys_brs[physical_network], - 'add_flow'), - mock.patch.object( - self.agent.dvr_agent.phys_brs[physical_network], - 'delete_flows') - ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, - get_vif_fn, add_flow_int_fn, delete_flows_int_fn, - add_flow_tun_fn, delete_flows_tun_fn, - add_flow_phys_fn, delete_flows_phys_fn): - self.agent.port_bound( - self._port, self._net_uuid, network_type, - physical_network, segmentation_id, self._fixed_ips, - n_const.DEVICE_OWNER_DVR_INTERFACE, False) - lvm = self.agent.local_vlan_map[self._net_uuid] - expected_on_tun_br = [ - mock.call( - table=constants.TUN_TABLE['vxlan'], - priority=1, tun_id=lvm.segmentation_id, - actions="mod_vlan_vid:%s," - "resubmit(,%s)" % - (lvm.vlan, constants.DVR_NOT_LEARN)), - mock.call( - table=constants.DVR_PROCESS, priority=2, - dl_vlan=lvm.vlan, - dl_dst=self._port.vif_mac, - actions='drop'), - mock.call( - table=constants.DVR_PROCESS, priority=1, - dl_vlan=lvm.vlan, - dl_src=self._port.vif_mac, - actions="mod_dl_src:%s,resubmit(,%s)" % ( - self.agent.dvr_agent.dvr_mac_address, - constants.PATCH_LV_TO_TUN))] - if ip_version == 4: - expected_on_tun_br.insert(1, mock.call( - proto='arp', - nw_dst=gateway_ip, actions='drop', - priority=3, table=constants.DVR_PROCESS, - dl_vlan=lvm.vlan)) - else: - expected_on_tun_br.insert(1, mock.call( - icmp_type=n_const.ICMPV6_TYPE_RA, - proto='icmp6', - dl_src=self._port.vif_mac, - actions='drop', - priority=3, table=constants.DVR_PROCESS, - dl_vlan=lvm.vlan)) - self.assertEqual(expected_on_tun_br, - add_flow_tun_fn.call_args_list) - self.agent.port_bound(self._compute_port, self._net_uuid, - network_type, physical_network, - segmentation_id, - self._compute_fixed_ips, - device_owner, False) - expected_on_int_br = [ - mock.call(table=constants.DVR_TO_SRC_MAC, priority=4, - dl_dst=self._compute_port.vif_mac, - dl_vlan=lvm.vlan, - actions="strip_vlan,mod_dl_src:%s," - "output:%s" % - (gateway_mac, self._compute_port.ofport)) - ] - self.assertEqual(expected_on_int_br, - add_flow_int_fn.call_args_list) - self.assertFalse(add_flow_phys_fn.called) - expected_on_int_br = [ - mock.call(in_port=self._port.ofport), - mock.call(in_port=self._compute_port.ofport) - ] - self.assertEqual(expected_on_int_br, - delete_flows_int_fn.call_args_list) - self.assertFalse(add_flow_phys_fn.called) - self.assertFalse(delete_flows_tun_fn.called) - self.assertFalse(delete_flows_phys_fn.called) - - def test_port_bound_for_dvr_with_compute_ports(self): - self._test_port_bound_for_dvr_on_vlan_network( - device_owner="compute:None") - self._test_port_bound_for_dvr_on_vlan_network( - device_owner="compute:None", ip_version=6) - self._test_port_bound_for_dvr_on_vxlan_network( - device_owner="compute:None") - self._test_port_bound_for_dvr_on_vxlan_network( - device_owner="compute:None", ip_version=6) - - def test_port_bound_for_dvr_with_lbaas_vip_ports(self): - self._test_port_bound_for_dvr_on_vlan_network( - device_owner=n_const.DEVICE_OWNER_LOADBALANCER) - self._test_port_bound_for_dvr_on_vlan_network( - device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6) - self._test_port_bound_for_dvr_on_vxlan_network( - device_owner=n_const.DEVICE_OWNER_LOADBALANCER) - self._test_port_bound_for_dvr_on_vxlan_network( - device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6) - - def test_port_bound_for_dvr_with_dhcp_ports(self): - self._test_port_bound_for_dvr_on_vlan_network( - device_owner=n_const.DEVICE_OWNER_DHCP) - self._test_port_bound_for_dvr_on_vlan_network( - device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6) - self._test_port_bound_for_dvr_on_vxlan_network( - device_owner=n_const.DEVICE_OWNER_DHCP) - self._test_port_bound_for_dvr_on_vxlan_network( - device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6) - - def test_port_bound_for_dvr_with_csnat_ports(self, ofport=10): - self._setup_for_dvr_test() - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'set_db_attribute', - return_value=True): - with contextlib.nested( - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'db_get_val', - return_value=self._old_local_vlan), - mock.patch.object( - self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', - return_value={'gateway_ip': '1.1.1.1', - 'cidr': '1.1.1.0/24', - 'ip_version': 4, - 'gateway_mac': 'aa:bb:cc:11:22:33'}), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_ports_on_host_by_subnet', - return_value=[]), - mock.patch.object(self.agent.dvr_agent.int_br, - 'get_vif_port_by_id', - return_value=self._port), - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') - ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, - get_vif_fn, add_flow_int_fn, delete_flows_int_fn, - add_flow_tun_fn, delete_flows_tun_fn): - self.agent.port_bound( - self._port, self._net_uuid, 'vxlan', - None, None, self._fixed_ips, - n_const.DEVICE_OWNER_ROUTER_SNAT, - False) - self.assertTrue(add_flow_int_fn.called) - self.assertTrue(delete_flows_int_fn.called) - - def test_treat_devices_removed_for_dvr_interface(self, ofport=10): - self._test_treat_devices_removed_for_dvr_interface(ofport) - self._test_treat_devices_removed_for_dvr_interface( - ofport, ip_version=6) - - def _test_treat_devices_removed_for_dvr_interface(self, ofport=10, - ip_version=4): - self._setup_for_dvr_test() - if ip_version == 4: - gateway_ip = '1.1.1.1' - cidr = '1.1.1.0/24' - else: - gateway_ip = '2001:100::1' - cidr = '2001:100::0/64' - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'set_db_attribute', - return_value=True): - with contextlib.nested( - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'db_get_val', - return_value=self._old_local_vlan), - mock.patch.object( - self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', - return_value={'gateway_ip': gateway_ip, - 'cidr': cidr, - 'ip_version': ip_version, - 'gateway_mac': 'aa:bb:cc:11:22:33'}), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_ports_on_host_by_subnet', - return_value=[]), - mock.patch.object(self.agent.dvr_agent.int_br, - 'get_vif_port_by_id', - return_value=self._port), - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') - ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, - get_vif_fn, add_flow_int_fn, delete_flows_int_fn, - add_flow_tun_fn, delete_flows_tun_fn): - self.agent.port_bound( - self._port, self._net_uuid, 'vxlan', - None, None, self._fixed_ips, - n_const.DEVICE_OWNER_DVR_INTERFACE, - False) - self.assertTrue(add_flow_tun_fn.called) - self.assertTrue(delete_flows_int_fn.called) - - with contextlib.nested( - mock.patch.object(self.agent, 'reclaim_local_vlan'), - mock.patch.object(self.agent.plugin_rpc, 'update_device_down', - return_value=None), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.tun_br, - 'delete_flows')) as (reclaim_vlan_fn, - update_dev_down_fn, - delete_flows_int_fn, - delete_flows_tun_fn): - self.agent.treat_devices_removed([self._port.vif_id]) - if ip_version == 4: - expected = [mock.call( - proto='arp', - nw_dst=gateway_ip, - table=constants.DVR_PROCESS, - dl_vlan=( - self.agent.local_vlan_map[self._net_uuid].vlan))] - else: - expected = [mock.call( - icmp_type=n_const.ICMPV6_TYPE_RA, proto='icmp6', - dl_src='aa:bb:cc:11:22:33', - table=constants.DVR_PROCESS, - dl_vlan=( - self.agent.local_vlan_map[self._net_uuid].vlan))] - expected.extend([ - mock.call( - table=constants.DVR_PROCESS, - dl_dst=self._port.vif_mac, - dl_vlan=( - self.agent.local_vlan_map[self._net_uuid].vlan)), - mock.call( - table=constants.DVR_PROCESS, - dl_vlan=( - self.agent.local_vlan_map[self._net_uuid].vlan), - dl_src=self._port.vif_mac) - ]) - self.assertEqual(expected, delete_flows_tun_fn.call_args_list) - - def _test_treat_devices_removed_for_dvr(self, device_owner, ip_version=4): - self._setup_for_dvr_test() - if ip_version == 4: - gateway_ip = '1.1.1.1' - cidr = '1.1.1.0/24' - else: - gateway_ip = '2001:100::1' - cidr = '2001:100::0/64' - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'set_db_attribute', - return_value=True): - with contextlib.nested( - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'db_get_val', - return_value=self._old_local_vlan), - mock.patch.object( - self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', - return_value={'gateway_ip': gateway_ip, - 'cidr': cidr, - 'ip_version': ip_version, - 'gateway_mac': 'aa:bb:cc:11:22:33'}), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_ports_on_host_by_subnet', - return_value=[]), - mock.patch.object(self.agent.dvr_agent.int_br, - 'get_vif_port_by_id', - return_value=self._port), - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') - ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, - get_vif_fn, add_flow_int_fn, delete_flows_int_fn, - add_flow_tun_fn, delete_flows_tun_fn): - self.agent.port_bound( - self._port, self._net_uuid, 'vxlan', - None, None, self._fixed_ips, - n_const.DEVICE_OWNER_DVR_INTERFACE, - False) - self.agent.port_bound(self._compute_port, - self._net_uuid, 'vxlan', - None, None, - self._compute_fixed_ips, - device_owner, False) - self.assertTrue(add_flow_tun_fn.called) - self.assertTrue(add_flow_int_fn.called) - self.assertTrue(delete_flows_int_fn.called) - - with contextlib.nested( - mock.patch.object(self.agent, 'reclaim_local_vlan'), - mock.patch.object(self.agent.plugin_rpc, 'update_device_down', - return_value=None), - mock.patch.object(self.agent.dvr_agent.int_br, - 'delete_flows')) as (reclaim_vlan_fn, - update_dev_down_fn, - delete_flows_int_fn): - self.agent.treat_devices_removed([self._compute_port.vif_id]) - expected = [ - mock.call( - table=constants.DVR_TO_SRC_MAC, - dl_dst=self._compute_port.vif_mac, - dl_vlan=( - self.agent.local_vlan_map[self._net_uuid].vlan))] - self.assertEqual(expected, delete_flows_int_fn.call_args_list) - - def test_treat_devices_removed_for_dvr_with_compute_ports(self): - self._test_treat_devices_removed_for_dvr( - device_owner="compute:None") - self._test_treat_devices_removed_for_dvr( - device_owner="compute:None", ip_version=6) - - def test_treat_devices_removed_for_dvr_with_lbaas_vip_ports(self): - self._test_treat_devices_removed_for_dvr( - device_owner=n_const.DEVICE_OWNER_LOADBALANCER) - self._test_treat_devices_removed_for_dvr( - device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6) - - 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) - self._test_treat_devices_removed_for_dvr( - device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6) - - def test_treat_devices_removed_for_dvr_csnat_port(self, ofport=10): - self._setup_for_dvr_test() - with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'set_db_attribute', - return_value=True): - with contextlib.nested( - mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' - 'db_get_val', - return_value=self._old_local_vlan), - mock.patch.object( - self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', - return_value={'gateway_ip': '1.1.1.1', - 'cidr': '1.1.1.0/24', - 'ip_version': 4, - 'gateway_mac': 'aa:bb:cc:11:22:33'}), - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_ports_on_host_by_subnet', - return_value=[]), - mock.patch.object(self.agent.dvr_agent.int_br, - 'get_vif_port_by_id', - return_value=self._port), - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') - ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, - get_vif_fn, add_flow_int_fn, delete_flows_int_fn, - add_flow_tun_fn, delete_flows_tun_fn): - self.agent.port_bound( - self._port, self._net_uuid, 'vxlan', - None, None, self._fixed_ips, - n_const.DEVICE_OWNER_ROUTER_SNAT, - False) - self.assertTrue(add_flow_int_fn.called) - self.assertTrue(delete_flows_int_fn.called) - - with contextlib.nested( - mock.patch.object(self.agent, 'reclaim_local_vlan'), - mock.patch.object(self.agent.plugin_rpc, 'update_device_down', - return_value=None), - mock.patch.object(self.agent.dvr_agent.int_br, - 'delete_flows')) as (reclaim_vlan_fn, - update_dev_down_fn, - delete_flows_int_fn): - self.agent.treat_devices_removed([self._port.vif_id]) - self.assertTrue(delete_flows_int_fn.called) - - def test_setup_dvr_flows_on_int_br(self): - self._setup_for_dvr_test() - with contextlib.nested( - mock.patch.object(self.agent.dvr_agent.int_br, - 'remove_all_flows'), - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object( - self.agent.dvr_agent.plugin_rpc, - 'get_dvr_mac_address_list', - return_value=[{'host': 'cn1', - 'mac_address': 'aa:bb:cc:dd:ee:ff'}, - {'host': 'cn2', - 'mac_address': '11:22:33:44:55:66'}])) as \ - (remove_flows_fn, add_int_flow_fn, add_tun_flow_fn, - get_mac_list_fn): - self.agent.dvr_agent.setup_dvr_flows_on_integ_br() - self.assertTrue(self.agent.dvr_agent.in_distributed_mode()) - physical_networks = self.agent.dvr_agent.bridge_mappings.keys() - ioport = self.agent.dvr_agent.int_ofports[physical_networks[0]] - expected = [ - mock.call(table=constants.CANARY_TABLE, - priority=0, - actions="drop"), - mock.call(table=constants.DVR_TO_SRC_MAC, - priority=1, - actions="drop"), - mock.call(table=constants.DVR_TO_SRC_MAC_VLAN, - priority=1, - actions="drop"), - mock.call(table=constants.LOCAL_SWITCHING, - priority=1, - actions="normal"), - mock.call( - table=constants.LOCAL_SWITCHING, priority=2, - actions="drop", - in_port=ioport)] - self.assertTrue(remove_flows_fn.called) - self.assertEqual(expected, add_int_flow_fn.call_args_list) - self.assertEqual(add_int_flow_fn.call_count, 5) - - def test_get_dvr_mac_address(self): - self._setup_for_dvr_test() - self.agent.dvr_agent.dvr_mac_address = None - with mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_dvr_mac_address_by_host', - return_value={'host': 'cn1', - 'mac_address': 'aa:22:33:44:55:66'}): - self.agent.dvr_agent.get_dvr_mac_address() - self.assertEqual('aa:22:33:44:55:66', - self.agent.dvr_agent.dvr_mac_address) - self.assertTrue(self.agent.dvr_agent.in_distributed_mode()) - - def test_get_dvr_mac_address_exception(self): - self._setup_for_dvr_test() - self.agent.dvr_agent.dvr_mac_address = None - with contextlib.nested( - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_dvr_mac_address_by_host', - side_effect=oslo_messaging.RemoteError), - mock.patch.object(self.agent.dvr_agent.int_br, - 'add_flow')) as (gd_mac, add_int_flow_fn): - - self.agent.dvr_agent.get_dvr_mac_address() - self.assertIsNone(self.agent.dvr_agent.dvr_mac_address) - self.assertFalse(self.agent.dvr_agent.in_distributed_mode()) - self.assertEqual(add_int_flow_fn.call_count, 1) - - def test_get_dvr_mac_address_retried(self): - valid_entry = {'host': 'cn1', 'mac_address': 'aa:22:33:44:55:66'} - raise_timeout = oslo_messaging.MessagingTimeout() - # Raise a timeout the first 2 times it calls get_dvr_mac_address() - self._setup_for_dvr_test() - self.agent.dvr_agent.dvr_mac_address = None - with mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_dvr_mac_address_by_host', - side_effect=(raise_timeout, raise_timeout, - valid_entry)): - self.agent.dvr_agent.get_dvr_mac_address() - self.assertEqual('aa:22:33:44:55:66', - self.agent.dvr_agent.dvr_mac_address) - self.assertTrue(self.agent.dvr_agent.in_distributed_mode()) - self.assertEqual(self.agent.dvr_agent.plugin_rpc. - get_dvr_mac_address_by_host.call_count, 3) - - def test_get_dvr_mac_address_retried_max(self): - raise_timeout = oslo_messaging.MessagingTimeout() - # Raise a timeout every time until we give up, currently 5 tries - self._setup_for_dvr_test() - self.agent.dvr_agent.dvr_mac_address = None - with contextlib.nested( - mock.patch.object(self.agent.dvr_agent.plugin_rpc, - 'get_dvr_mac_address_by_host', - side_effect=raise_timeout), - mock.patch.object(utils, "execute"), - ) as (rpc_mock, execute_mock): - self.agent.dvr_agent.get_dvr_mac_address() - self.assertIsNone(self.agent.dvr_agent.dvr_mac_address) - self.assertFalse(self.agent.dvr_agent.in_distributed_mode()) - self.assertEqual(self.agent.dvr_agent.plugin_rpc. - get_dvr_mac_address_by_host.call_count, 5) - - def test_dvr_mac_address_update(self): - self._setup_for_dvr_test() - newhost = 'cn2' - newmac = 'aa:bb:cc:dd:ee:ff' - int_ofport = self.agent.dvr_agent.int_ofports['physeth1'] - patch_int_ofport = self.agent.dvr_agent.patch_int_ofport - patch_tun_ofport = self.agent.dvr_agent.patch_tun_ofport - with contextlib.nested( - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.phys_brs['physeth1'], - 'add_flow') - ) as (add_flow_fn, add_flow_tn_fn, del_flows_fn, add_flow_phys_fn): - self.agent.dvr_agent.\ - dvr_mac_address_update( - dvr_macs=[{'host': newhost, - 'mac_address': newmac}]) - expected = [ - mock.call(table=constants.LOCAL_SWITCHING, - priority=4, - in_port=int_ofport, - dl_src=newmac, - actions="resubmit(,%s)" % - constants.DVR_TO_SRC_MAC_VLAN), - mock.call(table=constants.LOCAL_SWITCHING, - priority=2, - in_port=patch_tun_ofport, - dl_src=newmac, - actions="resubmit(,%s)" % - constants.DVR_TO_SRC_MAC)] - self.assertEqual(expected, add_flow_fn.call_args_list) - add_flow_phys_fn.assert_called_with( - table=constants.DVR_NOT_LEARN_VLAN, - priority=2, - dl_src=newmac, - actions="output:%s" % - self.agent.dvr_agent.phys_ofports['physeth1']) - add_flow_tn_fn.assert_called_with(table=constants.DVR_NOT_LEARN, - priority=1, - dl_src=newmac, - actions="output:%s" - % patch_int_ofport) - self.assertFalse(del_flows_fn.called) - with contextlib.nested( - mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), - mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), - mock.patch.object(self.agent.dvr_agent.phys_brs['physeth1'], - 'delete_flows'), - ) as (add_flow_fn, del_flows_tn_fn, del_flows_fn, del_flows_phys_fn): - self.agent.dvr_agent.dvr_mac_address_update(dvr_macs=[]) - ioport = self.agent.dvr_agent.int_ofports['physeth1'] - expected = [ - mock.call(table=constants.LOCAL_SWITCHING, - in_port=ioport, - dl_src=newmac), - mock.call(table=constants.LOCAL_SWITCHING, - in_port=patch_tun_ofport, - dl_src=newmac)] - self.assertEqual(expected, del_flows_fn.call_args_list) - del_flows_phys_fn.asert_called_with( - table=constants.DVR_NOT_LEARN_VLAN, - dl_src=newmac) - del_flows_tn_fn.assert_called_with(table=constants.DVR_NOT_LEARN, - dl_src=newmac) - self.assertFalse(add_flow_fn.called) - - def test_ovs_restart(self): - self._setup_for_dvr_test() - reset_methods = ( - 'reset_ovs_parameters', 'reset_dvr_parameters', - 'setup_dvr_flows_on_integ_br', 'setup_dvr_flows_on_tun_br', - 'setup_dvr_flows_on_phys_br', 'setup_dvr_mac_flows_on_all_brs') - reset_mocks = [mock.patch.object(self.agent.dvr_agent, method).start() - for method in reset_methods] - with contextlib.nested( - mock.patch.object(self.agent, 'check_ovs_status', - return_value=constants.OVS_RESTARTED), - mock.patch.object(self.agent, '_agent_has_updates', - side_effect=TypeError('loop exit')) - ): - # block RPC calls and bridge calls - self.agent.setup_physical_bridges = mock.Mock() - self.agent.setup_integration_br = mock.Mock() - self.agent.reset_tunnel_br = mock.Mock() - self.agent.state_rpc = mock.Mock() - try: - self.agent.rpc_loop(polling_manager=mock.Mock()) - except TypeError: - pass - self.assertTrue(all([x.called for x in reset_mocks])) diff --git a/neutron/tests/unit/plugins/openvswitch/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/openvswitch/test_ovs_neutron_agent.py index 58f2769ac..f39ecd0ce 100644 --- a/neutron/tests/unit/plugins/openvswitch/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/openvswitch/test_ovs_neutron_agent.py @@ -20,6 +20,7 @@ import mock import netaddr from oslo_config import cfg from oslo_log import log +import oslo_messaging import testtools from neutron.agent.common import ovs_lib @@ -1157,3 +1158,797 @@ class AncillaryBridgesTest(base.BaseTestCase): def test_ancillary_bridges_multiple(self): bridges = ['br-int', 'br-ex1', 'br-ex2'] self._test_ancillary_bridges(bridges, ['br-ex1', 'br-ex2']) + + +class TestOvsDvrNeutronAgent(base.BaseTestCase): + + def setUp(self): + super(TestOvsDvrNeutronAgent, self).setUp() + notifier_p = mock.patch(NOTIFIER) + notifier_cls = notifier_p.start() + self.notifier = mock.Mock() + notifier_cls.return_value = self.notifier + cfg.CONF.set_default('firewall_driver', + 'neutron.agent.firewall.NoopFirewallDriver', + group='SECURITYGROUP') + kwargs = ovs_neutron_agent.create_agent_config_map(cfg.CONF) + + class MockFixedIntervalLoopingCall(object): + def __init__(self, f): + self.f = f + + def start(self, interval=0): + self.f() + + with contextlib.nested( + mock.patch('neutron.plugins.openvswitch.agent.ovs_neutron_agent.' + 'OVSNeutronAgent.setup_integration_br'), + mock.patch('neutron.plugins.openvswitch.agent.ovs_neutron_agent.' + 'OVSNeutronAgent.setup_ancillary_bridges', + return_value=[]), + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'create'), + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'set_secure_mode'), + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'get_local_port_mac', + return_value='00:00:00:00:00:01'), + mock.patch('neutron.agent.linux.utils.get_interface_mac', + return_value='00:00:00:00:00:01'), + mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges'), + mock.patch('neutron.openstack.common.loopingcall.' + 'FixedIntervalLoopingCall', + new=MockFixedIntervalLoopingCall)): + self.agent = ovs_neutron_agent.OVSNeutronAgent(**kwargs) + # set back to true because initial report state will succeed due + # to mocked out RPC calls + self.agent.use_call = True + self.agent.tun_br = mock.Mock() + self.agent.sg_agent = mock.Mock() + + def _setup_for_dvr_test(self, ofport=10): + self._port = mock.Mock() + self._port.ofport = ofport + self._port.vif_id = "1234-5678-90" + self._physical_network = 'physeth1' + self._old_local_vlan = None + self._segmentation_id = 2001 + self.agent.enable_distributed_routing = True + self.agent.enable_tunneling = True + self.agent.patch_tun_ofport = 1 + self.agent.patch_int_ofport = 2 + self.agent.dvr_agent.local_ports = {} + self.agent.local_vlan_map = {} + self.agent.dvr_agent.enable_distributed_routing = True + self.agent.dvr_agent.enable_tunneling = True + self.agent.dvr_agent.patch_tun_ofport = 1 + self.agent.dvr_agent.patch_int_ofport = 2 + self.agent.dvr_agent.tun_br = mock.Mock() + self.agent.dvr_agent.phys_brs[self._physical_network] = mock.Mock() + self.agent.dvr_agent.bridge_mappings = {self._physical_network: + 'br-eth1'} + self.agent.dvr_agent.int_ofports[self._physical_network] = 30 + self.agent.dvr_agent.phys_ofports[self._physical_network] = 40 + self.agent.dvr_agent.local_dvr_map = {} + self.agent.dvr_agent.registered_dvr_macs = set() + self.agent.dvr_agent.dvr_mac_address = 'aa:22:33:44:55:66' + self._net_uuid = 'my-net-uuid' + self._fixed_ips = [{'subnet_id': 'my-subnet-uuid', + 'ip_address': '1.1.1.1'}] + self._compute_port = mock.Mock() + self._compute_port.ofport = 20 + self._compute_port.vif_id = "1234-5678-91" + self._compute_fixed_ips = [{'subnet_id': 'my-subnet-uuid', + 'ip_address': '1.1.1.3'}] + + def _test_port_bound_for_dvr_on_vlan_network(self, device_owner, + ip_version=4): + self._setup_for_dvr_test() + if ip_version == 4: + gateway_ip = '1.1.1.1' + cidr = '1.1.1.0/24' + else: + gateway_ip = '2001:100::1' + cidr = '2001:100::0/64' + self._port.vif_mac = gateway_mac = 'aa:bb:cc:11:22:33' + self._compute_port.vif_mac = '77:88:99:00:11:22' + physical_network = self._physical_network + segmentation_id = self._segmentation_id + network_type = p_const.TYPE_VLAN + with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'set_db_attribute', + return_value=True): + with contextlib.nested( + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'db_get_val', + return_value=self._old_local_vlan), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_subnet_for_dvr', + return_value={ + 'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, + 'gateway_mac': gateway_mac}), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]), + mock.patch.object(self.agent.dvr_agent.int_br, + 'get_vif_port_by_id', + return_value=self._port), + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'), + mock.patch.object( + self.agent.dvr_agent.phys_brs[physical_network], + 'add_flow'), + mock.patch.object( + self.agent.dvr_agent.phys_brs[physical_network], + 'delete_flows') + ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, + get_vif_fn, add_flow_int_fn, delete_flows_int_fn, + add_flow_tun_fn, delete_flows_tun_fn, add_flow_phys_fn, + delete_flows_phys_fn): + self.agent.port_bound( + self._port, self._net_uuid, network_type, + physical_network, segmentation_id, self._fixed_ips, + n_const.DEVICE_OWNER_DVR_INTERFACE, False) + lvm = self.agent.local_vlan_map[self._net_uuid] + phy_ofp = self.agent.dvr_agent.phys_ofports[physical_network] + int_ofp = self.agent.dvr_agent.int_ofports[physical_network] + expected_on_phys_br = [ + mock.call(table=constants.LOCAL_VLAN_TRANSLATION, + priority=4, + in_port=phy_ofp, + dl_vlan=lvm.vlan, + actions="mod_vlan_vid:%s,normal" % + (lvm.segmentation_id)), + mock.call(table=constants.DVR_PROCESS_VLAN, + priority=2, + dl_vlan=lvm.vlan, + dl_dst=self._port.vif_mac, + actions="drop"), + mock.call(table=constants.DVR_PROCESS_VLAN, + priority=1, + dl_vlan=lvm.vlan, + dl_src=self._port.vif_mac, + actions="mod_dl_src:%s,resubmit(,%s)" % + (self.agent.dvr_agent.dvr_mac_address, + constants.LOCAL_VLAN_TRANSLATION)) + ] + if ip_version == 4: + expected_on_phys_br.insert(1, mock.call( + proto='arp', + nw_dst=gateway_ip, actions='drop', + priority=3, table=constants.DVR_PROCESS_VLAN, + dl_vlan=lvm.vlan)) + else: + expected_on_phys_br.insert(1, mock.call( + icmp_type=n_const.ICMPV6_TYPE_RA, proto='icmp6', + dl_src=self._port.vif_mac, actions='drop', + priority=3, table=constants.DVR_PROCESS_VLAN, + dl_vlan=lvm.vlan)) + self.assertEqual(expected_on_phys_br, + add_flow_phys_fn.call_args_list) + self.agent.port_bound(self._compute_port, self._net_uuid, + network_type, physical_network, + segmentation_id, + self._compute_fixed_ips, + device_owner, False) + expected_on_int_br = [ + mock.call(priority=3, + in_port=int_ofp, + dl_vlan=lvm.segmentation_id, + actions="mod_vlan_vid:%s,normal" % lvm.vlan), + mock.call(table=constants.DVR_TO_SRC_MAC_VLAN, + priority=4, + dl_dst=self._compute_port.vif_mac, + dl_vlan=lvm.segmentation_id, + actions="strip_vlan,mod_dl_src:%s," + "output:%s" % + (gateway_mac, + self._compute_port.ofport)) + ] + self.assertEqual(expected_on_int_br, + add_flow_int_fn.call_args_list) + expected_on_int_br = [ + mock.call(in_port=self._port.ofport), + mock.call(in_port=self._compute_port.ofport) + ] + self.assertEqual(expected_on_int_br, + delete_flows_int_fn.call_args_list) + self.assertFalse(add_flow_tun_fn.called) + self.assertFalse(delete_flows_tun_fn.called) + self.assertFalse(delete_flows_phys_fn.called) + + def _test_port_bound_for_dvr_on_vxlan_network(self, device_owner, + ip_version=4): + self._setup_for_dvr_test() + if ip_version == 4: + gateway_ip = '1.1.1.1' + cidr = '1.1.1.0/24' + else: + gateway_ip = '2001:100::1' + cidr = '2001:100::0/64' + network_type = p_const.TYPE_VXLAN + self._port.vif_mac = gateway_mac = 'aa:bb:cc:11:22:33' + self._compute_port.vif_mac = '77:88:99:00:11:22' + physical_network = self._physical_network + segmentation_id = self._segmentation_id + with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'set_db_attribute', + return_value=True): + with contextlib.nested( + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'db_get_val', + return_value=self._old_local_vlan), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_subnet_for_dvr', + return_value={ + 'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, + 'gateway_mac': gateway_mac}), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]), + mock.patch.object(self.agent.dvr_agent.int_br, + 'get_vif_port_by_id', + return_value=self._port), + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'), + mock.patch.object( + self.agent.dvr_agent.phys_brs[physical_network], + 'add_flow'), + mock.patch.object( + self.agent.dvr_agent.phys_brs[physical_network], + 'delete_flows') + ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, + get_vif_fn, add_flow_int_fn, delete_flows_int_fn, + add_flow_tun_fn, delete_flows_tun_fn, + add_flow_phys_fn, delete_flows_phys_fn): + self.agent.port_bound( + self._port, self._net_uuid, network_type, + physical_network, segmentation_id, self._fixed_ips, + n_const.DEVICE_OWNER_DVR_INTERFACE, False) + lvm = self.agent.local_vlan_map[self._net_uuid] + expected_on_tun_br = [ + mock.call( + table=constants.TUN_TABLE['vxlan'], + priority=1, tun_id=lvm.segmentation_id, + actions="mod_vlan_vid:%s," + "resubmit(,%s)" % + (lvm.vlan, constants.DVR_NOT_LEARN)), + mock.call( + table=constants.DVR_PROCESS, priority=2, + dl_vlan=lvm.vlan, + dl_dst=self._port.vif_mac, + actions='drop'), + mock.call( + table=constants.DVR_PROCESS, priority=1, + dl_vlan=lvm.vlan, + dl_src=self._port.vif_mac, + actions="mod_dl_src:%s,resubmit(,%s)" % ( + self.agent.dvr_agent.dvr_mac_address, + constants.PATCH_LV_TO_TUN))] + if ip_version == 4: + expected_on_tun_br.insert(1, mock.call( + proto='arp', + nw_dst=gateway_ip, actions='drop', + priority=3, table=constants.DVR_PROCESS, + dl_vlan=lvm.vlan)) + else: + expected_on_tun_br.insert(1, mock.call( + icmp_type=n_const.ICMPV6_TYPE_RA, + proto='icmp6', + dl_src=self._port.vif_mac, + actions='drop', + priority=3, table=constants.DVR_PROCESS, + dl_vlan=lvm.vlan)) + self.assertEqual(expected_on_tun_br, + add_flow_tun_fn.call_args_list) + self.agent.port_bound(self._compute_port, self._net_uuid, + network_type, physical_network, + segmentation_id, + self._compute_fixed_ips, + device_owner, False) + expected_on_int_br = [ + mock.call(table=constants.DVR_TO_SRC_MAC, priority=4, + dl_dst=self._compute_port.vif_mac, + dl_vlan=lvm.vlan, + actions="strip_vlan,mod_dl_src:%s," + "output:%s" % + (gateway_mac, self._compute_port.ofport)) + ] + self.assertEqual(expected_on_int_br, + add_flow_int_fn.call_args_list) + self.assertFalse(add_flow_phys_fn.called) + expected_on_int_br = [ + mock.call(in_port=self._port.ofport), + mock.call(in_port=self._compute_port.ofport) + ] + self.assertEqual(expected_on_int_br, + delete_flows_int_fn.call_args_list) + self.assertFalse(add_flow_phys_fn.called) + self.assertFalse(delete_flows_tun_fn.called) + self.assertFalse(delete_flows_phys_fn.called) + + def test_port_bound_for_dvr_with_compute_ports(self): + self._test_port_bound_for_dvr_on_vlan_network( + device_owner="compute:None") + self._test_port_bound_for_dvr_on_vlan_network( + device_owner="compute:None", ip_version=6) + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner="compute:None") + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner="compute:None", ip_version=6) + + def test_port_bound_for_dvr_with_lbaas_vip_ports(self): + self._test_port_bound_for_dvr_on_vlan_network( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER) + self._test_port_bound_for_dvr_on_vlan_network( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6) + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER) + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6) + + def test_port_bound_for_dvr_with_dhcp_ports(self): + self._test_port_bound_for_dvr_on_vlan_network( + device_owner=n_const.DEVICE_OWNER_DHCP) + self._test_port_bound_for_dvr_on_vlan_network( + device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6) + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner=n_const.DEVICE_OWNER_DHCP) + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6) + + def test_port_bound_for_dvr_with_csnat_ports(self, ofport=10): + self._setup_for_dvr_test() + with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'set_db_attribute', + return_value=True): + with contextlib.nested( + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'db_get_val', + return_value=self._old_local_vlan), + mock.patch.object( + self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', + return_value={'gateway_ip': '1.1.1.1', + 'cidr': '1.1.1.0/24', + 'ip_version': 4, + 'gateway_mac': 'aa:bb:cc:11:22:33'}), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]), + mock.patch.object(self.agent.dvr_agent.int_br, + 'get_vif_port_by_id', + return_value=self._port), + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') + ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, + get_vif_fn, add_flow_int_fn, delete_flows_int_fn, + add_flow_tun_fn, delete_flows_tun_fn): + self.agent.port_bound( + self._port, self._net_uuid, 'vxlan', + None, None, self._fixed_ips, + n_const.DEVICE_OWNER_ROUTER_SNAT, + False) + self.assertTrue(add_flow_int_fn.called) + self.assertTrue(delete_flows_int_fn.called) + + def test_treat_devices_removed_for_dvr_interface(self, ofport=10): + self._test_treat_devices_removed_for_dvr_interface(ofport) + self._test_treat_devices_removed_for_dvr_interface( + ofport, ip_version=6) + + def _test_treat_devices_removed_for_dvr_interface(self, ofport=10, + ip_version=4): + self._setup_for_dvr_test() + if ip_version == 4: + gateway_ip = '1.1.1.1' + cidr = '1.1.1.0/24' + else: + gateway_ip = '2001:100::1' + cidr = '2001:100::0/64' + with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'set_db_attribute', + return_value=True): + with contextlib.nested( + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'db_get_val', + return_value=self._old_local_vlan), + mock.patch.object( + self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', + return_value={'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, + 'gateway_mac': 'aa:bb:cc:11:22:33'}), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]), + mock.patch.object(self.agent.dvr_agent.int_br, + 'get_vif_port_by_id', + return_value=self._port), + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') + ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, + get_vif_fn, add_flow_int_fn, delete_flows_int_fn, + add_flow_tun_fn, delete_flows_tun_fn): + self.agent.port_bound( + self._port, self._net_uuid, 'vxlan', + None, None, self._fixed_ips, + n_const.DEVICE_OWNER_DVR_INTERFACE, + False) + self.assertTrue(add_flow_tun_fn.called) + self.assertTrue(delete_flows_int_fn.called) + + with contextlib.nested( + mock.patch.object(self.agent, 'reclaim_local_vlan'), + mock.patch.object(self.agent.plugin_rpc, 'update_device_down', + return_value=None), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.tun_br, + 'delete_flows')) as (reclaim_vlan_fn, + update_dev_down_fn, + delete_flows_int_fn, + delete_flows_tun_fn): + self.agent.treat_devices_removed([self._port.vif_id]) + if ip_version == 4: + expected = [mock.call( + proto='arp', + nw_dst=gateway_ip, + table=constants.DVR_PROCESS, + dl_vlan=( + self.agent.local_vlan_map[self._net_uuid].vlan))] + else: + expected = [mock.call( + icmp_type=n_const.ICMPV6_TYPE_RA, proto='icmp6', + dl_src='aa:bb:cc:11:22:33', + table=constants.DVR_PROCESS, + dl_vlan=( + self.agent.local_vlan_map[self._net_uuid].vlan))] + expected.extend([ + mock.call( + table=constants.DVR_PROCESS, + dl_dst=self._port.vif_mac, + dl_vlan=( + self.agent.local_vlan_map[self._net_uuid].vlan)), + mock.call( + table=constants.DVR_PROCESS, + dl_vlan=( + self.agent.local_vlan_map[self._net_uuid].vlan), + dl_src=self._port.vif_mac) + ]) + self.assertEqual(expected, delete_flows_tun_fn.call_args_list) + + def _test_treat_devices_removed_for_dvr(self, device_owner, ip_version=4): + self._setup_for_dvr_test() + if ip_version == 4: + gateway_ip = '1.1.1.1' + cidr = '1.1.1.0/24' + else: + gateway_ip = '2001:100::1' + cidr = '2001:100::0/64' + with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'set_db_attribute', + return_value=True): + with contextlib.nested( + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'db_get_val', + return_value=self._old_local_vlan), + mock.patch.object( + self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', + return_value={'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, + 'gateway_mac': 'aa:bb:cc:11:22:33'}), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]), + mock.patch.object(self.agent.dvr_agent.int_br, + 'get_vif_port_by_id', + return_value=self._port), + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') + ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, + get_vif_fn, add_flow_int_fn, delete_flows_int_fn, + add_flow_tun_fn, delete_flows_tun_fn): + self.agent.port_bound( + self._port, self._net_uuid, 'vxlan', + None, None, self._fixed_ips, + n_const.DEVICE_OWNER_DVR_INTERFACE, + False) + self.agent.port_bound(self._compute_port, + self._net_uuid, 'vxlan', + None, None, + self._compute_fixed_ips, + device_owner, False) + self.assertTrue(add_flow_tun_fn.called) + self.assertTrue(add_flow_int_fn.called) + self.assertTrue(delete_flows_int_fn.called) + + with contextlib.nested( + mock.patch.object(self.agent, 'reclaim_local_vlan'), + mock.patch.object(self.agent.plugin_rpc, 'update_device_down', + return_value=None), + mock.patch.object(self.agent.dvr_agent.int_br, + 'delete_flows')) as (reclaim_vlan_fn, + update_dev_down_fn, + delete_flows_int_fn): + self.agent.treat_devices_removed([self._compute_port.vif_id]) + expected = [ + mock.call( + table=constants.DVR_TO_SRC_MAC, + dl_dst=self._compute_port.vif_mac, + dl_vlan=( + self.agent.local_vlan_map[self._net_uuid].vlan))] + self.assertEqual(expected, delete_flows_int_fn.call_args_list) + + def test_treat_devices_removed_for_dvr_with_compute_ports(self): + self._test_treat_devices_removed_for_dvr( + device_owner="compute:None") + self._test_treat_devices_removed_for_dvr( + device_owner="compute:None", ip_version=6) + + def test_treat_devices_removed_for_dvr_with_lbaas_vip_ports(self): + self._test_treat_devices_removed_for_dvr( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER) + self._test_treat_devices_removed_for_dvr( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER, ip_version=6) + + 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) + self._test_treat_devices_removed_for_dvr( + device_owner=n_const.DEVICE_OWNER_DHCP, ip_version=6) + + def test_treat_devices_removed_for_dvr_csnat_port(self, ofport=10): + self._setup_for_dvr_test() + with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'set_db_attribute', + return_value=True): + with contextlib.nested( + mock.patch('neutron.agent.common.ovs_lib.OVSBridge.' + 'db_get_val', + return_value=self._old_local_vlan), + mock.patch.object( + self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr', + return_value={'gateway_ip': '1.1.1.1', + 'cidr': '1.1.1.0/24', + 'ip_version': 4, + 'gateway_mac': 'aa:bb:cc:11:22:33'}), + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]), + mock.patch.object(self.agent.dvr_agent.int_br, + 'get_vif_port_by_id', + return_value=self._port), + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows') + ) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn, + get_vif_fn, add_flow_int_fn, delete_flows_int_fn, + add_flow_tun_fn, delete_flows_tun_fn): + self.agent.port_bound( + self._port, self._net_uuid, 'vxlan', + None, None, self._fixed_ips, + n_const.DEVICE_OWNER_ROUTER_SNAT, + False) + self.assertTrue(add_flow_int_fn.called) + self.assertTrue(delete_flows_int_fn.called) + + with contextlib.nested( + mock.patch.object(self.agent, 'reclaim_local_vlan'), + mock.patch.object(self.agent.plugin_rpc, 'update_device_down', + return_value=None), + mock.patch.object(self.agent.dvr_agent.int_br, + 'delete_flows')) as (reclaim_vlan_fn, + update_dev_down_fn, + delete_flows_int_fn): + self.agent.treat_devices_removed([self._port.vif_id]) + self.assertTrue(delete_flows_int_fn.called) + + def test_setup_dvr_flows_on_int_br(self): + self._setup_for_dvr_test() + with contextlib.nested( + mock.patch.object(self.agent.dvr_agent.int_br, + 'remove_all_flows'), + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object( + self.agent.dvr_agent.plugin_rpc, + 'get_dvr_mac_address_list', + return_value=[{'host': 'cn1', + 'mac_address': 'aa:bb:cc:dd:ee:ff'}, + {'host': 'cn2', + 'mac_address': '11:22:33:44:55:66'}])) as \ + (remove_flows_fn, add_int_flow_fn, add_tun_flow_fn, + get_mac_list_fn): + self.agent.dvr_agent.setup_dvr_flows_on_integ_br() + self.assertTrue(self.agent.dvr_agent.in_distributed_mode()) + physical_networks = self.agent.dvr_agent.bridge_mappings.keys() + ioport = self.agent.dvr_agent.int_ofports[physical_networks[0]] + expected = [ + mock.call(table=constants.CANARY_TABLE, + priority=0, + actions="drop"), + mock.call(table=constants.DVR_TO_SRC_MAC, + priority=1, + actions="drop"), + mock.call(table=constants.DVR_TO_SRC_MAC_VLAN, + priority=1, + actions="drop"), + mock.call(table=constants.LOCAL_SWITCHING, + priority=1, + actions="normal"), + mock.call( + table=constants.LOCAL_SWITCHING, priority=2, + actions="drop", + in_port=ioport)] + self.assertTrue(remove_flows_fn.called) + self.assertEqual(expected, add_int_flow_fn.call_args_list) + self.assertEqual(add_int_flow_fn.call_count, 5) + + def test_get_dvr_mac_address(self): + self._setup_for_dvr_test() + self.agent.dvr_agent.dvr_mac_address = None + with mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_dvr_mac_address_by_host', + return_value={'host': 'cn1', + 'mac_address': 'aa:22:33:44:55:66'}): + self.agent.dvr_agent.get_dvr_mac_address() + self.assertEqual('aa:22:33:44:55:66', + self.agent.dvr_agent.dvr_mac_address) + self.assertTrue(self.agent.dvr_agent.in_distributed_mode()) + + def test_get_dvr_mac_address_exception(self): + self._setup_for_dvr_test() + self.agent.dvr_agent.dvr_mac_address = None + with contextlib.nested( + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_dvr_mac_address_by_host', + side_effect=oslo_messaging.RemoteError), + mock.patch.object(self.agent.dvr_agent.int_br, + 'add_flow')) as (gd_mac, add_int_flow_fn): + + self.agent.dvr_agent.get_dvr_mac_address() + self.assertIsNone(self.agent.dvr_agent.dvr_mac_address) + self.assertFalse(self.agent.dvr_agent.in_distributed_mode()) + self.assertEqual(add_int_flow_fn.call_count, 1) + + def test_get_dvr_mac_address_retried(self): + valid_entry = {'host': 'cn1', 'mac_address': 'aa:22:33:44:55:66'} + raise_timeout = oslo_messaging.MessagingTimeout() + # Raise a timeout the first 2 times it calls get_dvr_mac_address() + self._setup_for_dvr_test() + self.agent.dvr_agent.dvr_mac_address = None + with mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_dvr_mac_address_by_host', + side_effect=(raise_timeout, raise_timeout, + valid_entry)): + self.agent.dvr_agent.get_dvr_mac_address() + self.assertEqual('aa:22:33:44:55:66', + self.agent.dvr_agent.dvr_mac_address) + self.assertTrue(self.agent.dvr_agent.in_distributed_mode()) + self.assertEqual(self.agent.dvr_agent.plugin_rpc. + get_dvr_mac_address_by_host.call_count, 3) + + def test_get_dvr_mac_address_retried_max(self): + raise_timeout = oslo_messaging.MessagingTimeout() + # Raise a timeout every time until we give up, currently 5 tries + self._setup_for_dvr_test() + self.agent.dvr_agent.dvr_mac_address = None + with contextlib.nested( + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_dvr_mac_address_by_host', + side_effect=raise_timeout), + mock.patch.object(utils, "execute"), + ) as (rpc_mock, execute_mock): + self.agent.dvr_agent.get_dvr_mac_address() + self.assertIsNone(self.agent.dvr_agent.dvr_mac_address) + self.assertFalse(self.agent.dvr_agent.in_distributed_mode()) + self.assertEqual(self.agent.dvr_agent.plugin_rpc. + get_dvr_mac_address_by_host.call_count, 5) + + def test_dvr_mac_address_update(self): + self._setup_for_dvr_test() + newhost = 'cn2' + newmac = 'aa:bb:cc:dd:ee:ff' + int_ofport = self.agent.dvr_agent.int_ofports['physeth1'] + patch_int_ofport = self.agent.dvr_agent.patch_int_ofport + patch_tun_ofport = self.agent.dvr_agent.patch_tun_ofport + with contextlib.nested( + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.phys_brs['physeth1'], + 'add_flow') + ) as (add_flow_fn, add_flow_tn_fn, del_flows_fn, add_flow_phys_fn): + self.agent.dvr_agent.\ + dvr_mac_address_update( + dvr_macs=[{'host': newhost, + 'mac_address': newmac}]) + expected = [ + mock.call(table=constants.LOCAL_SWITCHING, + priority=4, + in_port=int_ofport, + dl_src=newmac, + actions="resubmit(,%s)" % + constants.DVR_TO_SRC_MAC_VLAN), + mock.call(table=constants.LOCAL_SWITCHING, + priority=2, + in_port=patch_tun_ofport, + dl_src=newmac, + actions="resubmit(,%s)" % + constants.DVR_TO_SRC_MAC)] + self.assertEqual(expected, add_flow_fn.call_args_list) + add_flow_phys_fn.assert_called_with( + table=constants.DVR_NOT_LEARN_VLAN, + priority=2, + dl_src=newmac, + actions="output:%s" % + self.agent.dvr_agent.phys_ofports['physeth1']) + add_flow_tn_fn.assert_called_with(table=constants.DVR_NOT_LEARN, + priority=1, + dl_src=newmac, + actions="output:%s" + % patch_int_ofport) + self.assertFalse(del_flows_fn.called) + with contextlib.nested( + mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'), + mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'), + mock.patch.object(self.agent.dvr_agent.phys_brs['physeth1'], + 'delete_flows'), + ) as (add_flow_fn, del_flows_tn_fn, del_flows_fn, del_flows_phys_fn): + self.agent.dvr_agent.dvr_mac_address_update(dvr_macs=[]) + ioport = self.agent.dvr_agent.int_ofports['physeth1'] + expected = [ + mock.call(table=constants.LOCAL_SWITCHING, + in_port=ioport, + dl_src=newmac), + mock.call(table=constants.LOCAL_SWITCHING, + in_port=patch_tun_ofport, + dl_src=newmac)] + self.assertEqual(expected, del_flows_fn.call_args_list) + del_flows_phys_fn.asert_called_with( + table=constants.DVR_NOT_LEARN_VLAN, + dl_src=newmac) + del_flows_tn_fn.assert_called_with(table=constants.DVR_NOT_LEARN, + dl_src=newmac) + self.assertFalse(add_flow_fn.called) + + def test_ovs_restart(self): + self._setup_for_dvr_test() + reset_methods = ( + 'reset_ovs_parameters', 'reset_dvr_parameters', + 'setup_dvr_flows_on_integ_br', 'setup_dvr_flows_on_tun_br', + 'setup_dvr_flows_on_phys_br', 'setup_dvr_mac_flows_on_all_brs') + reset_mocks = [mock.patch.object(self.agent.dvr_agent, method).start() + for method in reset_methods] + with contextlib.nested( + mock.patch.object(self.agent, 'check_ovs_status', + return_value=constants.OVS_RESTARTED), + mock.patch.object(self.agent, '_agent_has_updates', + side_effect=TypeError('loop exit')) + ): + # block RPC calls and bridge calls + self.agent.setup_physical_bridges = mock.Mock() + self.agent.setup_integration_br = mock.Mock() + self.agent.reset_tunnel_br = mock.Mock() + self.agent.state_rpc = mock.Mock() + try: + self.agent.rpc_loop(polling_manager=mock.Mock()) + except TypeError: + pass + self.assertTrue(all([x.called for x in reset_mocks]))