Browse Source

Closes #1773: Moved child prefixes table to its own view

Jeremy Stretch 7 years ago
parent
commit
50395aa821

+ 28 - 15
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):
 

+ 1 - 0
netbox/ipam/urls.py

@@ -51,6 +51,7 @@ urlpatterns = [
     url(r'^prefixes/(?P<pk>\d+)/$', views.PrefixView.as_view(), name='prefix'),
     url(r'^prefixes/(?P<pk>\d+)/edit/$', views.PrefixEditView.as_view(), name='prefix_edit'),
     url(r'^prefixes/(?P<pk>\d+)/delete/$', views.PrefixDeleteView.as_view(), name='prefix_delete'),
+    url(r'^prefixes/(?P<pk>\d+)/prefixes/$', views.PrefixPrefixesView.as_view(), name='prefix_prefixes'),
     url(r'^prefixes/(?P<pk>\d+)/ip-addresses/$', views.PrefixIPAddressesView.as_view(), name='prefix_ipaddresses'),
 
     # IP addresses

+ 23 - 10
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),

+ 8 - 2
netbox/templates/ipam/inc/prefix_header.html

@@ -22,8 +22,13 @@
     </div>
 </div>
 <div class="pull-right">
-    {% if perms.ipam.add_ipaddress %}
-		<a href="{% url 'ipam:ipaddress_add' %}?address={{ prefix.get_first_available_ip }}&vrf={{ prefix.vrf.pk }}&tenant_group={{ prefix.tenant.group.pk }}&tenant={{ prefix.tenant.pk }}" class="btn btn-success">
+    {% if perms.ipam.add_prefix and active_tab == 'prefixes' and first_available_prefix %}
+        <a href="{% url 'ipam:prefix_add' %}?prefix={{ first_available_prefix }}&vrf={{ prefix.vrf.pk }}&site={{ prefix.site.pk }}&tenant_group={{ prefix.tenant.group.pk }}&tenant={{ prefix.tenant.pk }}" class="btn btn-success">
+            <i class="fa fa-plus" aria-hidden="true"></i> Add Child Prefix
+        </a>
+    {% endif %}
+    {% if perms.ipam.add_ipaddress and active_tab == 'ip-addresses' and first_available_ip %}
+		<a href="{% url 'ipam:ipaddress_add' %}?address={{ first_available_ip }}&vrf={{ prefix.vrf.pk }}&tenant_group={{ prefix.tenant.group.pk }}&tenant={{ prefix.tenant.pk }}" class="btn btn-success">
 			<span class="fa fa-plus" aria-hidden="true"></span>
 			Add an IP Address
 		</a>
@@ -45,5 +50,6 @@
 {% include 'inc/created_updated.html' with obj=prefix %}
 <ul class="nav nav-tabs" style="margin-bottom: 20px">
     <li role="presentation"{% if active_tab == 'prefix' %} class="active"{% endif %}><a href="{% url 'ipam:prefix' pk=prefix.pk %}">Prefix</a></li>
+    <li role="presentation"{% if active_tab == 'prefixes' %} class="active"{% endif %}><a href="{% url 'ipam:prefix_prefixes' pk=prefix.pk %}">Child Prefixes <span class="badge">{{ prefix.get_child_prefixes.count }}</span></a></li>
     <li role="presentation"{% if active_tab == 'ip-addresses' %} class="active"{% endif %}><a href="{% url 'ipam:prefix_ipaddresses' pk=prefix.pk %}">IP Addresses <span class="badge">{{ prefix.get_child_ips.count }}</span></a></li>
 </ul>

+ 0 - 11
netbox/templates/ipam/prefix.html

@@ -139,15 +139,4 @@
         {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' %}
 	</div>
 </div>
-<div class="row">
-	<div class="col-md-12">
-        {% 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 %}
-            <a href="{% url 'ipam:prefix_add' %}?prefix={{ prefix.new_subnet }}{% if prefix.vrf %}&vrf={{ prefix.vrf.pk }}{% endif %}{% if prefix.site %}&site={{ prefix.site.pk }}{% endif %}" class="btn btn-success">
-                <i class="fa fa-plus" aria-hidden="true"></i> Add Child Prefix
-            </a>
-        {% endif %}
-    </div>
-</div>
 {% endblock %}

+ 5 - 5
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' %}
-<div class="row">
-	<div class="col-md-12">
-        {% 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' %}
+    <div class="row">
+        <div class="col-md-12">
+            {% 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' %}
+        </div>
     </div>
-</div>
 {% endblock %}

+ 12 - 0
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' %}
+    <div class="row">
+        <div class="col-md-12">
+            {% 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' %}
+        </div>
+    </div>
+{% endblock %}