5
5
from dcim .models import *
6
6
from ipam .models import *
7
7
from circuits .models import *
8
- from .models import SavedTopology
8
+ from extras .models import SavedFilter
9
9
from . import forms , filters
10
10
from django .contrib .auth .mixins import PermissionRequiredMixin
11
11
from django .conf import settings
@@ -247,101 +247,6 @@ def filter_tags(tags):
247
247
tags = filtered_tags
248
248
return tags
249
249
250
- def get_vlan_topology (nb_devices_qs , vlans ):
251
-
252
- topology_dict = {'nodes' : [], 'edges' : []}
253
- device_roles = set ()
254
- all_device_tags = set ()
255
- multi_cable_connections = []
256
- vlan = VLAN .objects .get (id = vlans )
257
- interfaces = vlan .get_interfaces ()
258
- filtred_devices = [d .id for d in nb_devices_qs ]
259
- filtred_interfaces = []
260
- for interface in interfaces :
261
- if interface .is_connectable :
262
- direct_device_id = interface .device .id
263
- interface_trace = interface .trace ()
264
- if len (interface_trace ) != 0 :
265
- termination_b_iface = interface_trace [- 1 ][- 1 ]
266
- connected_device_id = termination_b_iface .device .id
267
- if (direct_device_id in filtred_devices ) or (direct_device_id in filtred_devices ):
268
- filtred_interfaces .append (interface )
269
-
270
-
271
-
272
- devices = []
273
- for interface in filtred_interfaces :
274
- if interface .is_connectable :
275
- if interface .device not in devices :
276
- devices .append (interface .device )
277
- interface_trace = interface .trace ()
278
- if len (interface_trace ) != 0 :
279
- termination_b_iface = interface_trace [- 1 ][- 1 ]
280
- if termination_b_iface .device not in devices :
281
- devices .append (termination_b_iface .device )
282
-
283
-
284
- device_ids = [d .id for d in devices ]
285
- for device in devices :
286
- device_is_passive = False
287
- device_url = device .get_absolute_url ()
288
- if NETBOX_CURRENT_VERSION >= version .parse ("4.0.0" ):
289
- device_role_obj = device .role
290
- else :
291
- device_role_obj = device .device_role
292
- primary_ip = ''
293
- if device .primary_ip :
294
- primary_ip = str (device .primary_ip .address )
295
- tags = [str (tag ) for tag in device .tags .names ()]
296
- for tag in tags :
297
- all_device_tags .add ((tag , not tag_is_hidden (tag )))
298
- topology_dict ['nodes' ].append ({
299
- 'id' : device .name ,
300
- 'name' : device .name ,
301
- 'label' : {'text' : device .name },
302
- 'dcimDeviceLink' : device_url ,
303
- 'primaryIP' : primary_ip ,
304
- 'serial_number' : device .serial ,
305
- 'model' : device .device_type .model ,
306
- 'deviceRole' : device_role_obj .slug ,
307
- 'layer' : get_node_layer_sort_preference (
308
- device_role_obj .slug
309
- ),
310
- 'iconName' : get_icon_type (
311
- device .id
312
- ),
313
- 'isPassive' : device_is_passive ,
314
- 'tags' : tags ,
315
- })
316
- is_visible = not (device_role_obj .slug in UNDISPLAYED_DEVICE_ROLE_SLUGS )
317
- device_roles .add ((device_role_obj .slug , device_role_obj .name , is_visible ))
318
-
319
- mapped_links = []
320
- for interface in filtred_interfaces :
321
- if interface .is_connectable :
322
- interface_trace = interface .trace ()
323
- if len (interface_trace ) != 0 :
324
- source_cable = interface_trace [0 ]
325
- dest_cable = interface_trace [- 1 ]
326
- mapping_link = [source_cable [0 ].device .id ,dest_cable [- 1 ].device .id ]
327
- if (mapping_link not in mapped_links ) and (mapping_link .reverse () not in mapped_links ):
328
- mapped_links .append (mapping_link )
329
-
330
- topology_dict ['edges' ].append ({
331
- 'id' : source_cable [1 ].id ,
332
- 'dcimCableURL' : source_cable [1 ].get_absolute_url (),
333
- 'label' : f"Cable { source_cable [1 ].id } " ,
334
- 'source' : source_cable [0 ].device .name ,
335
- 'target' : dest_cable [- 1 ].device .name ,
336
- 'sourceDeviceName' : source_cable [0 ].device .name ,
337
- 'targetDeviceName' : dest_cable [- 1 ].device .name ,
338
- "srcIfName" : if_shortname (source_cable [0 ].name ),
339
- "tgtIfName" : if_shortname (dest_cable [- 1 ].name ),
340
- })
341
-
342
- return topology_dict , device_roles , multi_cable_connections , list (all_device_tags )
343
-
344
-
345
250
def get_topology (nb_devices_qs , params ):
346
251
display_unconnected = params .get ('display_unconnected' )
347
252
display_passive = params .get ('display_passive' )
@@ -403,7 +308,7 @@ def get_topology(nb_devices_qs, params):
403
308
node_data = {
404
309
'id' : f'device-{ nb_device .id } ' ,
405
310
'name' : nb_device .name ,
406
- 'label' : { 'text' : nb_device .name } ,
311
+ 'label' : nb_device .name ,
407
312
'layer' : get_node_layer_sort_preference (
408
313
device_role_obj .slug
409
314
),
@@ -460,8 +365,10 @@ def get_topology(nb_devices_qs, params):
460
365
"label" : f"Cable { link .id } " ,
461
366
"source" : f"device-{ link .a_terminations [0 ].device .id } " ,
462
367
"target" : f"device-{ link .b_terminations [0 ].device .id } " ,
463
- "sourceInterfaceLabel" : if_shortname (link .a_terminations [0 ].name ),
464
- "targetInterfaceLabel" : if_shortname (link .b_terminations [0 ].name ),
368
+ "sourceInterface" : link .a_terminations [0 ].name ,
369
+ "sourceInterfaceLabel" : {'text' : if_shortname (link .a_terminations [0 ].name )},
370
+ "targetInterface" : link .b_terminations [0 ].name ,
371
+ "targetInterfaceLabel" : {'text' : if_shortname (link .b_terminations [0 ].name )},
465
372
"customAttributes" : {
466
373
"name" : f"Cable { link .id } " ,
467
374
"dcimCableURL" : link_url ,
@@ -512,10 +419,12 @@ def get_topology(nb_devices_qs, params):
512
419
source_device_id = f"device-{ side_a_interface .device .id } "
513
420
target_device_id = f"device-{ side_b_interface .device .id } "
514
421
topology_dict ['edges' ].append ({
515
- 'source' : source_device_id ,
516
- 'target' : target_device_id ,
517
- "sourceInterfaceLabel" : if_shortname (side_a_interface .name ),
518
- "targetInterfaceLabel" : if_shortname (side_b_interface .name ),
422
+ "source" : source_device_id ,
423
+ "target" : target_device_id ,
424
+ "sourceInterface" : link .a_terminations [0 ].name ,
425
+ "sourceInterfaceLabel" : {'text' : if_shortname (link .a_terminations [0 ].name )},
426
+ "targetInterface" : link .b_terminations [0 ].name ,
427
+ "targetInterfaceLabel" : {'text' : if_shortname (link .b_terminations [0 ].name )},
519
428
"isLogicalMultiCable" : True ,
520
429
"customAttributes" : {
521
430
"name" : f"Multi-Cable Connection" ,
@@ -527,40 +436,6 @@ def get_topology(nb_devices_qs, params):
527
436
return topology_dict , device_roles , multi_cable_connections , all_device_tags
528
437
529
438
530
- def get_saved_topology (id ):
531
- topology_dict = {}
532
- device_roles = []
533
- device_tags = []
534
- device_roles_detailed = []
535
- device_tags_detailed = []
536
- layout_context = {}
537
- topology_data = SavedTopology .objects .get (id = id )
538
- if not topology_data :
539
- return topology_dict , device_roles , device_tags , layout_context
540
- topology_dict = dict (topology_data .topology )
541
- if 'nodes' not in topology_dict :
542
- return topology_dict , device_roles , device_tags , layout_context
543
- device_roles = list (set ([str (d .get ('deviceRole' )) for d in topology_dict ['nodes' ] if d .get ('deviceRole' )]))
544
- for device_role in device_roles :
545
- is_visible = not (device_role in UNDISPLAYED_DEVICE_ROLE_SLUGS )
546
- device_role_obj = DeviceRole .objects .get (slug = device_role )
547
- if not device_role_obj :
548
- device_roles_detailed .append ((device_role , device_role , is_visible ))
549
- continue
550
- device_roles_detailed .append ((device_role_obj .slug , device_role_obj .name , is_visible ))
551
- device_roles_detailed .sort (key = lambda i : get_node_layer_sort_preference (i [0 ]))
552
- device_tags = set ()
553
- for device in topology_dict ['nodes' ]:
554
- if 'tags' not in device :
555
- continue
556
- for tag in device ['tags' ]:
557
- device_tags .add (str (tag ))
558
- device_tags = list (device_tags )
559
- device_tags_detailed = list ([(tag , not tag_is_hidden (tag )) for tag in device_tags ])
560
- layout_context = dict (topology_data .layout_context )
561
- return topology_dict , device_roles_detailed , device_tags_detailed , layout_context
562
-
563
-
564
439
class TopologyView (PermissionRequiredMixin , View ):
565
440
"""Generic Topology View"""
566
441
permission_required = ('dcim.view_site' , 'dcim.view_device' , 'dcim.view_cable' )
@@ -570,45 +445,39 @@ class TopologyView(PermissionRequiredMixin, View):
570
445
571
446
def get (self , request ):
572
447
573
- if not request .GET :
574
- self . queryset = Device . objects . none ()
575
- elif 'saved_topology_id' in request . GET :
448
+ clean_request = request .GET . copy ()
449
+
450
+ if not clean_request :
576
451
self .queryset = Device .objects .none ()
577
452
578
- display_unconnected = request .GET .get ('display_unconnected' )
579
- if display_unconnected is not None :
580
- display_unconnected = display_unconnected .lower == 'true'
453
+ self .queryset = self .filterset (clean_request , self .queryset ).qs
581
454
582
- display_passive = request .GET .get ('display_passive' )
583
- if display_passive is not None :
584
- display_passive = display_passive .lower () == 'true'
455
+ saved_filter = None
456
+ if 'filter_id' in clean_request and clean_request ['filter_id' ]:
457
+ filter_id = clean_request ['filter_id' ]
458
+ saved_filter = SavedFilter .objects .get (pk = filter_id )
459
+
460
+ if saved_filter :
461
+ # Extract only plugin-specific filters from the SavedFilter.
462
+ # All NetBox-native filters are handled by filtersets.
463
+ display_unconnected = saved_filter .parameters .get ('display_unconnected' , [DISPLAY_UNCONNECTED ])[0 ]
464
+ display_passive = saved_filter .parameters .get ('display_passive' , [DISPLAY_PASSIVE_DEVICES ])[0 ]
585
465
else :
466
+ display_unconnected = DISPLAY_UNCONNECTED
586
467
display_passive = DISPLAY_PASSIVE_DEVICES
587
468
588
- params = {
589
- 'display_unconnected' : display_unconnected ,
590
- 'display_passive' : display_passive ,
591
- }
469
+ if clean_request .get ('display_unconnected' ) is not None :
470
+ display_unconnected = clean_request .get ('display_unconnected' )
592
471
593
- saved_topology_id = request . GET . get ('saved_topology_id' )
594
- layout_context = {}
472
+ if clean_request . get ('display_passive' ) is not None :
473
+ display_passive = clean_request . get ( 'display_passive' )
595
474
596
- if saved_topology_id is not None :
597
- topology_dict , device_roles , device_tags , layout_context = get_saved_topology (saved_topology_id )
598
- else :
599
- vlans = []
600
- if 'vlan_id' in request .GET :
601
- clean_request = request .GET .copy ()
602
- clean_request .pop ('vlan_id' )
603
- vlans = request .GET .get ('vlan_id' )
604
- else :
605
- clean_request = request .GET .copy ()
475
+ params = {
476
+ 'display_unconnected' : str (display_unconnected ).lower () == 'true' ,
477
+ 'display_passive' : str (display_passive ).lower () == 'true' ,
478
+ }
606
479
607
- self .queryset = self .filterset (clean_request , self .queryset ).qs
608
- if len (vlans ) == 0 :
609
- topology_dict , device_roles , multi_cable_connections , device_tags = get_topology (self .queryset , params )
610
- else :
611
- topology_dict , device_roles , multi_cable_connections , device_tags = get_vlan_topology (self .queryset , vlans )
480
+ topology_dict , device_roles , multi_cable_connections , device_tags = get_topology (self .queryset , params )
612
481
613
482
return render (request , self .template_name , {
614
483
'source_data' : json .dumps (topology_dict ),
0 commit comments