Browse Source

Fixes #658: Added is_pool field to Prefix model

Jeremy Stretch 8 years ago
parent
commit
8edaff860c

+ 1 - 1
netbox/ipam/api/serializers.py

@@ -138,7 +138,7 @@ class PrefixSerializer(CustomFieldSerializer, serializers.ModelSerializer):
 
     class Meta:
         model = Prefix
-        fields = ['id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'description',
+        fields = ['id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
                   'custom_fields']
 
 

+ 2 - 10
netbox/ipam/forms.py

@@ -158,15 +158,7 @@ class PrefixForm(BootstrapMixin, CustomFieldForm):
 
     class Meta:
         model = Prefix
-        fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan', 'status', 'role', 'description']
-        help_texts = {
-            'prefix': "IPv4 or IPv6 network",
-            'vrf': "VRF (if applicable)",
-            'site': "The site to which this prefix is assigned (if applicable)",
-            'vlan': "The VLAN to which this prefix is assigned (if applicable)",
-            'status': "Operational status of this prefix",
-            'role': "The primary function of this prefix",
-        }
+        fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan', 'status', 'role', 'is_pool', 'description']
 
     def __init__(self, *args, **kwargs):
         super(PrefixForm, self).__init__(*args, **kwargs)
@@ -197,7 +189,7 @@ class PrefixFromCSVForm(forms.ModelForm):
 
     class Meta:
         model = Prefix
-        fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan_group_name', 'vlan_vid', 'status_name', 'role',
+        fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan_group_name', 'vlan_vid', 'status_name', 'role', 'is_pool',
                   'description']
 
     def clean(self):

+ 37 - 0
netbox/ipam/migrations/0013_prefix_add_is_pool.py

@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.4 on 2016-12-27 19:34
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+import ipam.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('ipam', '0012_services'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='prefix',
+            name='is_pool',
+            field=models.BooleanField(default=False, help_text=b'All IP addresses within this prefix are considered usable', verbose_name=b'Is a pool'),
+        ),
+        migrations.AlterField(
+            model_name='prefix',
+            name='prefix',
+            field=ipam.fields.IPNetworkField(help_text=b'IPv4 or IPv6 network with mask'),
+        ),
+        migrations.AlterField(
+            model_name='prefix',
+            name='role',
+            field=models.ForeignKey(blank=True, help_text=b'The primary function of this prefix', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='prefixes', to='ipam.Role'),
+        ),
+        migrations.AlterField(
+            model_name='prefix',
+            name='status',
+            field=models.PositiveSmallIntegerField(choices=[(0, b'Container'), (1, b'Active'), (2, b'Reserved'), (3, b'Deprecated')], default=1, help_text=b'Operational status of this prefix', verbose_name=b'Status'),
+        ),
+    ]

+ 7 - 3
netbox/ipam/models.py

@@ -269,15 +269,19 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel):
     assigned to a VLAN where appropriate.
     """
     family = models.PositiveSmallIntegerField(choices=AF_CHOICES, editable=False)
-    prefix = IPNetworkField()
+    prefix = IPNetworkField(help_text="IPv4 or IPv6 network with mask")
     site = models.ForeignKey('dcim.Site', related_name='prefixes', on_delete=models.PROTECT, blank=True, null=True)
     vrf = models.ForeignKey('VRF', related_name='prefixes', on_delete=models.PROTECT, blank=True, null=True,
                             verbose_name='VRF')
     tenant = models.ForeignKey(Tenant, related_name='prefixes', blank=True, null=True, on_delete=models.PROTECT)
     vlan = models.ForeignKey('VLAN', related_name='prefixes', on_delete=models.PROTECT, blank=True, null=True,
                              verbose_name='VLAN')
-    status = models.PositiveSmallIntegerField('Status', choices=PREFIX_STATUS_CHOICES, default=1)
-    role = models.ForeignKey('Role', related_name='prefixes', on_delete=models.SET_NULL, blank=True, null=True)
+    status = models.PositiveSmallIntegerField('Status', choices=PREFIX_STATUS_CHOICES, default=PREFIX_STATUS_ACTIVE,
+                                              help_text="Operational status of this prefix")
+    role = models.ForeignKey('Role', related_name='prefixes', on_delete=models.SET_NULL, blank=True, null=True,
+                             help_text="The primary function of this prefix")
+    is_pool = models.BooleanField(verbose_name='Is a pool', default=False,
+                                  help_text="All IP addresses within this prefix are considered usable")
     description = models.CharField(max_length=100, blank=True)
     custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
 

+ 7 - 10
netbox/ipam/views.py

@@ -38,24 +38,21 @@ def add_available_prefixes(parent, prefix_list):
     return prefix_list
 
 
-def add_available_ipaddresses(prefix, ipaddress_list):
+def add_available_ipaddresses(prefix, ipaddress_list, is_pool=False):
     """
-    Annotate ranges of available IP addresses within a given prefix.
+    Annotate ranges of available IP addresses within a given prefix. If is_pool is True, the first and last IP will be
+    considered usable (regardless of mask length).
     """
 
     output = []
     prev_ip = None
 
-    # Ignore the "network address" for IPv4 prefixes larger than /31
-    if prefix.version == 4 and prefix.prefixlen < 31:
+    # Ignore the network and broadcast addresses for non-pool IPv4 prefixes larger than /31.
+    if prefix.version == 4 and prefix.prefixlen < 31 and not is_pool:
         first_ip_in_prefix = netaddr.IPAddress(prefix.first + 1)
-    else:
-        first_ip_in_prefix = netaddr.IPAddress(prefix.first)
-
-    # Ignore the broadcast address for IPv4 prefixes larger than /31
-    if prefix.version == 4 and prefix.prefixlen < 31:
         last_ip_in_prefix = netaddr.IPAddress(prefix.last - 1)
     else:
+        first_ip_in_prefix = netaddr.IPAddress(prefix.first)
         last_ip_in_prefix = netaddr.IPAddress(prefix.last)
 
     if not ipaddress_list:
@@ -476,7 +473,7 @@ def prefix_ipaddresses(request, pk):
     # Find all IPAddresses belonging to this Prefix
     ipaddresses = IPAddress.objects.filter(vrf=prefix.vrf, address__net_contained_or_equal=str(prefix.prefix))\
         .select_related('vrf', 'interface__device', 'primary_ip4_for', 'primary_ip6_for')
-    ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses)
+    ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool)
 
     ip_table = tables.IPAddressTable(ipaddresses)
     if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'):

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

@@ -86,6 +86,16 @@
                     </td>
                 </tr>
                 <tr>
+                    <td>Is a pool</td>
+                    <td>
+                        {% if prefix.is_pool %}
+                            <i class="glyphicon glyphicon-ok text-success" title="Yes"></i>
+                        {% else %}
+                            <i class="glyphicon glyphicon-remove text-danger" title="No"></i>
+                        {% endif %}
+                    </td>
+                </tr>
+                <tr>
                     <td>Description</td>
                     <td>
                         {% if prefix.description %}

+ 1 - 0
netbox/templates/ipam/prefix_edit.html

@@ -12,6 +12,7 @@
             {% render_field form.vlan %}
             {% render_field form.status %}
             {% render_field form.role %}
+            {% render_field form.is_pool %}
             {% render_field form.description %}
         </div>
     </div>

+ 6 - 1
netbox/templates/ipam/prefix_import.html

@@ -69,6 +69,11 @@
 					<td>Customer</td>
 				</tr>
 				<tr>
+					<td>Is a pool</td>
+					<td>True if all IPs are considered usable</td>
+					<td>False</td>
+				</tr>
+				<tr>
 					<td>Description</td>
 					<td>Short description (optional)</td>
 					<td>7th floor WiFi</td>
@@ -76,7 +81,7 @@
 			</tbody>
 		</table>
 		<h4>Example</h4>
-		<pre>192.168.42.0/24,65000:123,ABC01,HQ,Customers,801,Active,Customer,7th floor WiFi</pre>
+		<pre>192.168.42.0/24,65000:123,ABC01,HQ,Customers,801,Active,Customer,False,7th floor WiFi</pre>
 	</div>
 </div>
 {% endblock %}