Quellcode durchsuchen

Closes #3485: Enable embedded graphs for devices

Jeremy Stretch vor 6 Jahren
Ursprung
Commit
51fb0b59ec

+ 1 - 0
CHANGELOG.md

@@ -6,6 +6,7 @@ v2.6.4 (FUTURE)
 * [#3027](https://github.com/netbox-community/netbox/issues/3028) - Add `local_context_data` boolean filter for devices
 * [#3318](https://github.com/netbox-community/netbox/issues/3318) - Increase length of platform name and slug to 100 characters
 * [#3341](https://github.com/netbox-community/netbox/issues/3341) - Enable inline VLAN assignment while editing an interface
+* [#3485](https://github.com/netbox-community/netbox/issues/3485) - Enable embedded graphs for devices
 * [#3510](https://github.com/netbox-community/netbox/issues/3510) - Add minimum/maximum prefix length enforcement for `IPNetworkVar`
 
 ## Bug Fixes

+ 1 - 1
netbox/circuits/api/views.py

@@ -35,7 +35,7 @@ class ProviderViewSet(CustomFieldModelViewSet):
     filterset_class = filters.ProviderFilter
 
     @action(detail=True)
-    def graphs(self, request, pk=None):
+    def graphs(self, request, pk):
         """
         A convenience method for rendering graphs for a particular provider.
         """

+ 15 - 3
netbox/dcim/api/views.py

@@ -23,7 +23,8 @@ from dcim.models import (
 )
 from extras.api.serializers import RenderedGraphSerializer
 from extras.api.views import CustomFieldModelViewSet
-from extras.models import Graph, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
+from extras.constants import GRAPH_TYPE_DEVICE, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
+from extras.models import Graph
 from ipam.models import Prefix, VLAN
 from utilities.api import (
     get_serializer_for_model, IsAuthenticatedOrLoginNotRequired, FieldChoicesViewSet, ModelViewSet, ServiceUnavailable,
@@ -123,7 +124,7 @@ class SiteViewSet(CustomFieldModelViewSet):
     filterset_class = filters.SiteFilter
 
     @action(detail=True)
-    def graphs(self, request, pk=None):
+    def graphs(self, request, pk):
         """
         A convenience method for rendering graphs for a particular site.
         """
@@ -346,6 +347,17 @@ class DeviceViewSet(CustomFieldModelViewSet):
 
         return serializers.DeviceWithConfigContextSerializer
 
+    @action(detail=True)
+    def graphs(self, request, pk):
+        """
+        A convenience method for rendering graphs for a particular Device.
+        """
+        device = get_object_or_404(Device, pk=pk)
+        queryset = Graph.objects.filter(type=GRAPH_TYPE_DEVICE)
+        serializer = RenderedGraphSerializer(queryset, many=True, context={'graphed_object': device})
+
+        return Response(serializer.data)
+
     @action(detail=True, url_path='napalm')
     def napalm(self, request, pk):
         """
@@ -458,7 +470,7 @@ class InterfaceViewSet(CableTraceMixin, ModelViewSet):
     filterset_class = filters.InterfaceFilter
 
     @action(detail=True)
-    def graphs(self, request, pk=None):
+    def graphs(self, request, pk):
         """
         A convenience method for rendering graphs for a particular interface.
         """

+ 4 - 5
netbox/dcim/views.py

@@ -16,7 +16,8 @@ from django.utils.safestring import mark_safe
 from django.views.generic import View
 
 from circuits.models import Circuit
-from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
+from extras.constants import GRAPH_TYPE_DEVICE, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
+from extras.models import Graph, TopologyMap
 from extras.views import ObjectConfigContextView
 from ipam.models import Prefix, VLAN
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
@@ -972,9 +973,6 @@ class DeviceView(PermissionRequiredMixin, View):
             'rack', 'device_type__manufacturer'
         )[:10]
 
-        # Show graph button on interfaces only if at least one graph has been created.
-        show_graphs = Graph.objects.filter(type=GRAPH_TYPE_INTERFACE).exists()
-
         return render(request, 'dcim/device.html', {
             'device': device,
             'console_ports': console_ports,
@@ -989,7 +987,8 @@ class DeviceView(PermissionRequiredMixin, View):
             'secrets': secrets,
             'vc_members': vc_members,
             'related_devices': related_devices,
-            'show_graphs': show_graphs,
+            'show_graphs': Graph.objects.filter(type=GRAPH_TYPE_DEVICE).exists(),
+            'show_interface_graphs': Graph.objects.filter(type=GRAPH_TYPE_INTERFACE).exists(),
         })
 
 

+ 2 - 0
netbox/extras/constants.py

@@ -88,10 +88,12 @@ BUTTON_CLASS_CHOICES = (
 
 # Graph types
 GRAPH_TYPE_INTERFACE = 100
+GRAPH_TYPE_DEVICE = 150
 GRAPH_TYPE_PROVIDER = 200
 GRAPH_TYPE_SITE = 300
 GRAPH_TYPE_CHOICES = (
     (GRAPH_TYPE_INTERFACE, 'Interface'),
+    (GRAPH_TYPE_DEVICE, 'Device'),
     (GRAPH_TYPE_PROVIDER, 'Provider'),
     (GRAPH_TYPE_SITE, 'Site'),
 )

+ 6 - 0
netbox/templates/dcim/device.html

@@ -35,6 +35,12 @@
         </div>
     </div>
     <div class="pull-right noprint">
+        {% if show_graphs %}
+            <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#graphs_modal" data-obj="{{ device.name }}" data-url="{% url 'dcim-api:device-graphs' pk=device.pk %}" title="Show graphs">
+                <i class="fa fa-signal" aria-hidden="true"></i>
+                Graphs
+            </button>
+        {% endif %}
         {% if perms.dcim.change_device %}
             <div class="btn-group">
                 <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">

+ 1 - 1
netbox/templates/dcim/inc/interface.html

@@ -135,7 +135,7 @@
 
     {# Buttons #}
     <td class="text-right text-nowrap noprint">
-        {% if show_graphs %}
+        {% if show_interface_graphs %}
             {% if iface.connected_endpoint %}
                 <button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#graphs_modal" data-obj="{{ device.name }} - {{ iface.name }}" data-url="{% url 'dcim-api:interface-graphs' pk=iface.pk %}" title="Show graphs">
                     <i class="glyphicon glyphicon-signal" aria-hidden="true"></i>