Merge "ML2 mechanism driver access to binding details"

This commit is contained in:
Jenkins 2014-03-06 00:14:39 +00:00 committed by Gerrit Code Review
commit 24ac4a7de8
6 changed files with 117 additions and 13 deletions

View File

@ -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.

View File

@ -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],

View File

@ -70,6 +70,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

View File

@ -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):

View File

@ -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)

View File

@ -109,18 +109,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', '')