Coverage for ipam/api/serializers_/vlans.py: 99%

68 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from django.contrib.contenttypes.models import ContentType 

2from rest_framework import serializers 

3 

4from dcim.api.serializers_.sites import SiteSerializer 

5from ipam.choices import * 

6from ipam.constants import VLANGROUP_SCOPE_TYPES 

7from ipam.models import VLAN, VLANGroup, VLANTranslationPolicy, VLANTranslationRule 

8from netbox.api.fields import ChoiceField, ContentTypeField, IntegerRangeSerializer, RelatedObjectCountField 

9from netbox.api.gfk_fields import GFKSerializerField 

10from netbox.api.serializers import NetBoxModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer 

11from tenancy.api.serializers_.tenants import TenantSerializer 

12from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer 

13 

14from .nested import NestedVLANSerializer 

15from .roles import RoleSerializer 

16 

17__all__ = ( 

18 'AvailableVLANSerializer', 

19 'CreateAvailableVLANSerializer', 

20 'VLANGroupSerializer', 

21 'VLANSerializer', 

22 'VLANTranslationPolicySerializer', 

23 'VLANTranslationRuleSerializer', 

24) 

25 

26 

27class VLANGroupSerializer(OrganizationalModelSerializer): 

28 scope_type = ContentTypeField( 

29 queryset=ContentType.objects.filter( 

30 model__in=VLANGROUP_SCOPE_TYPES 

31 ), 

32 allow_null=True, 

33 required=False, 

34 default=None 

35 ) 

36 scope_id = serializers.IntegerField(allow_null=True, required=False, default=None) 

37 scope = GFKSerializerField(read_only=True) 

38 vid_ranges = IntegerRangeSerializer(many=True, required=False) 

39 total_vlan_ids = serializers.IntegerField(read_only=True) 

40 utilization = serializers.CharField(read_only=True) 

41 tenant = TenantSerializer(nested=True, required=False, allow_null=True) 

42 

43 # Related object counts 

44 vlan_count = RelatedObjectCountField('vlans') 

45 

46 class Meta: 

47 model = VLANGroup 

48 fields = [ 

49 'id', 'url', 'display_url', 'display', 'name', 'slug', 'scope_type', 'scope_id', 'scope', 'vid_ranges', 

50 'total_vlan_ids', 'tenant', 'description', 'owner', 'comments', 'tags', 'custom_fields', 

51 'created', 'last_updated', 

52 'vlan_count', 'utilization', 

53 ] 

54 brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'vlan_count') 

55 validators = [] 

56 

57 

58class VLANSerializer(PrimaryModelSerializer): 

59 site = SiteSerializer(nested=True, required=False, allow_null=True) 

60 group = VLANGroupSerializer(nested=True, required=False, allow_null=True, default=None) 

61 tenant = TenantSerializer(nested=True, required=False, allow_null=True) 

62 status = ChoiceField(choices=VLANStatusChoices, required=False) 

63 role = RoleSerializer(nested=True, required=False, allow_null=True) 

64 qinq_role = ChoiceField(choices=VLANQinQRoleChoices, required=False, allow_null=True) 

65 qinq_svlan = NestedVLANSerializer(required=False, allow_null=True, default=None) 

66 l2vpn_termination = L2VPNTerminationSerializer(nested=True, read_only=True, allow_null=True) 

67 

68 # Related object counts 

69 prefix_count = RelatedObjectCountField('prefixes') 

70 

71 class Meta: 

72 model = VLAN 

73 fields = [ 

74 'id', 'url', 'display_url', 'display', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 

75 'description', 'qinq_role', 'qinq_svlan', 'owner', 'comments', 'l2vpn_termination', 'tags', 'custom_fields', 

76 'created', 'last_updated', 'prefix_count', 

77 ] 

78 brief_fields = ('id', 'url', 'display', 'vid', 'name', 'description') 

79 

80 

81class AvailableVLANSerializer(serializers.Serializer): 

82 """ 

83 Representation of a VLAN which does not exist in the database. 

84 """ 

85 vid = serializers.IntegerField(read_only=True) 

86 group = VLANGroupSerializer(nested=True, read_only=True, allow_null=True) 

87 

88 def to_representation(self, instance): 

89 return { 

90 'vid': instance, 

91 'group': VLANGroupSerializer( 

92 self.context['group'], 

93 nested=True, 

94 context={'request': self.context['request']} 

95 ).data, 

96 } 

97 

98 

99class CreateAvailableVLANSerializer(NetBoxModelSerializer): 

100 site = SiteSerializer(nested=True, required=False, allow_null=True) 

101 tenant = TenantSerializer(nested=True, required=False, allow_null=True) 

102 status = ChoiceField(choices=VLANStatusChoices, required=False) 

103 role = RoleSerializer(nested=True, required=False, allow_null=True) 

104 

105 class Meta: 

106 model = VLAN 

107 fields = [ 

108 'name', 'site', 'tenant', 'status', 'role', 'description', 'tags', 'custom_fields', 

109 ] 

110 

111 def validate(self, data): 

112 # Bypass model validation since we don't have a VID yet 

113 return data 

114 

115 

116class VLANTranslationRuleSerializer(NetBoxModelSerializer): 

117 

118 class Meta: 

119 model = VLANTranslationRule 

120 fields = [ 

121 'id', 'url', 'display_url', 'display', 'policy', 'local_vid', 'remote_vid', 'description', 'tags', 

122 'custom_fields', 'created', 'last_updated', 

123 ] 

124 brief_fields = ('id', 'url', 'display', 'policy', 'local_vid', 'remote_vid', 'description') 

125 

126 

127class VLANTranslationPolicySerializer(PrimaryModelSerializer): 

128 rules = VLANTranslationRuleSerializer(nested=True, many=True, read_only=True) 

129 

130 class Meta: 

131 model = VLANTranslationPolicy 

132 fields = [ 

133 'id', 'url', 'display_url', 'display', 'name', 'description', 'rules', 'owner', 'comments', 'tags', 

134 'custom_fields', 'created', 'last_updated', 

135 ] 

136 brief_fields = ('id', 'url', 'display', 'name', 'description')