1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

383 lines
12 KiB
Python
Raw Normal View History

from rest_framework.mixins import (
CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin,
)
2016-03-01 11:23:03 -05:00
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet, ModelViewSet
2016-03-01 11:23:03 -05:00
from django.conf import settings
2016-08-22 17:15:20 -04:00
from django.contrib.contenttypes.models import ContentType
2016-03-01 11:23:03 -05:00
from django.http import Http404
from django.shortcuts import get_object_or_404
2016-05-18 16:02:53 -04:00
from dcim.models import (
ConsolePort, ConsoleServerPort, Device, DeviceBay, DeviceRole, DeviceType, Interface, InterfaceConnection,
Manufacturer, Module, Platform, PowerOutlet, PowerPort, Rack, RackGroup, RackRole, Site,
2016-05-18 16:02:53 -04:00
)
from dcim import filters
2017-01-24 17:12:16 -05:00
from extras.api.views import CustomFieldModelViewSet
2016-03-07 23:57:49 -06:00
from extras.api.renderers import BINDZoneRenderer, FlatJSONRenderer
2016-03-01 11:23:03 -05:00
from utilities.api import ServiceUnavailable
2016-08-22 13:20:30 -04:00
from .exceptions import MissingFilterException
from . import serializers
2016-03-01 11:23:03 -05:00
#
# Sites
#
2017-01-24 17:12:16 -05:00
class SiteViewSet(CustomFieldModelViewSet):
queryset = Site.objects.select_related('tenant')
2016-05-18 16:02:53 -04:00
serializer_class = serializers.SiteSerializer
2016-03-01 11:23:03 -05:00
#
# Rack groups
#
2017-01-24 17:12:16 -05:00
class RackGroupViewSet(ModelViewSet):
2016-07-27 14:40:19 -04:00
queryset = RackGroup.objects.select_related('site')
2016-05-18 16:02:53 -04:00
serializer_class = serializers.RackGroupSerializer
filter_class = filters.RackGroupFilter
2016-03-01 11:23:03 -05:00
2016-08-10 11:52:27 -04:00
#
# Rack roles
#
2017-01-24 17:12:16 -05:00
class RackRoleViewSet(ModelViewSet):
2016-08-10 11:52:27 -04:00
queryset = RackRole.objects.all()
serializer_class = serializers.RackRoleSerializer
2016-03-01 11:23:03 -05:00
#
# Racks
#
2017-01-24 17:12:16 -05:00
class RackViewSet(CustomFieldModelViewSet):
queryset = Rack.objects.select_related('site', 'group__site', 'tenant')
2016-05-18 16:02:53 -04:00
filter_class = filters.RackFilter
2016-03-01 11:23:03 -05:00
2017-01-24 17:12:16 -05:00
def get_serializer_class(self):
if self.action == 'retrieve':
return serializers.RackDetailSerializer
return serializers.RackSerializer
2016-03-01 11:23:03 -05:00
class RackUnitListView(APIView):
"""
List rack units (by rack)
"""
def get(self, request, pk):
rack = get_object_or_404(Rack, pk=pk)
face = request.GET.get('face', 0)
exclude_pk = request.GET.get('exclude', None)
if exclude_pk is not None:
try:
exclude_pk = int(exclude_pk)
except ValueError:
exclude_pk = None
elevation = rack.get_rack_units(face, exclude_pk)
2016-03-01 11:23:03 -05:00
# Serialize Devices within the rack elevation
for u in elevation:
if u['device']:
2016-05-18 16:02:53 -04:00
u['device'] = serializers.DeviceNestedSerializer(instance=u['device']).data
2016-03-01 11:23:03 -05:00
return Response(elevation)
#
# Manufacturers
#
2017-01-24 17:12:16 -05:00
class ManufacturerViewSet(ModelViewSet):
2016-03-01 11:23:03 -05:00
queryset = Manufacturer.objects.all()
2016-05-18 16:02:53 -04:00
serializer_class = serializers.ManufacturerSerializer
2016-03-01 11:23:03 -05:00
#
# Device Types
#
2017-01-24 17:12:16 -05:00
class DeviceTypeViewSet(CustomFieldModelViewSet):
queryset = DeviceType.objects.select_related('manufacturer')
2016-05-18 16:02:53 -04:00
filter_class = filters.DeviceTypeFilter
2016-03-01 11:23:03 -05:00
#
# Device Roles
2016-03-01 11:23:03 -05:00
#
2017-01-24 17:12:16 -05:00
class DeviceRoleViewSet(ModelViewSet):
2016-03-01 11:23:03 -05:00
queryset = DeviceRole.objects.all()
2016-05-18 16:02:53 -04:00
serializer_class = serializers.DeviceRoleSerializer
2016-03-01 11:23:03 -05:00
#
# Platforms
#
2017-01-24 17:12:16 -05:00
class PlatformViewSet(ModelViewSet):
2016-03-01 11:23:03 -05:00
queryset = Platform.objects.all()
2016-05-18 16:02:53 -04:00
serializer_class = serializers.PlatformSerializer
2016-03-01 11:23:03 -05:00
#
# Devices
#
2017-01-24 17:12:16 -05:00
class DeviceViewSet(CustomFieldModelViewSet):
queryset = Device.objects.select_related(
'device_type__manufacturer', 'device_role', 'tenant', 'platform', 'rack__site', 'parent_bay',
).prefetch_related(
'primary_ip4__nat_outside', 'primary_ip6__nat_outside',
)
2016-05-18 16:02:53 -04:00
serializer_class = serializers.DeviceSerializer
filter_class = filters.DeviceFilter
2016-03-07 23:57:49 -06:00
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [BINDZoneRenderer, FlatJSONRenderer]
2016-03-01 11:23:03 -05:00
#
# Console Ports
2016-03-01 11:23:03 -05:00
#
class ConsolePortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
queryset = ConsolePort.objects.select_related('cs_port')
serializer_class = serializers.ConsolePortSerializer
class NestedConsolePortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = serializers.NestedConsolePortSerializer
2016-03-01 11:23:03 -05:00
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return ConsolePort.objects.filter(device=device).select_related('cs_port')
#
# Console Server Ports
2016-03-01 11:23:03 -05:00
#
class ConsoleServerPortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
queryset = ConsoleServerPort.objects.select_related('connected_console')
serializer_class = serializers.ConsoleServerPortSerializer
class NestedConsoleServerPortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = serializers.NestedConsoleServerPortSerializer
2016-03-01 11:23:03 -05:00
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return ConsoleServerPort.objects.filter(device=device).select_related('connected_console')
#
# Power Ports
2016-03-01 11:23:03 -05:00
#
class PowerPortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
queryset = PowerPort.objects.select_related('power_outlet')
serializer_class = serializers.PowerPortSerializer
class NestedPowerPortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = serializers.NestedPowerPortSerializer
2016-03-01 11:23:03 -05:00
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return PowerPort.objects.filter(device=device).select_related('power_outlet')
#
# Power Outlets
2016-03-01 11:23:03 -05:00
#
class PowerOutletViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
queryset = PowerOutlet.objects.select_related('connected_port')
serializer_class = serializers.PowerOutletSerializer
class NestedPowerOutletViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = serializers.NestedPowerOutletSerializer
2016-03-01 11:23:03 -05:00
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return PowerOutlet.objects.filter(device=device).select_related('connected_port')
#
# Interfaces
#
class InterfaceViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
queryset = Interface.objects.select_related('device')
serializer_class = serializers.InterfaceDetailSerializer
class NestedInterfaceViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = serializers.NestedInterfaceSerializer
2016-05-18 16:02:53 -04:00
filter_class = filters.InterfaceFilter
2016-03-01 11:23:03 -05:00
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return Interface.objects.order_naturally(device.device_type.interface_ordering).filter(device=device)\
.select_related('connected_as_a', 'connected_as_b', 'circuit_termination')
2016-03-01 11:23:03 -05:00
2016-07-05 13:43:19 -04:00
#
# Device bays
#
class DeviceBayViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
queryset = DeviceBay.objects.select_related('installed_device')
serializer_class = serializers.DeviceBaySerializer
class NestedDeviceBayViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = serializers.NestedDeviceBaySerializer
2016-07-05 13:43:19 -04:00
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return DeviceBay.objects.filter(device=device).select_related('installed_device')
2016-07-05 13:43:19 -04:00
#
# Modules
#
class ModuleViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
queryset = Module.objects.select_related('device', 'manufacturer')
serializer_class = serializers.ModuleSerializer
class NestedModuleViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = serializers.NestedModuleSerializer
def get_queryset(self):
device = get_object_or_404(Device, pk=self.kwargs['pk'])
return Module.objects.filter(device=device).select_related('device', 'manufacturer')
2016-07-05 13:43:19 -04:00
#
# Interface connections
#
class InterfaceConnectionViewSet(ModelViewSet):
queryset = InterfaceConnection.objects.all()
serializer_class = serializers.InterfaceConnectionSerializer
2016-03-01 11:23:03 -05:00
#
# Live queries
#
class LLDPNeighborsView(APIView):
"""
Retrieve live LLDP neighbors of a device
"""
def get(self, request, pk):
device = get_object_or_404(Device, pk=pk)
if not device.primary_ip:
raise ServiceUnavailable(detail="No IP configured for this device.")
RPC = device.get_rpc_client()
if not RPC:
raise ServiceUnavailable(detail="No RPC client available for this platform ({}).".format(device.platform))
# Connect to device and retrieve inventory info
try:
with RPC(device, username=settings.NETBOX_USERNAME, password=settings.NETBOX_PASSWORD) as rpc_client:
lldp_neighbors = rpc_client.get_lldp_neighbors()
except:
raise ServiceUnavailable(detail="Error connecting to the remote device.")
return Response(lldp_neighbors)
#
# Miscellaneous
#
class RelatedConnectionsView(APIView):
"""
Retrieve all connections related to a given console/power/interface connection
"""
2016-08-22 17:15:20 -04:00
def __init__(self):
super(RelatedConnectionsView, self).__init__()
# Custom fields
2017-01-24 17:12:16 -05:00
content_type = ContentType.objects.get_for_model(Device)
custom_fields = content_type.custom_fields.prefetch_related('choices')
# Cache all relevant CustomFieldChoices. This saves us from having to do a lookup per select field per object.
custom_field_choices = {}
for field in custom_fields:
for cfc in field.choices.all():
custom_field_choices[cfc.id] = cfc.value
self.context = {
'custom_fields': custom_fields,
'custom_field_choices': custom_field_choices,
}
2016-08-22 17:15:20 -04:00
2016-03-01 11:23:03 -05:00
def get(self, request):
peer_device = request.GET.get('peer-device')
peer_interface = request.GET.get('peer-interface')
# Search by interface
if peer_device and peer_interface:
# Determine local interface from peer interface's connection
try:
peer_iface = Interface.objects.get(device__name=peer_device, name=peer_interface)
except Interface.DoesNotExist:
raise Http404()
local_iface = peer_iface.connected_interface
2016-03-01 11:23:03 -05:00
if local_iface:
device = local_iface.device
else:
return Response()
else:
raise MissingFilterException(detail='Must specify search parameters "peer-device" and "peer-interface".')
2016-03-01 11:23:03 -05:00
# Initialize response skeleton
response = {
2017-01-24 17:12:16 -05:00
'device': serializers.DeviceSerializer(device, context=self.context).data,
'console-ports': [],
'power-ports': [],
'interfaces': [],
}
# Console connections
2016-03-01 11:23:03 -05:00
console_ports = ConsolePort.objects.filter(device=device).select_related('cs_port__device')
for cp in console_ports:
data = serializers.ConsolePortSerializer(instance=cp).data
del(data['device'])
response['console-ports'].append(data)
2016-03-01 11:23:03 -05:00
# Power connections
2016-03-01 11:23:03 -05:00
power_ports = PowerPort.objects.filter(device=device).select_related('power_outlet__device')
for pp in power_ports:
data = serializers.PowerPortSerializer(instance=pp).data
del(data['device'])
response['power-ports'].append(data)
2016-03-01 11:23:03 -05:00
# Interface connections
interfaces = Interface.objects.order_naturally(device.device_type.interface_ordering).filter(device=device)\
.select_related('connected_as_a', 'connected_as_b', 'circuit_termination')
2016-03-01 11:23:03 -05:00
for iface in interfaces:
data = serializers.InterfaceDetailSerializer(instance=iface).data
del(data['device'])
response['interfaces'].append(data)
2016-03-01 11:23:03 -05:00
2016-06-16 15:02:01 -04:00
return Response(response)