Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b8da219d1 | ||
|
|
8c87506043 | ||
|
|
8179fa5ab4 | ||
|
|
2b3f37aa62 | ||
|
|
962e219325 | ||
|
|
2387e5d0cc | ||
|
|
0bcbd35082 | ||
|
|
0ce1c6df13 | ||
|
|
7dcd72a3f9 | ||
|
|
616c0ab1b5 | ||
|
|
8385dc23f8 | ||
|
|
449fdf3f80 | ||
|
|
b53ceed2ae | ||
|
|
064751f727 | ||
|
|
deedee78bd | ||
|
|
683e125cd5 |
@@ -4,7 +4,7 @@ class TopologyViewsConfig(PluginConfig):
|
|||||||
name = 'netbox_topology_views'
|
name = 'netbox_topology_views'
|
||||||
verbose_name = 'Topology views'
|
verbose_name = 'Topology views'
|
||||||
description = 'An plugin to render topology maps'
|
description = 'An plugin to render topology maps'
|
||||||
version = '1.1.0-beta.1'
|
version = '1.0.0-beta.1'
|
||||||
author = 'Mattijs Vanhaverbeke'
|
author = 'Mattijs Vanhaverbeke'
|
||||||
author_email = 'author@example.com'
|
author_email = 'author@example.com'
|
||||||
base_url = 'netbox_topology_views'
|
base_url = 'netbox_topology_views'
|
||||||
@@ -15,7 +15,7 @@ class TopologyViewsConfig(PluginConfig):
|
|||||||
'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,
|
||||||
'preselected_tags' : [],
|
'preselected_tags' : [],
|
||||||
'enable_circuit_terminations': False,
|
'enable_circuit_terminations': True,
|
||||||
'draw_default_layout': False
|
'draw_default_layout': False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
#no models yet
|
||||||
@@ -1,21 +1,16 @@
|
|||||||
import django_filters
|
import django_filters
|
||||||
|
from extras.filters import TagFilter
|
||||||
|
from dcim.models import Device, DeviceRole, Region, Site, Location
|
||||||
|
from utilities.filters import TreeNodeMultipleChoiceFilter
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
from dcim.models import Device, DeviceRole, Region, Site, Location
|
class DeviceFilterSet(django_filters.FilterSet):
|
||||||
|
|
||||||
from netbox.filtersets import NetBoxModelFilterSet
|
|
||||||
|
|
||||||
from tenancy.models import TenantGroup, Tenant
|
|
||||||
from tenancy.filtersets import TenancyFilterSet
|
|
||||||
|
|
||||||
from utilities.filters import TreeNodeMultipleChoiceFilter
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
|
||||||
q = django_filters.CharFilter(
|
q = django_filters.CharFilter(
|
||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
tag = TagFilter()
|
||||||
|
|
||||||
device_role_id = django_filters.ModelMultipleChoiceFilter(
|
device_role_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
field_name='device_role_id',
|
field_name='device_role_id',
|
||||||
queryset=DeviceRole.objects.all(),
|
queryset=DeviceRole.objects.all(),
|
||||||
@@ -40,7 +35,7 @@ class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Device
|
model = Device
|
||||||
fields = ['id', 'name']
|
fields = ['id', 'name', ]
|
||||||
|
|
||||||
def search(self, queryset, name, value):
|
def search(self, queryset, name, value):
|
||||||
"""Perform the filtered search."""
|
"""Perform the filtered search."""
|
||||||
@@ -49,4 +44,4 @@ class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
|||||||
qs_filter = (
|
qs_filter = (
|
||||||
Q(name__icontains=value)
|
Q(name__icontains=value)
|
||||||
)
|
)
|
||||||
return queryset.filter(qs_filter)
|
return queryset.filter(qs_filter)
|
||||||
@@ -1,30 +1,22 @@
|
|||||||
import imp
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
from extras.models import Tag
|
||||||
from dcim.models import Device, Site, Region, DeviceRole, Location
|
from dcim.models import Device, Site, Region, DeviceRole, Location
|
||||||
|
|
||||||
from django import forms
|
|
||||||
from tenancy.models import TenantGroup, Tenant
|
|
||||||
from tenancy.forms import TenancyFilterForm
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from netbox.forms import NetBoxModelFilterSetForm
|
|
||||||
from utilities.forms import (TagFilterField, DynamicModelMultipleChoiceField)
|
|
||||||
|
|
||||||
|
from utilities.forms import (TagFilterField, DynamicModelMultipleChoiceField, FilterForm)
|
||||||
allow_coordinates_saving = settings.PLUGINS_CONFIG["netbox_topology_views"]["allow_coordinates_saving"]
|
allow_coordinates_saving = settings.PLUGINS_CONFIG["netbox_topology_views"]["allow_coordinates_saving"]
|
||||||
|
|
||||||
|
class DeviceFilterForm(FilterForm):
|
||||||
class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|
||||||
model = Device
|
model = Device
|
||||||
fieldsets = (
|
field_groups = [
|
||||||
(None, ('q', 'hide_unconnected', 'save_coords')),
|
['q', 'hide_unconnected', 'save_coords'],
|
||||||
(None, ('tenant_group_id', 'tenant_id')),
|
['region_id', 'site_id', 'location_id'],
|
||||||
(None, ('region_id', 'site_id', 'location_id')),
|
['device_role_id'],
|
||||||
(None, ('device_role_id',)),
|
['tag'],
|
||||||
(None, ('tag',)),
|
]
|
||||||
)
|
|
||||||
|
|
||||||
region_id = DynamicModelMultipleChoiceField(
|
region_id = DynamicModelMultipleChoiceField(
|
||||||
queryset=Region.objects.all(),
|
queryset=Region.objects.all(),
|
||||||
@@ -53,6 +45,7 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|||||||
},
|
},
|
||||||
label=_('Location')
|
label=_('Location')
|
||||||
)
|
)
|
||||||
|
|
||||||
hide_unconnected = forms.BooleanField(
|
hide_unconnected = forms.BooleanField(
|
||||||
label=_("Hide Unconnected"),
|
label=_("Hide Unconnected"),
|
||||||
required=False,
|
required=False,
|
||||||
@@ -63,4 +56,5 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|||||||
required=False,
|
required=False,
|
||||||
disabled=(not allow_coordinates_saving),
|
disabled=(not allow_coordinates_saving),
|
||||||
initial=False)
|
initial=False)
|
||||||
|
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# no modeles yet
|
||||||
@@ -4,6 +4,14 @@ from utilities.choices import ButtonColorChoices
|
|||||||
menu_items = (
|
menu_items = (
|
||||||
PluginMenuItem(
|
PluginMenuItem(
|
||||||
link='plugins:netbox_topology_views:home',
|
link='plugins:netbox_topology_views:home',
|
||||||
link_text='Topology'
|
link_text='Topology',
|
||||||
|
buttons=(
|
||||||
|
PluginMenuButton(
|
||||||
|
link='plugins:netbox_topology_views:home',
|
||||||
|
title='Topology View',
|
||||||
|
icon_class='mdi mdi-plus-thick',
|
||||||
|
permissions=[],
|
||||||
|
),
|
||||||
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1 +1 @@
|
|||||||
var graph=null,container=null,downloadButton=null,MIME_TYPE="image/png",canvas=null,csrftoken=null,nodes=new vis.DataSet,edges=new vis.DataSet,options={interaction:{hover:!0,hoverConnectedEdges:!0,multiselect:!1},nodes:{shape:"image",brokenImage:"../../static/netbox_topology_views/img/role-unknown.png",size:35,font:{multi:"md",face:"helvetica"}},edges:{length:100,width:2,font:{face:"helvetica"}},physics:{solver:"forceAtlas2Based"}},selected_regions=[],selected_sites=[],coord_save_checkbox=null,htmlElement=null;function getCookie(e){var t=null;if(document.cookie&&""!==document.cookie)for(var n=document.cookie.split(";"),o=0;o<n.length;o++){var a=n[o].trim();if(a.substring(0,e.length+1)===e+"="){t=decodeURIComponent(a.substring(e.length+1));break}}return t}function htmlTitle(e){return(container=document.createElement("div")).innerHTML=e,container}function addEdge(e){e.title=htmlTitle(e.title),edges.add(e)}function addNode(e){e.title=htmlTitle(e.title),nodes.add(e)}function iniPlotboxIndex(){document.addEventListener("DOMContentLoaded",function(){csrftoken=getCookie("csrftoken"),container=document.getElementById("visgraph"),htmlElement=document.getElementsByTagName("html")[0],handleLoadData(),downloadButton=document.getElementById("btnDownloadImage"),btnFullView=document.getElementById("btnFullView"),coord_save_checkbox=document.getElementById("id_save_coords")},!1)}function handleLoadData(){null!==topology_data&&("dark"==htmlElement.dataset.netboxColorMode&&(options.nodes.font.color="#fff"),graph=null,nodes=new vis.DataSet,edges=new vis.DataSet,graph=new vis.Network(container,{nodes:nodes,edges:edges},options),topology_data.edges.forEach(addEdge),topology_data.nodes.forEach(addNode),graph.fit(),canvas=document.getElementById("visgraph").getElementsByTagName("canvas")[0],graph.on("afterDrawing",function(){var e=canvas.toDataURL(MIME_TYPE);downloadButton.href=e,downloadButton.download="topology"}),graph.on("dragEnd",function(e){if(dragged=this.getPositions(e.nodes),coord_save_checkbox.checked&&0!==Object.keys(dragged).length)for(dragged_device in dragged){var t=dragged_device,n=new XMLHttpRequest;n.open("PATCH","/api/plugins/netbox_topology_views/save-coords/save_coords/"),n.setRequestHeader("X-CSRFToken",csrftoken),n.setRequestHeader("Accept","application/json"),n.setRequestHeader("Content-Type","application/json"),n.onreadystatechange=function(){4===n.readyState&&(console.log(n.status),console.log(n.responseText))};var o=JSON.stringify({node_id:t,x:dragged[t].x,y:dragged[t].y});n.send(o)}}))}
|
var graph=null,container=null,downloadButton=null,MIME_TYPE="image/png",canvas=null,csrftoken=null,nodes=new vis.DataSet,edges=new vis.DataSet,options={interaction:{hover:!0,hoverConnectedEdges:!0,multiselect:!1},nodes:{shape:"image",brokenImage:"../../static/netbox_topology_views/img/role-unknown.png",size:35,font:{multi:"md",face:"helvetica"}},edges:{length:100,width:2,font:{face:"helvetica"}},physics:{solver:"forceAtlas2Based"}},selected_regions=[],selected_sites=[],coord_save_checkbox=null;function getCookie(e){var t=null;if(document.cookie&&""!==document.cookie)for(var n=document.cookie.split(";"),o=0;o<n.length;o++){var a=n[o].trim();if(a.substring(0,e.length+1)===e+"="){t=decodeURIComponent(a.substring(e.length+1));break}}return t}function htmlTitle(e){return(container=document.createElement("div")).innerHTML=e,container}function addEdge(e){e.title=htmlTitle(e.title),edges.add(e)}function addNode(e){e.title=htmlTitle(e.title),nodes.add(e)}function iniPlotboxIndex(){document.addEventListener("DOMContentLoaded",function(){csrftoken=getCookie("csrftoken"),container=document.getElementById("visgraph"),handleLoadData(),downloadButton=document.getElementById("btnDownloadImage"),btnFullView=document.getElementById("btnFullView"),coord_save_checkbox=document.getElementById("id_save_coords")},!1)}function handleLoadData(){null!==topology_data&&(graph=null,nodes=new vis.DataSet,edges=new vis.DataSet,graph=new vis.Network(container,{nodes:nodes,edges:edges},options),topology_data.edges.forEach(addEdge),topology_data.nodes.forEach(addNode),graph.fit(),canvas=document.getElementById("visgraph").getElementsByTagName("canvas")[0],graph.on("afterDrawing",function(){var e=canvas.toDataURL(MIME_TYPE);downloadButton.href=e,downloadButton.download="topology"}),graph.on("dragEnd",function(e){if(dragged=this.getPositions(e.nodes),coord_save_checkbox.checked&&0!==Object.keys(dragged).length)for(dragged_device in dragged){var t=dragged_device,n=new XMLHttpRequest;n.open("PATCH","/api/plugins/netbox_topology_views/save-coords/save_coords/"),n.setRequestHeader("X-CSRFToken",csrftoken),n.setRequestHeader("Accept","application/json"),n.setRequestHeader("Content-Type","application/json"),n.onreadystatechange=function(){4===n.readyState&&(console.log(n.status),console.log(n.responseText))};var o=JSON.stringify({node_id:t,x:dragged[t].x,y:dragged[t].y});n.send(o)}}))}
|
||||||
@@ -35,7 +35,6 @@ var options = {
|
|||||||
var selected_regions = [];
|
var selected_regions = [];
|
||||||
var selected_sites = [];
|
var selected_sites = [];
|
||||||
var coord_save_checkbox = null;
|
var coord_save_checkbox = null;
|
||||||
var htmlElement = null;
|
|
||||||
|
|
||||||
function getCookie(name) {
|
function getCookie(name) {
|
||||||
var cookieValue = null;
|
var cookieValue = null;
|
||||||
@@ -74,7 +73,6 @@ function iniPlotboxIndex() {
|
|||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
csrftoken = getCookie('csrftoken');
|
csrftoken = getCookie('csrftoken');
|
||||||
container = document.getElementById('visgraph');
|
container = document.getElementById('visgraph');
|
||||||
htmlElement = document.getElementsByTagName("html")[0];
|
|
||||||
handleLoadData();
|
handleLoadData();
|
||||||
downloadButton = document.getElementById('btnDownloadImage');
|
downloadButton = document.getElementById('btnDownloadImage');
|
||||||
btnFullView = document.getElementById('btnFullView');
|
btnFullView = document.getElementById('btnFullView');
|
||||||
@@ -84,11 +82,6 @@ function iniPlotboxIndex() {
|
|||||||
|
|
||||||
function handleLoadData() {
|
function handleLoadData() {
|
||||||
if (topology_data !== null) {
|
if (topology_data !== null) {
|
||||||
|
|
||||||
if (htmlElement.dataset.netboxColorMode == "dark") {
|
|
||||||
options.nodes.font.color = "#fff";
|
|
||||||
}
|
|
||||||
|
|
||||||
graph = null;
|
graph = null;
|
||||||
nodes = new vis.DataSet();
|
nodes = new vis.DataSet();
|
||||||
edges = new vis.DataSet();
|
edges = new vis.DataSet();
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link" id="filters-form-tab" data-bs-toggle="tab" data-bs-target="#filters-form" type="button" role="tab" aria-controls="object-list" aria-selected="false">
|
<button class="nav-link" id="filters-form-tab" data-bs-toggle="tab" data-bs-target="#filters-form" type="button" role="tab" aria-controls="object-list" aria-selected="false">
|
||||||
Filters
|
Filters
|
||||||
{% if filter_form %}{% badge filter_form.changed_data|length bg_color="blue" %}{% endif %}
|
{% if filter_form %}{% badge filter_form.changed_data|length bg_class="primary" %}{% endif %}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -45,31 +45,30 @@
|
|||||||
{% endblock tabs %}
|
{% endblock tabs %}
|
||||||
|
|
||||||
{% block content-wrapper %}
|
{% block content-wrapper %}
|
||||||
{% with config=settings.PLUGINS_CONFIG.netbox_topology_views %}
|
{% with config=settings.PLUGINS_CONFIG.netbox_topology_views %}
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
|
||||||
<div class="tab-pane show active" id="networks" role="tabpanel" aria-labelledby="network-tab">
|
<div class="tab-pane show active" id="networks" role="tabpanel" aria-labelledby="network-tab">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div id="visgraph" class=""></div>
|
<div id="visgraph" class=""></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var topology_data = {{ topology_data | safe }};
|
var topology_data = {{ topology_data | safe }};
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if filter_form %}
|
{% if filter_form %}
|
||||||
<div class="tab-pane show" id="filters-form" role="tabpanel" aria-labelledby="filters-form-tab">
|
<div class="tab-pane show" id="filters-form" role="tabpanel" aria-labelledby="filters-form-tab">
|
||||||
{% include 'inc/filter_list.html' %}
|
{% include 'inc/filter_list.html' %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endwith %}
|
|
||||||
{% endblock content-wrapper %}
|
|
||||||
|
|
||||||
{% block javascript %}
|
<script src="{% static 'netbox_topology_views/js/vendor.js' %}"></script>
|
||||||
<script src="{% static 'netbox_topology_views/js/vendor.js' %}"></script>
|
|
||||||
<script src="{% static 'netbox_topology_views/js/app.js' %}"></script>
|
<script src="{% static 'netbox_topology_views/js/app.js' %}"></script>
|
||||||
<script type="application/javascript">iniPlotboxIndex()</script>
|
|
||||||
{% endblock javascript %}
|
<script type="application/javascript"> iniPlotboxIndex()</script>
|
||||||
|
{% endwith %}
|
||||||
|
{% endblock content-wrapper %}
|
||||||
|
|||||||
@@ -66,53 +66,52 @@ def get_topology_data(queryset, hide_unconnected):
|
|||||||
device_has_connections = True
|
device_has_connections = True
|
||||||
else:
|
else:
|
||||||
if settings.PLUGINS_CONFIG["netbox_topology_views"]["enable_circuit_terminations"]:
|
if settings.PLUGINS_CONFIG["netbox_topology_views"]["enable_circuit_terminations"]:
|
||||||
if link_from.termination_a_type.name == "circuit termination":
|
if link_from.termination_a.circuit.id not in circuit_ids:
|
||||||
if link_from.termination_a.circuit.id not in circuit_ids:
|
circuit_ids.append(link_from.termination_a.circuit.id)
|
||||||
circuit_ids.append(link_from.termination_a.circuit.id)
|
edge_ids += 1
|
||||||
edge_ids += 1
|
|
||||||
|
|
||||||
cable_b_dev_name = link_from.termination_b.device.name
|
cable_b_dev_name = link_from.termination_b.device.name
|
||||||
if cable_b_dev_name is None:
|
if cable_b_dev_name is None:
|
||||||
cable_b_dev_name = "device B name unknown"
|
cable_b_dev_name = "device B name unknown"
|
||||||
cable_b_name = link_from.termination_b.name
|
cable_b_name = link_from.termination_b.name
|
||||||
if cable_b_name is None:
|
if cable_b_name is None:
|
||||||
cable_b_name = "cable B name unknown"
|
cable_b_name = "cable B name unknown"
|
||||||
|
|
||||||
edge = {}
|
edge = {}
|
||||||
edge["id"] = edge_ids
|
edge["id"] = edge_ids
|
||||||
edge["to"] = link_from.termination_b.device.id
|
edge["to"] = link_from.termination_b.device.id
|
||||||
edge["dashes"] = True
|
edge["dashes"] = True
|
||||||
title = ""
|
title = ""
|
||||||
|
|
||||||
title += "Circuit provider: " + link_from.termination_a.circuit.provider.name + "<br>"
|
title += "Circuit provider: " + link_from.termination_a.circuit.provider.name + "<br>"
|
||||||
title += "Termination between <br>"
|
title += "Termination between <br>"
|
||||||
title += cable_b_dev_name + " [" + cable_b_name + "]<br>"
|
title += cable_b_dev_name + " [" + cable_b_name + "]<br>"
|
||||||
|
|
||||||
if link_from.termination_a.circuit.termination_a is not None and link_from.termination_a.circuit.termination_a.cable is not None and link_from.termination_a.circuit.termination_a.cable.id != link_from.id and link_from.termination_a.circuit.termination_a.cable.termination_b is not None and link_from.termination_a.circuit.termination_a.cable.termination_b.device is not None:
|
if link_from.termination_a.circuit.termination_a is not None and link_from.termination_a.circuit.termination_a.cable is not None and link_from.termination_a.circuit.termination_a.cable.id != link_from.id and link_from.termination_a.circuit.termination_a.cable.termination_b is not None and link_from.termination_a.circuit.termination_a.cable.termination_b.device is not None:
|
||||||
edge["from"] = link_from.termination_a.circuit.termination_a.cable.termination_b.device.id
|
edge["from"] = link_from.termination_a.circuit.termination_a.cable.termination_b.device.id
|
||||||
|
|
||||||
cable_a_dev_name = link_from.termination_a.circuit.termination_a.cable.termination_b.device.name
|
cable_a_dev_name = link_from.termination_a.circuit.termination_a.cable.termination_b.device.name
|
||||||
if cable_a_dev_name is None:
|
if cable_a_dev_name is None:
|
||||||
cable_a_dev_name = "device B name unknown"
|
cable_a_dev_name = "device B name unknown"
|
||||||
cable_b_name = link_from.termination_a.circuit.termination_a.cable.termination_b.name
|
cable_b_name = link_from.termination_a.circuit.termination_a.cable.termination_b.name
|
||||||
if cable_a_name is None:
|
if cable_a_name is None:
|
||||||
cable_a_name = "cable B name unknown"
|
cable_a_name = "cable B name unknown"
|
||||||
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
|
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
|
||||||
edge["title"] = title
|
edge["title"] = title
|
||||||
edges.append(edge)
|
edges.append(edge)
|
||||||
|
|
||||||
if link_from.termination_a.circuit.termination_z is not None and link_from.termination_a.circuit.termination_z.cable is not None and link_from.termination_a.circuit.termination_z.cable.id != link_from.id and link_from.termination_a.circuit.termination_z.cable.termination_b is not None and link_from.termination_a.circuit.termination_z.cable.termination_b.device is not None:
|
if link_from.termination_a.circuit.termination_z is not None and link_from.termination_a.circuit.termination_z.cable is not None and link_from.termination_a.circuit.termination_z.cable.id != link_from.id and link_from.termination_a.circuit.termination_z.cable.termination_b is not None and link_from.termination_a.circuit.termination_z.cable.termination_b.device is not None:
|
||||||
edge["from"] = link_from.termination_a.circuit.termination_z.cable.termination_b.device.id
|
edge["from"] = link_from.termination_a.circuit.termination_z.cable.termination_b.device.id
|
||||||
|
|
||||||
cable_a_dev_name = link_from.termination_a.circuit.termination_z.cable.termination_b.device.name
|
cable_a_dev_name = link_from.termination_a.circuit.termination_z.cable.termination_b.device.name
|
||||||
if cable_a_dev_name is None:
|
if cable_a_dev_name is None:
|
||||||
cable_a_dev_name = "device B name unknown"
|
cable_a_dev_name = "device B name unknown"
|
||||||
cable_a_name = link_from.termination_a.circuit.termination_z.cable.termination_b.name
|
cable_a_name = link_from.termination_a.circuit.termination_z.cable.termination_b.name
|
||||||
if cable_a_name is None:
|
if cable_a_name is None:
|
||||||
cable_a_name = "cable B name unknown"
|
cable_a_name = "cable B name unknown"
|
||||||
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
|
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
|
||||||
edge["title"] = title
|
edge["title"] = title
|
||||||
edges.append(edge)
|
edges.append(edge)
|
||||||
|
|
||||||
if qs_device.id not in nodes_ids:
|
if qs_device.id not in nodes_ids:
|
||||||
if hide_unconnected == None or (hide_unconnected is True and device_has_connections is True):
|
if hide_unconnected == None or (hide_unconnected is True and device_has_connections is True):
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "netbox_topology_views",
|
"name": "netbox_topology_views",
|
||||||
"version": "1.1.0-beta.1",
|
"version": "1.0.0-beta.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "netbox_topology_views",
|
"name": "netbox_topology_views",
|
||||||
"version": "1.1.0-beta.1",
|
"version": "1.0.0-beta.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"resources": "gulp build",
|
"resources": "gulp build",
|
||||||
"resources_dev": "gulp build_dev"
|
"resources_dev": "gulp build_dev"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='netbox-topology-views',
|
name='netbox-topology-views',
|
||||||
version='1.1.0-beta.1',
|
version='1.0.0-beta.1',
|
||||||
description='An NetBox plugin to create Topology maps',
|
description='An NetBox plugin to create Topology maps',
|
||||||
url='https://github.com/mattieserver/netbox-topology-views',
|
url='https://github.com/mattieserver/netbox-topology-views',
|
||||||
author='Mattijs Vanhaverbeke',
|
author='Mattijs Vanhaverbeke',
|
||||||
|
|||||||
Reference in New Issue
Block a user