Friday, October 11, 2019

Forgetting that we have an IPAM, today I wrote a Python 3.7 script for parsing available Subnets

As the title says, I totally forgot that we have an IPAM, and was tasked to add a new IP-scope for Customer Premises Equipment. We have a /16 allocated internally for CPE usage, but to say that there were no structure followed when issuing scopes earlier is an understatement.

I ended up using this script for solving the problem, but was quickly reminded by colleagues that we had an IPAM for that. Some of you might not have that, so this might come in handy for you.

Here is the (not pretty) script:

import ipaddress import argparse import re # Setting up the arguments. parser = argparse.ArgumentParser(description="Given an IP-Scope, and subnets, gives back the unused subnets.",formatter_class = argparse.RawTextHelpFormatter) parser.add_argument("scope", action="store", help="The main IP-scope that you want to parse. DEFAULT-NETMASK=/24") parser.add_argument("-s", "--subnet", action="append", help="The subnets that you want to compare against the main-scope.", default=[]) args = parser.parse_args() def main(): mainscope = createScope(args.scope) args.subnet = [createScope(x) for x in args.subnet] remainingScopes = [] # A loop which goes through all of the scopes, and splits them up, to get all the "unused" scopes. for scope in args.subnet: if not remainingScopes: # initiates the list containing the remaining scopes. # !!FYI .subnet_of is new in Python 3.7!! Compares each scope agaisnt the remaining "super-nets". if scope.subnet_of(mainscope): for x in mainscope.address_exclude(scope): remainingScopes.append(x) # If the list has been initiated, then continue with further filtering. else: for x in remainingScopes: # !!FYI .subnet_of is new in Python 3.7!! Compares each scope agaisnt the remaining "super-nets". if scope.subnet_of(x): for y in x.address_exclude(scope): remainingScopes.append(y) # Removes the "super-net" from the list to avoid it being subneted further. remainingScopes.remove(x) print(f"Original scope: {mainscope}") print("Available scope(s):") for i in sorted(remainingScopes): print(i) if not remainingScopes: print(mainscope) def createScope(scope): """Searches for an IP-scope, and "corrects" it before creating an IPv4Network.""" # Find the format of the ip-scope. if re.search(r'(\d{1,3}\.){3}\d{1,3} */ *\d{1,2}', scope): # IP-address + / + shorthand scope = ipaddress.IPv4Network(scope.replace(" ", ""), strict=False) elif re.search(r"(\d{1,3}\.){3}\d{1,3} */ *(\d{1,3}\.){3}\d{1,3}", scope): # IP-address + / + netmask scope = ipaddress.IPv4Network(scope.replace(" ", ""), strict=False) elif re.search(r"(\d{1,3}\.){3}\d{1,3} *(\d{1,3}\.){3}\d{1,3}", scope): # IP-address + " " + netmask scope = ipaddress.IPv4Network("/".join(scope.split()), strict=False) elif re.search(r'(\d{1,3}\.){3}\d{1,3} *\d{1,2}', scope): # IP-address + " " + shorthand scope = ipaddress.IPv4Network("/".join(scope.split()), strict=False) elif re.search(r'(\d{1,3}\.){3}\d{1,3} *', scope): # IP-address without netmask/shorthand. scope = ipaddress.IPv4Network(scope.strip() + "/24", strict=False) else: return None return scope if __name__ == "__main__": main() 

Example of operation:

python.exe .\ipAvailableSubnet.py 172.16.0.0/24 -s 172.16.0.23/32 -s 172.16.0.128/25 -s 172.16.0.64/26 Original scope: 172.16.0.0/24 Available scope(s): 172.16.0.0/28 172.16.0.16/30 172.16.0.20/31 172.16.0.22/32 172.16.0.24/29 172.16.0.32/27 


No comments:

Post a Comment