Skip to content

Instantly share code, notes, and snippets.

@mosheavni
Created November 21, 2020 14:59
Show Gist options
  • Save mosheavni/81d8377f264072e81ac70d4a9ee42d75 to your computer and use it in GitHub Desktop.
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
#!/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