diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index 6d629d89c..5d11622f6 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -159,9 +159,11 @@ class Aggregate(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel): @property def family(self): - if self.prefix: - return self.prefix.version - return None + if not self.prefix: + return None + if isinstance(self.prefix, str): + return netaddr.IPNetwork(self.prefix).version + return self.prefix.version @property def ipv6_full(self): @@ -335,11 +337,19 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, CachedScopeMixin, Primary @property def family(self): - return self.prefix.version if self.prefix else None + if not self.prefix: + return None + if isinstance(self.prefix, str): + return netaddr.IPNetwork(self.prefix).version + return self.prefix.version @property def mask_length(self): - return self.prefix.prefixlen if self.prefix else None + if not self.prefix: + return None + if isinstance(self.prefix, str): + return netaddr.IPNetwork(self.prefix).prefixlen + return self.prefix.prefixlen @property def ipv6_full(self): @@ -642,7 +652,11 @@ class IPRange(ContactsMixin, PrimaryModel): @property def family(self): - return self.start_address.version if self.start_address else None + if not self.start_address: + return None + if isinstance(self.start_address, str): + return netaddr.IPAddress(self.start_address.split('/')[0]).version + return self.start_address.version @property def range(self): @@ -990,9 +1004,11 @@ class IPAddress(ContactsMixin, PrimaryModel): @property def family(self): - if self.address: - return self.address.version - return None + if not self.address: + return None + if isinstance(self.address, str): + return netaddr.IPNetwork(self.address).version + return self.address.version @property def is_oob_ip(self): diff --git a/netbox/ipam/tests/test_models.py b/netbox/ipam/tests/test_models.py index 80ac92ef2..e81900ec9 100644 --- a/netbox/ipam/tests/test_models.py +++ b/netbox/ipam/tests/test_models.py @@ -11,6 +11,13 @@ from utilities.data import string_to_ranges class TestAggregate(TestCase): + def test_family_string(self): + # Test property when prefix is a string + agg = Aggregate(prefix='10.0.0.0/8') + self.assertEqual(agg.family, 4) + agg_v6 = Aggregate(prefix='2001:db8::/32') + self.assertEqual(agg_v6.family, 6) + def test_get_utilization(self): rir = RIR.objects.create(name='RIR 1', slug='rir-1') aggregate = Aggregate(prefix=IPNetwork('10.0.0.0/8'), rir=rir) @@ -40,6 +47,13 @@ class TestAggregate(TestCase): class TestIPRange(TestCase): + def test_family_string(self): + # Test property when start_address is a string + ip_range = IPRange(start_address='10.0.0.1/24', end_address='10.0.0.254/24') + self.assertEqual(ip_range.family, 4) + ip_range_v6 = IPRange(start_address='2001:db8::1/64', end_address='2001:db8::ffff/64') + self.assertEqual(ip_range_v6.family, 6) + def test_overlapping_range(self): iprange_192_168 = IPRange.objects.create( start_address=IPNetwork('192.168.0.1/22'), end_address=IPNetwork('192.168.0.49/22') @@ -90,6 +104,20 @@ class TestIPRange(TestCase): class TestPrefix(TestCase): + def test_family_string(self): + # Test property when prefix is a string + prefix = Prefix(prefix='10.0.0.0/8') + self.assertEqual(prefix.family, 4) + prefix_v6 = Prefix(prefix='2001:db8::/32') + self.assertEqual(prefix_v6.family, 6) + + def test_mask_length_string(self): + # Test property when prefix is a string + prefix = Prefix(prefix='10.0.0.0/8') + self.assertEqual(prefix.mask_length, 8) + prefix_v6 = Prefix(prefix='2001:db8::/32') + self.assertEqual(prefix_v6.mask_length, 32) + def test_get_duplicates(self): prefixes = Prefix.objects.bulk_create(( Prefix(prefix=IPNetwork('192.0.2.0/24')), @@ -533,6 +561,13 @@ class TestPrefixHierarchy(TestCase): class TestIPAddress(TestCase): + def test_family_string(self): + # Test property when address is a string + ip = IPAddress(address='10.0.0.1/24') + self.assertEqual(ip.family, 4) + ip_v6 = IPAddress(address='2001:db8::1/64') + self.assertEqual(ip_v6.family, 6) + def test_get_duplicates(self): ips = IPAddress.objects.bulk_create(( IPAddress(address=IPNetwork('192.0.2.1/24')),