Convert Pyroute2 byte results to strings

Pyroute2 can return information structures with values as bytes
instead of strings. In order to unify the output, those byte
parameters will be converted to string. This is needed in case of
having dictionaries with keys as bytes instead of strings.

Change-Id: Ic665b2c5e28d06e21190f06d9f3f8e8f8c3c792d
Closes-Bug: #1846360
(cherry picked from commit 592b446299)
This commit is contained in:
Rodolfo Alonso Hernandez 2019-10-02 16:14:05 +00:00
parent b46b62a257
commit 57edfee5da
2 changed files with 32 additions and 5 deletions

View File

@ -518,15 +518,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
@ -582,8 +591,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

View File

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