diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index b38f04ecc..e96fe7806 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -408,8 +408,6 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, CachedScopeMixin, Primary """ Return all available IPs within this prefix as an IPSet. """ - # TODO: Add mark_populated - prefix = netaddr.IPSet(self.prefix) child_ips = netaddr.IPSet([ ip.address.ip for ip in self.get_child_ips() @@ -889,6 +887,20 @@ class IPAddress(ContactsMixin, PrimaryModel): ) }) + # Disallow the creation of IPAddresses within an IPRange with mark_populated=True + parent_range = IPRange.objects.filter( + start_address__lte=self.address, + end_address__gte=self.address, + vrf=self.vrf, + mark_populated=True + ).first() + if parent_range: + raise ValidationError({ + 'address': _( + "Cannot create IP address {ip} inside range {range}." + ).format(ip=self.address, range=parent_range) + }) + if self._original_assigned_object_id and self._original_assigned_object_type_id: parent = getattr(self.assigned_object, 'parent_object', None) ct = ObjectType.objects.get_for_id(self._original_assigned_object_type_id) diff --git a/netbox/ipam/tests/test_models.py b/netbox/ipam/tests/test_models.py index f41c93539..246ca0e22 100644 --- a/netbox/ipam/tests/test_models.py +++ b/netbox/ipam/tests/test_models.py @@ -582,6 +582,27 @@ class TestIPAddress(TestCase): IPAddress.objects.create(address=IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) IPAddress.objects.create(address=IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) + # + # Range validation + # + + def test_create_ip_in_unpopulated_range(self): + IPRange.objects.create( + start_address=IPNetwork('192.0.2.1/24'), + end_address=IPNetwork('192.0.2.100/24') + ) + ip = IPAddress(address=IPNetwork('192.0.2.10/24')) + ip.full_clean() + + def test_create_ip_in_populated_range(self): + IPRange.objects.create( + start_address=IPNetwork('192.0.2.1/24'), + end_address=IPNetwork('192.0.2.100/24'), + mark_populated=True + ) + ip = IPAddress(address=IPNetwork('192.0.2.10/24')) + self.assertRaises(ValidationError, ip.full_clean) + class TestVLANGroup(TestCase):