Skip to content

Commit 2893fff

Browse files
authored
Closes #484: Show device information (#573)
* Add model and individual option * Add forms and views * minor changes
1 parent 25fdcb6 commit 2893fff

File tree

8 files changed

+94
-12
lines changed

8 files changed

+94
-12
lines changed

Diff for: netbox_topology_views/api/serializers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ class Meta:
5050
class IndividualOptionsSerializer(NetBoxModelSerializer):
5151
class Meta:
5252
model = IndividualOptions
53-
fields = ("ignore_cable_type", "save_coords", "show_unconnected", "show_cables", "show_logical_connections", "show_single_cable_logical_conns", "show_neighbors", "show_circuit", "show_power", "show_wireless", "group_sites", "group_locations", "group_racks", "group_virtualchassis", "draw_default_layout", "straight_cables", "grid_size")
53+
fields = ("ignore_cable_type", "save_coords", "show_unconnected", "show_cables", "show_logical_connections", "show_single_cable_logical_conns", "show_neighbors", "show_circuit", "show_power", "show_wireless", "group_sites", "group_locations", "group_racks", "group_virtualchassis", "draw_default_layout", "straight_cables", "grid_size", "node_label_items")

Diff for: netbox_topology_views/api/views.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def list(self, request):
114114

115115
if request.GET:
116116

117-
filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, grid_size = get_query_settings(request)
117+
filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, grid_size, node_label_items = get_query_settings(request)
118118

119119
# Read options from saved filters as NetBox does not handle custom plugin filters
120120
if "filter_id" in request.GET and request.GET["filter_id"] != '':
@@ -138,6 +138,7 @@ def list(self, request):
138138
if show_neighbors == False and 'show_neighbors' in saved_filter_params: show_neighbors = saved_filter_params['show_neighbors']
139139
if straight_cables == False and 'straight_cables' in saved_filter_params: show_neighbors = saved_filter_params['straight_cables']
140140
if grid_size == 0 and 'grid_size' in saved_filter_params: grid_size = saved_filter_params['grid_size']
141+
if node_label_items == () and 'node_label_items' in saved_filter_params: node_label_items = saved_filter_params['node_label_items']
141142
except SavedFilter.DoesNotExist: # filter_id not found
142143
pass
143144
except Exception as inst:
@@ -170,8 +171,9 @@ def list(self, request):
170171
group_id=group_id,
171172
straight_cables=straight_cables,
172173
grid_size=grid_size,
174+
node_label_items=node_label_items,
173175
)
174-
xml_data = export_data_to_xml(topo_data).decode('utf-8')
176+
xml_data = export_data_to_xml(topo_data).decode('utf-8').replace('\n', '
')
175177

176178
return HttpResponse(xml_data, content_type="application/xml; charset=utf-8")
177179
else:

Diff for: netbox_topology_views/choices.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from utilities.choices import ChoiceSet
2+
3+
class NodeLabelItems(ChoiceSet):
4+
DEVICE_NAME = 'devicename'
5+
PRIMARY_IPV4 = 'primaryipv4'
6+
PRIMARY_IPV6 = 'primaryipv6'
7+
OUT_OF_BAND_IP = 'outofbandip'
8+
9+
CHOICES = [
10+
(DEVICE_NAME, 'Device Name'),
11+
(PRIMARY_IPV4, 'Primary IPv4'),
12+
(PRIMARY_IPV6, 'Primary IPv6'),
13+
(OUT_OF_BAND_IP, 'Out-of-band IP'),
14+
]

Diff for: netbox_topology_views/forms.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
)
2424

2525
from netbox_topology_views.models import IndividualOptions, CoordinateGroup, Coordinate, CircuitCoordinate, PowerPanelCoordinate, PowerFeedCoordinate
26+
from netbox_topology_views.choices import NodeLabelItems
2627

2728
class DeviceFilterForm(
2829
LocalConfigContextFilterForm,
@@ -36,7 +37,7 @@ class DeviceFilterForm(
3637
FieldSet(
3738
'group', 'ignore_cable_type', 'save_coords', 'show_unconnected', 'show_cables', 'show_logical_connections',
3839
'show_single_cable_logical_conns', 'show_neighbors', 'show_circuit', 'show_power', 'show_wireless',
39-
'group_sites', 'group_locations', 'group_racks', 'group_virtualchassis', 'straight_cables', 'grid_size', name=_("Options")
40+
'group_sites', 'group_locations', 'group_racks', 'group_virtualchassis', 'straight_cables', 'grid_size', 'node_label_items', name=_("Options")
4041
),
4142
FieldSet('id', name=_("Device")),
4243
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_("Location")),
@@ -335,6 +336,11 @@ class DeviceFilterForm(
335336
max_value=1000,
336337
help_text=_('Show grid and snap dragged icons to grid. Set to 0 to disable grid and snapping.')
337338
)
339+
node_label_items = forms.MultipleChoiceField(
340+
label=_('Node Label Items'),
341+
required=False,
342+
choices=NodeLabelItems
343+
)
338344

339345
class CoordinateGroupsForm(NetBoxModelForm):
340346
fieldsets = (
@@ -530,6 +536,7 @@ class IndividualOptionsForm(NetBoxModelForm):
530536
'draw_default_layout',
531537
'straight_cables',
532538
'grid_size',
539+
'node_label_items',
533540
),
534541
)
535542

@@ -681,6 +688,12 @@ class IndividualOptionsForm(NetBoxModelForm):
681688
'Integers between 0 and 1000 are allowed. Snap to grid will be '
682689
'automatically enabled for values > 0.')
683690
)
691+
node_label_items = forms.MultipleChoiceField(
692+
label=_('Node Label Items'),
693+
required=False,
694+
choices=NodeLabelItems,
695+
help_text=_('Choose Label Items that you want to be displayed.')
696+
)
684697

685698
class Meta:
686699
model = IndividualOptions
@@ -689,5 +702,5 @@ class Meta:
689702
'save_coords', 'show_unconnected', 'show_cables', 'show_logical_connections',
690703
'show_single_cable_logical_conns', 'show_neighbors', 'show_circuit', 'show_power',
691704
'show_wireless', 'group_sites', 'group_locations', 'group_racks', 'group_virtualchassis', 'draw_default_layout',
692-
'straight_cables', 'grid_size'
705+
'straight_cables', 'grid_size', 'node_label_items'
693706
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.0.9 on 2024-09-27 18:19
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('netbox_topology_views', '0010_individualoptions_grid_size'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='individualoptions',
15+
name='node_label_items',
16+
field=models.CharField(blank=True, max_length=255),
17+
),
18+
]

Diff for: netbox_topology_views/models.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
image_static_url,
2626
)
2727

28+
from netbox_topology_views.choices import NodeLabelItems
2829

2930
class RoleImage(ChangeLoggingMixin, ExportTemplatesMixin, EventRulesMixin):
3031
class Meta:
@@ -407,7 +408,11 @@ class IndividualOptions(NetBoxModel):
407408
grid_size = models.PositiveSmallIntegerField(
408409
default=0
409410
)
410-
411+
node_label_items = models.CharField(
412+
max_length=255,
413+
blank=True
414+
)
415+
411416
_netbox_private = True
412417

413418
def __str___(self):

Diff for: netbox_topology_views/utils.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,11 @@ def get_query_settings(request):
200200
if "grid_size" in request.GET:
201201
grid_size = request.GET.getlist('grid_size')
202202

203-
return filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, grid_size
203+
node_label_items = ()
204+
if "node_label_items" in request.GET:
205+
node_label_items = request.GET.getlist('node_label_items')
206+
207+
return filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, grid_size, node_label_items
204208

205209
class LinePattern():
206210
wireless = [2, 10, 2, 10]

Diff for: netbox_topology_views/views.py

+31-5
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
IMAGE_FILETYPES
7979
)
8080

81-
81+
from netbox_topology_views.choices import NodeLabelItems
8282

8383
def get_image_for_entity(entity: Union[Device, Circuit, PowerPanel, PowerFeed]):
8484
is_device = isinstance(entity, Device)
@@ -97,7 +97,10 @@ def get_image_for_entity(entity: Union[Device, Circuit, PowerPanel, PowerFeed]):
9797

9898

9999
def create_node(
100-
device: Union[Device, Circuit, PowerPanel, PowerFeed], save_coords: bool, group_id="default"
100+
device: Union[Device, Circuit, PowerPanel, PowerFeed],
101+
save_coords: bool,
102+
node_label_items: list,
103+
group_id="default"
101104
):
102105
node = {}
103106
node_content = ""
@@ -229,7 +232,22 @@ def create_node(
229232
dev_title = "<table><tbody> %s</tbody></table>" % (node_content)
230233
node["title"] = dev_title
231234
node["name"] = dev_name
232-
node["label"] = dev_name
235+
236+
# Create a list of possible label items. Omit None types
237+
label_mapping = {
238+
NodeLabelItems.DEVICE_NAME: dev_name,
239+
NodeLabelItems.PRIMARY_IPV4: device.primary_ip4,
240+
NodeLabelItems.PRIMARY_IPV6: device.primary_ip6,
241+
NodeLabelItems.OUT_OF_BAND_IP: device.oob_ip,
242+
}
243+
244+
label_items = []
245+
for item in node_label_items:
246+
if label_mapping[item] is not None:
247+
label_items.append(str(label_mapping[item]))
248+
node_label = '\n'.join(label_items)
249+
250+
node["label"] = node_label
233251
node["shape"] = "image"
234252
node["href"] = device.get_absolute_url()
235253
node["image"] = get_image_for_entity(device)
@@ -350,6 +368,7 @@ def get_topology_data(
350368
group_id,
351369
straight_cables: bool,
352370
grid_size: list,
371+
node_label_items: list,
353372
):
354373

355374
supported_termination_types = []
@@ -698,7 +717,7 @@ def get_topology_data(
698717
results = {}
699718

700719
for d in nodes_devices.values():
701-
nodes.append(create_node(d, save_coords, group_id))
720+
nodes.append(create_node(d, save_coords, node_label_items, group_id))
702721

703722
results["nodes"] = nodes
704723
results["edges"] = edges
@@ -729,7 +748,7 @@ def get(self, request):
729748

730749
if request.GET:
731750

732-
filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, grid_size = get_query_settings(request)
751+
filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, grid_size, node_label_items = get_query_settings(request)
733752

734753
# Read options from saved filters as NetBox does not handle custom plugin filters
735754
if "filter_id" in request.GET and request.GET["filter_id"] != '':
@@ -753,6 +772,7 @@ def get(self, request):
753772
if show_neighbors == False and 'show_neighbors' in saved_filter_params: show_neighbors = saved_filter_params['show_neighbors']
754773
if straight_cables == False and 'straight_cables' in saved_filter_params: straight_cables = saved_filter_params['straight_cables']
755774
if grid_size == 0 and 'grid_size' in saved_filter_params: grid_size = saved_filter_params['grid_size']
775+
if node_label_items == () and 'node_label_items' in saved_filter_params: node_label_items = saved_filter_params['node_label_items']
756776
except SavedFilter.DoesNotExist: # filter_id not found
757777
pass
758778
except Exception as inst:
@@ -787,6 +807,7 @@ def get(self, request):
787807
group_id=group_id,
788808
straight_cables=straight_cables,
789809
grid_size=grid_size,
810+
node_label_items=node_label_items,
790811
)
791812

792813
else:
@@ -816,6 +837,10 @@ def get(self, request):
816837
if individualOptions.group_virtualchassis: q['group_virtualchassis'] = "True"
817838
if individualOptions.straight_cables: q['straight_cables'] = "True"
818839
if individualOptions.grid_size: q['grid_size'] = individualOptions.grid_size
840+
node_label_items = IndividualOptions.objects.get(id=individualOptions.id).node_label_items.translate({ord(i): None for i in '[]\''}).split(', ')
841+
if node_label_items == ['']: node_label_items = []
842+
q.setlist("node_label_items", node_label_items)
843+
819844
if individualOptions.draw_default_layout:
820845
q['draw_init'] = "True"
821846
else:
@@ -1177,6 +1202,7 @@ def get(self, request):
11771202
'draw_default_layout': queryset.draw_default_layout,
11781203
'straight_cables': queryset.straight_cables,
11791204
'grid_size': queryset.grid_size,
1205+
'node_label_items': tuple(queryset.node_label_items.translate({ord(i): None for i in '[]\''}).split(', ')),
11801206
},
11811207
)
11821208

0 commit comments

Comments
 (0)