Unmarshall portinfo on update_fdb_entries calls

The unmarshalling function was not aware of the data
structure used by update_fdb_entries, so it would not
setup PortInfo named tuples in the 'before' and 'after'
fields. This would break the fdb_chg_ip_tun function
which expected to be able to use named attributes.

This patch adjusts the unmarshalling function to be aware
of this datastrucure.

This has likely been broken since the change that added
named tuples here: I7f8c93b0e12ee0179bb23dfbb3a3d814615b1c2e
It probably went undetected for so long because the exception
will only be observed when the updated entry does not have
an agent IP that matches the local agent's (i.e. not single-node).
Even in a multi-node environment, this would only trigger an
error when the fixed_ips of a port changed so it wouldn't show
up in a normal port wiring life-cycle.

Closes-Bug: #1538387
Change-Id: I0aacb3af9ebd160ebfb801f77b186075303c3df5
(cherry picked from commit 8dcf39aae7)
This commit is contained in:
Kevin Benton 2016-01-27 02:17:01 -08:00 committed by Ihar Hrachyshka
parent 5ceb23d77f
commit fe0a1cafd3
2 changed files with 39 additions and 0 deletions

View File

@ -14,6 +14,7 @@
# under the License.
import abc
import itertools
from oslo_config import cfg
from oslo_log import helpers as log_helpers
@ -65,10 +66,26 @@ class L2populationRpcCallBackMixin(object):
'ports': {
<ip address>: [ [<mac>, <ip>], ... ],
...
Or in the case of an update:
{ 'chg_ip': {
'<uuid>': {
'<agent1-IP>': {
'before': [ [<mac>, <ip>], ... ],
'after' : [ [<mac>, <ip>], ... ],
},
'<agent2-IP>': {
'before': ...
:returns: Deep copy with [<mac>, <ip>] converted to PortInfo
"""
unmarshalled = dict(fdb_entries)
chg_ip_nets = [net.values()
for net in unmarshalled.get('chg_ip', {}).values()]
for agent in itertools.chain.from_iterable(chg_ip_nets):
for when in ('before', 'after'):
if when in agent:
agent[when] = [l2pop_rpc.PortInfo(*pi)
for pi in agent[when]]
for value in unmarshalled.values():
if 'ports' in value:
value['ports'] = dict(

View File

@ -129,6 +129,16 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
'ports': {'192.168.0.10': [['00:00:00:00:00:00', '0.0.0.0'],
['fa:16:3e:ff:8c:0f', '10.0.0.6']]},
'network_type': 'vxlan'}}
entries['chg_ip'] = {
'foouuid': {
'192.168.0.1': {'before': [['fa:16:3e:ff:8c:0f', '10.0.0.6']],
'after': [['fa:16:3e:ff:8c:0f', '10.0.0.7']]},
'192.168.0.2': {'before': [['fa:16:3e:ff:8c:0e', '10.0.0.8']]}
},
'foouuid2': {
'192.168.0.1': {'before': [['ff:16:3e:ff:8c:0e', '1.0.0.8']]}
}
}
mixin = l2population_rpc.L2populationRpcCallBackMixin
entries = mixin._unmarshall_fdb_entries(entries)
@ -139,6 +149,18 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
self.assertIsInstance(port_info_list[1], l2pop_rpc.PortInfo)
self.assertEqual(('00:00:00:00:00:00', '0.0.0.0'), port_info_list[0])
self.assertEqual(('fa:16:3e:ff:8c:0f', '10.0.0.6'), port_info_list[1])
agt1 = entries['chg_ip']['foouuid']['192.168.0.1']
self.assertIsInstance(agt1['before'][0], l2pop_rpc.PortInfo)
self.assertIsInstance(agt1['after'][0], l2pop_rpc.PortInfo)
self.assertEqual(('fa:16:3e:ff:8c:0f', '10.0.0.6'), agt1['before'][0])
self.assertEqual(('fa:16:3e:ff:8c:0f', '10.0.0.7'), agt1['after'][0])
agt1_net2 = entries['chg_ip']['foouuid2']['192.168.0.1']
self.assertEqual(('ff:16:3e:ff:8c:0e', '1.0.0.8'),
agt1_net2['before'][0])
self.assertIsInstance(agt1_net2['before'][0], l2pop_rpc.PortInfo)
agt2 = entries['chg_ip']['foouuid']['192.168.0.2']
self.assertIsInstance(agt2['before'][0], l2pop_rpc.PortInfo)
self.assertEqual(('fa:16:3e:ff:8c:0e', '10.0.0.8'), agt2['before'][0])
def test__marshall_fdb_entries(self):
entries = {'foouuid': {