From 50395aa8212b7fb05c52601bc80f4b81482a7982 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 20 Dec 2017 14:01:37 -0500 Subject: [PATCH] Closes #1773: Moved child prefixes table to its own view --- netbox/ipam/models.py | 43 ++++++++++++------- netbox/ipam/urls.py | 1 + netbox/ipam/views.py | 33 +++++++++----- netbox/templates/ipam/inc/prefix_header.html | 10 ++++- netbox/templates/ipam/prefix.html | 11 ----- netbox/templates/ipam/prefix_ipaddresses.html | 10 ++--- netbox/templates/ipam/prefix_prefixes.html | 12 ++++++ 7 files changed, 77 insertions(+), 43 deletions(-) create mode 100644 netbox/templates/ipam/prefix_prefixes.html diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 0ce0afbdf..bdaec4fd8 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -281,12 +281,28 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): def get_duplicates(self): return Prefix.objects.filter(vrf=self.vrf, prefix=str(self.prefix)).exclude(pk=self.pk) + def get_child_prefixes(self): + """ + Return all Prefixes within this Prefix and VRF. + """ + return Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf) + def get_child_ips(self): """ - Return all IPAddresses within this Prefix. + Return all IPAddresses within this Prefix and VRF. """ 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. @@ -304,15 +320,23 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): 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). """ available_ips = self.get_available_ips() - if available_ips: - return '{}/{}'.format(next(available_ips.__iter__()), self.prefix.prefixlen) - else: + if not available_ips: return None + return '{}/{}'.format(next(available_ips.__iter__()), self.prefix.prefixlen) def get_utilization(self): """ @@ -330,17 +354,6 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): prefix_size -= 2 return int(float(child_count) / prefix_size * 100) - @property - def new_subnet(self): - if self.family == 4: - if self.prefix.prefixlen <= 30: - return netaddr.IPNetwork('{}/{}'.format(self.prefix.network, self.prefix.prefixlen + 1)) - return None - if self.family == 6: - if self.prefix.prefixlen <= 126: - return netaddr.IPNetwork('{}/{}'.format(self.prefix.network, self.prefix.prefixlen + 1)) - return None - class IPAddressManager(models.Manager): diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py index a67e9e865..383b13d8f 100644 --- a/netbox/ipam/urls.py +++ b/netbox/ipam/urls.py @@ -51,6 +51,7 @@ urlpatterns = [ url(r'^prefixes/(?P\d+)/$', views.PrefixView.as_view(), name='prefix'), url(r'^prefixes/(?P\d+)/edit/$', views.PrefixEditView.as_view(), name='prefix_edit'), url(r'^prefixes/(?P\d+)/delete/$', views.PrefixDeleteView.as_view(), name='prefix_delete'), + url(r'^prefixes/(?P\d+)/prefixes/$', views.PrefixPrefixesView.as_view(), name='prefix_prefixes'), url(r'^prefixes/(?P\d+)/ip-addresses/$', views.PrefixIPAddressesView.as_view(), name='prefix_ipaddresses'), # IP addresses diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index e36162938..25475eec8 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -476,6 +476,20 @@ class PrefixView(View): duplicate_prefix_table = tables.PrefixTable(list(duplicate_prefixes), orderable=False) duplicate_prefix_table.exclude = ('vrf',) + return render(request, 'ipam/prefix.html', { + 'prefix': prefix, + 'aggregate': aggregate, + 'parent_prefix_table': parent_prefix_table, + 'duplicate_prefix_table': duplicate_prefix_table, + }) + + +class PrefixPrefixesView(View): + + def get(self, request, pk): + + prefix = get_object_or_404(Prefix.objects.all(), pk=pk) + # Child prefixes table child_prefixes = Prefix.objects.filter( vrf=prefix.vrf, prefix__net_contained=str(prefix.prefix) @@ -484,15 +498,16 @@ class PrefixView(View): ).annotate_depth(limit=0) if child_prefixes: child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes) - child_prefix_table = tables.PrefixDetailTable(child_prefixes) + + prefix_table = tables.PrefixDetailTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): - child_prefix_table.columns.show('pk') + prefix_table.columns.show('pk') paginate = { 'klass': EnhancedPaginator, 'per_page': request.GET.get('per_page', settings.PAGINATE_COUNT) } - RequestConfig(request, paginate).configure(child_prefix_table) + RequestConfig(request, paginate).configure(prefix_table) # Compile permissions list for rendering the object table permissions = { @@ -501,15 +516,12 @@ class PrefixView(View): 'delete': request.user.has_perm('ipam.delete_prefix'), } - return render(request, 'ipam/prefix.html', { + return render(request, 'ipam/prefix_prefixes.html', { 'prefix': prefix, - 'aggregate': aggregate, - 'parent_prefix_table': parent_prefix_table, - 'child_prefix_table': child_prefix_table, - 'duplicate_prefix_table': duplicate_prefix_table, - 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf or '0', prefix.prefix), + 'first_available_prefix': prefix.get_first_available_prefix(), + 'prefix_table': prefix_table, 'permissions': permissions, - 'return_url': prefix.get_absolute_url(), + 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), }) @@ -544,6 +556,7 @@ class PrefixIPAddressesView(View): return render(request, 'ipam/prefix_ipaddresses.html', { 'prefix': prefix, + 'first_available_ip': prefix.get_first_available_ip(), 'ip_table': ip_table, 'permissions': permissions, 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), diff --git a/netbox/templates/ipam/inc/prefix_header.html b/netbox/templates/ipam/inc/prefix_header.html index 553af1a66..f3c694c64 100644 --- a/netbox/templates/ipam/inc/prefix_header.html +++ b/netbox/templates/ipam/inc/prefix_header.html @@ -22,8 +22,13 @@
- {% if perms.ipam.add_ipaddress %} - + {% if perms.ipam.add_prefix and active_tab == 'prefixes' and first_available_prefix %} + + Add Child Prefix + + {% endif %} + {% if perms.ipam.add_ipaddress and active_tab == 'ip-addresses' and first_available_ip %} + Add an IP Address @@ -45,5 +50,6 @@ {% include 'inc/created_updated.html' with obj=prefix %} diff --git a/netbox/templates/ipam/prefix.html b/netbox/templates/ipam/prefix.html index 3447f2ad9..5c168e247 100644 --- a/netbox/templates/ipam/prefix.html +++ b/netbox/templates/ipam/prefix.html @@ -139,15 +139,4 @@ {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' %}
-
-
- {% if child_prefix_table.rows %} - {% include 'utilities/obj_table.html' with table=child_prefix_table table_template='panel_table.html' heading='Child Prefixes' parent=prefix bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' %} - {% elif prefix.new_subnet %} - - Add Child Prefix - - {% endif %} -
-
{% endblock %} diff --git a/netbox/templates/ipam/prefix_ipaddresses.html b/netbox/templates/ipam/prefix_ipaddresses.html index 1b777417d..02e90569d 100644 --- a/netbox/templates/ipam/prefix_ipaddresses.html +++ b/netbox/templates/ipam/prefix_ipaddresses.html @@ -3,10 +3,10 @@ {% block title %}{{ prefix }} - IP Addresses{% endblock %} {% block content %} -{% include 'ipam/inc/prefix_header.html' with active_tab='ip-addresses' %} -
-
- {% include 'utilities/obj_table.html' with table=ip_table table_template='panel_table.html' heading='IP Addresses' bulk_edit_url='ipam:ipaddress_bulk_edit' bulk_delete_url='ipam:ipaddress_bulk_delete' %} + {% include 'ipam/inc/prefix_header.html' with active_tab='ip-addresses' %} +
+
+ {% include 'utilities/obj_table.html' with table=ip_table table_template='panel_table.html' heading='IP Addresses' bulk_edit_url='ipam:ipaddress_bulk_edit' bulk_delete_url='ipam:ipaddress_bulk_delete' %} +
-
{% endblock %} diff --git a/netbox/templates/ipam/prefix_prefixes.html b/netbox/templates/ipam/prefix_prefixes.html new file mode 100644 index 000000000..4951942c3 --- /dev/null +++ b/netbox/templates/ipam/prefix_prefixes.html @@ -0,0 +1,12 @@ +{% extends '_base.html' %} + +{% block title %}{{ prefix }} - Prefixes{% endblock %} + +{% block content %} + {% include 'ipam/inc/prefix_header.html' with active_tab='prefixes' %} +
+
+ {% include 'utilities/obj_table.html' with table=prefix_table table_template='panel_table.html' heading='Child Prefixes' bulk_edit_url='ipam:prefix_bulk_edit' bulk_delete_url='ipam:prefix_bulk_delete' %} +
+
+{% endblock %}