From f022caed48f7e0c2c97be22b90f4c3c5f24c6c31 Mon Sep 17 00:00:00 2001 From: Chengli XU Date: Wed, 25 Jun 2014 22:26:04 +0800 Subject: [PATCH] l2-pop shouldn't notify agent about inactive ports When an agent starts, or the first port of an agent becomes active, l2 population mechanism driver will notify the agent of all ports on other agents. It should not notify about inactive ports. Basically, this patch-set is needed for fixing the bug 1332450. Co-Authored-By: Romil Gupta Closes-Bug: #1334292 Change-Id: Ifbbd7c4e22d4a6383a3c77a9d9ac9a37302c38c3 --- neutron/plugins/ml2/drivers/l2pop/db.py | 15 ++--- .../plugins/ml2/drivers/l2pop/mech_driver.py | 4 +- .../unit/ml2/drivers/test_l2population.py | 60 +++++++++++++++++-- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/neutron/plugins/ml2/drivers/l2pop/db.py b/neutron/plugins/ml2/drivers/l2pop/db.py index 65faa7ce0..3cdfb1dd9 100644 --- a/neutron/plugins/ml2/drivers/l2pop/db.py +++ b/neutron/plugins/ml2/drivers/l2pop/db.py @@ -15,7 +15,6 @@ from oslo_serialization import jsonutils from oslo_utils import timeutils -from sqlalchemy import sql from neutron.common import constants as const from neutron.db import agents_db @@ -56,7 +55,7 @@ class L2populationDbMixin(base_db.CommonDbMixin): l2_const.SUPPORTED_AGENT_TYPES)) return query.first() - def get_network_ports(self, session, network_id): + def _get_active_network_ports(self, session, network_id): with session.begin(subtransactions=True): query = session.query(ml2_models.PortBinding, agents_db.Agent) @@ -65,17 +64,18 @@ class L2populationDbMixin(base_db.CommonDbMixin): ml2_models.PortBinding.host) query = query.join(models_v2.Port) query = query.filter(models_v2.Port.network_id == network_id, - models_v2.Port.admin_state_up == sql.true(), + models_v2.Port.status == + const.PORT_STATUS_ACTIVE, agents_db.Agent.agent_type.in_( l2_const.SUPPORTED_AGENT_TYPES)) return query - def get_nondvr_network_ports(self, session, network_id): - query = self.get_network_ports(session, network_id) + def get_nondvr_active_network_ports(self, session, network_id): + query = self._get_active_network_ports(session, network_id) return query.filter(models_v2.Port.device_owner != const.DEVICE_OWNER_DVR_INTERFACE) - def get_dvr_network_ports(self, session, network_id): + def get_dvr_active_network_ports(self, session, network_id): with session.begin(subtransactions=True): query = session.query(ml2_models.DVRPortBinding, agents_db.Agent) @@ -84,7 +84,8 @@ class L2populationDbMixin(base_db.CommonDbMixin): ml2_models.DVRPortBinding.host) query = query.join(models_v2.Port) query = query.filter(models_v2.Port.network_id == network_id, - models_v2.Port.admin_state_up == sql.true(), + models_v2.Port.status == + const.PORT_STATUS_ACTIVE, models_v2.Port.device_owner == const.DEVICE_OWNER_DVR_INTERFACE, agents_db.Agent.agent_type.in_( diff --git a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py index a93c0c76a..fc413fe95 100644 --- a/neutron/plugins/ml2/drivers/l2pop/mech_driver.py +++ b/neutron/plugins/ml2/drivers/l2pop/mech_driver.py @@ -185,9 +185,9 @@ class L2populationMechanismDriver(api.MechanismDriver, 'network_type': segment['network_type'], 'ports': {}}} tunnel_network_ports = ( - self.get_dvr_network_ports(session, network_id).all()) + self.get_dvr_active_network_ports(session, network_id).all()) fdb_network_ports = ( - self.get_nondvr_network_ports(session, network_id).all()) + self.get_nondvr_active_network_ports(session, network_id).all()) ports = agent_fdb_entries[network_id]['ports'] ports.update(self._get_tunnels( fdb_network_ports + tunnel_network_ports, diff --git a/neutron/tests/unit/ml2/drivers/test_l2population.py b/neutron/tests/unit/ml2/drivers/test_l2population.py index 0c51de404..12f0f6b21 100644 --- a/neutron/tests/unit/ml2/drivers/test_l2population.py +++ b/neutron/tests/unit/ml2/drivers/test_l2population.py @@ -303,6 +303,46 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): self.mock_fanout.assert_called_with( mock.ANY, 'add_fdb_entries', expected) + def test_fdb_called_for_active_ports(self): + self._register_ml2_agents() + + with self.subnet(network=self._network) as subnet: + host_arg = {portbindings.HOST_ID: HOST} + with self.port(subnet=subnet, + device_owner=DEVICE_OWNER_COMPUTE, + arg_list=(portbindings.HOST_ID,), + **host_arg) as port1: + host_arg = {portbindings.HOST_ID: HOST + '_2'} + with self.port(subnet=subnet, + device_owner=DEVICE_OWNER_COMPUTE, + arg_list=(portbindings.HOST_ID,), + **host_arg): + p1 = port1['port'] + + device1 = 'tap' + p1['id'] + + self.mock_cast.reset_mock() + self.mock_fanout.reset_mock() + self.callbacks.update_device_up(self.adminContext, + agent_id=HOST, + device=device1) + + p1_ips = [p['ip_address'] for p in p1['fixed_ips']] + + self.assertFalse(self.mock_cast.called) + + expected2 = {p1['network_id']: + {'ports': + {'20.0.0.1': [constants.FLOODING_ENTRY, + l2pop_rpc.PortInfo( + p1['mac_address'], + p1_ips[0])]}, + 'network_type': 'vxlan', + 'segment_id': 1}} + + self.mock_fanout.assert_called_with( + mock.ANY, 'add_fdb_entries', expected2) + def test_fdb_add_two_agents(self): self._register_ml2_agents() @@ -323,13 +363,17 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): p1 = port1['port'] p2 = port2['port'] - device = 'tap' + p1['id'] + device1 = 'tap' + p1['id'] + device2 = 'tap' + p2['id'] self.mock_cast.reset_mock() self.mock_fanout.reset_mock() + self.callbacks.update_device_up(self.adminContext, + agent_id=HOST + '_2', + device=device2) self.callbacks.update_device_up(self.adminContext, agent_id=HOST, - device=device) + device=device1) p1_ips = [p['ip_address'] for p in p1['fixed_ips']] p2_ips = [p['ip_address'] for p in p2['fixed_ips']] @@ -381,13 +425,17 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): p1 = port1['port'] p3 = port3['port'] - device = 'tap' + p3['id'] + device1 = 'tap' + p1['id'] + device3 = 'tap' + p3['id'] self.mock_cast.reset_mock() self.mock_fanout.reset_mock() + self.callbacks.update_device_up( + self.adminContext, agent_id=HOST + '_2', + device=device1) self.callbacks.update_device_up( self.adminContext, agent_id=HOST, - device=device) + device=device3) p1_ips = [p['ip_address'] for p in p1['fixed_ips']] @@ -886,10 +934,10 @@ class TestL2PopulationMechDriver(base.BaseTestCase): 'get_agent_ip', side_effect=agent_ip_side_effect), mock.patch.object(l2pop_db.L2populationDbMixin, - 'get_nondvr_network_ports', + 'get_nondvr_active_network_ports', new=fdb_network_ports_query), mock.patch.object(l2pop_db.L2populationDbMixin, - 'get_dvr_network_ports', + 'get_dvr_active_network_ports', new=tunnel_network_ports_query)): session = mock.Mock() agent = mock.Mock() -- 2.45.2