views.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. from __future__ import unicode_literals
  2. from rest_framework import status
  3. from rest_framework.decorators import detail_route
  4. from rest_framework.exceptions import PermissionDenied
  5. from rest_framework.response import Response
  6. from rest_framework.viewsets import ModelViewSet
  7. from django.conf import settings
  8. from django.shortcuts import get_object_or_404
  9. from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
  10. from ipam import filters
  11. from extras.api.views import CustomFieldModelViewSet
  12. from utilities.api import WritableSerializerMixin
  13. from . import serializers
  14. #
  15. # VRFs
  16. #
  17. class VRFViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
  18. queryset = VRF.objects.select_related('tenant')
  19. serializer_class = serializers.VRFSerializer
  20. write_serializer_class = serializers.WritableVRFSerializer
  21. filter_class = filters.VRFFilter
  22. #
  23. # RIRs
  24. #
  25. class RIRViewSet(ModelViewSet):
  26. queryset = RIR.objects.all()
  27. serializer_class = serializers.RIRSerializer
  28. filter_class = filters.RIRFilter
  29. #
  30. # Aggregates
  31. #
  32. class AggregateViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
  33. queryset = Aggregate.objects.select_related('rir')
  34. serializer_class = serializers.AggregateSerializer
  35. write_serializer_class = serializers.WritableAggregateSerializer
  36. filter_class = filters.AggregateFilter
  37. #
  38. # Roles
  39. #
  40. class RoleViewSet(ModelViewSet):
  41. queryset = Role.objects.all()
  42. serializer_class = serializers.RoleSerializer
  43. filter_class = filters.RoleFilter
  44. #
  45. # Prefixes
  46. #
  47. class PrefixViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
  48. queryset = Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role')
  49. serializer_class = serializers.PrefixSerializer
  50. write_serializer_class = serializers.WritablePrefixSerializer
  51. filter_class = filters.PrefixFilter
  52. @detail_route(url_path='available-ips', methods=['get', 'post'])
  53. def available_ips(self, request, pk=None):
  54. """
  55. A convenience method for returning available IP addresses within a prefix. By default, the number of IPs
  56. returned will be equivalent to PAGINATE_COUNT. An arbitrary limit (up to MAX_PAGE_SIZE, if set) may be passed,
  57. however results will not be paginated.
  58. """
  59. prefix = get_object_or_404(Prefix, pk=pk)
  60. # Create the next available IP within the prefix
  61. if request.method == 'POST':
  62. # Permissions check
  63. if not request.user.has_perm('ipam.add_ipaddress'):
  64. raise PermissionDenied()
  65. # Find the first available IP address in the prefix
  66. try:
  67. ipaddress = list(prefix.get_available_ips())[0]
  68. except IndexError:
  69. return Response(
  70. {
  71. "detail": "There are no available IPs within this prefix ({})".format(prefix)
  72. },
  73. status=status.HTTP_400_BAD_REQUEST
  74. )
  75. # Create the new IP address
  76. data = request.data.copy()
  77. data['address'] = '{}/{}'.format(ipaddress, prefix.prefix.prefixlen)
  78. data['vrf'] = prefix.vrf.pk if prefix.vrf else None
  79. serializer = serializers.WritableIPAddressSerializer(data=data)
  80. if serializer.is_valid():
  81. serializer.save()
  82. return Response(serializer.data, status=status.HTTP_201_CREATED)
  83. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  84. # Determine the maximum amount of IPs to return
  85. else:
  86. try:
  87. limit = int(request.query_params.get('limit', settings.PAGINATE_COUNT))
  88. except ValueError:
  89. limit = settings.PAGINATE_COUNT
  90. if settings.MAX_PAGE_SIZE:
  91. limit = min(limit, settings.MAX_PAGE_SIZE)
  92. # Calculate available IPs within the prefix
  93. ip_list = []
  94. for index, ip in enumerate(prefix.get_available_ips(), start=1):
  95. ip_list.append(ip)
  96. if index == limit:
  97. break
  98. serializer = serializers.AvailableIPSerializer(ip_list, many=True, context={
  99. 'request': request,
  100. 'prefix': prefix.prefix,
  101. 'vrf': prefix.vrf,
  102. })
  103. return Response(serializer.data)
  104. #
  105. # IP addresses
  106. #
  107. class IPAddressViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
  108. queryset = IPAddress.objects.select_related(
  109. 'vrf__tenant', 'tenant', 'nat_inside'
  110. ).prefetch_related(
  111. 'interface__device'
  112. )
  113. serializer_class = serializers.IPAddressSerializer
  114. write_serializer_class = serializers.WritableIPAddressSerializer
  115. filter_class = filters.IPAddressFilter
  116. #
  117. # VLAN groups
  118. #
  119. class VLANGroupViewSet(WritableSerializerMixin, ModelViewSet):
  120. queryset = VLANGroup.objects.select_related('site')
  121. serializer_class = serializers.VLANGroupSerializer
  122. write_serializer_class = serializers.WritableVLANGroupSerializer
  123. filter_class = filters.VLANGroupFilter
  124. #
  125. # VLANs
  126. #
  127. class VLANViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
  128. queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role')
  129. serializer_class = serializers.VLANSerializer
  130. write_serializer_class = serializers.WritableVLANSerializer
  131. filter_class = filters.VLANFilter
  132. #
  133. # Services
  134. #
  135. class ServiceViewSet(WritableSerializerMixin, ModelViewSet):
  136. queryset = Service.objects.select_related('device')
  137. serializer_class = serializers.ServiceSerializer
  138. write_serializer_class = serializers.WritableServiceSerializer
  139. filter_class = filters.ServiceFilter