ip.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. from django.contrib.contenttypes.models import ContentType
  2. from rest_framework import serializers
  3. from dcim.constants import LOCATION_SCOPE_TYPES
  4. from ipam.choices import *
  5. from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS
  6. from ipam.models import Aggregate, IPAddress, IPRange, Prefix
  7. from netbox.api.fields import ChoiceField, ContentTypeField
  8. from netbox.api.gfk_fields import GFKSerializerField
  9. from netbox.api.serializers import PrimaryModelSerializer
  10. from tenancy.api.serializers_.tenants import TenantSerializer
  11. from .asns import RIRSerializer
  12. from .nested import NestedIPAddressSerializer
  13. from .roles import RoleSerializer
  14. from .vlans import VLANSerializer
  15. from .vrfs import VRFSerializer
  16. from ..field_serializers import IPAddressField, IPNetworkField
  17. __all__ = (
  18. 'AggregateSerializer',
  19. 'AvailableIPSerializer',
  20. 'AvailablePrefixSerializer',
  21. 'IPAddressSerializer',
  22. 'IPRangeSerializer',
  23. 'PrefixLengthSerializer',
  24. 'PrefixSerializer',
  25. )
  26. class AggregateSerializer(PrimaryModelSerializer):
  27. family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
  28. rir = RIRSerializer(nested=True)
  29. tenant = TenantSerializer(nested=True, required=False, allow_null=True)
  30. prefix = IPNetworkField()
  31. class Meta:
  32. model = Aggregate
  33. fields = [
  34. 'id', 'url', 'display_url', 'display', 'family', 'prefix', 'rir', 'tenant', 'date_added', 'description',
  35. 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
  36. ]
  37. brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description')
  38. class PrefixSerializer(PrimaryModelSerializer):
  39. family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
  40. vrf = VRFSerializer(nested=True, required=False, allow_null=True)
  41. scope_type = ContentTypeField(
  42. queryset=ContentType.objects.filter(
  43. model__in=LOCATION_SCOPE_TYPES
  44. ),
  45. allow_null=True,
  46. required=False,
  47. default=None
  48. )
  49. scope_id = serializers.IntegerField(allow_null=True, required=False, default=None)
  50. scope = GFKSerializerField(read_only=True)
  51. tenant = TenantSerializer(nested=True, required=False, allow_null=True)
  52. vlan = VLANSerializer(nested=True, required=False, allow_null=True)
  53. status = ChoiceField(choices=PrefixStatusChoices, required=False)
  54. role = RoleSerializer(nested=True, required=False, allow_null=True)
  55. children = serializers.IntegerField(read_only=True)
  56. _depth = serializers.IntegerField(read_only=True)
  57. prefix = IPNetworkField()
  58. class Meta:
  59. model = Prefix
  60. fields = [
  61. 'id', 'url', 'display_url', 'display', 'family', 'prefix', 'vrf', 'scope_type', 'scope_id', 'scope',
  62. 'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description', 'owner', 'comments', 'tags',
  63. 'custom_fields', 'created', 'last_updated', 'children', '_depth',
  64. ]
  65. brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description', '_depth')
  66. class PrefixLengthSerializer(serializers.Serializer):
  67. prefix_length = serializers.IntegerField()
  68. def to_internal_value(self, data):
  69. requested_prefix = data.get('prefix_length')
  70. if requested_prefix is None:
  71. raise serializers.ValidationError({
  72. 'prefix_length': 'this field can not be missing'
  73. })
  74. if not isinstance(requested_prefix, int):
  75. raise serializers.ValidationError({
  76. 'prefix_length': 'this field must be int type'
  77. })
  78. prefix = self.context.get('prefix')
  79. if prefix.family == 4 and requested_prefix > 32:
  80. raise serializers.ValidationError({
  81. 'prefix_length': 'Invalid prefix length ({}) for IPv4'.format(requested_prefix)
  82. })
  83. elif prefix.family == 6 and requested_prefix > 128:
  84. raise serializers.ValidationError({
  85. 'prefix_length': 'Invalid prefix length ({}) for IPv6'.format(requested_prefix)
  86. })
  87. return data
  88. class AvailablePrefixSerializer(serializers.Serializer):
  89. """
  90. Representation of a prefix which does not exist in the database.
  91. """
  92. family = serializers.IntegerField(read_only=True)
  93. prefix = serializers.CharField(read_only=True)
  94. vrf = VRFSerializer(nested=True, read_only=True, allow_null=True)
  95. def to_representation(self, instance):
  96. if self.context.get('vrf'):
  97. vrf = VRFSerializer(self.context['vrf'], nested=True, context={'request': self.context['request']}).data
  98. else:
  99. vrf = None
  100. return {
  101. 'family': instance.version,
  102. 'prefix': str(instance),
  103. 'vrf': vrf,
  104. }
  105. #
  106. # IP ranges
  107. #
  108. class IPRangeSerializer(PrimaryModelSerializer):
  109. family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
  110. start_address = IPAddressField()
  111. end_address = IPAddressField()
  112. vrf = VRFSerializer(nested=True, required=False, allow_null=True)
  113. tenant = TenantSerializer(nested=True, required=False, allow_null=True)
  114. status = ChoiceField(choices=IPRangeStatusChoices, required=False)
  115. role = RoleSerializer(nested=True, required=False, allow_null=True)
  116. class Meta:
  117. model = IPRange
  118. fields = [
  119. 'id', 'url', 'display_url', 'display', 'family', 'start_address', 'end_address', 'size', 'vrf', 'tenant',
  120. 'status', 'role', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
  121. 'mark_populated', 'mark_utilized',
  122. ]
  123. brief_fields = ('id', 'url', 'display', 'family', 'start_address', 'end_address', 'description')
  124. #
  125. # IP addresses
  126. #
  127. class IPAddressSerializer(PrimaryModelSerializer):
  128. family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
  129. address = IPAddressField()
  130. vrf = VRFSerializer(nested=True, required=False, allow_null=True)
  131. tenant = TenantSerializer(nested=True, required=False, allow_null=True)
  132. status = ChoiceField(choices=IPAddressStatusChoices, required=False)
  133. role = ChoiceField(choices=IPAddressRoleChoices, allow_blank=True, required=False)
  134. assigned_object_type = ContentTypeField(
  135. queryset=ContentType.objects.filter(IPADDRESS_ASSIGNMENT_MODELS),
  136. required=False,
  137. allow_null=True
  138. )
  139. assigned_object = GFKSerializerField(read_only=True)
  140. nat_inside = NestedIPAddressSerializer(required=False, allow_null=True)
  141. nat_outside = NestedIPAddressSerializer(many=True, read_only=True)
  142. class Meta:
  143. model = IPAddress
  144. fields = [
  145. 'id', 'url', 'display_url', 'display', 'family', 'address', 'vrf', 'tenant', 'status', 'role',
  146. 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'nat_inside', 'nat_outside',
  147. 'dns_name', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
  148. ]
  149. brief_fields = ('id', 'url', 'display', 'family', 'address', 'description')
  150. class AvailableIPSerializer(serializers.Serializer):
  151. """
  152. Representation of an IP address which does not exist in the database.
  153. """
  154. family = serializers.IntegerField(read_only=True)
  155. address = serializers.CharField(read_only=True)
  156. vrf = VRFSerializer(nested=True, read_only=True, allow_null=True)
  157. description = serializers.CharField(required=False)
  158. def to_representation(self, instance):
  159. if self.context.get('vrf'):
  160. vrf = VRFSerializer(self.context['vrf'], nested=True, context={'request': self.context['request']}).data
  161. else:
  162. vrf = None
  163. return {
  164. 'family': self.context['parent'].family,
  165. 'address': f"{instance}/{self.context['parent'].mask_length}",
  166. 'vrf': vrf,
  167. }