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
This commit is contained in:
parent
44571236ca
commit
8dcf39aae7
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
import abc
|
||||
import itertools
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import helpers as log_helpers
|
||||
|
@ -62,10 +63,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(
|
||||
|
|
|
@ -128,6 +128,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)
|
||||
|
@ -138,6 +148,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': {
|
||||
|
|
Loading…
Reference in New Issue