254 lines
13 KiB
Python
254 lines
13 KiB
Python
from rest_framework.viewsets import ModelViewSet, ViewSet, ReadOnlyModelViewSet, GenericViewSet
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
|
from .serializers import PreDeviceRoleSerializer, TopologyDummySerializer, PreTagSerializer
|
|
from django.conf import settings
|
|
|
|
from utilities.api import IsAuthenticatedOrLoginNotRequired
|
|
|
|
from dcim.models import DeviceRole, Device, Cable
|
|
from circuits.models import Circuit
|
|
from extras.models import Tag, CustomField, CustomFieldValue
|
|
|
|
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 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(GenericViewSet):
|
|
queryset = Device.objects.all()
|
|
serializer_class = TopologyDummySerializer
|
|
|
|
@action(detail=False, methods=['post'])
|
|
def save_coords(self, request):
|
|
results = {}
|
|
if settings.PLUGINS_CONFIG["netbox_topology_views"]["allow_coordinates_saving"]:
|
|
try:
|
|
cfCoords = CustomField.objects.get(name='coordinates')
|
|
except CustomField.DoesNotExist:
|
|
results["status"] = "coords custom field not created"
|
|
return Response(status=500)
|
|
|
|
obj_type = ContentType.objects.get_for_model(Device)
|
|
|
|
device_id = None
|
|
x_coord = None
|
|
y_coord = None
|
|
if "node_id" in request.data:
|
|
if request.data["node_id"]:
|
|
device_id = request.data["node_id"]
|
|
if "x" in request.data:
|
|
if request.data["x"]:
|
|
x_coord = request.data["x"]
|
|
if "y" in request.data:
|
|
if request.data["y"]:
|
|
y_coord = request.data["y"]
|
|
|
|
actual_device= Device.objects.get(id=device_id)
|
|
try:
|
|
cfvCoords = CustomFieldValue.objects.get(obj_type=obj_type, obj_id=actual_device.pk, field__name='coordinates')
|
|
cfvCoords.value = "%s;%s" % (x_coord,y_coord)
|
|
cfvCoords.save()
|
|
results["status"] = "coords set"
|
|
except CustomFieldValue.DoesNotExist:
|
|
cfvCoords = CustomFieldValue(field=cfCoords, obj_type=obj_type, obj_id=actual_device.id)
|
|
cfvCoords.value = "%s;%s" % (x_coord,y_coord)
|
|
cfvCoords.save()
|
|
results["status"] = "coords set for first time"
|
|
|
|
return Response(results)
|
|
else:
|
|
results["status"] = "not allowed to save coords"
|
|
return Response(results, status=500)
|
|
|
|
class SearchViewSet(GenericViewSet):
|
|
#_ignore_model_permissions = True
|
|
#permission_classes = [IsAuthenticatedOrLoginNotRequired]
|
|
|
|
queryset = Device.objects.all()
|
|
serializer_class = TopologyDummySerializer
|
|
|
|
def _filter(self, site, role, name, tags):
|
|
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)
|
|
return filter_devices
|
|
|
|
|
|
@action(detail=False, methods=['post'])
|
|
def search(self, request):
|
|
name = None
|
|
sites = None
|
|
devicerole = None
|
|
tags = None
|
|
if "devicerole" in request.data:
|
|
if request.data["devicerole"]:
|
|
devicerole = request.data["devicerole"]
|
|
if "sites" in request.data:
|
|
if request.data["sites"]:
|
|
sites = request.data["sites"]
|
|
if "name" in request.data:
|
|
if request.data["name"]:
|
|
name = request.data["name"]
|
|
if "tags" in request.data:
|
|
if request.data["tags"]:
|
|
tags = request.data["tags"]
|
|
|
|
devices = self._filter(sites, devicerole, name, tags)
|
|
|
|
nodes = []
|
|
edges = []
|
|
edge_ids = 0
|
|
cable_ids = []
|
|
circuit_ids = []
|
|
for device in devices:
|
|
cables = device.get_cables()
|
|
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>"
|
|
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:
|
|
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)
|
|
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:
|
|
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)
|
|
|
|
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
|
|
|
|
for device_custom_field in device.custom_field_values.all():
|
|
if device_custom_field.field.name == "coordinates":
|
|
cords = device_custom_field.serialized_value.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)
|