Merge "Set trunk status to DOWN when parent port is unbound"

This commit is contained in:
Jenkins 2016-09-05 07:05:26 +00:00 committed by Gerrit Code Review
commit 86f7cfefb0
2 changed files with 72 additions and 0 deletions

View File

@ -25,6 +25,7 @@ from neutron.db import api as db_api
from neutron.db import common_db_mixin from neutron.db import common_db_mixin
from neutron.db import db_base_plugin_common from neutron.db import db_base_plugin_common
from neutron.db import db_base_plugin_v2 from neutron.db import db_base_plugin_v2
from neutron.extensions import portbindings
from neutron.objects import base as objects_base from neutron.objects import base as objects_base
from neutron.objects import trunk as trunk_objects from neutron.objects import trunk as trunk_objects
from neutron.services import service_base from neutron.services import service_base
@ -70,6 +71,11 @@ class TrunkPlugin(service_base.ServicePluginBase,
drivers.register() drivers.register()
registry.subscribe(rules.enforce_port_deletion_rules, registry.subscribe(rules.enforce_port_deletion_rules,
resources.PORT, events.BEFORE_DELETE) resources.PORT, events.BEFORE_DELETE)
# NOTE(tidwellr) Consider keying off of PRECOMMIT_UPDATE if we find
# AFTER_UPDATE to be problematic for setting trunk status when a
# a parent port becomes unbound.
registry.subscribe(self._trigger_trunk_status_change,
resources.PORT, events.AFTER_UPDATE)
registry.notify(constants.TRUNK_PLUGIN, events.AFTER_INIT, self) registry.notify(constants.TRUNK_PLUGIN, events.AFTER_INIT, self)
for driver in self._drivers: for driver in self._drivers:
LOG.debug('Trunk plugin loaded with driver %s', driver.name) LOG.debug('Trunk plugin loaded with driver %s', driver.name)
@ -345,3 +351,22 @@ class TrunkPlugin(service_base.ServicePluginBase,
raise trunk_exc.TrunkNotFound(trunk_id=trunk_id) raise trunk_exc.TrunkNotFound(trunk_id=trunk_id)
return obj return obj
def _trigger_trunk_status_change(self, resource, event, trigger, **kwargs):
updated_port = kwargs['port']
trunk_details = updated_port.get('trunk_details')
# If no trunk_details, the port is not the parent of a trunk.
if not trunk_details:
return
context = kwargs['context']
original_port = kwargs['original_port']
orig_vif_type = original_port.get(portbindings.VIF_TYPE)
new_vif_type = updated_port.get(portbindings.VIF_TYPE)
vif_type_changed = orig_vif_type != new_vif_type
if vif_type_changed and new_vif_type == portbindings.VIF_TYPE_UNBOUND:
trunk = self._get_trunk(context, trunk_details['trunk_id'])
# NOTE(status_police) Trunk status goes to DOWN when the parent
# port is unbound. This means there are no more physical resources
# associated with the logical resource.
trunk.update(status=constants.DOWN_STATUS)

View File

@ -19,6 +19,8 @@ import testtools
from neutron.callbacks import events from neutron.callbacks import events
from neutron.callbacks import registry from neutron.callbacks import registry
from neutron.callbacks import resources
from neutron.extensions import portbindings
from neutron import manager from neutron import manager
from neutron.objects import trunk as trunk_objects from neutron.objects import trunk as trunk_objects
from neutron.services.trunk import callbacks from neutron.services.trunk import callbacks
@ -266,6 +268,51 @@ class TrunkPluginTestCase(test_plugin.Ml2PluginV2TestCase):
{'sub_ports': [{'port_id': subport['port']['id']}]}) {'sub_ports': [{'port_id': subport['port']['id']}]})
self.assertEqual(constants.DOWN_STATUS, trunk['status']) self.assertEqual(constants.DOWN_STATUS, trunk['status'])
def test__trigger_trunk_status_change_vif_type_changed_unbound(self):
with self.port() as parent:
parent[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_UNBOUND
original_port = {portbindings.VIF_TYPE: 'fakeviftype'}
self._test__trigger_trunk_status_change(parent,
original_port,
constants.ACTIVE_STATUS,
constants.DOWN_STATUS)
def test__trigger_trunk_status_change_vif_type_unchanged(self):
with self.port() as parent:
parent[portbindings.VIF_TYPE] = 'fakeviftype'
original_port = {portbindings.VIF_TYPE: 'fakeviftype'}
self._test__trigger_trunk_status_change(parent,
original_port,
constants.ACTIVE_STATUS,
constants.ACTIVE_STATUS)
def test__trigger_trunk_status_change_vif_type_changed(self):
with self.port() as parent:
parent[portbindings.VIF_TYPE] = 'realviftype'
original_port = {portbindings.VIF_TYPE: 'fakeviftype'}
self._test__trigger_trunk_status_change(parent,
original_port,
constants.ACTIVE_STATUS,
constants.ACTIVE_STATUS)
def _test__trigger_trunk_status_change(self, new_parent,
original_parent,
initial_trunk_status,
final_trunk_status):
trunk = self._create_test_trunk(new_parent)
trunk = self._get_trunk_obj(trunk['id'])
trunk.update(status=initial_trunk_status)
trunk_details = {'trunk_id': trunk.id}
new_parent['trunk_details'] = trunk_details
original_parent['trunk_details'] = trunk_details
kwargs = {'context': self.context, 'port': new_parent,
'original_port': original_parent}
self.trunk_plugin._trigger_trunk_status_change(resources.PORT,
events.AFTER_UPDATE,
None, **kwargs)
trunk = self._get_trunk_obj(trunk.id)
self.assertEqual(final_trunk_status, trunk.status)
class TrunkPluginDriversTestCase(test_plugin.Ml2PluginV2TestCase): class TrunkPluginDriversTestCase(test_plugin.Ml2PluginV2TestCase):