Created
November 21, 2020 14:59
-
-
Save mosheavni/81d8377f264072e81ac70d4a9ee42d75 to your computer and use it in GitHub Desktop.
Subnet picker - Generate non-overlapping list of CIDRs based on base CIDR and existing subnets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import ipaddress | |
import re | |
import sys | |
def main(results): | |
# Convert existing_subnet to ip_network object | |
existing_subnets = [] | |
if results.existing_subnet: | |
try: | |
existing_subnets = [ | |
ipaddress.ip_network(net) for net in results.existing_subnet | |
] | |
except ValueError as e: | |
print(e) | |
sys.exit(1) | |
# Sanity checks | |
try: | |
base_network = ipaddress.ip_network(results.base_cidr) | |
except ValueError: | |
print(f"{results.base_cidr} is not a valid network.") | |
sys.exit(1) | |
if not base_network.is_private: | |
print(f"{base_network} is not a private network.") | |
sys.exit(1) | |
# Generate possible subnets list | |
new_nets = [] | |
for new_subnet in results.new_subnet: | |
new_bits, num_of_subnets = new_subnet.split("=") | |
networks = base_network.subnets(int(new_bits)) | |
available_nets = [] | |
for net in networks: | |
# Check overlap | |
overlapping = any(net.overlaps(ex_subnet) for ex_subnet in existing_subnets) | |
if not overlapping: | |
available_nets.append(net) | |
new_nets_of_bits = available_nets[: int(num_of_subnets)] | |
new_nets.extend(new_nets_of_bits) | |
existing_subnets.extend(new_nets_of_bits) | |
print("\n".join([format(i) for i in new_nets])) | |
def check_new_subnet(val): | |
if not re.compile(r"^\d+=\d+").match(val): | |
raise argparse.ArgumentTypeError( | |
"New subnet must be in the format: new_bits:num_of_subnets\n\ | |
I.E: 5=3 - 3 new subnets with 5 new bits from the base CIDR" | |
) | |
return val | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser() | |
parser.add_argument( | |
"-b", "--base-cidr", default=None, help="Base CIDR to create subnets from" | |
) | |
parser.add_argument( | |
"-e", | |
"--existing-subnet", | |
action="append", | |
help="Existing subnet (specify multiple times for multiple subnets)", | |
) | |
parser.add_argument( | |
"new_subnet", | |
nargs="+", | |
type=check_new_subnet, | |
help="Subnet to create. new_bits=num_of_subnets. I.E: 2=5 will result\ | |
in 5 new subnets and each will be 2 bits more than the base", | |
) | |
results = parser.parse_args() | |
main(results) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment