Compare commits

...
10 Commits
Author SHA1 Message Date
Mattijs Vanhaverbeke 9ce13cd1d2 bump version 2022-09-16 16:14:42 +02:00
mattieserver b4e2f2418e added extra checks (#166) 2022-09-16 16:13:32 +02:00
mattieserver 5563e3c084 added device filter option (#165) 2022-09-16 16:07:14 +02:00
mattieserver 77a8a2c0d6 Removed print 2022-09-16 14:52:00 +02:00
mattieserver 010179742c 159 fix power filter (#164)
* fix site_ids var

* fixed power cable name + change power filter name
2022-09-16 14:50:24 +02:00
mattieserver f2bbaed317 added console cable support (#157)
* added console cable support

* removed print
2022-09-14 14:50:10 +02:00
mattieserver 8c56f21f16 Update README.md 2022-09-13 08:46:05 +02:00
mattieserver eb627bdedc Update README.md 2022-09-12 18:36:27 +02:00
mattieserver 291c033e34 Update README.md 2022-09-12 18:23:33 +02:00
mattieserver 1f389b3faa Update README.md 2022-09-12 18:20:18 +02:00
6 changed files with 49 additions and 26 deletions
+13 -2
View File
@@ -29,7 +29,15 @@ Once installed, the plugin needs to be enabled in your `configuration.py`
PLUGINS = ["netbox_topology_views"] PLUGINS = ["netbox_topology_views"]
``` ```
Then run `python3 manage.py collectstatic --no-input` First run `source /opt/netbox/venv/bin/activate` to enter the Python virtual environment.
Then run
```bash
cd /opt/netbox/netbox
pip3 install netbox-topology-views
python3 manage.py collectstatic --no-input
```
### Versions ### Versions
@@ -48,7 +56,10 @@ There is also support for custom fields.
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. 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".
Please read the "Configure" chapter to set the `allow_coordinates_saving` option to True.
You might also set the `always_save_coordinates` option to True.
## Configure ## Configure
+1 -1
View File
@@ -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 = '3.0.0' version = '3.0.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'
+2 -3
View File
@@ -41,10 +41,9 @@ class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
) )
status = django_filters.MultipleChoiceFilter( status = django_filters.MultipleChoiceFilter(
choices=DeviceStatusChoices, choices=DeviceStatusChoices,
null_value=None null_value=None,
) )
class Meta: class Meta:
model = Device model = Device
fields = ['id', 'name'] fields = ['id', 'name']
+16 -5
View File
@@ -22,10 +22,10 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = Device model = Device
fieldsets = ( fieldsets = (
(None, ('q', 'hide_unconnected', 'save_coords', 'show_circuit', 'show_power' ,)), (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', )), (None, ('device_role_id','id','status', )),
(None, ('tag', 'status')), (None, ('tag', )),
) )
region_id = DynamicModelMultipleChoiceField( region_id = DynamicModelMultipleChoiceField(
@@ -38,6 +38,17 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
required=False, required=False,
label=_('Device Role') label=_('Device Role')
) )
id = DynamicModelMultipleChoiceField(
queryset=Device.objects.all(),
required=False,
label=_('Device'),
query_params={
'location_id' : '$location_id',
'region_id': '$region_id',
'site_id': '$site_id',
'role_id': '$device_role_id',
},
)
site_id = DynamicModelMultipleChoiceField( site_id = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,
@@ -66,7 +77,7 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
initial=False initial=False
) )
show_power = forms.BooleanField( show_power = forms.BooleanField(
label=_("Show Power panel/feed"), label=_("Show Power Feeds"),
required=False, required=False,
initial=False initial=False
) )
+16 -14
View File
@@ -1,5 +1,4 @@
from platform import node from django.shortcuts import 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
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
@@ -7,18 +6,17 @@ 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, CableTermination, DeviceRole, PathEndpoint, Interface, FrontPort, RearPort, PowerPanel, PowerFeed from dcim.models import Device, CableTermination, DeviceRole, Interface, FrontPort, RearPort, PowerPanel, PowerFeed
from circuits.models import CircuitTermination, ProviderNetwork from circuits.models import CircuitTermination
from wireless.models import WirelessLink 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"] supported_termination_types = ["interface", "front port", "rear port", "power outlet", "power port", "console port", "console server port"]
def create_node(device, save_coords, circuit = None, powerpanel = None, powerfeed= None): def create_node(device, save_coords, circuit = None, powerpanel = None, powerfeed= None):
@@ -170,9 +168,9 @@ def get_topology_data(queryset, hide_unconnected, save_coords, show_circuit, sho
ignore_cable_type = settings.PLUGINS_CONFIG["netbox_topology_views"]["ignore_cable_type"] ignore_cable_type = settings.PLUGINS_CONFIG["netbox_topology_views"]["ignore_cable_type"]
device_ids = [d.id for d in queryset] device_ids = [d.id for d in queryset]
site_ids = [d.site.id for d in queryset]
if show_circuit: if show_circuit:
site_ids = [d.site.id for d in queryset]
circuits = CircuitTermination.objects.filter( Q(site_id__in=site_ids) | Q( provider_network__isnull=False) ).prefetch_related("provider_network", "circuit") circuits = CircuitTermination.objects.filter( Q(site_id__in=site_ids) | Q( provider_network__isnull=False) ).prefetch_related("provider_network", "circuit")
for circuit in circuits: for circuit in circuits:
if not hide_unconnected and circuit.circuit.id not in nodes_circuits: if not hide_unconnected and circuit.circuit.id not in nodes_circuits:
@@ -224,16 +222,18 @@ def get_topology_data(queryset, hide_unconnected, save_coords, show_circuit, sho
if power_feed.power_panel.id not in nodes_powerpanel: if power_feed.power_panel.id not in nodes_powerpanel:
nodes_powerpanel[power_feed.power_panel.id] = power_feed.power_panel nodes_powerpanel[power_feed.power_panel.id] = power_feed.power_panel
power_link_name = ""
if power_feed.id not in nodes_powerfeed: if power_feed.id not in nodes_powerfeed:
if hide_unconnected: if hide_unconnected:
if power_feed.link_peers[0].device.id in device_ids: if power_feed.link_peers[0].device.id in device_ids:
nodes_powerfeed[power_feed.id] = power_feed nodes_powerfeed[power_feed.id] = power_feed
power_link_name =power_feed.link_peers[0].name
else: else:
nodes_powerfeed[power_feed.id] = power_feed nodes_powerfeed[power_feed.id] = power_feed
edge_ids += 1 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_a = { "termination_name": power_feed.power_panel.name, "termination_device_name": "", "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) } termination_b = { "termination_name": power_feed.name, "termination_device_name": power_link_name, "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)) 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 is not None:
@@ -259,14 +259,16 @@ def get_topology_data(queryset, hide_unconnected, save_coords, show_circuit, sho
if link.cable.id not in cable_ids: if link.cable.id not in cable_ids:
cable_ids[link.cable.id] = {} cable_ids[link.cable.id] = {}
else: else:
if cable_ids[link.cable.id]['B'] is not None: if 'B' in cable_ids[link.cable.id]:
complete_link = True if cable_ids[link.cable.id]['B'] is not None:
complete_link = True
elif link.cable_end == "B": elif link.cable_end == "B":
if link.cable.id not in cable_ids: if link.cable.id not in cable_ids:
cable_ids[link.cable.id] = {} cable_ids[link.cable.id] = {}
else: else:
if cable_ids[link.cable.id]['A'] is not None: if 'A' in cable_ids[link.cable.id]:
complete_link = True if cable_ids[link.cable.id]['A'] is not None:
complete_link = True
else: else:
print("Unkown cable end") print("Unkown cable end")
cable_ids[link.cable.id][link.cable_end] = link cable_ids[link.cable.id][link.cable_end] = link
@@ -288,7 +290,7 @@ def get_topology_data(queryset, hide_unconnected, save_coords, show_circuit, sho
termination_a = cable_ids[link.cable.id]["A"] 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)) 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: for wlan_link in wlan_links:
if wlan_link.interface_a.device.id not in nodes_devices: if wlan_link.interface_a.device.id not in nodes_devices:
nodes_devices[wlan_link.interface_a.device.id] = wlan_link.interface_a.device nodes_devices[wlan_link.interface_a.device.id] = wlan_link.interface_a.device
+1 -1
View File
@@ -7,7 +7,7 @@ with open(path.join(top_level_directory, 'README.md'), encoding='utf-8') as file
setup( setup(
name='netbox-topology-views', name='netbox-topology-views',
version='3.0.0', version='3.0.1',
description='An NetBox plugin to create Topology maps', description='An NetBox plugin to create Topology maps',
long_description=long_description, long_description=long_description,
long_description_content_type='text/markdown', long_description_content_type='text/markdown',