2023-03-21 17:00:06 -04:00
|
|
|
from django.http import Http404, HttpResponse
|
2020-01-15 09:59:44 -05:00
|
|
|
from django.shortcuts import get_object_or_404
|
2023-03-30 11:32:59 -07:00
|
|
|
from drf_spectacular.types import OpenApiTypes
|
2023-05-31 06:06:09 -07:00
|
|
|
from drf_spectacular.utils import extend_schema, OpenApiParameter
|
2018-06-29 11:48:21 -04:00
|
|
|
from rest_framework.decorators import action
|
2016-03-01 11:23:03 -05:00
|
|
|
from rest_framework.response import Response
|
2020-08-13 12:45:38 -04:00
|
|
|
from rest_framework.routers import APIRootView
|
2021-07-14 15:29:04 -04:00
|
|
|
from rest_framework.viewsets import ViewSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
2021-04-29 16:38:56 -04:00
|
|
|
from dcim import filtersets
|
2022-06-27 15:53:34 -04:00
|
|
|
from dcim.constants import CABLE_TRACE_SVG_DEFAULT_WIDTH
|
2021-03-08 13:28:53 -05:00
|
|
|
from dcim.models import *
|
2022-07-07 12:48:44 -04:00
|
|
|
from dcim.svg import CableTraceSVG
|
2023-11-17 16:32:58 +03:00
|
|
|
from extras.api.mixins import ConfigContextQuerySetMixin, RenderConfigMixin
|
2020-10-13 15:54:23 -04:00
|
|
|
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
|
|
|
|
from netbox.api.metadata import ContentTypeMetadata
|
2022-06-13 20:45:08 +02:00
|
|
|
from netbox.api.pagination import StripCountAnnotationsPaginator
|
2023-10-17 07:35:01 -07:00
|
|
|
from netbox.api.viewsets import NetBoxModelViewSet, MPTTLockedMixin
|
2023-05-31 06:06:09 -07:00
|
|
|
from netbox.api.viewsets.mixins import SequentialBulkCreatesMixin
|
2020-10-13 15:54:23 -04:00
|
|
|
from utilities.api import get_serializer_for_model
|
2023-11-01 13:47:14 -04:00
|
|
|
from utilities.query_functions import CollateAsChar
|
2016-08-22 13:20:30 -04:00
|
|
|
from . import serializers
|
2017-11-07 11:08:23 -05:00
|
|
|
from .exceptions import MissingFilterException
|
2016-03-01 11:23:03 -05:00
|
|
|
|
|
|
|
|
2020-08-13 12:45:38 -04:00
|
|
|
class DCIMRootView(APIRootView):
|
|
|
|
"""
|
|
|
|
DCIM API root view
|
|
|
|
"""
|
|
|
|
def get_view_name(self):
|
|
|
|
return 'DCIM'
|
|
|
|
|
|
|
|
|
2018-10-29 15:43:41 -04:00
|
|
|
# Mixins
|
|
|
|
|
2020-10-02 14:54:16 -04:00
|
|
|
class PathEndpointMixin(object):
|
2018-10-29 15:43:41 -04:00
|
|
|
|
|
|
|
@action(detail=True, url_path='trace')
|
|
|
|
def trace(self, request, pk):
|
|
|
|
"""
|
|
|
|
Trace a complete cable path and return each segment as a three-tuple of (termination, cable, termination).
|
|
|
|
"""
|
2020-06-29 14:41:43 -04:00
|
|
|
obj = get_object_or_404(self.queryset, pk=pk)
|
2018-10-29 15:43:41 -04:00
|
|
|
|
|
|
|
# Initialize the path array
|
|
|
|
path = []
|
|
|
|
|
2022-07-07 12:48:44 -04:00
|
|
|
# Render SVG image if requested
|
2021-07-13 15:38:34 -04:00
|
|
|
if request.GET.get('render', None) == 'svg':
|
2021-07-16 17:06:27 -04:00
|
|
|
try:
|
2022-06-27 15:53:34 -04:00
|
|
|
width = int(request.GET.get('width', CABLE_TRACE_SVG_DEFAULT_WIDTH))
|
2021-07-16 17:09:52 -04:00
|
|
|
except (ValueError, TypeError):
|
2022-06-27 15:53:34 -04:00
|
|
|
width = CABLE_TRACE_SVG_DEFAULT_WIDTH
|
2022-07-07 14:35:02 -04:00
|
|
|
drawing = CableTraceSVG(obj, base_url=request.build_absolute_uri('/'), width=width)
|
2022-07-07 12:48:44 -04:00
|
|
|
return HttpResponse(drawing.render().tostring(), content_type='image/svg+xml')
|
2021-07-13 15:38:34 -04:00
|
|
|
|
2022-07-07 12:48:44 -04:00
|
|
|
# Serialize path objects, iterating over each three-tuple in the path
|
2022-08-01 13:29:39 -04:00
|
|
|
for near_ends, cable, far_ends in obj.trace():
|
|
|
|
if near_ends:
|
2024-02-27 14:56:36 -05:00
|
|
|
serializer_a = get_serializer_for_model(near_ends[0])
|
|
|
|
near_ends = serializer_a(near_ends, nested=True, many=True, context={'request': request}).data
|
2022-07-07 12:48:44 -04:00
|
|
|
else:
|
|
|
|
# Path is split; stop here
|
2020-10-08 14:01:47 -04:00
|
|
|
break
|
2022-08-01 13:29:39 -04:00
|
|
|
if cable:
|
2022-07-07 12:48:44 -04:00
|
|
|
cable = serializers.TracedCableSerializer(cable[0], context={'request': request}).data
|
2022-08-01 13:29:39 -04:00
|
|
|
if far_ends:
|
2024-02-27 14:56:36 -05:00
|
|
|
serializer_b = get_serializer_for_model(far_ends[0])
|
|
|
|
far_ends = serializer_b(far_ends, nested=True, many=True, context={'request': request}).data
|
2018-10-29 15:43:41 -04:00
|
|
|
|
2022-08-01 13:29:39 -04:00
|
|
|
path.append((near_ends, cable, far_ends))
|
2018-10-29 15:43:41 -04:00
|
|
|
|
|
|
|
return Response(path)
|
|
|
|
|
|
|
|
|
2020-10-08 10:32:17 -04:00
|
|
|
class PassThroughPortMixin(object):
|
|
|
|
|
|
|
|
@action(detail=True, url_path='paths')
|
|
|
|
def paths(self, request, pk):
|
|
|
|
"""
|
|
|
|
Return all CablePaths which traverse a given pass-through port.
|
|
|
|
"""
|
|
|
|
obj = get_object_or_404(self.queryset, pk=pk)
|
2022-05-13 11:04:38 -04:00
|
|
|
cablepaths = CablePath.objects.filter(_nodes__contains=obj)
|
2020-10-08 10:32:17 -04:00
|
|
|
serializer = serializers.CablePathSerializer(cablepaths, context={'request': request}, many=True)
|
|
|
|
|
|
|
|
return Response(serializer.data)
|
|
|
|
|
|
|
|
|
2017-02-28 16:10:53 -05:00
|
|
|
#
|
|
|
|
# Regions
|
|
|
|
#
|
|
|
|
|
2023-10-17 07:35:01 -07:00
|
|
|
class RegionViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
2020-07-20 12:07:19 -04:00
|
|
|
queryset = Region.objects.add_related_count(
|
|
|
|
Region.objects.all(),
|
|
|
|
Site,
|
|
|
|
'region',
|
|
|
|
'site_count',
|
|
|
|
cumulative=True
|
2024-02-14 09:28:37 -05:00
|
|
|
)
|
2017-02-28 16:10:53 -05:00
|
|
|
serializer_class = serializers.RegionSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.RegionFilterSet
|
2017-02-28 16:10:53 -05:00
|
|
|
|
|
|
|
|
2021-03-08 13:28:53 -05:00
|
|
|
#
|
|
|
|
# Site groups
|
|
|
|
#
|
|
|
|
|
2023-10-17 07:35:01 -07:00
|
|
|
class SiteGroupViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
2021-03-08 13:28:53 -05:00
|
|
|
queryset = SiteGroup.objects.add_related_count(
|
|
|
|
SiteGroup.objects.all(),
|
|
|
|
Site,
|
|
|
|
'group',
|
|
|
|
'site_count',
|
|
|
|
cumulative=True
|
2024-02-14 09:28:37 -05:00
|
|
|
)
|
2021-03-08 13:28:53 -05:00
|
|
|
serializer_class = serializers.SiteGroupSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.SiteGroupFilterSet
|
2021-03-08 13:28:53 -05:00
|
|
|
|
|
|
|
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
# Sites
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class SiteViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = Site.objects.all()
|
2016-05-18 16:02:53 -04:00
|
|
|
serializer_class = serializers.SiteSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.SiteFilterSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
#
|
2021-04-11 13:43:06 -04:00
|
|
|
# Locations
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
|
2023-10-17 07:35:01 -07:00
|
|
|
class LocationViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
2021-03-03 13:30:33 -05:00
|
|
|
queryset = Location.objects.add_related_count(
|
2021-04-05 11:04:12 -04:00
|
|
|
Location.objects.add_related_count(
|
|
|
|
Location.objects.all(),
|
|
|
|
Device,
|
|
|
|
'location',
|
|
|
|
'device_count',
|
|
|
|
cumulative=True
|
|
|
|
),
|
2020-07-20 12:07:19 -04:00
|
|
|
Rack,
|
2021-03-03 13:30:33 -05:00
|
|
|
'location',
|
2020-07-20 12:07:19 -04:00
|
|
|
'rack_count',
|
|
|
|
cumulative=True
|
2024-02-14 09:28:37 -05:00
|
|
|
)
|
2021-03-03 13:30:33 -05:00
|
|
|
serializer_class = serializers.LocationSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.LocationFilterSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
|
|
|
|
2016-08-10 11:52:27 -04:00
|
|
|
#
|
|
|
|
# Rack roles
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class RackRoleViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = RackRole.objects.all()
|
2016-08-10 11:52:27 -04:00
|
|
|
serializer_class = serializers.RackRoleSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.RackRoleFilterSet
|
2016-08-10 11:52:27 -04:00
|
|
|
|
|
|
|
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
# Racks
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class RackViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = Rack.objects.all()
|
2017-01-27 12:22:29 -05:00
|
|
|
serializer_class = serializers.RackSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.RackFilterSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
2024-02-21 10:39:32 -08:00
|
|
|
@extend_schema(
|
|
|
|
operation_id='dcim_racks_elevation_retrieve',
|
|
|
|
filters=False,
|
|
|
|
parameters=[serializers.RackElevationDetailFilterSerializer],
|
|
|
|
responses={200: serializers.RackUnitSerializer(many=True)}
|
|
|
|
)
|
2019-12-10 03:18:10 -05:00
|
|
|
@action(detail=True)
|
|
|
|
def elevation(self, request, pk=None):
|
|
|
|
"""
|
|
|
|
Rack elevation representing the list of rack units. Also supports rendering the elevation as an SVG.
|
|
|
|
"""
|
2020-06-29 14:41:43 -04:00
|
|
|
rack = get_object_or_404(self.queryset, pk=pk)
|
2019-12-11 09:45:08 -05:00
|
|
|
serializer = serializers.RackElevationDetailFilterSerializer(data=request.GET)
|
|
|
|
if not serializer.is_valid():
|
|
|
|
return Response(serializer.errors, 400)
|
|
|
|
data = serializer.validated_data
|
2019-11-18 15:42:42 +01:00
|
|
|
|
2019-12-11 17:33:58 -05:00
|
|
|
if data['render'] == 'svg':
|
2022-06-24 11:04:38 -04:00
|
|
|
# Determine attributes for highlighting devices (if any)
|
|
|
|
highlight_params = []
|
|
|
|
for param in request.GET.getlist('highlight'):
|
|
|
|
try:
|
|
|
|
highlight_params.append(param.split(':', 1))
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
|
2019-12-11 13:39:10 -05:00
|
|
|
# Render and return the elevation as an SVG drawing with the correct content type
|
2020-02-20 13:09:43 -05:00
|
|
|
drawing = rack.get_elevation_svg(
|
|
|
|
face=data['face'],
|
2020-07-29 09:43:13 -04:00
|
|
|
user=request.user,
|
2020-02-20 13:09:43 -05:00
|
|
|
unit_width=data['unit_width'],
|
|
|
|
unit_height=data['unit_height'],
|
|
|
|
legend_width=data['legend_width'],
|
2020-04-03 13:16:35 -04:00
|
|
|
include_images=data['include_images'],
|
2022-06-24 11:04:38 -04:00
|
|
|
base_url=request.build_absolute_uri('/'),
|
|
|
|
highlight_params=highlight_params
|
2020-02-20 13:09:43 -05:00
|
|
|
)
|
2019-12-10 03:18:10 -05:00
|
|
|
return HttpResponse(drawing.tostring(), content_type='image/svg+xml')
|
|
|
|
|
|
|
|
else:
|
2019-12-11 13:39:10 -05:00
|
|
|
# Return a JSON representation of the rack units in the elevation
|
2019-12-11 09:45:08 -05:00
|
|
|
elevation = rack.get_rack_units(
|
|
|
|
face=data['face'],
|
2020-08-03 13:37:32 -04:00
|
|
|
user=request.user,
|
2019-12-11 09:45:08 -05:00
|
|
|
exclude=data['exclude'],
|
|
|
|
expand_devices=data['expand_devices']
|
|
|
|
)
|
2019-11-20 18:27:04 +01:00
|
|
|
|
2020-02-22 08:16:29 -06:00
|
|
|
# Enable filtering rack units by ID
|
|
|
|
q = data['q']
|
|
|
|
if q:
|
|
|
|
elevation = [u for u in elevation if q in str(u['id']) or q in str(u['name'])]
|
|
|
|
|
2019-12-10 03:18:10 -05:00
|
|
|
page = self.paginate_queryset(elevation)
|
|
|
|
if page is not None:
|
|
|
|
rack_units = serializers.RackUnitSerializer(page, many=True, context={'request': request})
|
|
|
|
return self.get_paginated_response(rack_units.data)
|
2019-11-18 15:42:42 +01:00
|
|
|
|
2019-11-21 16:58:07 +01:00
|
|
|
|
2017-02-16 13:46:58 -05:00
|
|
|
#
|
|
|
|
# Rack reservations
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class RackReservationViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = RackReservation.objects.all()
|
2017-02-16 13:46:58 -05:00
|
|
|
serializer_class = serializers.RackReservationSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.RackReservationFilterSet
|
2017-02-16 13:46:58 -05:00
|
|
|
|
|
|
|
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
# Manufacturers
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class ManufacturerViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = Manufacturer.objects.all()
|
2016-05-18 16:02:53 -04:00
|
|
|
serializer_class = serializers.ManufacturerSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.ManufacturerFilterSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
#
|
2021-12-17 12:18:37 -05:00
|
|
|
# Device/module types
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class DeviceTypeViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = DeviceType.objects.all()
|
2017-01-27 12:22:29 -05:00
|
|
|
serializer_class = serializers.DeviceTypeSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.DeviceTypeFilterSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class ModuleTypeViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = ModuleType.objects.all()
|
2021-12-17 12:18:37 -05:00
|
|
|
serializer_class = serializers.ModuleTypeSerializer
|
|
|
|
filterset_class = filtersets.ModuleTypeFilterSet
|
|
|
|
|
|
|
|
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
2017-02-03 17:18:47 -05:00
|
|
|
# Device type components
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class ConsolePortTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = ConsolePortTemplate.objects.all()
|
2017-02-03 17:18:47 -05:00
|
|
|
serializer_class = serializers.ConsolePortTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.ConsolePortTemplateFilterSet
|
2017-02-03 17:18:47 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class ConsoleServerPortTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = ConsoleServerPortTemplate.objects.all()
|
2017-02-03 17:18:47 -05:00
|
|
|
serializer_class = serializers.ConsoleServerPortTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.ConsoleServerPortTemplateFilterSet
|
2017-02-03 17:18:47 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class PowerPortTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = PowerPortTemplate.objects.all()
|
2017-02-03 17:18:47 -05:00
|
|
|
serializer_class = serializers.PowerPortTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.PowerPortTemplateFilterSet
|
2017-02-03 17:18:47 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class PowerOutletTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = PowerOutletTemplate.objects.all()
|
2017-02-03 17:18:47 -05:00
|
|
|
serializer_class = serializers.PowerOutletTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.PowerOutletTemplateFilterSet
|
2017-02-03 17:18:47 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class InterfaceTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = InterfaceTemplate.objects.all()
|
2017-02-03 17:18:47 -05:00
|
|
|
serializer_class = serializers.InterfaceTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.InterfaceTemplateFilterSet
|
2017-02-03 17:18:47 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class FrontPortTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = FrontPortTemplate.objects.all()
|
2018-10-25 12:08:13 -04:00
|
|
|
serializer_class = serializers.FrontPortTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.FrontPortTemplateFilterSet
|
2018-10-03 14:04:16 -04:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class RearPortTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = RearPortTemplate.objects.all()
|
2018-10-25 12:08:13 -04:00
|
|
|
serializer_class = serializers.RearPortTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.RearPortTemplateFilterSet
|
2018-10-03 14:04:16 -04:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class ModuleBayTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = ModuleBayTemplate.objects.all()
|
2021-12-17 09:35:57 -05:00
|
|
|
serializer_class = serializers.ModuleBayTemplateSerializer
|
|
|
|
filterset_class = filtersets.ModuleBayTemplateFilterSet
|
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class DeviceBayTemplateViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = DeviceBayTemplate.objects.all()
|
2017-02-03 17:18:47 -05:00
|
|
|
serializer_class = serializers.DeviceBayTemplateSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.DeviceBayTemplateFilterSet
|
2017-02-03 17:18:47 -05:00
|
|
|
|
|
|
|
|
2023-10-17 07:35:01 -07:00
|
|
|
class InventoryItemTemplateViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = InventoryItemTemplate.objects.all()
|
2021-12-29 15:02:25 -05:00
|
|
|
serializer_class = serializers.InventoryItemTemplateSerializer
|
|
|
|
filterset_class = filtersets.InventoryItemTemplateFilterSet
|
|
|
|
|
|
|
|
|
2017-02-03 17:18:47 -05:00
|
|
|
#
|
|
|
|
# Device roles
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class DeviceRoleViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = DeviceRole.objects.all()
|
2016-05-18 16:02:53 -04:00
|
|
|
serializer_class = serializers.DeviceRoleSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.DeviceRoleFilterSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Platforms
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class PlatformViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = Platform.objects.all()
|
2016-05-18 16:02:53 -04:00
|
|
|
serializer_class = serializers.PlatformSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.PlatformFilterSet
|
2016-03-01 11:23:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
#
|
2021-12-17 16:12:03 -05:00
|
|
|
# Devices/modules
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
|
2023-05-31 06:06:09 -07:00
|
|
|
class DeviceViewSet(
|
|
|
|
SequentialBulkCreatesMixin,
|
|
|
|
ConfigContextQuerySetMixin,
|
2023-11-17 16:32:58 +03:00
|
|
|
RenderConfigMixin,
|
2023-05-31 06:06:09 -07:00
|
|
|
NetBoxModelViewSet
|
|
|
|
):
|
2019-08-19 01:53:39 -04:00
|
|
|
queryset = Device.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'parent_bay', # Referenced by DeviceSerializer.get_parent_device()
|
2017-01-24 17:12:16 -05:00
|
|
|
)
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.DeviceFilterSet
|
2022-06-13 20:45:08 +02:00
|
|
|
pagination_class = StripCountAnnotationsPaginator
|
2016-03-01 11:23:03 -05:00
|
|
|
|
2018-07-03 12:29:20 -04:00
|
|
|
def get_serializer_class(self):
|
|
|
|
"""
|
2019-02-18 21:37:00 -05:00
|
|
|
Select the specific serializer based on the request context.
|
|
|
|
|
|
|
|
If the `brief` query param equates to True, return the NestedDeviceSerializer
|
|
|
|
|
|
|
|
If the `exclude` query param includes `config_context` as a value, return the DeviceSerializer
|
|
|
|
|
|
|
|
Else, return the DeviceWithConfigContextSerializer
|
2018-07-03 12:29:20 -04:00
|
|
|
"""
|
2018-10-04 16:20:01 -04:00
|
|
|
request = self.get_serializer_context()['request']
|
2024-02-23 15:26:06 -05:00
|
|
|
if self.brief or 'config_context' in request.query_params.get('exclude', []):
|
2019-02-18 21:37:00 -05:00
|
|
|
return serializers.DeviceSerializer
|
|
|
|
|
|
|
|
return serializers.DeviceWithConfigContextSerializer
|
2018-06-27 16:02:34 -04:00
|
|
|
|
2017-07-14 14:42:56 -04:00
|
|
|
|
2022-11-11 06:55:49 -06:00
|
|
|
class VirtualDeviceContextViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = VirtualDeviceContext.objects.all()
|
2022-11-11 06:55:49 -06:00
|
|
|
serializer_class = serializers.VirtualDeviceContextSerializer
|
|
|
|
filterset_class = filtersets.VirtualDeviceContextFilterSet
|
|
|
|
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class ModuleViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = Module.objects.all()
|
2021-12-17 16:12:03 -05:00
|
|
|
serializer_class = serializers.ModuleSerializer
|
|
|
|
filterset_class = filtersets.ModuleFilterSet
|
|
|
|
|
|
|
|
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
2017-02-01 14:34:19 -05:00
|
|
|
# Device components
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class ConsolePortViewSet(PathEndpointMixin, NetBoxModelViewSet):
|
2021-12-17 20:31:15 -05:00
|
|
|
queryset = ConsolePort.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'_path', 'cable__terminations',
|
2021-12-17 20:31:15 -05:00
|
|
|
)
|
2017-01-26 17:58:36 -05:00
|
|
|
serializer_class = serializers.ConsolePortSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.ConsolePortFilterSet
|
2017-01-26 17:58:36 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class ConsoleServerPortViewSet(PathEndpointMixin, NetBoxModelViewSet):
|
2020-10-06 14:30:46 -04:00
|
|
|
queryset = ConsoleServerPort.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'_path', 'cable__terminations',
|
2020-10-06 14:30:46 -04:00
|
|
|
)
|
2017-01-26 17:58:36 -05:00
|
|
|
serializer_class = serializers.ConsoleServerPortSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.ConsoleServerPortFilterSet
|
2017-01-26 17:58:36 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class PowerPortViewSet(PathEndpointMixin, NetBoxModelViewSet):
|
2021-12-17 20:31:15 -05:00
|
|
|
queryset = PowerPort.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'_path', 'cable__terminations',
|
2021-12-17 20:31:15 -05:00
|
|
|
)
|
2017-01-26 17:58:36 -05:00
|
|
|
serializer_class = serializers.PowerPortSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.PowerPortFilterSet
|
2017-01-26 17:58:36 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class PowerOutletViewSet(PathEndpointMixin, NetBoxModelViewSet):
|
2021-12-17 20:31:15 -05:00
|
|
|
queryset = PowerOutlet.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'_path', 'cable__terminations',
|
2021-12-17 20:31:15 -05:00
|
|
|
)
|
2017-01-26 17:58:36 -05:00
|
|
|
serializer_class = serializers.PowerOutletSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.PowerOutletFilterSet
|
2017-01-26 17:58:36 -05:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class InterfaceViewSet(PathEndpointMixin, NetBoxModelViewSet):
|
2020-10-06 14:30:46 -04:00
|
|
|
queryset = Interface.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'_path', 'cable__terminations',
|
|
|
|
'l2vpn_terminations', # Referenced by InterfaceSerializer.l2vpn_termination
|
|
|
|
'ip_addresses', # Referenced by Interface.count_ipaddresses()
|
|
|
|
'fhrp_group_assignments', # Referenced by Interface.count_fhrp_groups()
|
2020-10-06 14:30:46 -04:00
|
|
|
)
|
2017-01-30 15:35:01 -05:00
|
|
|
serializer_class = serializers.InterfaceSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.InterfaceFilterSet
|
2017-01-26 17:58:36 -05:00
|
|
|
|
2023-11-01 13:47:14 -04:00
|
|
|
def get_bulk_destroy_queryset(self):
|
|
|
|
# Ensure child interfaces are deleted prior to their parents
|
|
|
|
return self.get_queryset().order_by('device', 'parent', CollateAsChar('_name'))
|
|
|
|
|
2017-01-26 17:58:36 -05:00
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class FrontPortViewSet(PassThroughPortMixin, NetBoxModelViewSet):
|
2021-12-17 20:31:15 -05:00
|
|
|
queryset = FrontPort.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'cable__terminations',
|
2021-12-17 20:31:15 -05:00
|
|
|
)
|
2018-10-25 12:08:13 -04:00
|
|
|
serializer_class = serializers.FrontPortSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.FrontPortFilterSet
|
2018-10-03 14:04:16 -04:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class RearPortViewSet(PassThroughPortMixin, NetBoxModelViewSet):
|
2021-12-17 20:31:15 -05:00
|
|
|
queryset = RearPort.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'cable__terminations',
|
2021-12-17 20:31:15 -05:00
|
|
|
)
|
2018-10-25 12:08:13 -04:00
|
|
|
serializer_class = serializers.RearPortSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.RearPortFilterSet
|
2018-10-03 14:04:16 -04:00
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class ModuleBayViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = ModuleBay.objects.all()
|
2021-12-17 09:35:57 -05:00
|
|
|
serializer_class = serializers.ModuleBaySerializer
|
|
|
|
filterset_class = filtersets.ModuleBayFilterSet
|
|
|
|
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class DeviceBayViewSet(NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = DeviceBay.objects.all()
|
2017-01-26 17:58:36 -05:00
|
|
|
serializer_class = serializers.DeviceBaySerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.DeviceBayFilterSet
|
2017-01-26 17:58:36 -05:00
|
|
|
|
|
|
|
|
2023-10-17 07:35:01 -07:00
|
|
|
class InventoryItemViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = InventoryItem.objects.all()
|
2017-03-21 12:54:08 -04:00
|
|
|
serializer_class = serializers.InventoryItemSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.InventoryItemFilterSet
|
2017-01-31 12:19:41 -05:00
|
|
|
|
2016-07-05 13:43:19 -04:00
|
|
|
|
2021-12-27 10:18:39 -05:00
|
|
|
#
|
|
|
|
# Device component roles
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class InventoryItemRoleViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = InventoryItemRole.objects.all()
|
2021-12-27 10:18:39 -05:00
|
|
|
serializer_class = serializers.InventoryItemRoleSerializer
|
|
|
|
filterset_class = filtersets.InventoryItemRoleFilterSet
|
|
|
|
|
|
|
|
|
2018-10-26 12:25:11 -04:00
|
|
|
#
|
|
|
|
# Cables
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class CableViewSet(NetBoxModelViewSet):
|
2022-05-16 15:33:57 -04:00
|
|
|
queryset = Cable.objects.prefetch_related('terminations__termination')
|
2018-10-26 12:25:11 -04:00
|
|
|
serializer_class = serializers.CableSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.CableFilterSet
|
2018-10-26 12:25:11 -04:00
|
|
|
|
|
|
|
|
2022-05-16 16:16:51 -04:00
|
|
|
class CableTerminationViewSet(NetBoxModelViewSet):
|
|
|
|
metadata_class = ContentTypeMetadata
|
2024-02-14 09:28:37 -05:00
|
|
|
queryset = CableTermination.objects.all()
|
2022-05-16 16:16:51 -04:00
|
|
|
serializer_class = serializers.CableTerminationSerializer
|
|
|
|
filterset_class = filtersets.CableTerminationFilterSet
|
|
|
|
|
|
|
|
|
2017-11-17 16:47:26 -05:00
|
|
|
#
|
|
|
|
# Virtual chassis
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class VirtualChassisViewSet(NetBoxModelViewSet):
|
2024-03-13 16:32:55 -04:00
|
|
|
queryset = VirtualChassis.objects.prefetch_related(
|
|
|
|
# Prefetch related object for the display of unnamed devices
|
|
|
|
'master__virtual_chassis',
|
|
|
|
)
|
2017-11-17 16:47:26 -05:00
|
|
|
serializer_class = serializers.VirtualChassisSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.VirtualChassisFilterSet
|
2017-11-17 16:47:26 -05:00
|
|
|
|
|
|
|
|
2019-03-12 11:36:29 -04:00
|
|
|
#
|
|
|
|
# Power panels
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:09:06 -05:00
|
|
|
class PowerPanelViewSet(NetBoxModelViewSet):
|
2024-02-15 14:49:27 -05:00
|
|
|
queryset = PowerPanel.objects.all()
|
2019-03-12 11:36:29 -04:00
|
|
|
serializer_class = serializers.PowerPanelSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.PowerPanelFilterSet
|
2019-03-12 11:36:29 -04:00
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Power feeds
|
|
|
|
#
|
|
|
|
|
2022-03-09 11:44:55 -05:00
|
|
|
class PowerFeedViewSet(PathEndpointMixin, NetBoxModelViewSet):
|
2020-10-06 14:30:46 -04:00
|
|
|
queryset = PowerFeed.objects.prefetch_related(
|
2024-02-14 09:28:37 -05:00
|
|
|
'_path', 'cable__terminations',
|
2020-10-06 14:30:46 -04:00
|
|
|
)
|
2019-03-12 11:36:29 -04:00
|
|
|
serializer_class = serializers.PowerFeedSerializer
|
2021-04-29 16:38:56 -04:00
|
|
|
filterset_class = filtersets.PowerFeedFilterSet
|
2019-03-12 11:36:29 -04:00
|
|
|
|
|
|
|
|
2016-03-01 11:23:03 -05:00
|
|
|
#
|
|
|
|
# Miscellaneous
|
|
|
|
#
|
|
|
|
|
2017-03-09 12:18:53 -05:00
|
|
|
class ConnectedDeviceViewSet(ViewSet):
|
2016-03-01 11:23:03 -05:00
|
|
|
"""
|
2017-03-09 12:18:53 -05:00
|
|
|
This endpoint allows a user to determine what device (if any) is connected to a given peer device and peer
|
|
|
|
interface. This is useful in a situation where a device boots with no configuration, but can detect its neighbors
|
|
|
|
via a protocol such as LLDP. Two query parameters must be included in the request:
|
2017-01-24 17:12:16 -05:00
|
|
|
|
2018-11-06 00:51:55 -05:00
|
|
|
* `peer_device`: The name of the peer device
|
|
|
|
* `peer_interface`: The name of the peer interface
|
2017-03-09 12:18:53 -05:00
|
|
|
"""
|
2017-08-02 11:17:57 -04:00
|
|
|
permission_classes = [IsAuthenticatedOrLoginNotRequired]
|
2023-03-30 11:32:59 -07:00
|
|
|
_device_param = OpenApiParameter(
|
2018-11-06 11:44:32 -05:00
|
|
|
name='peer_device',
|
2023-03-30 11:32:59 -07:00
|
|
|
location='query',
|
2018-11-06 11:44:32 -05:00
|
|
|
description='The name of the peer device',
|
|
|
|
required=True,
|
2023-03-30 11:32:59 -07:00
|
|
|
type=OpenApiTypes.STR
|
2018-11-06 11:44:32 -05:00
|
|
|
)
|
2023-03-30 11:32:59 -07:00
|
|
|
_interface_param = OpenApiParameter(
|
2018-11-06 11:44:32 -05:00
|
|
|
name='peer_interface',
|
2023-03-30 11:32:59 -07:00
|
|
|
location='query',
|
2018-11-06 11:44:32 -05:00
|
|
|
description='The name of the peer interface',
|
|
|
|
required=True,
|
2023-03-30 11:32:59 -07:00
|
|
|
type=OpenApiTypes.STR
|
2018-11-06 11:44:32 -05:00
|
|
|
)
|
2023-03-30 11:32:59 -07:00
|
|
|
serializer_class = serializers.DeviceSerializer
|
2017-01-24 17:12:16 -05:00
|
|
|
|
2017-03-20 21:54:01 -04:00
|
|
|
def get_view_name(self):
|
|
|
|
return "Connected Device Locator"
|
|
|
|
|
2023-06-14 15:45:07 +05:30
|
|
|
@extend_schema(
|
|
|
|
parameters=[_device_param, _interface_param],
|
|
|
|
responses={200: serializers.DeviceSerializer}
|
|
|
|
)
|
2017-03-09 12:18:53 -05:00
|
|
|
def list(self, request):
|
2016-08-22 17:15:20 -04:00
|
|
|
|
2018-03-16 16:48:08 -04:00
|
|
|
peer_device_name = request.query_params.get(self._device_param.name)
|
|
|
|
peer_interface_name = request.query_params.get(self._interface_param.name)
|
2018-11-06 11:44:32 -05:00
|
|
|
|
2017-03-09 12:18:53 -05:00
|
|
|
if not peer_device_name or not peer_interface_name:
|
2018-11-06 00:51:55 -05:00
|
|
|
raise MissingFilterException(detail='Request must include "peer_device" and "peer_interface" filters.')
|
2016-03-01 11:23:03 -05:00
|
|
|
|
2021-10-07 13:15:59 -04:00
|
|
|
# Determine local endpoint from peer interface's connection
|
|
|
|
peer_device = get_object_or_404(
|
|
|
|
Device.objects.restrict(request.user, 'view'),
|
|
|
|
name=peer_device_name
|
|
|
|
)
|
2020-06-29 14:41:43 -04:00
|
|
|
peer_interface = get_object_or_404(
|
2021-10-07 13:15:59 -04:00
|
|
|
Interface.objects.restrict(request.user, 'view'),
|
|
|
|
device=peer_device,
|
2020-06-29 14:41:43 -04:00
|
|
|
name=peer_interface_name
|
|
|
|
)
|
2022-05-13 16:23:44 -04:00
|
|
|
endpoints = peer_interface.connected_endpoints
|
2016-03-01 11:23:03 -05:00
|
|
|
|
2021-10-07 13:15:59 -04:00
|
|
|
# If an Interface, return the parent device
|
2022-05-13 16:23:44 -04:00
|
|
|
if endpoints and type(endpoints[0]) is Interface:
|
2021-10-07 13:15:59 -04:00
|
|
|
device = get_object_or_404(
|
|
|
|
Device.objects.restrict(request.user, 'view'),
|
2022-05-13 16:23:44 -04:00
|
|
|
pk=endpoints[0].device_id
|
2021-10-07 13:15:59 -04:00
|
|
|
)
|
|
|
|
return Response(serializers.DeviceSerializer(device, context={'request': request}).data)
|
2016-03-01 11:23:03 -05:00
|
|
|
|
2021-10-07 13:15:59 -04:00
|
|
|
# Connected endpoint is none or not an Interface
|
|
|
|
raise Http404
|