# 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
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))
+++ /dev/null
-# 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))
+++ /dev/null
-# 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]))
import netaddr
from oslo_config import cfg
from oslo_log import log
+import oslo_messaging
import testtools
from neutron.agent.common import ovs_lib
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]))