Daniel Sheppard 7 месяцев назад
Родитель
Сommit
7eb3a8d379

+ 15 - 9
netbox/ipam/api/serializers_/ip.py

@@ -67,11 +67,17 @@ class PrefixSerializer(NetBoxModelSerializer):
     class Meta:
         model = Prefix
         fields = [
-            'id', 'url', 'display_url', 'display', 'family', 'prefix', 'vrf', 'scope_type', 'scope_id', 'scope',
-            'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description', 'comments', 'tags',
-            'custom_fields', 'created', 'last_updated', '_children', '_depth',
+            'id', 'url', 'display_url', 'display', 'family', 'aggregate', 'parent', 'prefix', 'vrf', 'scope_type',
+            'scope_id', 'scope', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description',
+            'comments', 'tags', 'custom_fields', 'created', 'last_updated', '_children', '_depth',
         ]
-        brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description', '_depth')
+        brief_fields = ('id', 'url', 'display', 'family', 'aggregate', 'parent', 'prefix', 'description', '_depth')
+
+    def get_fields(self):
+        fields = super(PrefixSerializer, self).get_fields()
+        fields['parent'] = PrefixSerializer(nested=True, read_only=True)
+
+        return fields
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_scope(self, obj):
@@ -146,12 +152,12 @@ class IPRangeSerializer(NetBoxModelSerializer):
     class Meta:
         model = IPRange
         fields = [
-            'id', 'url', 'display_url', 'display', 'family', 'start_address', 'end_address', 'size', 'vrf', 'tenant',
-            'status', 'role', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
+            'id', 'url', 'display_url', 'display', 'family', 'prefix', 'start_address', 'end_address', 'size', 'vrf',
+            'tenant', 'status', 'role', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
             'mark_populated', 'mark_utilized', 'description', 'comments', 'tags', 'custom_fields', 'created',
             'last_updated',
         ]
-        brief_fields = ('id', 'url', 'display', 'family', 'start_address', 'end_address', 'description')
+        brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'start_address', 'end_address', 'description')
 
 
 #
@@ -178,11 +184,11 @@ class IPAddressSerializer(NetBoxModelSerializer):
     class Meta:
         model = IPAddress
         fields = [
-            'id', 'url', 'display_url', 'display', 'family', 'address', 'vrf', 'tenant', 'status', 'role',
+            'id', 'url', 'display_url', 'display', 'family', 'prefix', 'address', 'vrf', 'tenant', 'status', 'role',
             'assigned_object_type', 'assigned_object_id', 'assigned_object', 'nat_inside', 'nat_outside',
             'dns_name', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
         ]
-        brief_fields = ('id', 'url', 'display', 'family', 'address', 'description')
+        brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'address', 'description')
 
     @extend_schema_field(serializers.JSONField(allow_null=True))
     def get_assigned_object(self, obj):

+ 3 - 0
netbox/ipam/graphql/types.py

@@ -169,6 +169,7 @@ class IPAddressType(NetBoxObjectType, ContactsMixin, BaseIPAddressFamilyType):
     pagination=True
 )
 class IPRangeType(NetBoxObjectType, ContactsMixin):
+    prefix: Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')] | None
     start_address: str
     end_address: str
     vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
@@ -183,6 +184,8 @@ class IPRangeType(NetBoxObjectType, ContactsMixin):
     pagination=True
 )
 class PrefixType(NetBoxObjectType, ContactsMixin, BaseIPAddressFamilyType):
+    aggregate: Annotated["AggregateType", strawberry.lazy('ipam.graphql.types')] | None
+    parent: Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')] | None
     prefix: str
     vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
     tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None

+ 3 - 0
netbox/ipam/signals.py

@@ -195,6 +195,7 @@ def handle_prefix_saved(instance, created, **kwargs):
     if created or instance.vrf_id != instance._vrf_id or instance.prefix != instance._prefix:
 
         update_ipaddress_prefix(instance)
+        update_iprange_prefix(instance)
         update_prefix_parents(instance)
         update_parents_children(instance)
         update_children_depth(instance)
@@ -209,6 +210,7 @@ def handle_prefix_saved(instance, created, **kwargs):
 @receiver(pre_delete, sender=Prefix)
 def pre_handle_prefix_deleted(instance, **kwargs):
     update_ipaddress_prefix(instance, True)
+    update_iprange_prefix(instance, True)
     update_prefix_parents(instance, delete=True)
 
 
@@ -218,6 +220,7 @@ def handle_prefix_deleted(instance, **kwargs):
     update_parents_children(instance)
     update_children_depth(instance)
     update_ipaddress_prefix(instance, delete=True)
+    update_iprange_prefix(instance, delete=True)
     update_prefix_parents(instance, delete=True)
 
 

+ 3 - 3
netbox/ipam/tests/test_api.py

@@ -357,7 +357,7 @@ class RoleTest(APIViewTestCases.APIViewTestCase):
 class PrefixTest(APIViewTestCases.APIViewTestCase):
     model = Prefix
     # TODO: Alter for parent prefix
-    brief_fields = ['_depth', 'description', 'display', 'family', 'id', 'prefix', 'url']
+    brief_fields = ['_depth', 'aggregate', 'description', 'display', 'family', 'id', 'parent', 'prefix', 'url']
     create_data = [
         {
             'prefix': '192.168.4.0/24',
@@ -537,7 +537,7 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
 class IPRangeTest(APIViewTestCases.APIViewTestCase):
     model = IPRange
     # TODO: Alter for parent prefix
-    brief_fields = ['description', 'display', 'end_address', 'family', 'id', 'start_address', 'url']
+    brief_fields = ['description', 'display', 'end_address', 'family', 'id', 'prefix', 'start_address', 'url']
     create_data = [
         {
             'start_address': '192.168.4.10/24',
@@ -637,7 +637,7 @@ class IPRangeTest(APIViewTestCases.APIViewTestCase):
 class IPAddressTest(APIViewTestCases.APIViewTestCase):
     model = IPAddress
     # TODO: Alter for parent prefix
-    brief_fields = ['address', 'description', 'display', 'family', 'id', 'url']
+    brief_fields = ['address', 'description', 'display', 'family', 'id', 'prefix', 'url']
     create_data = [
         {
             'address': '192.168.0.4/24',

+ 4 - 4
netbox/ipam/tests/test_models.py

@@ -252,10 +252,10 @@ class TestPrefix(TestCase):
             prefix=IPNetwork('10.0.0.0/16'), status=PrefixStatusChoices.STATUS_CONTAINER
         )
         ips = IPAddress.objects.bulk_create((
-            IPAddress(address=IPNetwork('10.0.0.1/24'), vrf=None),
-            IPAddress(address=IPNetwork('10.0.1.1/24'), vrf=vrfs[0]),
-            IPAddress(address=IPNetwork('10.0.2.1/24'), vrf=vrfs[1]),
-            IPAddress(address=IPNetwork('10.0.3.1/24'), vrf=vrfs[2]),
+            IPAddress(prefix=parent_prefix, address=IPNetwork('10.0.0.1/24'), vrf=None),
+            IPAddress(prefix=parent_prefix, address=IPNetwork('10.0.1.1/24'), vrf=vrfs[0]),
+            IPAddress(prefix=parent_prefix, address=IPNetwork('10.0.2.1/24'), vrf=vrfs[1]),
+            IPAddress(prefix=parent_prefix, address=IPNetwork('10.0.3.1/24'), vrf=vrfs[2]),
         ))
         child_ip_pks = {p.pk for p in parent_prefix.ip_addresses.all()}
 

+ 6 - 6
netbox/ipam/tests/test_views.py

@@ -481,9 +481,9 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
     def test_prefix_ipranges(self):
         prefix = Prefix.objects.create(prefix=IPNetwork('192.168.0.0/16'))
         ip_ranges = (
-            IPRange(start_address='192.168.0.1/24', end_address='192.168.0.100/24', size=99),
-            IPRange(start_address='192.168.1.1/24', end_address='192.168.1.100/24', size=99),
-            IPRange(start_address='192.168.2.1/24', end_address='192.168.2.100/24', size=99),
+            IPRange(prefix=prefix, start_address='192.168.0.1/24', end_address='192.168.0.100/24', size=99),
+            IPRange(prefix=prefix, start_address='192.168.1.1/24', end_address='192.168.1.100/24', size=99),
+            IPRange(prefix=prefix, start_address='192.168.2.1/24', end_address='192.168.2.100/24', size=99),
         )
         IPRange.objects.bulk_create(ip_ranges)
         self.assertEqual(prefix.get_child_ranges().count(), 3)
@@ -495,9 +495,9 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
     def test_prefix_ipaddresses(self):
         prefix = Prefix.objects.create(prefix=IPNetwork('192.168.0.0/16'))
         ip_addresses = (
-            IPAddress(address=IPNetwork('192.168.0.1/16')),
-            IPAddress(address=IPNetwork('192.168.0.2/16')),
-            IPAddress(address=IPNetwork('192.168.0.3/16')),
+            IPAddress(prefix=prefix, address=IPNetwork('192.168.0.1/16')),
+            IPAddress(prefix=prefix, address=IPNetwork('192.168.0.2/16')),
+            IPAddress(prefix=prefix, address=IPNetwork('192.168.0.3/16')),
         )
         IPAddress.objects.bulk_create(ip_addresses)
         self.assertEqual(prefix.ip_addresses.all().count(), 3)