1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Initial work on a dynamic topology mapper

This commit is contained in:
Jeremy Stretch
2016-04-08 11:48:24 -04:00
parent 2cb99c6012
commit 42e16db8b4
2 changed files with 66 additions and 3 deletions

View File

@ -1,7 +1,7 @@
from django.conf.urls import url
from extras.models import GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
from extras.api.views import GraphListView
from extras.api.views import GraphListView, TopologyMapperView
from .views import *
@ -62,5 +62,6 @@ urlpatterns = [
# Miscellaneous
url(r'^related-connections/$', RelatedConnectionsView.as_view(), name='related_connections'),
url(r'^topology-mapper/$', TopologyMapperView.as_view(), name='topology_mapper'),
]

View File

@ -1,10 +1,15 @@
import pydot
from rest_framework import generics
from rest_framework.views import APIView
import tempfile
from wsgiref.util import FileWrapper
from django.http import Http404
from django.db.models import Q
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404
from circuits.models import Provider
from dcim.models import Site, Interface
from dcim.models import Site, Device, Interface, InterfaceConnection
from extras.models import Graph, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_PROVIDER, GRAPH_TYPE_SITE
from .serializers import GraphSerializer
@ -31,3 +36,60 @@ class GraphListView(generics.ListAPIView):
raise Http404()
queryset = Graph.objects.filter(type=graph_type)
return queryset
class TopologyMapperView(APIView):
"""
Generate a topology diagram
"""
def get(self, request):
# Glean device sets to map. Each set is represented as a hierarchical tier in the diagram.
device_sets = request.GET.getlist('devices', [])
# Construct the graph
graph = pydot.Dot(graph_type='graph', ranksep='1')
for i, device_set in enumerate(device_sets):
subgraph = pydot.Subgraph('sg{}'.format(i), rank='same')
# Add a pseudonode for each device_set to enforce hierarchical layout
subgraph.add_node(pydot.Node('set{}'.format(i), shape='none'))
if i:
graph.add_edge(pydot.Edge('set{}'.format(i - 1), 'set{}'.format(i), style='invis'))
# Add each device to the graph
devices = Device.objects.filter(name__regex=device_set)
for d in devices:
node = pydot.Node(d.name)
subgraph.add_node(node)
# Add an invisible connection to each successive device in a set to enforce horizontal order
for j in range(0, len(devices) - 1):
edge = pydot.Edge(devices[j].name, devices[j + 1].name)
# edge.set('style', 'invis') doesn't seem to work for some reason
edge.set_style('invis')
subgraph.add_edge(edge)
graph.add_subgraph(subgraph)
# Compile list of all devices
device_superset = Q()
for regex in device_sets:
device_superset = device_superset | Q(name__regex=regex)
# Add all connections to the graph
devices = Device.objects.filter(*(device_superset,))
connections = InterfaceConnection.objects.filter(interface_a__device__in=devices, interface_b__device__in=devices)
for c in connections:
edge = pydot.Edge(c.interface_a.device.name, c.interface_b.device.name)
graph.add_edge(edge)
# Write the image to disk and return
topo_file = tempfile.NamedTemporaryFile()
graph.write(topo_file.name, format='png')
response = HttpResponse(FileWrapper(topo_file), content_type='image/png')
topo_file.close()
return response