From ab706d24408929fa8144e83d1e320572c4cd8966 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 17 Jan 2017 12:32:54 -0500 Subject: [PATCH] Follow-up to #804 --- netbox/ipam/models.py | 34 ++++++------ netbox/ipam/tests/test_models.py | 88 ++++++++++++++------------------ 2 files changed, 53 insertions(+), 69 deletions(-) diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index fc404dbda3a..78bbf7caa0f 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -298,13 +298,11 @@ def __unicode__(self): def get_absolute_url(self): return reverse('ipam:prefix', args=[self.pk]) - def duplicates(self): - return Prefix.objects.filter( - vrf=self.vrf, - prefix=str(self.prefix) - ).exclude(pk=self.pk) + def get_duplicates(self): + return Prefix.objects.filter(vrf=self.vrf, prefix=str(self.prefix)).exclude(pk=self.pk) def clean(self): + # Disallow host masks if self.prefix: if self.prefix.version == 4 and self.prefix.prefixlen == 32: @@ -316,13 +314,14 @@ def clean(self): 'prefix': "Cannot create host addresses (/128) as prefixes. Create an IPv6 address instead." }) - if ((not self.vrf and settings.ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique)): - dupes = self.duplicates() - if dupes: + # Enforce unique IP space if applicable + if (self.vrf is None and settings.ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique): + duplicate_prefixes = self.get_duplicates() + if duplicate_prefixes: raise ValidationError({ 'prefix': "Duplicate prefix found in {}: {}".format( "VRF {}".format(self.vrf) if self.vrf else "global table", - dupes.first(), + duplicate_prefixes.first(), ) }) @@ -415,22 +414,19 @@ def __unicode__(self): def get_absolute_url(self): return reverse('ipam:ipaddress', args=[self.pk]) - def duplicates(self): - return IPAddress.objects.filter( - vrf=self.vrf, - address__net_host=str(self.address.ip) - ).exclude(pk=self.pk) + def get_duplicates(self): + return IPAddress.objects.filter(vrf=self.vrf, address__net_host=str(self.address.ip)).exclude(pk=self.pk) def clean(self): # Enforce unique IP space if applicable - if ((not self.vrf and settings.ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique)): - dupes = self.duplicates() - if dupes: + if (self.vrf is None and settings.ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique): + duplicate_ips = self.get_duplicates() + if duplicate_ips: raise ValidationError({ - 'address': "Duplicate IP Address found in {}: {}".format( + 'address': "Duplicate IP address found in {}: {}".format( "VRF {}".format(self.vrf) if self.vrf else "global table", - dupes.first(), + duplicate_ips.first(), ) }) diff --git a/netbox/ipam/tests/test_models.py b/netbox/ipam/tests/test_models.py index 49ca3b09b6a..3385c643f6e 100644 --- a/netbox/ipam/tests/test_models.py +++ b/netbox/ipam/tests/test_models.py @@ -8,65 +8,53 @@ class TestPrefix(TestCase): - fixtures = [ - 'dcim', - 'ipam' - ] - - def test_create(self): - prefix = Prefix.objects.create( - prefix=netaddr.IPNetwork('10.1.1.0/24'), - status=1 - ) - self.assertIsNone(prefix.clean()) - - @override_settings(ENFORCE_GLOBAL_UNIQUE=True) + @override_settings(ENFORCE_GLOBAL_UNIQUE=False) def test_duplicate_global(self): - prefix = Prefix.objects.create( - prefix=netaddr.IPNetwork('10.1.1.0/24'), - status=1 - ) - self.assertRaises(ValidationError, prefix.clean) + Prefix.objects.create(prefix=netaddr.IPNetwork('192.0.2.0/24')) + duplicate_prefix = Prefix(prefix=netaddr.IPNetwork('192.0.2.0/24')) + self.assertIsNone(duplicate_prefix.clean()) @override_settings(ENFORCE_GLOBAL_UNIQUE=True) + def test_duplicate_global_unique(self): + Prefix.objects.create(prefix=netaddr.IPNetwork('192.0.2.0/24')) + duplicate_prefix = Prefix(prefix=netaddr.IPNetwork('192.0.2.0/24')) + self.assertRaises(ValidationError, duplicate_prefix.clean) + def test_duplicate_vrf(self): - pfx_kwargs = { - "prefix": netaddr.IPNetwork('10.1.1.0/24'), - "status": 1, - "vrf": VRF.objects.create(name='Test', rd='1:1'), - } - Prefix.objects.create(**pfx_kwargs) - dup_prefix = Prefix.objects.create(**pfx_kwargs) - self.assertRaises(ValidationError, dup_prefix.clean) + vrf = VRF.objects.create(name='Test', rd='1:1', enforce_unique=False) + Prefix.objects.create(vrf=vrf, prefix=netaddr.IPNetwork('192.0.2.0/24')) + duplicate_prefix = Prefix(vrf=vrf, prefix=netaddr.IPNetwork('192.0.2.0/24')) + self.assertIsNone(duplicate_prefix.clean()) + def test_duplicate_vrf_unique(self): + vrf = VRF.objects.create(name='Test', rd='1:1', enforce_unique=True) + Prefix.objects.create(vrf=vrf, prefix=netaddr.IPNetwork('192.0.2.0/24')) + duplicate_prefix = Prefix(vrf=vrf, prefix=netaddr.IPNetwork('192.0.2.0/24')) + self.assertRaises(ValidationError, duplicate_prefix.clean) -class TestIPAddress(TestCase): - fixtures = [ - 'dcim', - 'ipam' - ] - - def test_create(self): - address = IPAddress.objects.create( - address=netaddr.IPNetwork('10.0.254.1/24'), - ) - self.assertIsNone(address.clean()) +class TestIPAddress(TestCase): - @override_settings(ENFORCE_GLOBAL_UNIQUE=True) + @override_settings(ENFORCE_GLOBAL_UNIQUE=False) def test_duplicate_global(self): - address = IPAddress.objects.create( - address=netaddr.IPNetwork('10.0.254.1/24'), - ) - self.assertRaises(ValidationError, address.clean) + IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24')) + duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')) + self.assertIsNone(duplicate_ip.clean()) @override_settings(ENFORCE_GLOBAL_UNIQUE=True) + def test_duplicate_global_unique(self): + IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24')) + duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')) + self.assertRaises(ValidationError, duplicate_ip.clean) + def test_duplicate_vrf(self): - pfx_kwargs = { - "address": netaddr.IPNetwork('10.0.254.1/24'), - "status": 1, - "vrf": VRF.objects.create(name='Test', rd='1:1'), - } - IPAddress.objects.create(**pfx_kwargs) - dup_address = IPAddress.objects.create(**pfx_kwargs) - self.assertRaises(ValidationError, dup_address.clean) + vrf = VRF.objects.create(name='Test', rd='1:1', enforce_unique=False) + IPAddress.objects.create(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24')) + duplicate_ip = IPAddress(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24')) + self.assertIsNone(duplicate_ip.clean()) + + def test_duplicate_vrf_unique(self): + vrf = VRF.objects.create(name='Test', rd='1:1', enforce_unique=True) + IPAddress.objects.create(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24')) + duplicate_ip = IPAddress(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24')) + self.assertRaises(ValidationError, duplicate_ip.clean)