From 8ebc635a18fd23fd6595551a703961a4d4392948 Mon Sep 17 00:00:00 2001 From: ZhaoBo Date: Mon, 31 Jul 2017 19:23:32 +0800 Subject: [PATCH] Subcribe trunk & subport events to set subport id Introduce a callback function in trunk plugin to receive after_create and after_delete events for the trunk and subport resources This function will set the subport device_id to trunk_id to prevent nova and neutron from reusing it. Closes-Bug: #1700428 Co-Authored-By: Nate Johnston Change-Id: I97fe59752f9ef2cbe0376cd6ee0739660f5937ad --- neutron/services/trunk/plugin.py | 20 +++++++++++ .../tests/unit/services/trunk/test_plugin.py | 34 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/neutron/services/trunk/plugin.py b/neutron/services/trunk/plugin.py index 63820dcb5b2..febc1a57ff6 100644 --- a/neutron/services/trunk/plugin.py +++ b/neutron/services/trunk/plugin.py @@ -433,3 +433,23 @@ class TrunkPlugin(service_base.ServicePluginBase): self.update_trunk( context, trunk_id, {'trunk': {'status': constants.TRUNK_DOWN_STATUS}}) + + @registry.receives(trunk_apidef.TRUNK, + [events.AFTER_CREATE, events.AFTER_DELETE]) + @registry.receives(resources.SUBPORTS, + [events.AFTER_CREATE, events.AFTER_DELETE]) + def _process_subport_device_id_event(self, resource, event, + trunk_plugin, payload): + context = payload.context + if resource == resources.SUBPORTS: + subports = payload.subports + trunk = payload.original_trunk + elif resource == trunk_apidef.TRUNK: + trunk = payload.current_trunk or payload.original_trunk + subports = trunk.sub_ports + if subports and trunk: + core_plugin = directory.get_plugin() + device_id = trunk.id if event == events.AFTER_CREATE else '' + for subport in subports: + core_plugin.update_port(context, subport.port_id, + {'port': {'device_id': device_id}}) diff --git a/neutron/tests/unit/services/trunk/test_plugin.py b/neutron/tests/unit/services/trunk/test_plugin.py index d4954ddcbf7..d2a090ae54d 100644 --- a/neutron/tests/unit/services/trunk/test_plugin.py +++ b/neutron/tests/unit/services/trunk/test_plugin.py @@ -345,6 +345,40 @@ class TrunkPluginTestCase(test_plugin.Ml2PluginV2TestCase): self.assertEqual(final_trunk_status, current_trunk.status) return trunk, current_trunk + def test__process_subport_device_id_event(self): + plugin = directory.get_plugin() + with self.port() as parent_port, self.port() as child_port1: + with self.port() as child_port2: + subport1 = create_subport_dict(child_port1['port']['id']) + trunk = self._create_test_trunk(parent_port, + subports=[subport1]) + child_port1 = plugin.get_port(self.context, + child_port1['port']['id']) + self.assertEqual(trunk['id'], child_port1['device_id']) + + subport2 = { + 'segmentation_type': 'vlan', + 'segmentation_id': 321, + 'port_id': child_port2['port']['id'] + } + self.trunk_plugin.add_subports(self.context, trunk['id'], + {'sub_ports': [subport2]}) + child_port2 = plugin.get_port(self.context, + child_port2['port']['id']) + self.assertEqual(trunk['id'], child_port2['device_id']) + + trunk = self.trunk_plugin.remove_subports( + self.context, trunk['id'], + {'sub_ports': [{'port_id': child_port2['id']}]}) + child_port2 = plugin.get_port(self.context, + child_port2['id']) + self.assertEqual('', child_port2['device_id']) + + self.trunk_plugin.delete_trunk(self.context, trunk['id']) + child_port1 = plugin.get_port(self.context, + child_port1['id']) + self.assertEqual('', child_port1['device_id']) + class TrunkPluginCompatDriversTestCase(test_plugin.Ml2PluginV2TestCase):