Add missing port UPDATE event to ML2

The ML2 plugin was missing a port AFTER_UPDATE event in its
binding commit operations. This was resulting in port binding
results not being serialized for push notifications.

This patch just adds in the AFTER_UPDATE event to the port
binding commit operation.

Partially-Implements: blueprint push-notifications
Change-Id: I67276a3efe97b60499601b1aceeee27ad8961062
This commit is contained in:
Kevin Benton 2017-01-22 16:49:13 -08:00
parent 28d2e699b5
commit 8a7909080c
3 changed files with 46 additions and 6 deletions

View File

@ -531,6 +531,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
# just finished, whether that transaction committed new
# results or discovered concurrent port state changes.
# Also, Trigger notification for successful binding commit.
kwargs = {
'context': plugin_context,
'port': port,
'mac_address_updated': False,
'original_port': oport,
}
registry.notify(resources.PORT, events.AFTER_UPDATE,
self, **kwargs)
self.mechanism_manager.update_port_postcommit(cur_context)
need_notify = True
try_again = False

View File

@ -36,6 +36,10 @@ class L3DvrTestCaseBase(ml2_test_base.ML2TestFramework):
super(L3DvrTestCaseBase, self).setUp()
self.l3_agent = helpers.register_l3_agent(
agent_mode=constants.L3_AGENT_MODE_DVR_SNAT)
# register OVS agents to avoid time wasted on committing
# port binding failures on every port update
helpers.register_ovs_agent(host='host1')
helpers.register_ovs_agent(host='host2')
def _create_router(self, distributed=True, ha=False, admin_state_up=True):
return (super(L3DvrTestCaseBase, self).
@ -1137,7 +1141,9 @@ class L3DvrTestCase(L3DvrTestCaseBase):
self.context, vm_port['port']['id'],
{'port': {
portbindings.PROFILE: live_migration_port_profile}})
l3_notifier.routers_updated_on_host.assert_called_once_with(
# this will be called twice, once for port update, and once
# for new binding
l3_notifier.routers_updated_on_host.assert_any_call(
self.context, {router['id']}, HOST2)
# Check the port-binding is still with the old HOST1, but
# the router update notification has been sent to the new
@ -1149,7 +1155,7 @@ class L3DvrTestCase(L3DvrTestCaseBase):
# Since we have already created the floatingip for the
# port, it should be creating the floatingip agent gw
# port for the new host if it does not exist.
fip_agent.assert_called_once_with(
fip_agent.assert_any_call(
mock.ANY, floating_ip['floating_network_id'], HOST2)
def test_router_notifications(self):

View File

@ -1050,6 +1050,23 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
# check that notifier was still triggered
self.assertTrue(notify.call_counts)
def test_registry_notify_after_port_binding(self):
plugin = directory.get_plugin()
ctx = context.get_admin_context()
update_events = []
receiver = lambda *a, **k: update_events.append(k['port'])
registry.subscribe(receiver, resources.PORT,
events.AFTER_UPDATE)
with self.port() as p:
port = {'port': {'binding:host_id': 'newhost'}}
plugin.update_port(ctx, p['port']['id'], port)
# updating in the host should result in two AFTER_UPDATE events.
# one to change the host_id, the second to commit a binding
self.assertEqual('newhost', update_events[0]['binding:host_id'])
self.assertEqual('unbound', update_events[0]['binding:vif_type'])
self.assertEqual('newhost', update_events[1]['binding:host_id'])
self.assertNotEqual('unbound', update_events[1]['binding:vif_type'])
def test_check_if_compute_port_serviced_by_dvr(self):
self.assertTrue(utils.is_dvr_serviced(DEVICE_OWNER_COMPUTE))
@ -2572,16 +2589,25 @@ class TestMl2PluginCreateUpdateDeletePort(base.BaseTestCase):
plugin = self._create_plugin_for_create_update_port()
original_port = plugin._make_port_dict(original_port_db)
plugin.update_port(self.context, port_id, mock.MagicMock())
res = plugin.update_port(self.context, port_id, mock.MagicMock())
kwargs = {
first_update = {
'context': self.context,
'port': updated_port,
'mac_address_updated': True,
'original_port': original_port,
}
self.notify.assert_called_once_with('port', 'after_update',
plugin, **kwargs)
bind_update = {
'context': self.context,
'port': res,
'mac_address_updated': False,
'original_port': original_port,
}
expected = [
mock.call('port', 'after_update', plugin, **first_update),
mock.call('port', 'after_update', plugin, **bind_update)
]
self.notify.assert_has_calls(expected)
def test_notify_outside_of_delete_transaction(self):
self.notify.side_effect = (