Created
August 4, 2022 09:14
-
-
Save p-sherratt/e0fd4d34a946c186995a27810cfed286 to your computer and use it in GitHub Desktop.
Produce a "CIDR report" from Netbox
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 | |
# quick hacky script to produce a "CIDR report" of your global address space from Netbox | |
# this is released to the public domain, free of copyright and licensing. | |
# by Paul Sherratt | |
import urllib3 | |
urllib3.disable_warnings() | |
import requests | |
import pynetbox | |
from netaddr import IPNetwork, IPAddress, IPSet | |
NETBOX_URL='https://netbox' | |
NETBOX_TOKEN='' | |
session = requests.Session() | |
session.verify = False | |
nb = pynetbox.api(NETBOX_URL, NETBOX_TOKEN) | |
nb.http_session = session | |
aggregates = nb.ipam.aggregates.filter(family=4, rir__n='private') | |
aggregates = {agg.prefix: {} for agg in aggregates} | |
roles = {} | |
total_addresses = 0 | |
for aggregate, data in aggregates.items(): | |
prefix, prefix_length = aggregate.split('/') | |
prefix_length = int(prefix_length) | |
data['addresses'] = 2**(32-prefix_length) | |
data['prefixes'] = list(nb.ipam.prefixes.filter(family=4, within=aggregate, status__n='container')) | |
total_addresses += data['addresses'] | |
for aggregate, data in aggregates.items(): | |
prefixes = {IPNetwork(p.prefix): str(p.role) for p in data['prefixes']} | |
data['ipset'] = IPSet() | |
last_network = 0 | |
for prefix, role in prefixes.items(): | |
if prefix.network == last_network: # ignore duplicate entries | |
continue | |
last_network = prefix.network | |
data['ipset'].add(prefix) | |
if role not in roles: | |
roles[role] = 0 | |
roles[role] += 2**(32-prefix.prefixlen) | |
data['gaps'] = IPSet(IPNetwork(aggregate)) - data['ipset'] | |
def cidr_report(prefix_length): | |
count = 0 | |
for data in aggregates.values(): | |
for network in data['gaps'].iter_cidrs(): | |
if network.prefixlen <= prefix_length: | |
count += 2**(prefix_length-network.prefixlen) | |
return count | |
def print_report(): | |
print("Addresses Total:", total_addresses) | |
print("Addresses Allocated:", sum(roles.values())) | |
print("Addresses Free:", total_addresses - sum(roles.values())) | |
print() | |
print("Addresses Allocated Per Role:") | |
for role in sorted(roles.keys()): | |
print(f" {role}: {roles[role]}") | |
print() | |
print("CIDR Report - Free Address Blocks:") | |
for x in range(23,33): | |
print(f" /{x}: {cidr_report(x)}") | |
print_report() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment