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 <romilg@hp.com>

Closes-Bug: #1334292
Change-Id: Ifbbd7c4e22d4a6383a3c77a9d9ac9a37302c38c3
This commit is contained in:
Chengli XU 2014-06-25 22:26:04 +08:00 committed by Romil Gupta
parent ec3f7562e0
commit f022caed48
3 changed files with 64 additions and 15 deletions

View File

@ -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_(

View File

@ -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,

View File

@ -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()