Netbox v3.3 Support (#145)
* init * added circuit (or at least part of) * refactor circuits + fix js * small changes * small changes * added power + rework settings * small changes
This commit is contained in:
@@ -45,7 +45,7 @@ Then run `python3 manage.py collectstatic --no-input`
|
|||||||
|
|
||||||
There is also support for custom fields.
|
There is also support for custom fields.
|
||||||
|
|
||||||
If you create a custom field "coordinates" for "dcim > device" with type "text" and name "coordinates" you will see the same layout every time.
|
If you create a custom field "coordinates" for "dcim > device" and "Circuits > circuit" with type "text" and name "coordinates" you will see the same layout every time.
|
||||||
|
|
||||||
The coordinates can then be provided as: "X;Y"
|
The coordinates can then be provided as: "X;Y"
|
||||||
|
|
||||||
@@ -67,12 +67,10 @@ PLUGINS_CONFIG = {
|
|||||||
| ------------- |-------------| -----|
|
| ------------- |-------------| -----|
|
||||||
| device_img |['access-switch', 'core-switch', 'firewall', 'router', 'distribution-switch', 'backup', 'storage,wan-network', 'wireless-ap', 'server', 'internal-switch', 'isp-cpe-material', 'non-racked-devices', 'power-units'] | The slug of the device roles that you have a image for. |
|
| device_img |['access-switch', 'core-switch', 'firewall', 'router', 'distribution-switch', 'backup', 'storage,wan-network', 'wireless-ap', 'server', 'internal-switch', 'isp-cpe-material', 'non-racked-devices', 'power-units'] | The slug of the device roles that you have a image for. |
|
||||||
| preselected_device_roles | ['Firewall', 'Router', 'Distribution Switch', 'Core Switch', 'Internal Switch', 'Access Switch', 'Server', 'Storage', 'Backup', 'Wireless AP'] | The full name of the device roles you want to pre select in the global view. Note that this is case sensitive|
|
| preselected_device_roles | ['Firewall', 'Router', 'Distribution Switch', 'Core Switch', 'Internal Switch', 'Access Switch', 'Server', 'Storage', 'Backup', 'Wireless AP'] | The full name of the device roles you want to pre select in the global view. Note that this is case sensitive|
|
||||||
| preselected_intermediate_dev_roles | ['Patch-panel'] | The full name of the device roles you want to display in the global view when using end-to-end connections mode. Note that this is case sensitive|
|
|
||||||
| allow_coordinates_saving | False | (bool) Set to true if you use the custom coordinates fields and want to save the coordinates |
|
| allow_coordinates_saving | False | (bool) Set to true if you use the custom coordinates fields and want to save the coordinates |
|
||||||
| always_save_coordinates | False | (bool) Set if you want to enable the option to save coordinates by default |
|
| always_save_coordinates | False | (bool) Set if you want to enable the option to save coordinates by default |
|
||||||
| ignore_cable_type | ['power outlet', 'power port'] | The cable types that you want to ignore in the views |
|
| ignore_cable_type | [] | The cable types that you want to ignore in the views |
|
||||||
| preselected_tags | '[]' | The name of tags you want to preload |
|
| preselected_tags | '[]' | The name of tags you want to preload |
|
||||||
| enable_circuit_terminations | False | (bool) Set to true if you want to see circuit terminations in the topology |
|
|
||||||
| draw_default_layout | False | (bool) Set to True if you want to load draw the topology on the initial load (when you go to the topology plugin page) |
|
| draw_default_layout | False | (bool) Set to True if you want to load draw the topology on the initial load (when you go to the topology plugin page) |
|
||||||
|
|
||||||
### Custom Images
|
### Custom Images
|
||||||
|
|||||||
@@ -11,14 +11,11 @@ class TopologyViewsConfig(PluginConfig):
|
|||||||
required_settings = []
|
required_settings = []
|
||||||
default_settings = {
|
default_settings = {
|
||||||
'preselected_device_roles': ['Firewall', 'Router', 'Distribution Switch', 'Core Switch', 'Internal Switch', 'Access Switch', 'Server', 'Storage', 'Backup', 'Wireless AP'],
|
'preselected_device_roles': ['Firewall', 'Router', 'Distribution Switch', 'Core Switch', 'Internal Switch', 'Access Switch', 'Server', 'Storage', 'Backup', 'Wireless AP'],
|
||||||
'preselected_intermediate_dev_roles' : [],
|
'ignore_cable_type': [],
|
||||||
'end2end_connections': False,
|
|
||||||
'ignore_cable_type': ['power outlet','power port'],
|
|
||||||
'device_img': ['access-switch', 'core-switch', 'firewall', 'router', 'distribution-switch', 'backup', 'storage', 'wan-network', 'wireless-ap', 'server', 'internal-switch', 'isp-cpe-material', 'non-racked-devices', 'power-units'],
|
'device_img': ['access-switch', 'core-switch', 'firewall', 'router', 'distribution-switch', 'backup', 'storage', 'wan-network', 'wireless-ap', 'server', 'internal-switch', 'isp-cpe-material', 'non-racked-devices', 'power-units'],
|
||||||
'allow_coordinates_saving': False,
|
'allow_coordinates_saving': False,
|
||||||
'always_save_coordinates': False,
|
'always_save_coordinates': False,
|
||||||
'preselected_tags' : [],
|
'preselected_tags' : [],
|
||||||
'enable_circuit_terminations': False,
|
|
||||||
'draw_default_layout': False
|
'draw_default_layout': False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from rest_framework.routers import APIRootView
|
|||||||
from .serializers import TopologyDummySerializer
|
from .serializers import TopologyDummySerializer
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from dcim.models import DeviceRole, Device, Cable
|
from dcim.models import DeviceRole, Device, Cable , PowerPanel, PowerFeed
|
||||||
from circuits.models import Circuit
|
from circuits.models import Circuit
|
||||||
from extras.models import Tag
|
from extras.models import Tag
|
||||||
|
|
||||||
@@ -37,8 +37,18 @@ class SaveCoordsViewSet(ReadOnlyModelViewSet):
|
|||||||
if "y" in request.data:
|
if "y" in request.data:
|
||||||
if request.data["y"]:
|
if request.data["y"]:
|
||||||
y_coord = request.data["y"]
|
y_coord = request.data["y"]
|
||||||
|
|
||||||
actual_device= Device.objects.get(id=device_id)
|
if device_id.startswith("c"):
|
||||||
|
device_id = device_id.lstrip('c')
|
||||||
|
actual_device= Circuit.objects.get(id=device_id)
|
||||||
|
elif device_id.startswith("p"):
|
||||||
|
device_id = device_id.lstrip('p')
|
||||||
|
actual_device= PowerPanel.objects.get(id=device_id)
|
||||||
|
elif device_id.startswith("f"):
|
||||||
|
device_id = device_id.lstrip('f')
|
||||||
|
actual_device= PowerFeed.objects.get(id=device_id)
|
||||||
|
else:
|
||||||
|
actual_device= Device.objects.get(id=device_id)
|
||||||
|
|
||||||
if "coordinates" in actual_device.custom_field_data:
|
if "coordinates" in actual_device.custom_field_data:
|
||||||
actual_device.custom_field_data["coordinates"] = "%s;%s" % (x_coord,y_coord)
|
actual_device.custom_field_data["coordinates"] = "%s;%s" % (x_coord,y_coord)
|
||||||
|
|||||||
@@ -16,16 +16,15 @@ from netbox.forms import NetBoxModelFilterSetForm
|
|||||||
from utilities.forms import (TagFilterField, DynamicModelMultipleChoiceField, MultipleChoiceField)
|
from utilities.forms import (TagFilterField, DynamicModelMultipleChoiceField, MultipleChoiceField)
|
||||||
|
|
||||||
allow_coordinates_saving = bool(settings.PLUGINS_CONFIG["netbox_topology_views"]["allow_coordinates_saving"])
|
allow_coordinates_saving = bool(settings.PLUGINS_CONFIG["netbox_topology_views"]["allow_coordinates_saving"])
|
||||||
end2end = settings.PLUGINS_CONFIG["netbox_topology_views"]["end2end_connections"]
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||||
model = Device
|
model = Device
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, ('q', 'hide_unconnected', 'save_coords', 'end2end_connections')),
|
(None, ('q', 'hide_unconnected', 'save_coords', 'show_circuit', 'show_power' ,)),
|
||||||
(None, ('tenant_group_id', 'tenant_id')),
|
(None, ('tenant_group_id', 'tenant_id')),
|
||||||
(None, ('region_id', 'site_id', 'location_id')),
|
(None, ('region_id', 'site_id', 'location_id')),
|
||||||
(None, ('device_role_id', 'intermediate_dev_role_id')),
|
(None, ('device_role_id', )),
|
||||||
(None, ('tag', 'status')),
|
(None, ('tag', 'status')),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,17 +38,6 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label=_('Device Role')
|
label=_('Device Role')
|
||||||
)
|
)
|
||||||
end2end_connections = forms.BooleanField(
|
|
||||||
label=_("Display end-to-end connections"),
|
|
||||||
required=False,
|
|
||||||
initial=end2end
|
|
||||||
)
|
|
||||||
intermediate_dev_role_id = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=DeviceRole.objects.all(),
|
|
||||||
required=False,
|
|
||||||
label=_('Intermediate Devices Role'),
|
|
||||||
help_text='Intermediate devices to display when using end-to-end connections mode, even if they do not match the query'
|
|
||||||
)
|
|
||||||
site_id = DynamicModelMultipleChoiceField(
|
site_id = DynamicModelMultipleChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@@ -72,6 +60,16 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|||||||
required=False,
|
required=False,
|
||||||
initial=False
|
initial=False
|
||||||
)
|
)
|
||||||
|
show_circuit = forms.BooleanField(
|
||||||
|
label=_("Show Circuit Terminations"),
|
||||||
|
required=False,
|
||||||
|
initial=False
|
||||||
|
)
|
||||||
|
show_power = forms.BooleanField(
|
||||||
|
label=_("Show Power panel/feed"),
|
||||||
|
required=False,
|
||||||
|
initial=False
|
||||||
|
)
|
||||||
save_coords = forms.BooleanField(
|
save_coords = forms.BooleanField(
|
||||||
label=_("Save Coordinates"),
|
label=_("Save Coordinates"),
|
||||||
required=False,
|
required=False,
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
File diff suppressed because one or more lines are too long
@@ -40,8 +40,6 @@ var options = {
|
|||||||
solver: 'forceAtlas2Based'
|
solver: 'forceAtlas2Based'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var selected_regions = [];
|
|
||||||
var selected_sites = [];
|
|
||||||
var coord_save_checkbox = null;
|
var coord_save_checkbox = null;
|
||||||
var htmlElement = null;
|
var htmlElement = null;
|
||||||
|
|
||||||
@@ -69,12 +67,12 @@ export function htmlTitle(html) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function addEdge(item) {
|
export function addEdge(item) {
|
||||||
item.title = htmlTitle( item.title );
|
item.title = htmlTitle(item.title);
|
||||||
edges.add(item);
|
edges.add(item);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function addNode(item) {
|
export function addNode(item) {
|
||||||
item.title = htmlTitle( item.title );
|
item.title = htmlTitle(item.title);
|
||||||
nodes.add(item);
|
nodes.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +135,6 @@ export function handleLoadData() {
|
|||||||
xhr.onreadystatechange = function () {
|
xhr.onreadystatechange = function () {
|
||||||
if (xhr.readyState === 4) {
|
if (xhr.readyState === 4) {
|
||||||
console.log(xhr.status);
|
console.log(xhr.status);
|
||||||
console.log(xhr.responseText);
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
var data = JSON.stringify({
|
var data = JSON.stringify({
|
||||||
@@ -154,7 +151,23 @@ export function handleLoadData() {
|
|||||||
graph.on("doubleClick", function (params) {
|
graph.on("doubleClick", function (params) {
|
||||||
let selected_devices = params.nodes;
|
let selected_devices = params.nodes;
|
||||||
for (let selected_device in selected_devices) {
|
for (let selected_device in selected_devices) {
|
||||||
let url = "/dcim/devices/" + selected_devices[selected_device] + "/";
|
let url = ""
|
||||||
|
if(String(selected_devices[selected_device]).startsWith("c")) {
|
||||||
|
cid = selected_devices[selected_device].substring(1);
|
||||||
|
url = "/circuits/circuits/" + cid + "/";
|
||||||
|
}
|
||||||
|
else if (String(selected_devices[selected_device]).startsWith("p")) {
|
||||||
|
cid = selected_devices[selected_device].substring(1);
|
||||||
|
url = "/dcim/power-panels/" + cid + "/";
|
||||||
|
}
|
||||||
|
else if (String(selected_devices[selected_device]).startsWith("f")) {
|
||||||
|
cid = selected_devices[selected_device].substring(1);
|
||||||
|
url = "/dcim/power-feeds/" + cid + "/";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
url = "/dcim/devices/" + selected_devices[selected_device] + "/";
|
||||||
|
}
|
||||||
|
|
||||||
window.open(url, "_blank");
|
window.open(url, "_blank");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +177,6 @@ export function handleLoadData() {
|
|||||||
|
|
||||||
export function load_doc() {
|
export function load_doc() {
|
||||||
if (document.readyState !== 'loading') {
|
if (document.readyState !== 'loading') {
|
||||||
console.log("test");
|
|
||||||
iniPlotboxIndex();
|
iniPlotboxIndex();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('DOMContentLoaded', iniPlotboxIndex);
|
document.addEventListener('DOMContentLoaded', iniPlotboxIndex);
|
||||||
|
|||||||
+248
-198
@@ -1,3 +1,5 @@
|
|||||||
|
from platform import node
|
||||||
|
from tkinter.messagebox import NO
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
@@ -6,61 +8,101 @@ from django.conf import settings
|
|||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
|
||||||
|
|
||||||
from .forms import DeviceFilterForm
|
from .forms import DeviceFilterForm
|
||||||
from .filters import DeviceFilterSet
|
from .filters import DeviceFilterSet
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from dcim.models import Device, Cable, DeviceRole, PathEndpoint
|
from dcim.models import Device, Cable, CableTermination, DeviceRole, PathEndpoint, Interface, FrontPort, RearPort, PowerPanel, PowerFeed
|
||||||
from circuits.models import CircuitTermination, ProviderNetwork
|
from circuits.models import CircuitTermination, ProviderNetwork
|
||||||
|
from wireless.models import WirelessLink
|
||||||
from extras.models import Tag
|
from extras.models import Tag
|
||||||
|
|
||||||
|
supported_termination_types = ["interface", "front port", "rear port", "power outlet", "power port"]
|
||||||
|
|
||||||
def create_node(device, save_coords):
|
def create_node(device, save_coords, circuit = None, powerpanel = None, powerfeed= None):
|
||||||
dev_name = device.name
|
|
||||||
if dev_name is None:
|
|
||||||
dev_name = "device name unknown"
|
|
||||||
|
|
||||||
node_content = ""
|
|
||||||
|
|
||||||
if device.device_type is not None:
|
|
||||||
node_content += "<tr><th>Type: </th><td>" + device.device_type.model + "</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>"
|
|
||||||
if device.site is not None:
|
|
||||||
node_content += "<tr><th>Site: </th><td>" + device.site.name + "</td></tr>"
|
|
||||||
if device.location is not None:
|
|
||||||
node_content += "<tr><th>Location: </th><td>" + device.location.name + "</td></tr>"
|
|
||||||
if device.rack is not None:
|
|
||||||
node_content += "<tr><th>Rack: </th><td>" + device.rack.name + "</td></tr>"
|
|
||||||
if device.position is not None:
|
|
||||||
if device.face is not None:
|
|
||||||
node_content += "<tr><th>Position: </th><td> {} ({}) </td></tr>".format(device.position, device.face)
|
|
||||||
else:
|
|
||||||
node_content += "<tr><th>Position: </th><td>" + device.position + "</td></tr>"
|
|
||||||
|
|
||||||
dev_title = "<table> %s </table>" % (node_content)
|
|
||||||
|
|
||||||
node = {}
|
node = {}
|
||||||
node["id"] = device.id
|
node_content = ""
|
||||||
|
if circuit:
|
||||||
|
dev_name = "Circuit " + str(device.cid)
|
||||||
|
node["image"] = "../../static/netbox_topology_views/img/circuit.png"
|
||||||
|
node["id"] = "c{}".format(device.id)
|
||||||
|
|
||||||
|
if device.provider is not None:
|
||||||
|
node_content += "<tr><th>Provider: </th><td>" + device.provider.name + "</td></tr>"
|
||||||
|
if device.type is not None:
|
||||||
|
node_content += "<tr><th>Type: </th><td>" + device.type.name + "</td></tr>"
|
||||||
|
elif powerpanel:
|
||||||
|
dev_name = "Power Panel " + str(device.id)
|
||||||
|
node["image"] = "../../static/netbox_topology_views/img/power-panel.png"
|
||||||
|
node["id"] = "p{}".format(device.id)
|
||||||
|
|
||||||
|
if device.site is not None:
|
||||||
|
node_content += "<tr><th>Site: </th><td>" + device.site.name + "</td></tr>"
|
||||||
|
if device.location is not None:
|
||||||
|
node_content += "<tr><th>Location: </th><td>" + device.location.name + "</td></tr>"
|
||||||
|
elif powerfeed:
|
||||||
|
dev_name = "Power Feed " + str(device.id)
|
||||||
|
node["image"] = "../../static/netbox_topology_views/img/power-feed.png"
|
||||||
|
node["id"] = "f{}".format(device.id)
|
||||||
|
|
||||||
|
if device.power_panel is not None:
|
||||||
|
node_content += "<tr><th>Power Panel: </th><td>" + device.power_panel.name + "</td></tr>"
|
||||||
|
if device.type is not None:
|
||||||
|
node_content += "<tr><th>Type: </th><td>" + device.type + "</td></tr>"
|
||||||
|
if device.supply is not None:
|
||||||
|
node_content += "<tr><th>Supply: </th><td>" + device.supply + "</td></tr>"
|
||||||
|
if device.phase is not None:
|
||||||
|
node_content += "<tr><th>Phase: </th><td>" + device.phase + "</td></tr>"
|
||||||
|
if device.amperage is not None:
|
||||||
|
node_content += "<tr><th>Amperage: </th><td>" + str(device.amperage )+ "</td></tr>"
|
||||||
|
if device.voltage is not None:
|
||||||
|
node_content += "<tr><th>Voltage: </th><td>" + str(device.voltage) + "</td></tr>"
|
||||||
|
else:
|
||||||
|
dev_name = device.name
|
||||||
|
if dev_name is None:
|
||||||
|
dev_name = "device name unknown"
|
||||||
|
|
||||||
|
if device.device_type is not None:
|
||||||
|
node_content += "<tr><th>Type: </th><td>" + device.device_type.model + "</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>"
|
||||||
|
if device.site is not None:
|
||||||
|
node_content += "<tr><th>Site: </th><td>" + device.site.name + "</td></tr>"
|
||||||
|
if device.location is not None:
|
||||||
|
node_content += "<tr><th>Location: </th><td>" + device.location.name + "</td></tr>"
|
||||||
|
if device.rack is not None:
|
||||||
|
node_content += "<tr><th>Rack: </th><td>" + device.rack.name + "</td></tr>"
|
||||||
|
if device.position is not None:
|
||||||
|
if device.face is not None:
|
||||||
|
node_content += "<tr><th>Position: </th><td> {} ({}) </td></tr>".format(device.position, device.face)
|
||||||
|
else:
|
||||||
|
node_content += "<tr><th>Position: </th><td>" + device.position + "</td></tr>"
|
||||||
|
|
||||||
|
node["id"] = device.id
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
dev_title = "<table><tbody> %s</tbody></table>" % (node_content)
|
||||||
|
|
||||||
|
node["title"] = dev_title
|
||||||
node["name"] = dev_name
|
node["name"] = dev_name
|
||||||
node["label"] = dev_name
|
node["label"] = dev_name
|
||||||
node["title"] = dev_title
|
|
||||||
node["shape"] = "image"
|
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
|
|
||||||
|
|
||||||
node["physics"] = True
|
|
||||||
|
|
||||||
|
node["physics"] = True
|
||||||
if "coordinates" in device.custom_field_data:
|
if "coordinates" in device.custom_field_data:
|
||||||
if device.custom_field_data["coordinates"] is not None:
|
if device.custom_field_data["coordinates"] is not None:
|
||||||
if ";" in device.custom_field_data["coordinates"]:
|
if ";" in device.custom_field_data["coordinates"]:
|
||||||
@@ -75,191 +117,202 @@ def create_node(device, save_coords):
|
|||||||
node["physics"] = True
|
node["physics"] = True
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def create_edge(edge_id, cable, termination_a, termination_b, path = None, circuit = None):
|
def create_edge(edge_id, termination_a, termination_b, circuit = None, cable = None, wireless = None, power=None):
|
||||||
cable_a_dev_name = "device A name unknown" if termination_a.device.name is None else termination_a.device.name
|
cable_a_name = "device A name unknown" if termination_a["termination_name"] is None else termination_a["termination_name"]
|
||||||
cable_a_name = "device A name unknown" if termination_a.name is None else termination_a.name
|
cable_a_dev_name = "device A name unknown" if termination_a["termination_device_name"] is None else termination_a["termination_device_name"]
|
||||||
cable_b_dev_name = "device A name unknown" if termination_b.device.name is None else termination_b.device.name
|
cable_b_name= "device A name unknown" if termination_b["termination_name"] is None else termination_b["termination_name"]
|
||||||
cable_b_name = "cable B name unknown" if termination_b.name is None else termination_b.name
|
cable_b_dev_name = "cable B name unknown" if termination_b["termination_device_name"] is None else termination_b["termination_device_name"]
|
||||||
|
|
||||||
edge = {}
|
edge = {}
|
||||||
edge["id"] = edge_id
|
edge["id"] = edge_id
|
||||||
edge["from"] = termination_a.device.id
|
edge["from"] = termination_a["device_id"]
|
||||||
edge["to"] = termination_b.device.id
|
edge["to"] = termination_b["device_id"]
|
||||||
|
|
||||||
if circuit is not None:
|
if circuit is not None:
|
||||||
edge["dashes"] = True
|
edge["dashes"] = True
|
||||||
edge["title"] = "Circuit provider: " + circuit.provider.name + "<br>"
|
edge["title"] = "Circuit provider: " + circuit["provider_name"] + "<br>"
|
||||||
edge["title"] += "Termination between <br>"
|
edge["title"] += "Termination between <br>"
|
||||||
edge["title"] += cable_b_dev_name + " [" + cable_b_name + "]<br>"
|
edge["title"] += cable_b_dev_name + " [" + cable_b_name + "]<br>"
|
||||||
edge["title"] += cable_a_dev_name + " [" + cable_a_name + "]"
|
edge["title"] += cable_a_dev_name + " [" + cable_a_name + "]"
|
||||||
|
elif wireless is not None:
|
||||||
|
edge["dashes"] = [2, 10, 2, 10]
|
||||||
|
edge["title"] = "Wireless Connection between <br> " + cable_a_dev_name + " [" + cable_a_name + "]<br>" + cable_b_dev_name + " [" + cable_b_name + "]"
|
||||||
|
elif power is not None:
|
||||||
|
edge["dashes"] = [5, 5, 3, 3]
|
||||||
|
edge["title"] = "Power Connection between <br> " + cable_a_dev_name + " [" + cable_a_name + "]<br>" + cable_b_dev_name + " [" + cable_b_name + "]"
|
||||||
else:
|
else:
|
||||||
edge["title"] = "Cable between <br> " + cable_a_dev_name + " [" + cable_a_name + "]<br>" + cable_b_dev_name + " [" + cable_b_name + "]"
|
edge["title"] = "Cable between <br> " + cable_a_dev_name + " [" + cable_a_name + "]<br>" + cable_b_dev_name + " [" + cable_b_name + "]"
|
||||||
|
|
||||||
if path is not None:
|
|
||||||
edge["title"] += "" if len(path) <= 0 else "<br>Through " + "/".join(path)
|
|
||||||
|
|
||||||
if cable is not None and cable.color != "":
|
if cable is not None and cable.color != "":
|
||||||
edge["color"] = "#" + cable.color
|
edge["color"] = "#" + cable.color
|
||||||
|
|
||||||
return edge
|
return edge
|
||||||
|
|
||||||
def get_topology_data(queryset, hide_unconnected, save_coords, intermediate_dev_role_ids, end2end_connections):
|
def create_circuit_termination(termination):
|
||||||
|
if isinstance(termination, CircuitTermination):
|
||||||
|
return { "termination_name": termination.circuit.provider.name, "termination_device_name": termination.circuit.cid, "device_id": "c{}".format(termination.circuit.id) }
|
||||||
|
if isinstance(termination, Interface) or isinstance(termination, FrontPort) or isinstance(termination, RearPort):
|
||||||
|
return { "termination_name": termination.name, "termination_device_name": termination.device.name, "device_id": termination.device.id }
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_topology_data(queryset, hide_unconnected, save_coords, show_circuit, show_power):
|
||||||
nodes_devices = {}
|
nodes_devices = {}
|
||||||
edges = []
|
edges = []
|
||||||
|
nodes = []
|
||||||
edge_ids = 0
|
edge_ids = 0
|
||||||
cable_ids = []
|
nodes_circuits = {}
|
||||||
circuit_ids = []
|
nodes_powerpanel = {}
|
||||||
|
nodes_powerfeed = {}
|
||||||
|
nodes_provider_networks = {}
|
||||||
|
cable_ids = {}
|
||||||
if not queryset:
|
if not queryset:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ignore_cable_type = settings.PLUGINS_CONFIG["netbox_topology_views"]["ignore_cable_type"]
|
ignore_cable_type = settings.PLUGINS_CONFIG["netbox_topology_views"]["ignore_cable_type"]
|
||||||
enable_circuit_terminations = settings.PLUGINS_CONFIG["netbox_topology_views"]["enable_circuit_terminations"]
|
|
||||||
|
|
||||||
device_ids = [d.id for d in queryset]
|
device_ids = [d.id for d in queryset]
|
||||||
|
|
||||||
links = Cable.objects.filter( Q(_termination_a_device_id__in=device_ids) | Q(_termination_b_device_id__in=device_ids) ) \
|
if show_circuit:
|
||||||
.select_related("termination_a_type", "termination_b_type") \
|
site_ids = [d.site.id for d in queryset]
|
||||||
.prefetch_related("termination_a", "termination_b")
|
circuits = CircuitTermination.objects.filter( Q(site_id__in=site_ids) | Q( provider_network__isnull=False) ).prefetch_related("provider_network", "circuit")
|
||||||
|
for circuit in circuits:
|
||||||
|
if not hide_unconnected and circuit.circuit.id not in nodes_circuits:
|
||||||
|
nodes_circuits[circuit.circuit.id] = circuit.circuit
|
||||||
|
|
||||||
|
termination_a = {}
|
||||||
|
termination_b = {}
|
||||||
|
circuit_model = {}
|
||||||
|
if circuit.cable is not None:
|
||||||
|
termination_a = create_circuit_termination(circuit.cable.a_terminations[0])
|
||||||
|
termination_b = create_circuit_termination(circuit.cable.b_terminations[0])
|
||||||
|
elif circuit.provider_network is not None:
|
||||||
|
if circuit.provider_network.id not in nodes_provider_networks:
|
||||||
|
nodes_provider_networks[circuit.provider_network.id] = circuit.provider_network
|
||||||
|
|
||||||
|
if bool(termination_a) and bool(termination_b):
|
||||||
|
circuit_model = {"provider_name": circuit.circuit.provider.name}
|
||||||
|
edge_ids += 1
|
||||||
|
edges.append(create_edge(edge_id=edge_ids,circuit=circuit_model, termination_a=termination_a, termination_b=termination_b))
|
||||||
|
|
||||||
|
circuit_has_connections = False
|
||||||
|
for termination in [circuit.cable.a_terminations[0], circuit.cable.b_terminations[0]]:
|
||||||
|
if not isinstance(termination, CircuitTermination):
|
||||||
|
if termination.device.id not in nodes_devices and termination.device.id in device_ids:
|
||||||
|
nodes_devices[termination.device.id] = termination.device
|
||||||
|
circuit_has_connections = True
|
||||||
|
else:
|
||||||
|
if termination.device.id in device_ids:
|
||||||
|
circuit_has_connections = True
|
||||||
|
|
||||||
|
if circuit_has_connections and hide_unconnected:
|
||||||
|
if circuit.circuit.id not in nodes_circuits:
|
||||||
|
nodes_circuits[circuit.circuit.id] = circuit.circuit
|
||||||
|
|
||||||
|
|
||||||
|
for d in nodes_circuits.values():
|
||||||
|
nodes.append(create_node(d, save_coords, circuit=True))
|
||||||
|
|
||||||
|
links = CableTermination.objects.filter( Q(_device_id__in=device_ids) ).select_related("termination_type")
|
||||||
|
wlan_links = WirelessLink.objects.filter( Q(_interface_a_device_id__in=device_ids) & Q(_interface_b_device_id__in=device_ids))
|
||||||
|
|
||||||
|
if show_power:
|
||||||
|
power_panels = PowerPanel.objects.filter( Q (site_id__in=site_ids))
|
||||||
|
power_panels_ids = [d.id for d in power_panels]
|
||||||
|
power_feeds = PowerFeed.objects.filter( Q (power_panel_id__in=power_panels_ids))
|
||||||
|
|
||||||
|
for power_feed in power_feeds:
|
||||||
|
if not hide_unconnected or (hide_unconnected and power_feed.cable_id is not None):
|
||||||
|
if power_feed.power_panel.id not in nodes_powerpanel:
|
||||||
|
nodes_powerpanel[power_feed.power_panel.id] = power_feed.power_panel
|
||||||
|
|
||||||
|
if power_feed.id not in nodes_powerfeed:
|
||||||
|
if hide_unconnected:
|
||||||
|
if power_feed.link_peers[0].device.id in device_ids:
|
||||||
|
nodes_powerfeed[power_feed.id] = power_feed
|
||||||
|
else:
|
||||||
|
nodes_powerfeed[power_feed.id] = power_feed
|
||||||
|
|
||||||
|
edge_ids += 1
|
||||||
|
termination_a = { "termination_name": power_feed.power_panel.name, "termination_device_name": str(power_feed.power_panel.id), "device_id": "p{}".format(power_feed.power_panel.id) }
|
||||||
|
termination_b = { "termination_name": power_feed.name, "termination_device_name": str(termination.id), "device_id": "f{}".format(power_feed.id) }
|
||||||
|
edges.append(create_edge(edge_id=edge_ids, termination_a=termination_a, termination_b=termination_b, power=True))
|
||||||
|
|
||||||
|
if power_feed.cable_id is not None:
|
||||||
|
if power_feed.cable.id not in cable_ids:
|
||||||
|
cable_ids[power_feed.cable.id] = {}
|
||||||
|
cable_ids[power_feed.cable.id][power_feed.cable_end] = termination_b
|
||||||
|
|
||||||
|
|
||||||
|
for d in nodes_powerfeed.values():
|
||||||
|
nodes.append(create_node(d, save_coords, powerfeed = True))
|
||||||
|
|
||||||
|
for d in nodes_powerpanel.values():
|
||||||
|
nodes.append(create_node(d, save_coords, powerpanel = True))
|
||||||
|
|
||||||
for link in links:
|
for link in links:
|
||||||
|
if link.termination_type.name in ignore_cable_type :
|
||||||
if link.termination_a_type.name in ignore_cable_type or link.termination_b_type.name in ignore_cable_type \
|
|
||||||
or link.id in cable_ids:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
a_is_path_endoint = isinstance(link.termination_a, PathEndpoint)
|
#Normal device cables
|
||||||
b_is_path_endoint = isinstance(link.termination_b, PathEndpoint)
|
if link.termination_type.name in supported_termination_types:
|
||||||
|
complete_link = False
|
||||||
if not end2end_connections or (not a_is_path_endoint and not b_is_path_endoint):
|
if link.cable_end == "A":
|
||||||
|
if link.cable.id not in cable_ids:
|
||||||
if isinstance(link.termination_a, CircuitTermination):
|
cable_ids[link.cable.id] = {}
|
||||||
if enable_circuit_terminations and link.termination_a.circuit.id not in circuit_ids:
|
else:
|
||||||
circuit = link.termination_a.circuit
|
if cable_ids[link.cable.id]['B'] is not None:
|
||||||
circuit_ids.append(circuit.id)
|
complete_link = True
|
||||||
cable_ids.append(link.id)
|
elif link.cable_end == "B":
|
||||||
|
if link.cable.id not in cable_ids:
|
||||||
path_destination = circuit.termination_z if link.termination_a.term_side == "A" else circuit.termination_a
|
cable_ids[link.cable.id] = {}
|
||||||
|
else:
|
||||||
if path_destination is not None and path_destination.provider_network is None:
|
if cable_ids[link.cable.id]['A'] is not None:
|
||||||
# ProviderNetwork not supported at the moment
|
complete_link = True
|
||||||
# $path_destination.cable would be none : there is no cable between a CircuitTermination and ProviderNetwork
|
|
||||||
|
|
||||||
if not hasattr(link.termination_b, 'device'):
|
|
||||||
#CircuitTermination B Missing Device
|
|
||||||
continue
|
|
||||||
|
|
||||||
origin_device = link.termination_b.device
|
|
||||||
destination_device = path_destination.cable.termination_b.device
|
|
||||||
|
|
||||||
if origin_device.id in device_ids and destination_device.id in device_ids:
|
|
||||||
if origin_device.id not in nodes_devices:
|
|
||||||
nodes_devices[origin_device.id] = origin_device
|
|
||||||
if destination_device.id not in nodes_devices:
|
|
||||||
nodes_devices[destination_device.id] = destination_device
|
|
||||||
|
|
||||||
edge_ids += 1
|
|
||||||
edges.append(create_edge(edge_ids, link, link.termination_b, path_destination.cable.termination_b, [circuit.cid], circuit))
|
|
||||||
|
|
||||||
elif link.termination_a.device.id in device_ids and link.termination_b.device.id in device_ids:
|
|
||||||
|
|
||||||
if link.termination_a.device.id not in nodes_devices:
|
|
||||||
nodes_devices[link.termination_a.device.id] = link.termination_a.device
|
|
||||||
if link.termination_b.device.id not in nodes_devices:
|
|
||||||
nodes_devices[link.termination_b.device.id] = link.termination_b.device
|
|
||||||
|
|
||||||
cable_ids.append(link.id)
|
|
||||||
edge_ids += 1
|
|
||||||
edges.append(create_edge(edge_ids, link, link.termination_a, link.termination_b))
|
|
||||||
else:
|
|
||||||
# termination_a can be a CircuitTermination (no trace()) while termination_b is a PathEndpoint
|
|
||||||
# If so, we swap them so we can follow the path using PathEndpoint#trace()
|
|
||||||
path_start = link.termination_a if a_is_path_endoint else link.termination_b
|
|
||||||
if path_start.device is not None and path_start.device.id not in device_ids:
|
|
||||||
# device not in queryset, skip
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Ignore incomplete path when in end-to-end connection mode
|
|
||||||
if path_start.path is not None:
|
|
||||||
if not path_start.path.is_active or path_start.path.is_split:
|
|
||||||
continue
|
|
||||||
else:
|
else:
|
||||||
continue
|
print("Unkown cable end")
|
||||||
|
cable_ids[link.cable.id][link.cable_end] = link
|
||||||
|
|
||||||
path_destination = path_start.path.destination
|
if complete_link:
|
||||||
if hasattr(path_destination, "device") and path_destination.device is not None and path_destination.device.id not in device_ids:
|
edge_ids += 1
|
||||||
# device not in queryset, skip
|
if isinstance(cable_ids[link.cable.id]["B"], CableTermination):
|
||||||
continue
|
if cable_ids[link.cable.id]["B"]._device_id not in nodes_devices:
|
||||||
|
nodes_devices[cable_ids[link.cable.id]["B"]._device_id] = cable_ids[link.cable.id]["B"].termination.device
|
||||||
|
termination_b = { "termination_name": cable_ids[link.cable.id]["B"].termination.name, "termination_device_name": cable_ids[link.cable.id]["B"].termination.device.name, "device_id": cable_ids[link.cable.id]["B"].termination.device.id }
|
||||||
|
else:
|
||||||
|
termination_b = cable_ids[link.cable.id]["B"]
|
||||||
|
|
||||||
valid_path = False
|
if isinstance(cable_ids[link.cable.id]["A"], CableTermination):
|
||||||
|
if cable_ids[link.cable.id]["A"]._device_id not in nodes_devices:
|
||||||
|
nodes_devices[cable_ids[link.cable.id]["A"]._device_id] = cable_ids[link.cable.id]["A"].termination.device
|
||||||
|
termination_a = { "termination_name": cable_ids[link.cable.id]["A"].termination.name, "termination_device_name": cable_ids[link.cable.id]["A"].termination.device.name, "device_id": cable_ids[link.cable.id]["A"].termination.device.id }
|
||||||
|
else:
|
||||||
|
termination_a = cable_ids[link.cable.id]["A"]
|
||||||
|
|
||||||
|
edges.append(create_edge(edge_id=edge_ids, cable=link.cable, termination_a=termination_a, termination_b=termination_b))
|
||||||
|
|
||||||
|
for wlan_link in wlan_links:
|
||||||
|
if wlan_link.interface_a.device.id not in nodes_devices:
|
||||||
|
nodes_devices[wlan_link.interface_a.device.id] = wlan_link.interface_a.device
|
||||||
|
if wlan_link.interface_b.device.id not in nodes_devices:
|
||||||
|
nodes_devices[wlan_link.interface_b.device.id] = wlan_link.interface_b.device
|
||||||
|
|
||||||
|
termination_a = {"termination_name": wlan_link.interface_a.name, "termination_device_name": wlan_link.interface_a.device.name, "device_id": wlan_link.interface_a.device.id}
|
||||||
|
termination_b = {"termination_name": wlan_link.interface_b.name, "termination_device_name": wlan_link.interface_b.device.name, "device_id": wlan_link.interface_b.device.id}
|
||||||
|
wireless = {"ssid": wlan_link.ssid }
|
||||||
|
|
||||||
# variables needed for trace() browsing
|
edge_ids += 1
|
||||||
origin = None
|
edges.append(create_edge(edge_id=edge_ids, termination_a=termination_a, termination_b=termination_b,wireless=wireless))
|
||||||
circuit = None
|
|
||||||
tmp_path = []
|
|
||||||
|
|
||||||
# trace() : Return the path as a list of three-tuples (A termination, cable, B termination)
|
|
||||||
# TODO device qui ne s"affichent pas si hide_unconnected
|
|
||||||
for (termination_a, cable, termination_b) in path_start.trace():
|
|
||||||
|
|
||||||
if origin is None:
|
|
||||||
# New part of the link
|
|
||||||
origin = termination_a
|
|
||||||
circuit = None
|
|
||||||
tmp_path = []
|
|
||||||
|
|
||||||
if isinstance(termination_b, ProviderNetwork):
|
|
||||||
# ProviderNetwork not supported at the moment
|
|
||||||
# It would need to manage several kind of nodes (Device, ProviderNetwork)
|
|
||||||
# and maps javascript nodes ID with Devices IDs and ProviderNetworks IDs
|
|
||||||
# When $termination_b is a ProviderNetwork instance, $cable will be None
|
|
||||||
break
|
|
||||||
|
|
||||||
if cable is not None and (cable.termination_a_type in ignore_cable_type or cable.termination_b_type in ignore_cable_type):
|
|
||||||
# Ignore this path
|
|
||||||
break
|
|
||||||
|
|
||||||
if isinstance(termination_b, CircuitTermination):
|
|
||||||
if enable_circuit_terminations:
|
|
||||||
circuit = termination_b.circuit
|
|
||||||
tmp_path.append(circuit.cid)
|
|
||||||
if circuit.id not in circuit_ids:
|
|
||||||
circuit_ids.append(circuit.id)
|
|
||||||
else:
|
|
||||||
# Ignore this path
|
|
||||||
break
|
|
||||||
elif end2end_connections and termination_b != path_destination \
|
|
||||||
and termination_b.device.device_role.id not in intermediate_dev_role_ids \
|
|
||||||
and termination_b.device.id not in device_ids:
|
|
||||||
# Skip this intermediate device, origin device is keep in $origin for next iteration
|
|
||||||
tmp_path.append(termination_b.device.name)
|
|
||||||
elif cable is not None and termination_b is not None:
|
|
||||||
if cable.id not in cable_ids:
|
|
||||||
# New part of the link we want to display
|
|
||||||
cable_ids.append(cable.id)
|
|
||||||
edge_ids += 1
|
|
||||||
edges.append(create_edge(edge_ids, cable, origin, termination_b, tmp_path, circuit))
|
|
||||||
|
|
||||||
if not valid_path:
|
|
||||||
valid_path = True
|
|
||||||
|
|
||||||
if termination_b.device.id not in nodes_devices and \
|
|
||||||
(termination_b.device.device_role.id in intermediate_dev_role_ids or termination_b.device.id in device_ids) :
|
|
||||||
nodes_devices[termination_b.device.id] = termination_b.device
|
|
||||||
# Reset for next iteration
|
|
||||||
origin = None
|
|
||||||
# endfor (trace)
|
|
||||||
|
|
||||||
if valid_path and path_start.device.id not in nodes_devices:
|
|
||||||
nodes_devices[path_start.device.id] = path_start.device
|
|
||||||
|
|
||||||
# endfor (link)
|
|
||||||
|
|
||||||
for qs_device in queryset:
|
for qs_device in queryset:
|
||||||
if qs_device.id not in nodes_devices and not hide_unconnected:
|
if qs_device.id not in nodes_devices and not hide_unconnected:
|
||||||
nodes_devices[qs_device.id] = qs_device
|
nodes_devices[qs_device.id] = qs_device
|
||||||
|
|
||||||
results = {}
|
results = {}
|
||||||
results["nodes"] = [create_node(d, save_coords) for d in nodes_devices.values()]
|
|
||||||
|
for d in nodes_devices.values():
|
||||||
|
nodes.append(create_node(d, save_coords))
|
||||||
|
|
||||||
|
results["nodes"] = nodes
|
||||||
results["edges"] = edges
|
results["edges"] = edges
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -286,34 +339,31 @@ class TopologyHomeView(PermissionRequiredMixin, View):
|
|||||||
if request.GET["hide_unconnected"] == "on" :
|
if request.GET["hide_unconnected"] == "on" :
|
||||||
hide_unconnected = True
|
hide_unconnected = True
|
||||||
|
|
||||||
if "intermediate_dev_role_id" in request.GET:
|
show_power = False
|
||||||
intermediate_dev_role_ids = list(map(int, request.GET.getlist("intermediate_dev_role_id")))
|
if "show_power" in request.GET:
|
||||||
else:
|
if request.GET["show_power"] == "on" :
|
||||||
intermediate_dev_role_ids = []
|
show_power = True
|
||||||
|
|
||||||
|
show_circuit = False
|
||||||
|
if "show_circuit" in request.GET:
|
||||||
|
if request.GET["show_circuit"] == "on" :
|
||||||
|
show_circuit = True
|
||||||
|
|
||||||
end2end_connections = False
|
|
||||||
if "end2end_connections" in request.GET:
|
|
||||||
if request.GET["end2end_connections"] == "on" :
|
|
||||||
end2end_connections = True
|
|
||||||
|
|
||||||
if "draw_init" in request.GET:
|
if "draw_init" in request.GET:
|
||||||
if request.GET["draw_init"].lower() == "true":
|
if request.GET["draw_init"].lower() == "true":
|
||||||
topo_data = get_topology_data(self.queryset, hide_unconnected, save_coords, intermediate_dev_role_ids, end2end_connections)
|
topo_data = get_topology_data(self.queryset, hide_unconnected, save_coords, show_circuit, show_power)
|
||||||
else:
|
else:
|
||||||
topo_data = get_topology_data(self.queryset, hide_unconnected, save_coords, intermediate_dev_role_ids, end2end_connections)
|
topo_data = get_topology_data(self.queryset, hide_unconnected, save_coords, show_circuit, show_power)
|
||||||
else:
|
else:
|
||||||
preselected_device_roles = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_device_roles"]
|
preselected_device_roles = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_device_roles"]
|
||||||
preselected_intermediate_dev_roles = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_intermediate_dev_roles"]
|
|
||||||
preselected_tags = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_tags"]
|
preselected_tags = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_tags"]
|
||||||
always_save_coordinates = bool(settings.PLUGINS_CONFIG["netbox_topology_views"]["always_save_coordinates"])
|
always_save_coordinates = bool(settings.PLUGINS_CONFIG["netbox_topology_views"]["always_save_coordinates"])
|
||||||
|
|
||||||
q_device_role_id = DeviceRole.objects.filter(name__in=preselected_device_roles).values_list("id", flat=True)
|
q_device_role_id = DeviceRole.objects.filter(name__in=preselected_device_roles).values_list("id", flat=True)
|
||||||
q_intermediate_dev_role_id = DeviceRole.objects.filter(name__in=preselected_intermediate_dev_roles).values_list("id", flat=True)
|
|
||||||
q_tags = Tag.objects.filter(name__in=preselected_tags).values_list("name", flat=True)
|
q_tags = Tag.objects.filter(name__in=preselected_tags).values_list("name", flat=True)
|
||||||
|
|
||||||
q = QueryDict(mutable=True)
|
q = QueryDict(mutable=True)
|
||||||
q.setlist("device_role_id", list(q_device_role_id))
|
q.setlist("device_role_id", list(q_device_role_id))
|
||||||
q.setlist("intermediate_dev_role_id", list(q_intermediate_dev_role_id))
|
|
||||||
q.setlist("tag", list(q_tags))
|
q.setlist("tag", list(q_tags))
|
||||||
q["draw_init"] = settings.PLUGINS_CONFIG["netbox_topology_views"]["draw_default_layout"]
|
q["draw_init"] = settings.PLUGINS_CONFIG["netbox_topology_views"]["draw_default_layout"]
|
||||||
if always_save_coordinates:
|
if always_save_coordinates:
|
||||||
|
|||||||
Reference in New Issue
Block a user