Browse Source

Replaced RelatedConnectionsView with views.ConnectedDeviceViewSet

Jeremy Stretch 8 years ago
parent
commit
ddec424429
2 changed files with 25 additions and 73 deletions
  1. 4 3
      netbox/dcim/api/urls.py
  2. 21 70
      netbox/dcim/api/views.py

+ 4 - 3
netbox/dcim/api/urls.py

@@ -48,11 +48,12 @@ router.register(r'services', ServiceViewSet)
 # Interface connections
 router.register(r'interface-connections', views.InterfaceConnectionViewSet)
 
+# Miscellaneous
+router.register(r'connected-device', views.ConnectedDeviceViewSet, base_name='connected-device')
+
+
 urlpatterns = [
 
     url(r'', include(router.urls)),
 
-    # Miscellaneous
-    url(r'^related-connections/$', views.RelatedConnectionsView.as_view(), name='related_connections'),
-
 ]

+ 21 - 70
netbox/dcim/api/views.py

@@ -1,8 +1,9 @@
 from rest_framework.decorators import detail_route
+from rest_framework.permissions import IsAuthenticated
 from rest_framework.response import Response
 from rest_framework.settings import api_settings
 from rest_framework.views import APIView
-from rest_framework.viewsets import ModelViewSet
+from rest_framework.viewsets import ModelViewSet, ViewSet
 
 from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
@@ -314,79 +315,29 @@ class InterfaceConnectionViewSet(WritableSerializerMixin, ModelViewSet):
 # Miscellaneous
 #
 
-class RelatedConnectionsView(APIView):
+class ConnectedDeviceViewSet(ViewSet):
     """
-    Retrieve all connections related to a given console/power/interface connection
-    """
-
-    def __init__(self):
-        super(RelatedConnectionsView, self).__init__()
-
-        # Custom fields
-        content_type = ContentType.objects.get_for_model(Device)
-        custom_fields = content_type.custom_fields.prefetch_related('choices')
+    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:
 
-        # 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
+    * `peer-device`: The name of the peer device
+    * `peer-interface`: The name of the peer interface
+    """
+    permission_classes = [IsAuthenticated]
 
-        self.context = {
-            'custom_fields': custom_fields,
-            'custom_field_choices': custom_field_choices,
-        }
+    def list(self, request):
 
-    def get(self, request):
+        peer_device_name = request.query_params.get('peer-device')
+        peer_interface_name = request.query_params.get('peer-interface')
+        if not peer_device_name or not peer_interface_name:
+            raise MissingFilterException(detail='Request must include "peer-device" and "peer-interface" filters.')
 
-        peer_device = request.GET.get('peer-device')
-        peer_interface = request.GET.get('peer-interface')
+        # Determine local interface from peer interface's connection
+        peer_interface = get_object_or_404(Interface, device__name=peer_device_name, name=peer_interface_name)
+        local_interface = peer_interface.connected_interface
 
-        # Search by interface
-        if peer_device and peer_interface:
+        if local_interface is None:
+            return Response()
 
-            # 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
-            if local_iface:
-                device = local_iface.device
-            else:
-                return Response()
-
-        else:
-            raise MissingFilterException(detail='Must specify search parameters "peer-device" and "peer-interface".')
-
-        # Initialize response skeleton
-        response = {
-            'device': serializers.DeviceSerializer(device, context=self.context).data,
-            'console-ports': [],
-            'power-ports': [],
-            'interfaces': [],
-        }
-
-        # Console connections
-        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)
-
-        # Power connections
-        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)
-
-        # 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')
-        for iface in interfaces:
-            data = serializers.InterfaceSerializer(instance=iface).data
-            del(data['device'])
-            response['interfaces'].append(data)
-
-        return Response(response)
+        return Response(serializers.DeviceSerializer(local_interface.device, context={'request': request}).data)