Why does:
>>> import ipaddress
>>> print [ip for ip in ipaddress.collapse_addresses([ipaddress.IPv4Network(u'192.0.128.0/24'), ipaddress.IPv4Network(u'192.0.129.0/24')])]
[IPv4Network(u'192.0.128.0/23')]
but:
>>> print [ip for ip in ipaddress.collapse_addresses([ipaddress.IPv4Network(u'192.0.129.0/24'), ipaddress.IPv4Network(u'192.0.130.0/24')])]
[IPv4Network(u'192.0.129.0/24'), IPv4Network(u'192.0.130.0/24')]
What I am trying to achieve:
>>> print [ip for ip in ipaddress.collapse_addresses([ipaddress.IPv4Network(u'192.0.129.0/24'), ipaddress.IPv4Network(u'192.0.130.0/24')])]
[IPv4Network(u'192.0.128.0/22')]
It seems like collapse_addresses
cannot collapse for more than 1 bit of the mask.
This function returns the smallest network that contain the ipv4 networks of a list:
ADDRESS_ANY = ip_address(u'0.0.0.0')
def one_net(subnets):
"""
Get the one IP network that covers all subnets in input,
or None is subnets are disjoint.
"""
if len(subnets) == 0:
return None
minlen = min([net.prefixlen for net in subnets])
while subnets.count(subnets[0]) < len(subnets) and minlen > 0:
# all subnets are not (yet) equal
subnets = [net.supernet(new_prefix=minlen) for net in subnets]
minlen -= 1
# 0.0.0.0/? -> no common subnet
if subnets[0].network_address == ADDRESS_ANY:
return None
return subnets[0]