netbox/netbox/ipam/api/views.py

203 lines
6.5 KiB
Python
Raw Normal View History

2017-05-24 11:33:11 -04:00
from __future__ import unicode_literals
from django.conf import settings
from django.shortcuts import get_object_or_404
from rest_framework import status
from rest_framework.decorators import detail_route
from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response
2016-03-01 11:23:03 -05:00
2017-01-24 17:12:16 -05:00
from extras.api.views import CustomFieldModelViewSet
from ipam import filters
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
from utilities.api import FieldChoicesViewSet, ModelViewSet
2016-05-18 16:20:30 -04:00
from . import serializers
2016-03-01 11:23:03 -05:00
#
# Field choices
#
class IPAMFieldChoicesViewSet(FieldChoicesViewSet):
fields = (
(Aggregate, ['family']),
(Prefix, ['family', 'status']),
(IPAddress, ['family', 'status', 'role']),
(VLAN, ['status']),
(Service, ['protocol']),
)
2016-07-15 13:26:54 -04:00
#
# VRFs
#
class VRFViewSet(CustomFieldModelViewSet):
2017-01-24 17:12:16 -05:00
queryset = VRF.objects.select_related('tenant')
2016-05-18 16:20:30 -04:00
serializer_class = serializers.VRFSerializer
write_serializer_class = serializers.WritableVRFSerializer
2016-07-15 13:26:54 -04:00
filter_class = filters.VRFFilter
2016-03-01 11:23:03 -05:00
2016-07-15 13:26:54 -04:00
#
# RIRs
#
2017-01-24 17:12:16 -05:00
class RIRViewSet(ModelViewSet):
2016-03-01 11:23:03 -05:00
queryset = RIR.objects.all()
2016-05-18 16:20:30 -04:00
serializer_class = serializers.RIRSerializer
filter_class = filters.RIRFilter
2016-03-01 11:23:03 -05:00
2016-07-15 13:26:54 -04:00
#
# Aggregates
#
class AggregateViewSet(CustomFieldModelViewSet):
2017-01-24 17:12:16 -05:00
queryset = Aggregate.objects.select_related('rir')
2016-05-18 16:20:30 -04:00
serializer_class = serializers.AggregateSerializer
write_serializer_class = serializers.WritableAggregateSerializer
2016-07-15 13:26:54 -04:00
filter_class = filters.AggregateFilter
2016-03-01 11:23:03 -05:00
#
# Roles
#
class RoleViewSet(ModelViewSet):
queryset = Role.objects.all()
serializer_class = serializers.RoleSerializer
filter_class = filters.RoleFilter
2016-07-15 13:26:54 -04:00
#
# Prefixes
#
class PrefixViewSet(CustomFieldModelViewSet):
2017-01-24 17:12:16 -05:00
queryset = Prefix.objects.select_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role')
2016-05-18 16:20:30 -04:00
serializer_class = serializers.PrefixSerializer
write_serializer_class = serializers.WritablePrefixSerializer
2016-07-15 13:26:54 -04:00
filter_class = filters.PrefixFilter
2016-03-01 11:23:03 -05:00
@detail_route(url_path='available-ips', methods=['get', 'post'])
def available_ips(self, request, pk=None):
"""
A convenience method for returning available IP addresses within a prefix. By default, the number of IPs
returned will be equivalent to PAGINATE_COUNT. An arbitrary limit (up to MAX_PAGE_SIZE, if set) may be passed,
however results will not be paginated.
"""
prefix = get_object_or_404(Prefix, pk=pk)
# Create the next available IP within the prefix
if request.method == 'POST':
# Permissions check
if not request.user.has_perm('ipam.add_ipaddress'):
raise PermissionDenied()
# Determine if the requested number of IPs is available
requested_count = len(request.data) if isinstance(request.data, list) else 1
available_ips = list(prefix.get_available_ips())
if len(available_ips) < requested_count:
return Response(
{
"detail": "An insufficient number of IP addresses are available within the prefix {} ({} "
"requested, {} available)".format(prefix, requested_count, len(available_ips))
},
status=status.HTTP_400_BAD_REQUEST
)
# Deserializing multiple IP addresses
if isinstance(request.data, list):
request_data = list(request.data) # Need a mutable copy
for obj in request_data:
obj['address'] = available_ips.pop(0)
obj['vrf'] = prefix.vrf.pk if prefix.vrf else None
serializer = serializers.WritableIPAddressSerializer(data=request_data, many=True)
# Deserializing a single IP address
else:
request_data = request.data.copy() # Need a mutable copy
request_data['address'] = available_ips.pop(0)
request_data['vrf'] = prefix.vrf.pk if prefix.vrf else None
serializer = serializers.WritableIPAddressSerializer(data=request_data)
# Create the new IP address(es)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# Determine the maximum number of IPs to return
else:
try:
limit = int(request.query_params.get('limit', settings.PAGINATE_COUNT))
except ValueError:
limit = settings.PAGINATE_COUNT
if settings.MAX_PAGE_SIZE:
limit = min(limit, settings.MAX_PAGE_SIZE)
# Calculate available IPs within the prefix
ip_list = []
for index, ip in enumerate(prefix.get_available_ips(), start=1):
ip_list.append(ip)
if index == limit:
break
serializer = serializers.AvailableIPSerializer(ip_list, many=True, context={
'request': request,
'prefix': prefix.prefix,
'vrf': prefix.vrf,
})
return Response(serializer.data)
2016-03-01 11:23:03 -05:00
2016-07-15 13:26:54 -04:00
#
# IP addresses
#
class IPAddressViewSet(CustomFieldModelViewSet):
queryset = IPAddress.objects.select_related(
'vrf__tenant', 'tenant', 'nat_inside'
).prefetch_related(
'interface__device', 'interface__virtual_machine'
)
2016-05-18 16:20:30 -04:00
serializer_class = serializers.IPAddressSerializer
write_serializer_class = serializers.WritableIPAddressSerializer
2016-07-15 13:26:54 -04:00
filter_class = filters.IPAddressFilter
2016-03-01 11:23:03 -05:00
2016-07-15 13:26:54 -04:00
#
# VLAN groups
#
class VLANGroupViewSet(ModelViewSet):
2016-07-27 14:40:19 -04:00
queryset = VLANGroup.objects.select_related('site')
2016-07-15 13:26:54 -04:00
serializer_class = serializers.VLANGroupSerializer
write_serializer_class = serializers.WritableVLANGroupSerializer
2016-07-15 13:26:54 -04:00
filter_class = filters.VLANGroupFilter
#
# VLANs
#
class VLANViewSet(CustomFieldModelViewSet):
2017-01-24 17:12:16 -05:00
queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role')
2016-05-18 16:20:30 -04:00
serializer_class = serializers.VLANSerializer
write_serializer_class = serializers.WritableVLANSerializer
2016-07-15 13:26:54 -04:00
filter_class = filters.VLANFilter
2016-03-01 11:23:03 -05:00
#
# Services
#
class ServiceViewSet(ModelViewSet):
2017-01-27 16:19:38 -05:00
queryset = Service.objects.select_related('device')
serializer_class = serializers.ServiceSerializer
write_serializer_class = serializers.WritableServiceSerializer
filter_class = filters.ServiceFilter