Notify L2pop driver from update_device_(up|down)

This patch calls update_port_up and update_port_down inside
of the l2pop driver directly from update_device_up and
update_device_down in the ML2 RPC layer. This allows the L2pop
driver to setup forwarding entries completely independent of
the port status update events.

This will allow L2pop to function without requiring the ports to
transition from ACTIVE->BUILD->ACTIVE every time the agent requests
device details.

This will unblock the push notifications work and will additionally
enable us to remove the update to BUILD status as part of a performance
improvement backport for bug #1665215.

Partial-Bug: #1665215
Partially-Implements: blueprint push-notifications
Change-Id: Icd4cd4e3f735e88299e86468380c5f786e7628fe
This commit is contained in:
Kevin Benton 2017-05-15 19:08:05 -07:00
parent 6d84a8fac5
commit 9f55d77016
2 changed files with 34 additions and 24 deletions

View File

@ -215,7 +215,7 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
"executed concurrently. Ignoring StaleDataError.")
return {'device': device,
'exists': port_exists}
self.notify_ha_port_status(port_id, rpc_context,
self.notify_l2pop_port_wiring(port_id, rpc_context,
n_const.PORT_STATUS_DOWN, host)
return {'device': device,
@ -250,8 +250,8 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
return
else:
self.update_port_status_to_active(port, rpc_context, port_id, host)
self.notify_ha_port_status(port_id, rpc_context,
n_const.PORT_STATUS_ACTIVE, host, port=port)
self.notify_l2pop_port_wiring(port_id, rpc_context,
n_const.PORT_STATUS_ACTIVE, host)
def update_port_status_to_active(self, port, rpc_context, port_id, host):
plugin = directory.get_plugin()
@ -274,23 +274,33 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
rpc_context, port['id'], resources.PORT,
provisioning_blocks.L2_AGENT_ENTITY)
def notify_ha_port_status(self, port_id, rpc_context,
status, host, port=None):
def notify_l2pop_port_wiring(self, port_id, rpc_context,
status, host):
"""Notify the L2pop driver that a port has been wired/unwired.
The L2pop driver uses this notification to broadcast forwarding
entries to other agents on the same network as the port for port_id.
"""
plugin = directory.get_plugin()
l2pop_driver = plugin.mechanism_manager.mech_drivers.get(
'l2population')
if not l2pop_driver:
return
if not port:
port = ml2_db.get_port(rpc_context, port_id)
if not port:
return
is_ha_port = l3_hamode_db.is_ha_router_port(rpc_context,
port['device_owner'],
port['device_id'])
if is_ha_port:
port_context = plugin.get_bound_port_context(
rpc_context, port_id)
if not port_context:
# port deleted
return
port = port_context.current
if (status == n_const.PORT_STATUS_ACTIVE and
port[portbindings.HOST_ID] != host and
not l3_hamode_db.is_ha_router_port(rpc_context,
port['device_owner'],
port['device_id'])):
# don't setup ACTIVE forwarding entries unless bound to this
# host or if it's an HA port (which is special-cased in the
# mech driver)
return
port_context.current['status'] = status
port_context.current[portbindings.HOST_ID] = host
if status == n_const.PORT_STATUS_ACTIVE:

View File

@ -59,7 +59,7 @@ class RpcCallbacksTestCase(base.BaseTestCase):
}
with mock.patch('neutron.plugins.ml2.plugin.Ml2Plugin'
'._device_to_port_id'),\
mock.patch.object(self.callbacks, 'notify_ha_port_status'):
mock.patch.object(self.callbacks, 'notify_l2pop_port_wiring'):
with mock.patch('neutron.db.provisioning_blocks.'
'provisioning_complete') as pc:
self.callbacks.update_device_up(mock.Mock(), **kwargs)
@ -212,7 +212,7 @@ class RpcCallbacksTestCase(base.BaseTestCase):
def _test_update_device_not_bound_to_host(self, func):
self.plugin.port_bound_to_host.return_value = False
self.callbacks.notify_ha_port_status = mock.Mock()
self.callbacks.notify_l2pop_port_wiring = mock.Mock()
self.plugin._device_to_port_id.return_value = 'fake_port_id'
res = func(mock.Mock(), device='fake_device', host='fake_host')
self.plugin.port_bound_to_host.assert_called_once_with(mock.ANY,
@ -235,7 +235,7 @@ class RpcCallbacksTestCase(base.BaseTestCase):
def test_update_device_down_call_update_port_status(self):
self.plugin.update_port_status.return_value = False
self.callbacks.notify_ha_port_status = mock.Mock()
self.callbacks.notify_l2pop_port_wiring = mock.Mock()
self.plugin._device_to_port_id.return_value = 'fake_port_id'
self.assertEqual(
{'device': 'fake_device', 'exists': False},