Update to support netbox v3.1 (#82)
* init for v3.1 * added coords + bump version * fix filter + added preselected roles * added draw_default_layout * upgraded packages * fixed edge/node labels * fixed enable_circuit_terminations * added filter for unconnected devices * added ignore_cable_type * fixed old settings using a string instead of array * removed distutils * fixed coords check * added coor saving * added doc img * updated docs * bump version * bump version
This commit is contained in:
@@ -3,18 +3,6 @@ from rest_framework.serializers import ModelSerializer
|
||||
from dcim.models import DeviceRole, Device
|
||||
from extras.models import Tag
|
||||
|
||||
class PreDeviceRoleSerializer(ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = DeviceRole
|
||||
fields = ('id', 'name')
|
||||
|
||||
class PreTagSerializer(ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = ('id', 'name')
|
||||
|
||||
|
||||
class TopologyDummySerializer(ModelSerializer):
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
from netbox.api import OrderedDefaultRouter
|
||||
from rest_framework import routers
|
||||
from . import views
|
||||
|
||||
router = OrderedDefaultRouter()
|
||||
router.APIRootView = views.TopologyViewsRootView
|
||||
router = routers.DefaultRouter()
|
||||
|
||||
|
||||
router.register('preselectdeviceroles', views.PreSelectDeviceRolesViewSet)
|
||||
router.register('preselecttags', views.PreSelectTagsViewSet)
|
||||
router.register('search', views.SearchViewSet, basename='search')
|
||||
router.register('save-coords', views.SaveCoordsViewSet, basename='save_coords')
|
||||
|
||||
urlpatterns = router.urls
|
||||
@@ -4,7 +4,7 @@ from rest_framework.response import Response
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from rest_framework.routers import APIRootView
|
||||
|
||||
from .serializers import PreDeviceRoleSerializer, TopologyDummySerializer, PreTagSerializer
|
||||
from .serializers import TopologyDummySerializer
|
||||
from django.conf import settings
|
||||
|
||||
from dcim.models import DeviceRole, Device, Cable
|
||||
@@ -12,26 +12,10 @@ from circuits.models import Circuit
|
||||
from extras.models import Tag
|
||||
|
||||
|
||||
ignore_cable_type_raw = settings.PLUGINS_CONFIG["netbox_topology_views"]["ignore_cable_type"]
|
||||
ignore_cable_type = ignore_cable_type_raw.split(",")
|
||||
|
||||
preselected_device_roles_raw = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_device_roles"]
|
||||
preselected_device_roles = preselected_device_roles_raw.split(",")
|
||||
|
||||
preselected_tags_raw = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_tags"]
|
||||
preselected_tags = preselected_tags_raw.split(",")
|
||||
|
||||
class TopologyViewsRootView(APIRootView):
|
||||
def get_view_name(self):
|
||||
return 'TopologyViews'
|
||||
|
||||
class PreSelectDeviceRolesViewSet(ReadOnlyModelViewSet):
|
||||
queryset = DeviceRole.objects.filter(name__in=preselected_device_roles)
|
||||
serializer_class = PreDeviceRoleSerializer
|
||||
|
||||
class PreSelectTagsViewSet(ReadOnlyModelViewSet):
|
||||
queryset = Tag.objects.filter(name__in=preselected_tags)
|
||||
serializer_class = PreTagSerializer
|
||||
|
||||
class SaveCoordsViewSet(ReadOnlyModelViewSet):
|
||||
queryset = Device.objects.all()
|
||||
@@ -74,200 +58,3 @@ class SaveCoordsViewSet(ReadOnlyModelViewSet):
|
||||
results["status"] = "not allowed to save coords"
|
||||
return Response(results, status=500)
|
||||
|
||||
class SearchViewSet(ReadOnlyModelViewSet):
|
||||
queryset = Device.objects.all()
|
||||
serializer_class = TopologyDummySerializer
|
||||
|
||||
def _filter(self, site, role, name, tags, region, location):
|
||||
filter_devices = Device.objects.all()
|
||||
if name is not None:
|
||||
filter_devices = filter_devices.filter(name__contains=name)
|
||||
if site is not None:
|
||||
filter_devices = filter_devices.filter(site__id__in=site)
|
||||
if role is not None:
|
||||
filter_devices = filter_devices.filter(device_role__id__in=role)
|
||||
if tags is not None:
|
||||
filter_devices = filter_devices.filter(tags__id__in=tags)
|
||||
if region is not None:
|
||||
filter_devices = filter_devices.filter(site__region__id__in=region)
|
||||
if location is not None:
|
||||
filter_devices = filter_devices.filter(location__id__in=location)
|
||||
return filter_devices
|
||||
|
||||
|
||||
@action(detail=False, methods=['get'])
|
||||
def search(self, request):
|
||||
name = request.query_params.get('name', None)
|
||||
if name == "":
|
||||
name = None
|
||||
|
||||
sites = request.query_params.getlist('sites[]', None)
|
||||
if sites == []:
|
||||
sites = None
|
||||
|
||||
devicerole = request.query_params.getlist('devicerole[]', None)
|
||||
if devicerole == []:
|
||||
devicerole = None
|
||||
|
||||
tags = request.query_params.getlist('tags[]', None)
|
||||
if tags == []:
|
||||
tags = None
|
||||
|
||||
regions = request.query_params.getlist('regions[]', None)
|
||||
if regions == []:
|
||||
regions = None
|
||||
|
||||
locations = request.query_params.getlist('locations[]', None)
|
||||
if locations == []:
|
||||
locations = None
|
||||
|
||||
hide_unconnected = request.query_params.get('hide_unconnected', None)
|
||||
if hide_unconnected == "":
|
||||
hide_unconnected = None
|
||||
|
||||
devices = self._filter(sites, devicerole, name, tags, regions, locations)
|
||||
|
||||
nodes = []
|
||||
edges = []
|
||||
edge_ids = 0
|
||||
cable_ids = []
|
||||
circuit_ids = []
|
||||
for device in devices:
|
||||
cables = device.get_cables()
|
||||
if cables.exists():
|
||||
device_has_connections = True
|
||||
for cable in cables:
|
||||
if cable.termination_a_type.name != "circuit termination" and cable.termination_b_type.name != "circuit termination":
|
||||
if cable.id not in cable_ids:
|
||||
if cable.termination_a_type.name not in ignore_cable_type and cable.termination_b_type.name not in ignore_cable_type:
|
||||
cable_ids.append(cable.id)
|
||||
edge_ids += 1
|
||||
|
||||
cable_a_dev_name = cable.termination_a.device.name
|
||||
if cable_a_dev_name is None:
|
||||
cable_a_dev_name = "device A name unknown"
|
||||
cable_a_name = cable.termination_a.name
|
||||
if cable_a_name is None:
|
||||
cable_a_name = "cable A name unknown"
|
||||
cable_b_dev_name = cable.termination_b.device.name
|
||||
if cable_b_dev_name is None:
|
||||
cable_b_dev_name = "device B name unknown"
|
||||
cable_b_name = cable.termination_b.name
|
||||
if cable_b_name is None:
|
||||
cable_b_name = "cable B name unknown"
|
||||
|
||||
edge = {}
|
||||
edge["id"] = edge_ids
|
||||
edge["from"] = cable.termination_a.device.id
|
||||
edge["to"] = cable.termination_b.device.id
|
||||
edge["title"] = "Cable between <br> " + cable_a_dev_name + " [" + cable_a_name + "]<br>" + cable_b_dev_name + " [" + cable_b_name + "]"
|
||||
if cable.color != "":
|
||||
edge["color"] = "#" + cable.color
|
||||
edges.append(edge)
|
||||
else:
|
||||
if cable.termination_a_type.name == "circuit termination":
|
||||
if settings.PLUGINS_CONFIG["netbox_topology_views"]["enable_circuit_terminations"]:
|
||||
if cable.termination_a.circuit.id not in circuit_ids:
|
||||
circuit_ids.append(cable.termination_a.circuit.id)
|
||||
edge_ids += 1
|
||||
|
||||
cable_b_dev_name = cable.termination_b.device.name
|
||||
if cable_b_dev_name is None:
|
||||
cable_b_dev_name = "device B name unknown"
|
||||
cable_b_name = cable.termination_b.name
|
||||
if cable_b_name is None:
|
||||
cable_b_name = "cable B name unknown"
|
||||
|
||||
edge = {}
|
||||
edge["id"] = edge_ids
|
||||
edge["to"] = cable.termination_b.device.id
|
||||
edge["dashes"] = True
|
||||
title = ""
|
||||
|
||||
title += "Circuit provider: " + cable.termination_a.circuit.provider.name + "<br>"
|
||||
title += "Termination between <br>"
|
||||
title += cable_b_dev_name + " [" + cable_b_name + "]<br>"
|
||||
# To Many if's
|
||||
if cable.termination_a.circuit.termination_a is not None:
|
||||
if cable.termination_a.circuit.termination_a.cable is not None:
|
||||
if cable.termination_a.circuit.termination_a.cable.id != cable.id:
|
||||
if cable.termination_a.circuit.termination_a.cable.termination_b is not None:
|
||||
if cable.termination_a.circuit.termination_a.cable.termination_b.device is not None:
|
||||
edge["from"] = cable.termination_a.circuit.termination_a.cable.termination_b.device.id
|
||||
|
||||
cable_a_dev_name = cable.termination_a.circuit.termination_a.cable.termination_b.device.name
|
||||
if cable_a_dev_name is None:
|
||||
cable_a_dev_name = "device B name unknown"
|
||||
cable_b_name = cable.termination_a.circuit.termination_a.cable.termination_b.name
|
||||
if cable_a_name is None:
|
||||
cable_a_name = "cable B name unknown"
|
||||
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
|
||||
edge["title"] = title
|
||||
edges.append(edge)
|
||||
# To Many if's
|
||||
if cable.termination_a.circuit.termination_z is not None:
|
||||
if cable.termination_a.circuit.termination_z.cable is not None:
|
||||
if cable.termination_a.circuit.termination_z.cable.id != cable.id:
|
||||
if cable.termination_a.circuit.termination_z.cable.termination_b is not None:
|
||||
if cable.termination_a.circuit.termination_z.cable.termination_b.device is not None:
|
||||
edge["from"] = cable.termination_a.circuit.termination_z.cable.termination_b.device.id
|
||||
|
||||
cable_a_dev_name = cable.termination_a.circuit.termination_z.cable.termination_b.device.name
|
||||
if cable_a_dev_name is None:
|
||||
cable_a_dev_name = "device B name unknown"
|
||||
cable_a_name = cable.termination_a.circuit.termination_z.cable.termination_b.name
|
||||
if cable_a_name is None:
|
||||
cable_a_name = "cable B name unknown"
|
||||
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
|
||||
edge["title"] = title
|
||||
edges.append(edge)
|
||||
else:
|
||||
device_has_connections = False
|
||||
|
||||
if hide_unconnected == 'false' or (hide_unconnected == 'true' and device_has_connections is True):
|
||||
dev_name = device.name
|
||||
if dev_name is None:
|
||||
dev_name = "device name unknown"
|
||||
|
||||
node_content = ""
|
||||
|
||||
if device.device_type.display_name is not None:
|
||||
node_content += "<tr><th>Type: </th><td>" + device.device_type.display_name + "</td></tr>"
|
||||
if device.device_role.name is not None:
|
||||
node_content += "<tr><th>Role: </th><td>" + device.device_role.name + "</td></tr>"
|
||||
if device.serial != "":
|
||||
node_content += "<tr><th>Serial: </th><td>" + device.serial + "</td></tr>"
|
||||
if device.primary_ip is not None:
|
||||
node_content += "<tr><th>IP Address: </th><td>" + str(device.primary_ip.address) + "</td></tr>"
|
||||
|
||||
dev_title = "<table> %s </table>" % (node_content)
|
||||
|
||||
node = {}
|
||||
node["id"] = device.id
|
||||
node["name"] = dev_name
|
||||
node["label"] = dev_name
|
||||
node["title"] = dev_title
|
||||
node["shape"] = 'image'
|
||||
if device.device_role.slug in settings.PLUGINS_CONFIG["netbox_topology_views"]["device_img"]:
|
||||
node["image"] = '../../static/netbox_topology_views/img/' + device.device_role.slug + ".png"
|
||||
else:
|
||||
node["image"] = "../../static/netbox_topology_views/img/role-unknown.png"
|
||||
|
||||
if device.device_role.color != "":
|
||||
node["color.border"] = "#" + device.device_role.color
|
||||
|
||||
if "coordinates" in device.custom_field_data:
|
||||
if device.custom_field_data["coordinates"] != "":
|
||||
cords = device.custom_field_data["coordinates"].split(";")
|
||||
node["x"] = int(cords[0])
|
||||
node["y"] = int(cords[1])
|
||||
node["physics"] = False
|
||||
|
||||
nodes.append(node)
|
||||
|
||||
results = {}
|
||||
results["nodes"] = nodes
|
||||
results["edges"] = edges
|
||||
|
||||
return Response(results)
|
||||
|
||||
Reference in New Issue
Block a user