ML2 mechanism driver access to binding details
The following properties are added to the PortContext object passed to ML2 mechanism drivers for port operations: * bound_driver - name of current bound driver * original_bound_driver - name previously bound driver in an update * original_bound_segment - network segment used in previous binding Some issues with the existing ML2 port binding unit tests were also fixed. The remainder of the fix for bug 1276395, making these binding details available to mechanism drivers when a port is deleted, will be addressed as part of the fix for bug 1276391. Partial-Bug: #1276395 Change-Id: I9ecff4a4e044920ed2dde709c89aeb9bc773220d
This commit is contained in:
parent
4a85c90579
commit
d31cbe9364
@ -218,7 +218,7 @@ class PortContext(object):
|
||||
|
||||
@abstractproperty
|
||||
def original(self):
|
||||
"""Return the original state of the port
|
||||
"""Return the original state of the port.
|
||||
|
||||
Return the original state of the port, prior to a call to
|
||||
update_port. Method is only valid within calls to
|
||||
@ -236,6 +236,31 @@ class PortContext(object):
|
||||
"""Return the currently bound segment dictionary."""
|
||||
pass
|
||||
|
||||
@abstractproperty
|
||||
def original_bound_segment(self):
|
||||
"""Return the original bound segment dictionary.
|
||||
|
||||
Return the original bound segment dictionary, prior to a call
|
||||
to update_port. Method is only valid within calls to
|
||||
update_port_precommit and update_port_postcommit.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractproperty
|
||||
def bound_driver(self):
|
||||
"""Return the currently bound mechanism driver name."""
|
||||
pass
|
||||
|
||||
@abstractproperty
|
||||
def original_bound_driver(self):
|
||||
"""Return the original bound mechanism driver name.
|
||||
|
||||
Return the original bound mechanism driver name, prior to a
|
||||
call to update_port. Method is only valid within calls to
|
||||
update_port_precommit and update_port_postcommit.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def host_agents(self, agent_type):
|
||||
"""Get agents of the specified type on port's host.
|
||||
|
@ -78,6 +78,12 @@ class PortContext(MechanismDriverContext, api.PortContext):
|
||||
network)
|
||||
self._binding = db.ensure_port_binding(plugin_context.session,
|
||||
port['id'])
|
||||
if original_port:
|
||||
self._original_bound_segment_id = self._binding.segment
|
||||
self._original_bound_driver = self._binding.driver
|
||||
else:
|
||||
self._original_bound_segment_id = None
|
||||
self._original_bound_driver = None
|
||||
|
||||
@property
|
||||
def current(self):
|
||||
@ -99,6 +105,21 @@ class PortContext(MechanismDriverContext, api.PortContext):
|
||||
if segment[api.ID] == id:
|
||||
return segment
|
||||
|
||||
@property
|
||||
def original_bound_segment(self):
|
||||
if self._original_bound_segment_id:
|
||||
for segment in self._network_context.network_segments:
|
||||
if segment[api.ID] == self._original_bound_segment_id:
|
||||
return segment
|
||||
|
||||
@property
|
||||
def bound_driver(self):
|
||||
return self._binding.driver
|
||||
|
||||
@property
|
||||
def original_bound_driver(self):
|
||||
return self._original_bound_driver
|
||||
|
||||
def host_agents(self, agent_type):
|
||||
return self._plugin.get_agents(self._plugin_context,
|
||||
filters={'agent_type': [agent_type],
|
||||
|
@ -67,6 +67,18 @@ class FakePortContext(api.PortContext):
|
||||
if segment[api.ID] == self._bound_segment_id:
|
||||
return segment
|
||||
|
||||
@property
|
||||
def original_bound_segment(self):
|
||||
return None
|
||||
|
||||
@property
|
||||
def bound_driver(self):
|
||||
return None
|
||||
|
||||
@property
|
||||
def original_bound_driver(self):
|
||||
return None
|
||||
|
||||
def host_agents(self, agent_type):
|
||||
if agent_type == self._agent_type:
|
||||
return self._agents
|
||||
|
@ -83,11 +83,19 @@ class LoggerMechanismDriver(api.MechanismDriver):
|
||||
def _log_port_call(self, method_name, context):
|
||||
network_context = context.network
|
||||
LOG.info(_("%(method)s called with port settings %(current)s "
|
||||
"(original settings %(original)s) on network %(network)s"),
|
||||
"(original settings %(original)s) "
|
||||
"bound to segment %(segment)s "
|
||||
"(original segment %(original_segment)s) "
|
||||
"using driver %(driver)s "
|
||||
"(original driver %(original_driver)s) "
|
||||
"on network %(network)s"),
|
||||
{'method': method_name,
|
||||
'current': context.current,
|
||||
'original': context.original,
|
||||
'segment': context.bound_segment,
|
||||
'original_segment': context.original_bound_segment,
|
||||
'driver': context.bound_driver,
|
||||
'original_driver': context.original_bound_driver,
|
||||
'network': network_context.current})
|
||||
|
||||
def create_port_precommit(self, context):
|
||||
|
@ -84,11 +84,34 @@ class TestMechanismDriver(api.MechanismDriver):
|
||||
assert(isinstance(context, api.PortContext))
|
||||
assert(isinstance(context.current, dict))
|
||||
assert(context.current['id'] is not None)
|
||||
|
||||
vif_type = context.current.get(portbindings.VIF_TYPE)
|
||||
assert(vif_type is not None)
|
||||
if vif_type in (portbindings.VIF_TYPE_UNBOUND,
|
||||
portbindings.VIF_TYPE_BINDING_FAILED):
|
||||
assert(context.bound_segment is None)
|
||||
assert(context.bound_driver is None)
|
||||
else:
|
||||
assert(isinstance(context.bound_segment, dict))
|
||||
assert(context.bound_driver == 'test')
|
||||
|
||||
if original_expected:
|
||||
assert(isinstance(context.original, dict))
|
||||
assert(context.current['id'] == context.original['id'])
|
||||
vif_type = context.original.get(portbindings.VIF_TYPE)
|
||||
assert(vif_type is not None)
|
||||
if vif_type in (portbindings.VIF_TYPE_UNBOUND,
|
||||
portbindings.VIF_TYPE_BINDING_FAILED):
|
||||
assert(context.original_bound_segment is None)
|
||||
assert(context.original_bound_driver is None)
|
||||
else:
|
||||
assert(isinstance(context.original_bound_segment, dict))
|
||||
assert(context.original_bound_driver == 'test')
|
||||
else:
|
||||
assert(not context.original)
|
||||
assert(context.original is None)
|
||||
assert(context.original_bound_segment is None)
|
||||
assert(context.original_bound_driver is None)
|
||||
|
||||
network_context = context.network
|
||||
assert(isinstance(network_context, api.NetworkContext))
|
||||
self._check_network_context(network_context, False)
|
||||
@ -112,7 +135,12 @@ class TestMechanismDriver(api.MechanismDriver):
|
||||
self._check_port_context(context, False)
|
||||
|
||||
def bind_port(self, context):
|
||||
self._check_port_context(context, False)
|
||||
# REVISIT(rkukura): Currently, bind_port() is called as part
|
||||
# of either a create or update transaction. The fix for bug
|
||||
# 1276391 will change it to be called outside any transaction,
|
||||
# so the context.original* will no longer be available.
|
||||
self._check_port_context(context, context.original is not None)
|
||||
|
||||
host = context.current.get(portbindings.HOST_ID, None)
|
||||
segment = context.network.network_segments[0][api.ID]
|
||||
if host == "host-ovs-no_filter":
|
||||
@ -123,8 +151,18 @@ class TestMechanismDriver(api.MechanismDriver):
|
||||
{portbindings.CAP_PORT_FILTER: True})
|
||||
|
||||
def validate_port_binding(self, context):
|
||||
self._check_port_context(context, False)
|
||||
# REVISIT(rkukura): Currently, validate_port_binding() is
|
||||
# called as part of either a create or update transaction. The
|
||||
# fix for bug 1276391 will change it to be called outside any
|
||||
# transaction (or eliminate it altogether), so the
|
||||
# context.original* will no longer be available.
|
||||
self._check_port_context(context, context.original is not None)
|
||||
return True
|
||||
|
||||
def unbind_port(self, context):
|
||||
self._check_port_context(context, False)
|
||||
# REVISIT(rkukura): Currently, unbind_port() is called as part
|
||||
# of either an update or delete transaction. The fix for bug
|
||||
# 1276391 will change it to be called outside any transaction
|
||||
# (or eliminate it altogether), so the context.original* will
|
||||
# no longer be available.
|
||||
self._check_port_context(context, context.original is not None)
|
||||
|
@ -108,18 +108,18 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase):
|
||||
self.assertFalse(notify_mock.called)
|
||||
|
||||
def test_update_with_new_host_binding_notifies_agent(self):
|
||||
self._test_update_port_binding('host-ovs-no-filter',
|
||||
'host-bridge-no-filter')
|
||||
self._test_update_port_binding('host-ovs-no_filter',
|
||||
'host-bridge-filter')
|
||||
|
||||
def test_update_with_same_host_binding_does_not_notify(self):
|
||||
self._test_update_port_binding('host-ovs-no-filter',
|
||||
'host-ovs-no-filter')
|
||||
self._test_update_port_binding('host-ovs-no_filter',
|
||||
'host-ovs-no_filter')
|
||||
|
||||
def test_update_without_binding_does_not_notify(self):
|
||||
self._test_update_port_binding('host-ovs-no-filter')
|
||||
self._test_update_port_binding('host-ovs-no_filter')
|
||||
|
||||
def testt_update_from_empty_to_host_binding_notifies_agent(self):
|
||||
self._test_update_port_binding('', 'host-ovs-no-filter')
|
||||
self._test_update_port_binding('', 'host-ovs-no_filter')
|
||||
|
||||
def test_update_from_host_to_empty_binding_notifies_agent(self):
|
||||
self._test_update_port_binding('host-ovs-no-filter', '')
|
||||
self._test_update_port_binding('host-ovs-no_filter', '')
|
||||
|
Loading…
x
Reference in New Issue
Block a user