From 51fb0b59ec90bc324fb3ba9af08a8a0d5dea1e05 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 18 Sep 2019 15:59:52 -0400 Subject: [PATCH] Closes #3485: Enable embedded graphs for devices --- CHANGELOG.md | 1 + netbox/circuits/api/views.py | 2 +- netbox/dcim/api/views.py | 18 +++++++++++++++--- netbox/dcim/views.py | 9 ++++----- netbox/extras/constants.py | 2 ++ netbox/templates/dcim/device.html | 6 ++++++ netbox/templates/dcim/inc/interface.html | 2 +- 7 files changed, 30 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7986d5afe..3bbb83fe7 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/netbox/circuits/api/views.py b/netbox/circuits/api/views.py index dc1133c5e..65b0db14b 100644 --- a/netbox/circuits/api/views.py +++ b/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. """ diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 4ddee7337..12774e4be 100644 --- a/netbox/dcim/api/views.py +++ b/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. """ diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index f953f95c2..301d05e84 100644 --- a/netbox/dcim/views.py +++ b/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(), }) diff --git a/netbox/extras/constants.py b/netbox/extras/constants.py index b72ae8c08..d136d3271 100644 --- a/netbox/extras/constants.py +++ b/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'), ) diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index dca3e60a6..57e2b03b8 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -35,6 +35,12 @@
+ {% if show_graphs %} + + {% endif %} {% if perms.dcim.change_device %}