Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ce13cd1d2 | ||
|
|
b4e2f2418e | ||
|
|
5563e3c084 | ||
|
|
77a8a2c0d6 | ||
|
|
010179742c | ||
|
|
f2bbaed317 | ||
|
|
8c56f21f16 | ||
|
|
eb627bdedc | ||
|
|
291c033e34 | ||
|
|
1f389b3faa | ||
|
|
3d3ddaa7c4 |
@@ -29,7 +29,15 @@ Once installed, the plugin needs to be enabled in your `configuration.py`
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ class TopologyViewsConfig(PluginConfig):
|
||||
name = 'netbox_topology_views'
|
||||
verbose_name = 'Topology views'
|
||||
description = 'An plugin to render topology maps'
|
||||
version = '3.0.0-beta.2'
|
||||
version = '3.0.1'
|
||||
author = 'Mattijs Vanhaverbeke'
|
||||
author_email = 'author@example.com'
|
||||
base_url = 'netbox_topology_views'
|
||||
|
||||
@@ -41,10 +41,9 @@ class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=DeviceStatusChoices,
|
||||
null_value=None
|
||||
null_value=None,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class Meta:
|
||||
model = Device
|
||||
fields = ['id', 'name']
|
||||
|
||||
@@ -22,10 +22,10 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
model = Device
|
||||
fieldsets = (
|
||||
(None, ('q', 'hide_unconnected', 'save_coords', 'show_circuit', 'show_power' ,)),
|
||||
(None, ('tenant_group_id', 'tenant_id')),
|
||||
(None, ('region_id', 'site_id', 'location_id')),
|
||||
(None, ('device_role_id', )),
|
||||
(None, ('tag', 'status')),
|
||||
(None, ('tenant_group_id', 'tenant_id',)),
|
||||
(None, ('region_id', 'site_id', 'location_id',)),
|
||||
(None, ('device_role_id','id','status', )),
|
||||
(None, ('tag', )),
|
||||
)
|
||||
|
||||
region_id = DynamicModelMultipleChoiceField(
|
||||
@@ -38,6 +38,17 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
required=False,
|
||||
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(
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
@@ -66,7 +77,7 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
initial=False
|
||||
)
|
||||
show_power = forms.BooleanField(
|
||||
label=_("Show Power panel/feed"),
|
||||
label=_("Show Power Feeds"),
|
||||
required=False,
|
||||
initial=False
|
||||
)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from platform import node
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.shortcuts import render
|
||||
from django.db.models import Q
|
||||
from django.views.generic import View
|
||||
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 HttpResponseRedirect
|
||||
|
||||
|
||||
from .forms import DeviceFilterForm
|
||||
from .filters import DeviceFilterSet
|
||||
|
||||
import json
|
||||
|
||||
from dcim.models import Device, Cable, CableTermination, DeviceRole, PathEndpoint, Interface, FrontPort, RearPort, PowerPanel, PowerFeed
|
||||
from circuits.models import CircuitTermination, ProviderNetwork
|
||||
from dcim.models import Device, CableTermination, DeviceRole, Interface, FrontPort, RearPort, PowerPanel, PowerFeed
|
||||
from circuits.models import CircuitTermination
|
||||
from wireless.models import WirelessLink
|
||||
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):
|
||||
|
||||
@@ -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"]
|
||||
|
||||
device_ids = [d.id for d in queryset]
|
||||
site_ids = [d.site.id for d in queryset]
|
||||
|
||||
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")
|
||||
for circuit in 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:
|
||||
nodes_powerpanel[power_feed.power_panel.id] = power_feed.power_panel
|
||||
|
||||
power_link_name = ""
|
||||
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
|
||||
power_link_name =power_feed.link_peers[0].name
|
||||
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) }
|
||||
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": 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))
|
||||
|
||||
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:
|
||||
cable_ids[link.cable.id] = {}
|
||||
else:
|
||||
if cable_ids[link.cable.id]['B'] is not None:
|
||||
complete_link = True
|
||||
if 'B' in cable_ids[link.cable.id]:
|
||||
if cable_ids[link.cable.id]['B'] is not None:
|
||||
complete_link = True
|
||||
elif link.cable_end == "B":
|
||||
if link.cable.id not in cable_ids:
|
||||
cable_ids[link.cable.id] = {}
|
||||
else:
|
||||
if cable_ids[link.cable.id]['A'] is not None:
|
||||
complete_link = True
|
||||
if 'A' in cable_ids[link.cable.id]:
|
||||
if cable_ids[link.cable.id]['A'] is not None:
|
||||
complete_link = True
|
||||
else:
|
||||
print("Unkown cable end")
|
||||
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"]
|
||||
|
||||
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
|
||||
|
||||
@@ -7,7 +7,7 @@ with open(path.join(top_level_directory, 'README.md'), encoding='utf-8') as file
|
||||
|
||||
setup(
|
||||
name='netbox-topology-views',
|
||||
version='3.0.0-beta.2',
|
||||
version='3.0.1',
|
||||
description='An NetBox plugin to create Topology maps',
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/markdown',
|
||||
|
||||
Reference in New Issue
Block a user