From 2fa8e27f05e68582ce5283c12fa2b6e980d89461 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 30 Dec 2021 12:00:37 -0500 Subject: [PATCH] Fixes #8192: Add "add prefix" button to aggregate child prefixes view --- docs/release-notes/version-3.1.md | 4 ++ netbox/ipam/models/ip.py | 45 ++++++++++--------- netbox/ipam/views.py | 1 + netbox/templates/ipam/aggregate/prefixes.html | 5 +++ 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md index f10459b96..9112aa100 100644 --- a/docs/release-notes/version-3.1.md +++ b/docs/release-notes/version-3.1.md @@ -2,6 +2,10 @@ ## v3.1.4 (FUTURE) +### Enhancements + +* [#8192](https://github.com/netbox-community/netbox/issues/8192) - Add "add prefix" button to aggregate child prefixes view + ### Bug Fixes * [#8191](https://github.com/netbox-community/netbox/issues/8191) - Fix return URL when adding IP addresses to VM interfaces diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index aeb71e70f..9c00a9068 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -32,6 +32,28 @@ __all__ = ( ) +class GetAvailablePrefixesMixin: + + def get_available_prefixes(self): + """ + Return all available Prefixes within this aggregate as an IPSet. + """ + prefix = netaddr.IPSet(self.prefix) + child_prefixes = netaddr.IPSet([child.prefix for child in self.get_child_prefixes()]) + available_prefixes = prefix - child_prefixes + + return available_prefixes + + def get_first_available_prefix(self): + """ + Return the first available child prefix within the prefix (or None). + """ + available_prefixes = self.get_available_prefixes() + if not available_prefixes: + return None + return available_prefixes.iter_cidrs()[0] + + @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks') class RIR(OrganizationalModel): """ @@ -110,7 +132,7 @@ class ASN(PrimaryModel): @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks') -class Aggregate(PrimaryModel): +class Aggregate(GetAvailablePrefixesMixin, PrimaryModel): """ An aggregate exists at the root level of the IP address space hierarchy in NetBox. Aggregates are used to organize the hierarchy and track the overall utilization of available address space. Each Aggregate is assigned to a RIR. @@ -245,7 +267,7 @@ class Role(OrganizationalModel): @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks') -class Prefix(PrimaryModel): +class Prefix(GetAvailablePrefixesMixin, PrimaryModel): """ A Prefix represents an IPv4 or IPv6 network, including mask length. Prefixes can optionally be assigned to Sites and VRFs. A Prefix must be assigned a status and may optionally be assigned a used-define Role. A Prefix can also be @@ -458,16 +480,6 @@ class Prefix(PrimaryModel): else: return IPAddress.objects.filter(address__net_host_contained=str(self.prefix), vrf=self.vrf) - def get_available_prefixes(self): - """ - Return all available Prefixes within this prefix as an IPSet. - """ - prefix = netaddr.IPSet(self.prefix) - child_prefixes = netaddr.IPSet([child.prefix for child in self.get_child_prefixes()]) - available_prefixes = prefix - child_prefixes - - return available_prefixes - def get_available_ips(self): """ Return all available IPs within this prefix as an IPSet. @@ -494,15 +506,6 @@ class Prefix(PrimaryModel): return available_ips - def get_first_available_prefix(self): - """ - Return the first available child prefix within the prefix (or None). - """ - available_prefixes = self.get_available_prefixes() - if not available_prefixes: - return None - return available_prefixes.iter_cidrs()[0] - def get_first_available_ip(self): """ Return the first available IP within the prefix (or None). diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 317caeaf2..501fe1153 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -299,6 +299,7 @@ class AggregatePrefixesView(generic.ObjectChildrenView): return { 'bulk_querystring': f'within={instance.prefix}', 'active_tab': 'prefixes', + 'first_available_prefix': instance.get_first_available_prefix(), 'show_available': bool(request.GET.get('show_available', 'true') == 'true'), 'show_assigned': bool(request.GET.get('show_assigned', 'true') == 'true'), } diff --git a/netbox/templates/ipam/aggregate/prefixes.html b/netbox/templates/ipam/aggregate/prefixes.html index 22a74bd45..3f805fc2e 100644 --- a/netbox/templates/ipam/aggregate/prefixes.html +++ b/netbox/templates/ipam/aggregate/prefixes.html @@ -3,6 +3,11 @@ {% block extra_controls %} {% include 'ipam/inc/toggle_available.html' %} + {% if perms.ipam.add_prefix and first_available_prefix %} + + Add Prefix + + {% endif %} {{ block.super }} {% endblock %}