Browse Source

Add REST API endpoint for CableTermination

jeremystretch 3 years ago
parent
commit
9ef9443969

+ 2 - 2
netbox/circuits/filtersets.py

@@ -1,7 +1,7 @@
 import django_filters
 from django.db.models import Q
 
-from dcim.filtersets import CableTerminationFilterSet
+from dcim.filtersets import CabledObjectFilterSet
 from dcim.models import Region, Site, SiteGroup
 from ipam.models import ASN
 from netbox.filtersets import ChangeLoggedModelFilterSet, NetBoxModelFilterSet, OrganizationalModelFilterSet
@@ -198,7 +198,7 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
         ).distinct()
 
 
-class CircuitTerminationFilterSet(ChangeLoggedModelFilterSet, CableTerminationFilterSet):
+class CircuitTerminationFilterSet(ChangeLoggedModelFilterSet, CabledObjectFilterSet):
     q = django_filters.CharFilter(
         method='search',
         label='Search',

+ 20 - 0
netbox/dcim/api/serializers.py

@@ -1061,6 +1061,26 @@ class TracedCableSerializer(serializers.ModelSerializer):
         ]
 
 
+class CableTerminationSerializer(NetBoxModelSerializer):
+    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail')
+    termination_type = ContentTypeField(
+        queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)
+    )
+    termination = serializers.SerializerMethodField(read_only=True)
+
+    class Meta:
+        model = CableTermination
+        fields = [
+            'id', 'url', 'display', 'cable', 'cable_end', 'termination_type', 'termination_id', 'termination'
+        ]
+
+    @swagger_serializer_method(serializer_or_field=serializers.DictField)
+    def get_termination(self, obj):
+        serializer = get_serializer_for_model(obj.termination, prefix='Nested')
+        context = {'request': self.context['request']}
+        return serializer(obj.termination, context=context).data
+
+
 class CablePathSerializer(serializers.ModelSerializer):
     origin_type = ContentTypeField(read_only=True)
     origin = serializers.SerializerMethodField(read_only=True)

+ 1 - 0
netbox/dcim/api/urls.py

@@ -56,6 +56,7 @@ router.register('inventory-item-roles', views.InventoryItemRoleViewSet)
 
 # Cables
 router.register('cables', views.CableViewSet)
+router.register('cable-terminations', views.CableTerminationViewSet)
 
 # Virtual chassis
 router.register('virtual-chassis', views.VirtualChassisViewSet)

+ 7 - 1
netbox/dcim/api/views.py

@@ -646,12 +646,18 @@ class InventoryItemRoleViewSet(NetBoxModelViewSet):
 #
 
 class CableViewSet(NetBoxModelViewSet):
-    metadata_class = ContentTypeMetadata
     queryset = Cable.objects.prefetch_related('terminations__termination')
     serializer_class = serializers.CableSerializer
     filterset_class = filtersets.CableFilterSet
 
 
+class CableTerminationViewSet(NetBoxModelViewSet):
+    metadata_class = ContentTypeMetadata
+    queryset = CableTermination.objects.prefetch_related('cable', 'termination')
+    serializer_class = serializers.CableTerminationSerializer
+    filterset_class = filtersets.CableTerminationFilterSet
+
+
 #
 # Virtual chassis
 #

+ 17 - 9
netbox/dcim/filtersets.py

@@ -21,6 +21,7 @@ from .models import *
 
 __all__ = (
     'CableFilterSet',
+    'CabledObjectFilterSet',
     'CableTerminationFilterSet',
     'ConsoleConnectionFilterSet',
     'ConsolePortFilterSet',
@@ -1107,7 +1108,7 @@ class ModularDeviceComponentFilterSet(DeviceComponentFilterSet):
     )
 
 
-class CableTerminationFilterSet(django_filters.FilterSet):
+class CabledObjectFilterSet(django_filters.FilterSet):
     cabled = django_filters.BooleanFilter(
         field_name='cable',
         lookup_expr='isnull',
@@ -1130,7 +1131,7 @@ class PathEndpointFilterSet(django_filters.FilterSet):
 class ConsolePortFilterSet(
     ModularDeviceComponentFilterSet,
     NetBoxModelFilterSet,
-    CableTerminationFilterSet,
+    CabledObjectFilterSet,
     PathEndpointFilterSet
 ):
     type = django_filters.MultipleChoiceFilter(
@@ -1146,7 +1147,7 @@ class ConsolePortFilterSet(
 class ConsoleServerPortFilterSet(
     ModularDeviceComponentFilterSet,
     NetBoxModelFilterSet,
-    CableTerminationFilterSet,
+    CabledObjectFilterSet,
     PathEndpointFilterSet
 ):
     type = django_filters.MultipleChoiceFilter(
@@ -1162,7 +1163,7 @@ class ConsoleServerPortFilterSet(
 class PowerPortFilterSet(
     ModularDeviceComponentFilterSet,
     NetBoxModelFilterSet,
-    CableTerminationFilterSet,
+    CabledObjectFilterSet,
     PathEndpointFilterSet
 ):
     type = django_filters.MultipleChoiceFilter(
@@ -1178,7 +1179,7 @@ class PowerPortFilterSet(
 class PowerOutletFilterSet(
     ModularDeviceComponentFilterSet,
     NetBoxModelFilterSet,
-    CableTerminationFilterSet,
+    CabledObjectFilterSet,
     PathEndpointFilterSet
 ):
     type = django_filters.MultipleChoiceFilter(
@@ -1198,7 +1199,7 @@ class PowerOutletFilterSet(
 class InterfaceFilterSet(
     ModularDeviceComponentFilterSet,
     NetBoxModelFilterSet,
-    CableTerminationFilterSet,
+    CabledObjectFilterSet,
     PathEndpointFilterSet
 ):
     # Override device and device_id filters from DeviceComponentFilterSet to match against any peer virtual chassis
@@ -1326,7 +1327,7 @@ class InterfaceFilterSet(
 class FrontPortFilterSet(
     ModularDeviceComponentFilterSet,
     NetBoxModelFilterSet,
-    CableTerminationFilterSet
+    CabledObjectFilterSet
 ):
     type = django_filters.MultipleChoiceFilter(
         choices=PortTypeChoices,
@@ -1341,7 +1342,7 @@ class FrontPortFilterSet(
 class RearPortFilterSet(
     ModularDeviceComponentFilterSet,
     NetBoxModelFilterSet,
-    CableTerminationFilterSet
+    CabledObjectFilterSet
 ):
     type = django_filters.MultipleChoiceFilter(
         choices=PortTypeChoices,
@@ -1552,6 +1553,13 @@ class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
         return queryset
 
 
+class CableTerminationFilterSet(BaseFilterSet):
+
+    class Meta:
+        model = CableTermination
+        fields = ['id', 'cable', 'cable_end', 'termination_type', 'termination_id']
+
+
 class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
     region_id = TreeNodeMultipleChoiceFilter(
         queryset=Region.objects.all(),
@@ -1609,7 +1617,7 @@ class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
         return queryset.filter(qs_filter)
 
 
-class PowerFeedFilterSet(NetBoxModelFilterSet, CableTerminationFilterSet, PathEndpointFilterSet):
+class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
     region_id = TreeNodeMultipleChoiceFilter(
         queryset=Region.objects.all(),
         field_name='power_panel__site__region',

+ 3 - 0
netbox/dcim/models/cables.py

@@ -13,6 +13,7 @@ from dcim.fields import PathField
 from dcim.utils import decompile_path_node, flatten_path, object_to_path_node, path_node_to_object
 from netbox.models import NetBoxModel
 from utilities.fields import ColorField
+from utilities.querysets import RestrictedQuerySet
 from utilities.utils import to_meters
 from wireless.models import WirelessLink
 from .devices import Device
@@ -222,6 +223,8 @@ class CableTermination(models.Model):
         fk_field='termination_id'
     )
 
+    objects = RestrictedQuerySet.as_manager()
+
     class Meta:
         ordering = ['pk']
         constraints = (