1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

#6732: Add asns relationship to SiteSerializer and extend tests

This commit is contained in:
jeremystretch
2021-11-03 15:15:14 -04:00
parent 7a97d5d4eb
commit 7a55832a22
6 changed files with 40 additions and 44 deletions

View File

@ -1,4 +1,3 @@
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from drf_yasg.utils import swagger_serializer_method
from rest_framework import serializers
@ -7,8 +6,8 @@ from timezone_field.rest_framework import TimeZoneSerializerField
from dcim.choices import *
from dcim.constants import *
from dcim.models import *
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer, NestedASNSerializer
from ipam.models import VLAN
from ipam.api.nested_serializers import NestedASNSerializer, NestedIPAddressSerializer, NestedVLANSerializer
from ipam.models import ASN, VLAN
from netbox.api import ChoiceField, ContentTypeField, SerializedPKRelatedField
from netbox.api.serializers import (
NestedGroupModelSerializer, PrimaryModelSerializer, ValidatedModelSerializer, WritableNestedSerializer,
@ -113,13 +112,19 @@ class SiteSerializer(PrimaryModelSerializer):
region = NestedRegionSerializer(required=False, allow_null=True)
group = NestedSiteGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
asns = NestedASNSerializer(many=True, required=False, allow_null=True)
time_zone = TimeZoneSerializerField(required=False)
asns = SerializedPKRelatedField(
queryset=ASN.objects.all(),
serializer=NestedASNSerializer,
required=False,
many=True
)
# Related object counts
circuit_count = serializers.IntegerField(read_only=True)
device_count = serializers.IntegerField(read_only=True)
prefix_count = serializers.IntegerField(read_only=True)
rack_count = serializers.IntegerField(read_only=True)
asn_count = serializers.IntegerField(read_only=True)
virtualmachine_count = serializers.IntegerField(read_only=True)
vlan_count = serializers.IntegerField(read_only=True)
@ -129,8 +134,7 @@ class SiteSerializer(PrimaryModelSerializer):
'id', 'url', 'display', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'asn', 'asns',
'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name',
'contact_phone', 'contact_email', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
'asn_count', 'circuit_count', 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count',
'vlan_count',
'circuit_count', 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count',
]

View File

@ -137,9 +137,8 @@ class SiteGroupViewSet(CustomFieldModelViewSet):
class SiteViewSet(CustomFieldModelViewSet):
queryset = Site.objects.prefetch_related(
'region', 'tenant', 'tags'
'region', 'tenant', 'asns', 'tags'
).annotate(
asn_count=count_related(ASN, 'sites'),
device_count=count_related(Device, 'site'),
rack_count=count_related(Rack, 'site'),
prefix_count=count_related(Prefix, 'site'),

View File

@ -6,7 +6,7 @@ from rest_framework import status
from dcim.choices import *
from dcim.constants import *
from dcim.models import *
from ipam.models import VLAN
from ipam.models import ASN, RIR, VLAN
from utilities.testing import APITestCase, APIViewTestCases
from virtualization.models import Cluster, ClusterType
@ -143,6 +143,13 @@ class SiteTest(APIViewTestCases.APIViewTestCase):
)
Site.objects.bulk_create(sites)
rir = RIR.objects.create(name='RFC 6996', is_private=True)
asns = [
ASN(asn=65000 + i, rir=rir) for i in range(8)
]
ASN.objects.bulk_create(asns)
cls.create_data = [
{
'name': 'Site 4',
@ -150,6 +157,7 @@ class SiteTest(APIViewTestCases.APIViewTestCase):
'region': regions[1].pk,
'group': groups[1].pk,
'status': SiteStatusChoices.STATUS_ACTIVE,
'asns': [asns[0].pk, asns[1].pk],
},
{
'name': 'Site 5',
@ -157,6 +165,7 @@ class SiteTest(APIViewTestCases.APIViewTestCase):
'region': regions[1].pk,
'group': groups[1].pk,
'status': SiteStatusChoices.STATUS_ACTIVE,
'asns': [asns[2].pk, asns[3].pk],
},
{
'name': 'Site 6',
@ -164,6 +173,7 @@ class SiteTest(APIViewTestCases.APIViewTestCase):
'region': regions[1].pk,
'group': groups[1].pk,
'status': SiteStatusChoices.STATUS_ACTIVE,
'asns': [asns[4].pk, asns[5].pk],
},
]

View File

@ -11,7 +11,7 @@ from netaddr import EUI
from dcim.choices import *
from dcim.constants import *
from dcim.models import *
from ipam.models import ASN, VLAN, RIR
from ipam.models import ASN, RIR, VLAN
from tenancy.models import Tenant
from utilities.testing import ViewTestCases, create_tags, create_test_device
@ -110,41 +110,24 @@ class SiteTestCase(ViewTestCases.PrimaryObjectViewTestCase):
for group in groups:
group.save()
rir = RIR.objects.create(name='RFC 6996', is_private=True)
asns = [
ASN(asn=65000 + i, rir=rir) for i in range(8)
]
ASN.objects.bulk_create(asns)
sites = Site.objects.bulk_create([
Site(name='Site 1', slug='site-1', region=regions[0], group=groups[1]),
Site(name='Site 2', slug='site-2', region=regions[0], group=groups[1]),
Site(name='Site 3', slug='site-3', region=regions[0], group=groups[1]),
])
sites[0].asns.set([asns[0], asns[1]])
sites[1].asns.set([asns[2], asns[3]])
sites[2].asns.set([asns[4], asns[5]])
tags = create_tags('Alpha', 'Bravo', 'Charlie')
rir = RIR.objects.create(name='RFC 6996', is_private=True)
asns = [
ASN(asn=65000, rir=rir),
ASN(asn=65001, rir=rir),
ASN(asn=65002, rir=rir),
ASN(asn=65003, rir=rir),
ASN(asn=65004, rir=rir),
ASN(asn=65005, rir=rir),
ASN(asn=65006, rir=rir),
ASN(asn=65007, rir=rir),
ASN(asn=65008, rir=rir),
ASN(asn=65009, rir=rir),
ASN(asn=65010, rir=rir),
]
ASN.objects.bulk_create(asns)
asns[0].sites.set([sites[0]])
asns[2].sites.set([sites[0]])
asns[3].sites.set([sites[1]])
asns[4].sites.set([sites[2]])
asns[5].sites.set([sites[1]])
asns[6].sites.set([sites[2]])
asns[7].sites.set([sites[2]])
asns[8].sites.set([sites[2]])
asns[10].sites.set([sites[0]])
cls.form_data = {
'name': 'Site X',
'slug': 'site-x',
@ -153,6 +136,7 @@ class SiteTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'group': groups[1].pk,
'tenant': None,
'facility': 'Facility X',
'asns': [asns[6].pk, asns[7].pk],
'time_zone': pytz.UTC,
'description': 'Site description',
'physical_address': '742 Evergreen Terrace, Springfield, USA',

View File

@ -23,7 +23,6 @@ from .nested_serializers import *
class ASNSerializer(PrimaryModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:asn-detail')
tenant = NestedTenantSerializer(required=False, allow_null=True)
site_count = serializers.IntegerField(read_only=True)
class Meta:

View File

@ -73,11 +73,12 @@ class RIR(OrganizationalModel):
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ASN(PrimaryModel):
"""
An autonomous system (AS) number is typically used to represent an independent routing domain. A site can have
one or more ASNs assigned to it.
"""
asn = ASNField(
unique=True,
blank=False,
null=False,
verbose_name='ASN',
help_text='32-bit autonomous system number'
)
@ -89,8 +90,7 @@ class ASN(PrimaryModel):
to='ipam.RIR',
on_delete=models.PROTECT,
related_name='asns',
blank=False,
null=False
verbose_name='RIR'
)
tenant = models.ForeignKey(
to='tenancy.Tenant',