Get rid of marshall_fdb_entries

This function isn't necessary. The json encoding of a
named tuple will already turn into a normal list.

ports = [l2pop_rpc.PortInfo('abcdef', '1.1.1.1')]
json.dumps(ports) == json.dumps([(mac, ip) for (mac, ip) in ports])

An argument could be made that the PortInfo object could have
something added to it later that we wouldn't want to serialize
in order to remain backward compatible. However, doing so would
break all of the constructions of PortInfo objects on the agents
once they got the updated code for PortInfo that requires the
new parameter.

So there is no way currently to add a new field to PortInfo without
breaking existing legacy clients or breaking new clients.
Given that, let's stop doing the json encoder's job.

This patch also adds a sanity unit test to make sure the json
serialization method used in oslo does not break on the named tuples.

Change-Id: I45ae69ef8c9c15ad21a28dc42f2d78b234ccfb0c
This commit is contained in:
Kevin Benton 2016-02-01 03:07:59 -08:00
parent 9546ee7d92
commit a19029d3d6
2 changed files with 8 additions and 46 deletions

View File

@ -14,7 +14,6 @@
# under the License. # under the License.
import collections import collections
import copy
from oslo_log import log as logging from oslo_log import log as logging
import oslo_messaging import oslo_messaging
@ -46,9 +45,8 @@ class L2populationAgentNotifyAPI(object):
'method': method, 'method': method,
'fdb_entries': fdb_entries}) 'fdb_entries': fdb_entries})
marshalled_fdb_entries = self._marshall_fdb_entries(fdb_entries)
cctxt = self.client.prepare(topic=self.topic_l2pop_update, fanout=True) cctxt = self.client.prepare(topic=self.topic_l2pop_update, fanout=True)
cctxt.cast(context, method, fdb_entries=marshalled_fdb_entries) cctxt.cast(context, method, fdb_entries=fdb_entries)
def _notification_host(self, context, method, fdb_entries, host): def _notification_host(self, context, method, fdb_entries, host):
LOG.debug('Notify l2population agent %(host)s at %(topic)s the ' LOG.debug('Notify l2population agent %(host)s at %(topic)s the '
@ -58,9 +56,8 @@ class L2populationAgentNotifyAPI(object):
'method': method, 'method': method,
'fdb_entries': fdb_entries}) 'fdb_entries': fdb_entries})
marshalled_fdb_entries = self._marshall_fdb_entries(fdb_entries)
cctxt = self.client.prepare(topic=self.topic_l2pop_update, server=host) cctxt = self.client.prepare(topic=self.topic_l2pop_update, server=host)
cctxt.cast(context, method, fdb_entries=marshalled_fdb_entries) cctxt.cast(context, method, fdb_entries=fdb_entries)
def add_fdb_entries(self, context, fdb_entries, host=None): def add_fdb_entries(self, context, fdb_entries, host=None):
if fdb_entries: if fdb_entries:
@ -88,28 +85,3 @@ class L2populationAgentNotifyAPI(object):
else: else:
self._notification_fanout(context, 'update_fdb_entries', self._notification_fanout(context, 'update_fdb_entries',
fdb_entries) fdb_entries)
@staticmethod
def _marshall_fdb_entries(fdb_entries):
"""Prepares fdb_entries for serialization to JSON for RPC.
All methods in this class that send messages should call this to
marshall fdb_entries for the wire.
:param fdb_entries: Original fdb_entries data-structure. Looks like:
{
<uuid>: {
...,
'ports': {
<ip address>: [ PortInfo, ... ],
...
:returns: Deep copy with PortInfo converted to [mac, ip]
"""
marshalled = copy.deepcopy(fdb_entries)
for value in marshalled.values():
if 'ports' in value:
for address, port_infos in value['ports'].items():
value['ports'][address] = [[mac, ip]
for mac, ip in port_infos]
return marshalled

View File

@ -14,6 +14,7 @@
# under the License. # under the License.
import mock import mock
from oslo_serialization import jsonutils
import testtools import testtools
from neutron.common import constants from neutron.common import constants
@ -138,22 +139,11 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
self.assertEqual(('00:00:00:00:00:00', '0.0.0.0'), port_info_list[0]) 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]) self.assertEqual(('fa:16:3e:ff:8c:0f', '10.0.0.6'), port_info_list[1])
def test__marshall_fdb_entries(self): def test_portinfo_marshalled_as_list(self):
entries = {'foouuid': { entry = ['fa:16:3e:ff:8c:0f', '10.0.0.6']
'segment_id': 1001, payload = {'netuuid': {'ports': {'1': [l2pop_rpc.PortInfo(*entry)]}}}
'ports': {'192.168.0.10': [('00:00:00:00:00:00', '0.0.0.0'), result = jsonutils.loads(jsonutils.dumps(payload))
('fa:16:3e:ff:8c:0f', '10.0.0.6')]}, self.assertEqual(entry, result['netuuid']['ports']['1'][0])
'network_type': 'vxlan'}}
entries = l2pop_rpc.L2populationAgentNotifyAPI._marshall_fdb_entries(
entries)
port_info_list = entries['foouuid']['ports']['192.168.0.10']
# Check that the PortInfo tuples have been converted to list
self.assertIsInstance(port_info_list[0], list)
self.assertIsInstance(port_info_list[1], list)
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])
def test_fdb_add_called(self): def test_fdb_add_called(self):
self._register_ml2_agents() self._register_ml2_agents()