Don't iterate through addresses in netaddr.IPNetwork

Currently, to_primitive tries to iterate through all addresses in the
network, because the type doesn't have a special handling that would
short curcuit it, but also has __iter__. This may be detrimental to
performance, up to the point of node crash due to memory exhaustion if
the passed network range is too large (think of 0.0.0.0/0 or even
2001::/64). This behavior also makes it impossible to restore the
original data format (CIDR).

This patch short curcuits the iteration by handling the IPNetwork type
as a special case, same as we do for IPAddress.

Change-Id: I6aecd2d057d282a655ff9e4918c164253142b188
Closes-Bug: #1698355
(cherry picked from commit 38ac21b523)
(cherry picked from commit be828c35d8)
This commit is contained in:
Ihar Hrachyshka 2017-06-16 11:43:21 -07:00 committed by ChangBo Guo(gcb)
parent be02fdbebc
commit e85a6706ae
2 changed files with 6 additions and 1 deletions

View File

@ -112,7 +112,7 @@ def to_primitive(value, convert_instances=False, convert_datetime=True,
if isinstance(value, uuid.UUID):
return six.text_type(value)
if netaddr and isinstance(value, netaddr.IPAddress):
if netaddr and isinstance(value, (netaddr.IPAddress, netaddr.IPNetwork)):
return six.text_type(value)
if ipaddress and isinstance(value,

View File

@ -320,6 +320,11 @@ class ToPrimitiveTestCase(test_base.BaseTestCase):
ret = jsonutils.to_primitive(thing)
self.assertEqual({'ip_addr': '2001:db8::'}, ret)
def test_ipnet_using_netaddr(self):
thing = {'ip_net': netaddr.IPNetwork('1.2.3.0/24')}
ret = jsonutils.to_primitive(thing)
self.assertEqual({'ip_net': '1.2.3.0/24'}, ret)
def test_message_with_param(self):
msg = self.trans_fixture.lazy('A message with param: %s')
msg = msg % 'test_domain'