diff --git a/neutron/privileged/agent/linux/ip_lib.py b/neutron/privileged/agent/linux/ip_lib.py index 4eae6577b6c..8eff37c6d3d 100644 --- a/neutron/privileged/agent/linux/ip_lib.py +++ b/neutron/privileged/agent/linux/ip_lib.py @@ -537,15 +537,24 @@ def make_serializable(value): This function converts 'netlink.nla_slot' object (key, value) in a list of two elements. """ + def _ensure_string(value): + # NOTE(ralonsoh): once support for PY2 is dropped, the str() + # conversion will be no needed and six.binary_type --> bytes. + return (str(value.decode('utf-8')) + if isinstance(value, six.binary_type) else value) + if isinstance(value, list): return [make_serializable(item) for item in value] - elif isinstance(value, dict): - return {key: make_serializable(data) for key, data in value.items()} elif isinstance(value, netlink.nla_slot): return [value[0], make_serializable(value[1])] + elif isinstance(value, netlink.nla_base) and six.PY3: + return make_serializable(value.dump()) + elif isinstance(value, dict): + return {_ensure_string(key): make_serializable(data) + for key, data in value.items()} elif isinstance(value, tuple): return tuple(make_serializable(item) for item in value) - return value + return _ensure_string(value) @_sync @@ -601,8 +610,9 @@ def list_ip_rules(namespace, ip_version, match=None, **kwargs): """List all IP rules""" try: with get_iproute(namespace) as ip: - rules = ip.get_rules(family=_IP_VERSION_FAMILY_MAP[ip_version], - match=match, **kwargs) + rules = make_serializable(ip.get_rules( + family=_IP_VERSION_FAMILY_MAP[ip_version], + match=match, **kwargs)) for rule in rules: rule['attrs'] = { key: value for key, value diff --git a/neutron/tests/unit/privileged/agent/linux/test_ip_lib.py b/neutron/tests/unit/privileged/agent/linux/test_ip_lib.py index a4845dc16ef..2efb168051c 100644 --- a/neutron/tests/unit/privileged/agent/linux/test_ip_lib.py +++ b/neutron/tests/unit/privileged/agent/linux/test_ip_lib.py @@ -16,6 +16,8 @@ import errno import mock import pyroute2 +from pyroute2 import netlink +from pyroute2.netlink.rtnl import ifinfmsg from neutron.privileged.agent.linux import ip_lib as priv_lib from neutron.tests import base @@ -210,3 +212,18 @@ class IpLibTestCase(base.BaseTestCase): self.fail("OSError exception not raised") except OSError as e: self.assertEqual(errno.EINVAL, e.errno) + + +class MakeSerializableTestCase(base.BaseTestCase): + + NLA_DATA = ifinfmsg.ifinfbase.state(data=b'54321') + INPUT_1 = {'key1': 'value1', b'key2': b'value2', 'key3': ('a', 2), + 'key4': [1, 2, 'c'], + 'key5': netlink.nla_slot('nla_name', NLA_DATA)} + OUTPUT_1 = {'key1': 'value1', 'key2': 'value2', 'key3': ('a', 2), + 'key4': [1, 2, 'c'], + 'key5': ['nla_name', '54321']} + + def test_make_serializable(self): + self.assertEqual(self.OUTPUT_1, + priv_lib.make_serializable(self.INPUT_1))