mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
#6934: Include child IP ranges under prefix view
This commit is contained in:
@@ -396,6 +396,16 @@ class Prefix(PrimaryModel):
|
||||
else:
|
||||
return Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf)
|
||||
|
||||
def get_child_ranges(self):
|
||||
"""
|
||||
Return all IPRanges within this Prefix and VRF.
|
||||
"""
|
||||
return IPRange.objects.filter(
|
||||
vrf=self.vrf,
|
||||
start_address__net_host_contained=str(self.prefix),
|
||||
end_address__net_host_contained=str(self.prefix)
|
||||
)
|
||||
|
||||
def get_child_ips(self):
|
||||
"""
|
||||
Return all IPAddresses within this Prefix and VRF. If this Prefix is a container in the global table, return
|
||||
|
@@ -3,7 +3,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
from ipam.choices import IPAddressRoleChoices, PrefixStatusChoices
|
||||
from ipam.models import Aggregate, IPAddress, Prefix, RIR, VLAN, VLANGroup, VRF
|
||||
from ipam.models import Aggregate, IPAddress, IPRange, Prefix, RIR, VLAN, VLANGroup, VRF
|
||||
|
||||
|
||||
class TestAggregate(TestCase):
|
||||
@@ -72,6 +72,23 @@ class TestPrefix(TestCase):
|
||||
# VRF container is limited to its own VRF
|
||||
self.assertSetEqual(child_prefix_pks, {prefixes[2].pk})
|
||||
|
||||
def test_get_child_ranges(self):
|
||||
prefix = Prefix(prefix='192.168.0.16/28')
|
||||
prefix.save()
|
||||
ranges = IPRange.objects.bulk_create((
|
||||
IPRange(start_address=IPNetwork('192.168.0.1/24'), end_address=IPNetwork('192.168.0.10/24'), size=10), # No overlap
|
||||
IPRange(start_address=IPNetwork('192.168.0.11/24'), end_address=IPNetwork('192.168.0.17/24'), size=7), # Partial overlap
|
||||
IPRange(start_address=IPNetwork('192.168.0.18/24'), end_address=IPNetwork('192.168.0.23/24'), size=6), # Full overlap
|
||||
IPRange(start_address=IPNetwork('192.168.0.24/24'), end_address=IPNetwork('192.168.0.30/24'), size=7), # Full overlap
|
||||
IPRange(start_address=IPNetwork('192.168.0.31/24'), end_address=IPNetwork('192.168.0.40/24'), size=10), # Partial overlap
|
||||
))
|
||||
|
||||
child_ranges = prefix.get_child_ranges()
|
||||
|
||||
self.assertEqual(len(child_ranges), 2)
|
||||
self.assertEqual(child_ranges[0], ranges[2])
|
||||
self.assertEqual(child_ranges[1], ranges[3])
|
||||
|
||||
def test_get_child_ips(self):
|
||||
vrfs = VRF.objects.bulk_create((
|
||||
VRF(name='VRF 1'),
|
||||
|
@@ -77,6 +77,7 @@ urlpatterns = [
|
||||
path('prefixes/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='prefix_changelog', kwargs={'model': Prefix}),
|
||||
path('prefixes/<int:pk>/journal/', ObjectJournalView.as_view(), name='prefix_journal', kwargs={'model': Prefix}),
|
||||
path('prefixes/<int:pk>/prefixes/', views.PrefixPrefixesView.as_view(), name='prefix_prefixes'),
|
||||
path('prefixes/<int:pk>/ip-ranges/', views.PrefixIPRangesView.as_view(), name='prefix_ipranges'),
|
||||
path('prefixes/<int:pk>/ip-addresses/', views.PrefixIPAddressesView.as_view(), name='prefix_ipaddresses'),
|
||||
|
||||
# IP ranges
|
||||
|
@@ -412,30 +412,44 @@ class PrefixPrefixesView(generic.ObjectView):
|
||||
if child_prefixes and request.GET.get('show_available', 'true') == 'true':
|
||||
child_prefixes = add_available_prefixes(instance.prefix, child_prefixes)
|
||||
|
||||
prefix_table = tables.PrefixDetailTable(child_prefixes)
|
||||
table = tables.PrefixDetailTable(child_prefixes)
|
||||
if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'):
|
||||
prefix_table.columns.show('pk')
|
||||
paginate_table(prefix_table, request)
|
||||
|
||||
# Compile permissions list for rendering the object table
|
||||
permissions = {
|
||||
'add': request.user.has_perm('ipam.add_prefix'),
|
||||
'change': request.user.has_perm('ipam.change_prefix'),
|
||||
'delete': request.user.has_perm('ipam.delete_prefix'),
|
||||
}
|
||||
table.columns.show('pk')
|
||||
paginate_table(table, request)
|
||||
|
||||
bulk_querystring = 'vrf_id={}&within={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix)
|
||||
|
||||
return {
|
||||
'first_available_prefix': instance.get_first_available_prefix(),
|
||||
'prefix_table': prefix_table,
|
||||
'permissions': permissions,
|
||||
'table': table,
|
||||
'bulk_querystring': bulk_querystring,
|
||||
'active_tab': 'prefixes',
|
||||
'show_available': request.GET.get('show_available', 'true') == 'true',
|
||||
}
|
||||
|
||||
|
||||
class PrefixIPRangesView(generic.ObjectView):
|
||||
queryset = Prefix.objects.all()
|
||||
template_name = 'ipam/prefix/ip_ranges.html'
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
# Find all IPRanges belonging to this Prefix
|
||||
ip_ranges = instance.get_child_ranges().restrict(request.user, 'view').prefetch_related('vrf')
|
||||
|
||||
table = tables.IPRangeTable(ip_ranges)
|
||||
if request.user.has_perm('ipam.change_iprange') or request.user.has_perm('ipam.delete_iprange'):
|
||||
table.columns.show('pk')
|
||||
paginate_table(table, request)
|
||||
|
||||
bulk_querystring = 'vrf_id={}&parent={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix)
|
||||
|
||||
return {
|
||||
'table': table,
|
||||
'bulk_querystring': bulk_querystring,
|
||||
'active_tab': 'ip-ranges',
|
||||
}
|
||||
|
||||
|
||||
class PrefixIPAddressesView(generic.ObjectView):
|
||||
queryset = Prefix.objects.all()
|
||||
template_name = 'ipam/prefix/ip_addresses.html'
|
||||
@@ -450,24 +464,16 @@ class PrefixIPAddressesView(generic.ObjectView):
|
||||
if request.GET.get('show_available', 'true') == 'true':
|
||||
ipaddresses = add_available_ipaddresses(instance.prefix, ipaddresses, instance.is_pool)
|
||||
|
||||
ip_table = tables.IPAddressTable(ipaddresses)
|
||||
table = tables.IPAddressTable(ipaddresses)
|
||||
if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'):
|
||||
ip_table.columns.show('pk')
|
||||
paginate_table(ip_table, request)
|
||||
|
||||
# Compile permissions list for rendering the object table
|
||||
permissions = {
|
||||
'add': request.user.has_perm('ipam.add_ipaddress'),
|
||||
'change': request.user.has_perm('ipam.change_ipaddress'),
|
||||
'delete': request.user.has_perm('ipam.delete_ipaddress'),
|
||||
}
|
||||
table.columns.show('pk')
|
||||
paginate_table(table, request)
|
||||
|
||||
bulk_querystring = 'vrf_id={}&parent={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix)
|
||||
|
||||
return {
|
||||
'first_available_ip': instance.get_first_available_ip(),
|
||||
'ip_table': ip_table,
|
||||
'permissions': permissions,
|
||||
'table': table,
|
||||
'bulk_querystring': bulk_querystring,
|
||||
'active_tab': 'ip-addresses',
|
||||
'show_available': request.GET.get('show_available', 'true') == 'true',
|
||||
|
@@ -17,13 +17,18 @@
|
||||
</li>
|
||||
<li role="presentation" class="nav-item">
|
||||
<a class="nav-link{% if active_tab == 'prefixes' %} active{% endif %}" href="{% url 'ipam:prefix_prefixes' pk=object.pk %}">
|
||||
Child Prefixes <span class="badge bg-primary">{{ object.get_child_prefixes.count }}</span>
|
||||
Child Prefixes {% badge object.get_child_prefixes.count %}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="nav-item">
|
||||
<a class="nav-link{% if active_tab == 'ip-ranges' %} active{% endif %}" href="{% url 'ipam:prefix_ipranges' pk=object.pk %}">
|
||||
Child Ranges {% badge object.get_child_ranges.count %}
|
||||
</a>
|
||||
</li>
|
||||
{% if perms.ipam.view_ipaddress and object.status != 'container' %}
|
||||
<li role="presentation" class="nav-item">
|
||||
<a class="nav-link{% if active_tab == 'ip-addresses' %} active{% endif %}" href="{% url 'ipam:prefix_ipaddresses' pk=object.pk %}">
|
||||
IP Addresses <span class="badge bg-primary">{{ object.get_child_ips.count }}</span>
|
||||
IP Addresses {% badge object.get_child_ips.count %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
{% include 'utilities/obj_table.html' with table=ip_table heading='IP Addresses' bulk_edit_url='ipam:ipaddress_bulk_edit' bulk_delete_url='ipam:ipaddress_bulk_delete' %}
|
||||
{% include 'utilities/obj_table.html' with heading='IP Addresses' bulk_edit_url='ipam:ipaddress_bulk_edit' bulk_delete_url='ipam:ipaddress_bulk_delete' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
10
netbox/templates/ipam/prefix/ip_ranges.html
Normal file
10
netbox/templates/ipam/prefix/ip_ranges.html
Normal file
@@ -0,0 +1,10 @@
|
||||
{% extends 'ipam/prefix/base.html' %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
{% include 'utilities/obj_table.html' with heading='Child IP Ranges' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' parent=prefix %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@@ -19,7 +19,7 @@
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
{% include 'utilities/obj_table.html' with table=prefix_table heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' parent=prefix %}
|
||||
{% include 'utilities/obj_table.html' with heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' parent=prefix %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
Reference in New Issue
Block a user