mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #43: Introduce toggle to enforce unique IP space per VRF
This commit is contained in:
@ -47,9 +47,17 @@ In order to send email, NetBox needs an email server configured. The following i
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
# ENFORCE_GLOBAL_UNIQUE
|
||||||
|
|
||||||
|
Default: False
|
||||||
|
|
||||||
|
Enforcement of unique IP space can be toggled on a per-VRF basis. To enforce unique IP space within the global table (all prefixes and IP addresses not assigned to a VRF), set `ENFORCE_GLOBAL_UNIQUE` to True.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## LOGIN_REQUIRED
|
## LOGIN_REQUIRED
|
||||||
|
|
||||||
Default: False,
|
Default: False
|
||||||
|
|
||||||
Setting this to True will permit only authenticated users to access any part of NetBox. By default, anonymous users are permitted to access most data in NetBox (excluding secrets) but not make any changes.
|
Setting this to True will permit only authenticated users to access any part of NetBox. By default, anonymous users are permitted to access most data in NetBox (excluding secrets) but not make any changes.
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ class VRFSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VRF
|
model = VRF
|
||||||
fields = ['id', 'name', 'rd', 'description']
|
fields = ['id', 'name', 'rd', 'enforce_unique', 'description']
|
||||||
|
|
||||||
|
|
||||||
class VRFNestedSerializer(VRFSerializer):
|
class VRFNestedSerializer(VRFSerializer):
|
||||||
|
@ -25,7 +25,7 @@ class VRFForm(forms.ModelForm, BootstrapMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VRF
|
model = VRF
|
||||||
fields = ['name', 'rd', 'description']
|
fields = ['name', 'rd', 'enforce_unique', 'description']
|
||||||
labels = {
|
labels = {
|
||||||
'rd': "RD",
|
'rd': "RD",
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ class VRFFromCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VRF
|
model = VRF
|
||||||
fields = ['name', 'rd', 'description']
|
fields = ['name', 'rd', 'enforce_unique', 'description']
|
||||||
|
|
||||||
|
|
||||||
class VRFImportForm(BulkImportForm, BootstrapMixin):
|
class VRFImportForm(BulkImportForm, BootstrapMixin):
|
||||||
|
20
netbox/ipam/migrations/0002_vrf_add_enforce_unique.py
Normal file
20
netbox/ipam/migrations/0002_vrf_add_enforce_unique.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.7 on 2016-07-14 19:34
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('ipam', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vrf',
|
||||||
|
name='enforce_unique',
|
||||||
|
field=models.BooleanField(default=True, help_text=b'Prevent duplicate prefixes/IP addresses within this VRF', verbose_name=b'Enforce unique space'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,5 +1,6 @@
|
|||||||
from netaddr import IPNetwork, cidr_merge
|
from netaddr import IPNetwork, cidr_merge
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
@ -45,6 +46,8 @@ class VRF(CreatedUpdatedModel):
|
|||||||
"""
|
"""
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
rd = models.CharField(max_length=21, unique=True, verbose_name='Route distinguisher')
|
rd = models.CharField(max_length=21, unique=True, verbose_name='Route distinguisher')
|
||||||
|
enforce_unique = models.BooleanField(default=True, verbose_name='Enforce unique space',
|
||||||
|
help_text="Prevent duplicate prefixes/IP addresses within this VRF")
|
||||||
description = models.CharField(max_length=100, blank=True)
|
description = models.CharField(max_length=100, blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -309,6 +312,21 @@ class IPAddress(CreatedUpdatedModel):
|
|||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('ipam:ipaddress', args=[self.pk])
|
return reverse('ipam:ipaddress', args=[self.pk])
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
|
||||||
|
# Enforce unique IP space if applicable
|
||||||
|
if self.vrf and self.vrf.enforce_unique:
|
||||||
|
duplicate_ips = IPAddress.objects.filter(vrf=self.vrf, address__net_host=str(self.address.ip))\
|
||||||
|
.exclude(pk=self.pk)
|
||||||
|
if duplicate_ips:
|
||||||
|
raise ValidationError("Duplicate IP address found in VRF {}: {}".format(self.vrf,
|
||||||
|
duplicate_ips.first()))
|
||||||
|
elif not self.vrf and settings.ENFORCE_GLOBAL_UNIQUE:
|
||||||
|
duplicate_ips = IPAddress.objects.filter(vrf=None, address__net_host=str(self.address.ip))\
|
||||||
|
.exclude(pk=self.pk)
|
||||||
|
if duplicate_ips:
|
||||||
|
raise ValidationError("Duplicate IP address found in global table: {}".format(duplicate_ips.first()))
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if self.address:
|
if self.address:
|
||||||
# Infer address family from IPAddress object
|
# Infer address family from IPAddress object
|
||||||
|
@ -82,3 +82,7 @@ BANNER_BOTTOM = ''
|
|||||||
# When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
|
# When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
|
||||||
# prefer IPv4 instead.
|
# prefer IPv4 instead.
|
||||||
PREFER_IPV4 = False
|
PREFER_IPV4 = False
|
||||||
|
|
||||||
|
# Enforcement of unique IP space can be toggled on a per-VRF basis. To enforce unique IP space within the global table
|
||||||
|
# (all prefixes and IP addresses not assigned to a VRF), set ENFORCE_GLOBAL_UNIQUE to True.
|
||||||
|
ENFORCE_GLOBAL_UNIQUE = False
|
||||||
|
@ -41,6 +41,7 @@ SHORT_DATETIME_FORMAT = getattr(configuration, 'SHORT_DATETIME_FORMAT', 'Y-m-d H
|
|||||||
BANNER_TOP = getattr(configuration, 'BANNER_TOP', False)
|
BANNER_TOP = getattr(configuration, 'BANNER_TOP', False)
|
||||||
BANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', False)
|
BANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', False)
|
||||||
PREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)
|
PREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)
|
||||||
|
ENFORCE_GLOBAL_UNIQUE = getattr(configuration, 'ENFORCE_GLOBAL_UNIQUE', False)
|
||||||
CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
|
CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
|
||||||
|
|
||||||
# Attempt to import LDAP configuration if it has been defined
|
# Attempt to import LDAP configuration if it has been defined
|
||||||
|
@ -30,6 +30,16 @@
|
|||||||
<td>Route Distinguisher</td>
|
<td>Route Distinguisher</td>
|
||||||
<td>{{ vrf.rd }}</td>
|
<td>{{ vrf.rd }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Enforce Uniqueness</td>
|
||||||
|
<td>
|
||||||
|
{% if vrf.enforce_unique %}
|
||||||
|
<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>
|
<tr>
|
||||||
<td>Description</td>
|
<td>Description</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
<td>Route distinguisher</td>
|
<td>Route distinguisher</td>
|
||||||
<td>65000:123456</td>
|
<td>65000:123456</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Enforce uniqueness</td>
|
||||||
|
<td>Prevent duplicate prefixes/IP addresses</td>
|
||||||
|
<td>True</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Description</td>
|
<td>Description</td>
|
||||||
<td>Short description (optional)</td>
|
<td>Short description (optional)</td>
|
||||||
@ -46,7 +51,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h4>Example</h4>
|
<h4>Example</h4>
|
||||||
<pre>Customer_ABC,65000:123456,Native VRF for customer ABC</pre>
|
<pre>Customer_ABC,65000:123456,True,Native VRF for customer ABC</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Reference in New Issue
Block a user