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:
@ -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',
|
||||
]
|
||||
|
||||
|
||||
|
@ -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'),
|
||||
|
@ -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],
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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:
|
||||
|
@ -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',
|
||||
|
Reference in New Issue
Block a user