From e21b23cd98704bdf6b159cd761b41f9fff240291 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 29 Oct 2018 12:24:16 -0400 Subject: [PATCH] Introduced 'cable' field on CableTermination to cache connected Cable --- netbox/dcim/migrations/0066_cables.py | 56 ++++++++++++++++++- netbox/dcim/models.py | 12 ++++ netbox/dcim/signals.py | 2 +- netbox/dcim/views.py | 28 ++++++---- netbox/templates/dcim/inc/consoleport.html | 13 ++--- .../templates/dcim/inc/consoleserverport.html | 13 ++--- netbox/templates/dcim/inc/interface.html | 15 ++--- netbox/templates/dcim/inc/poweroutlet.html | 13 ++--- netbox/templates/dcim/inc/powerport.html | 13 ++--- 9 files changed, 110 insertions(+), 55 deletions(-) diff --git a/netbox/dcim/migrations/0066_cables.py b/netbox/dcim/migrations/0066_cables.py index e095c3dda..8a391c97a 100644 --- a/netbox/dcim/migrations/0066_cables.py +++ b/netbox/dcim/migrations/0066_cables.py @@ -20,6 +20,7 @@ def console_connections_to_cables(apps, schema_editor): print("\n Adding console connections... ", end='', flush=True) for consoleport in ConsolePort.objects.filter(connected_endpoint__isnull=False): c = Cable() + # We have to assign GFK fields manually because we're inside a migration. c.termination_a_type = consoleport_type c.termination_a_id = consoleport.id @@ -28,6 +29,10 @@ def console_connections_to_cables(apps, schema_editor): c.connection_status = consoleport.connection_status c.save() + # Cache the Cable on its two termination points (replicate Cable.save()) + ConsolePort.objects.filter(pk=consoleport.id).update(cable=c) + ConsoleServerPort.objects.filter(pk=consoleport.connected_endpoint_id).update(cable=c) + cable_count = Cable.objects.filter(termination_a_type=consoleport_type).count() print("{} cables created".format(cable_count)) @@ -49,6 +54,7 @@ def power_connections_to_cables(apps, schema_editor): print(" Adding power connections... ", end='', flush=True) for powerport in PowerPort.objects.filter(connected_endpoint__isnull=False): c = Cable() + # We have to assign GFK fields manually because we're inside a migration. c.termination_a_type = powerport_type c.termination_a_id = powerport.id @@ -57,6 +63,10 @@ def power_connections_to_cables(apps, schema_editor): c.connection_status = powerport.connection_status c.save() + # Cache the Cable on its two termination points (replicate Cable.save()) + PowerPort.objects.filter(pk=powerport.id).update(cable=c) + PowerOutlet.objects.filter(pk=powerport.connected_endpoint_id).update(cable=c) + cable_count = Cable.objects.filter(termination_a_type=powerport_type).count() print("{} cables created".format(cable_count)) @@ -77,11 +87,14 @@ def interface_connections_to_cables(apps, schema_editor): print(" Adding interface connections... ", end='', flush=True) for conn in InterfaceConnection.objects.all(): c = Cable() + # We have to assign GFK fields manually because we're inside a migration. c.termination_a_type = interface_type c.termination_a_id = conn.interface_a_id + c.termination_a = conn.interface_a c.termination_b_type = interface_type c.termination_b_id = conn.interface_b_id + c.termination_b = conn.interface_b c.connection_status = conn.connection_status c.save() @@ -89,11 +102,13 @@ def interface_connections_to_cables(apps, schema_editor): # since these are new fields on Interface Interface.objects.filter(pk=conn.interface_a_id).update( connected_endpoint=conn.interface_b_id, - connection_status=conn.connection_status + connection_status=conn.connection_status, + cable=c ) Interface.objects.filter(pk=conn.interface_b_id).update( connected_endpoint=conn.interface_a_id, - connection_status=conn.connection_status + connection_status=conn.connection_status, + cable=c ) cable_count = Cable.objects.filter(termination_a_type=interface_type).count() @@ -146,11 +161,21 @@ class Migration(migrations.Migration): name='connected_endpoint', field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connected_endpoint', to='dcim.ConsoleServerPort'), ), + migrations.AddField( + model_name='consoleport', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.Cable'), + ), migrations.AlterField( model_name='consoleserverport', name='device', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consoleserverports', to='dcim.Device'), ), + migrations.AddField( + model_name='consoleserverport', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.Cable'), + ), # Alter power port models migrations.RenameField( @@ -163,11 +188,21 @@ class Migration(migrations.Migration): name='connected_endpoint', field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connected_endpoint', to='dcim.PowerOutlet'), ), + migrations.AddField( + model_name='powerport', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.Cable'), + ), migrations.AlterField( model_name='poweroutlet', name='device', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='poweroutlets', to='dcim.Device'), ), + migrations.AddField( + model_name='poweroutlet', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.Cable'), + ), # Alter the Interface model migrations.AddField( @@ -180,6 +215,23 @@ class Migration(migrations.Migration): name='connection_status', field=models.NullBooleanField(default=True), ), + migrations.AddField( + model_name='interface', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.Cable'), + ), + + # Alter front/rear port models + migrations.AddField( + model_name='frontport', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.Cable'), + ), + migrations.AddField( + model_name='rearport', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.Cable'), + ), # Copy console/power/interface connections as Cables migrations.RunPython(console_connections_to_cables), diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index bb5c13fd8..d1df21ca9 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -66,6 +66,12 @@ class ComponentModel(models.Model): class CableTermination(models.Model): + cable = models.ForeignKey( + to='dcim.Cable', + on_delete=models.SET_NULL, + blank=True, + null=True + ) class Meta: abstract = True @@ -2339,6 +2345,12 @@ class Cable(ChangeLoggedModel): super(Cable, self).save(*args, **kwargs) + # Cache the Cable on its two termination points + self.termination_a.cable = self + self.termination_a.save() + self.termination_b.cable = self + self.termination_b.save() + def get_path_endpoints(self): """ Traverse both ends of a cable path and return its connected endpoints. Note that one or both endpoints may be diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index e47865ac5..41ca61d09 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -32,7 +32,7 @@ def update_connected_endpoints(instance, **kwargs): termination_a.connection_status = True termination_a.save() termination_b.connected_endpoint = termination_a - termination_a.connection_status = True + termination_b.connection_status = True termination_b.save() diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 57971b5e3..42d12335d 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -876,47 +876,53 @@ class DeviceView(View): # VirtualChassis members if device.virtual_chassis is not None: - vc_members = Device.objects.filter(virtual_chassis=device.virtual_chassis).order_by('vc_position') + vc_members = Device.objects.filter( + virtual_chassis=device.virtual_chassis + ).order_by('vc_position') else: vc_members = [] # Console ports console_ports = natsorted( - ConsolePort.objects.filter(device=device).select_related('connected_endpoint__device'), key=attrgetter('name') + device.console_ports.select_related('connected_endpoint__device', 'cable'), + key=attrgetter('name') ) # Console server ports - consoleserverports = ConsoleServerPort.objects.filter(device=device).select_related('connected_endpoint__device') + consoleserverports = device.consoleserverports.select_related('connected_endpoint__device', 'cable') # Power ports power_ports = natsorted( - PowerPort.objects.filter(device=device).select_related('connected_endpoint__device'), key=attrgetter('name') + device.power_ports.select_related('connected_endpoint__device', 'cable'), + key=attrgetter('name') ) # Power outlets - poweroutlets = PowerOutlet.objects.filter(device=device).select_related('connected_endpoint__device') + poweroutlets = device.poweroutlets.select_related('connected_endpoint__device', 'cable') # Interfaces interfaces = device.vc_interfaces.order_naturally( device.device_type.interface_ordering ).select_related( - 'connected_endpoint__device', 'circuit_termination__circuit' - ).prefetch_related('ip_addresses') + 'lag', 'connected_endpoint__device', 'circuit_termination__circuit', 'cable' + ).prefetch_related( + 'cable__termination_a', 'cable__termination_b', 'ip_addresses' + ) # Front ports - front_ports = device.front_ports.select_related('rear_port') + front_ports = device.front_ports.select_related('rear_port', 'cable') # Rear ports - rear_ports = device.rear_ports.all() + rear_ports = device.rear_ports.select_related('cable') # Device bays device_bays = natsorted( - DeviceBay.objects.filter(device=device).select_related('installed_device__device_type__manufacturer'), + device.device_bays.select_related('installed_device__device_type__manufacturer'), key=attrgetter('name') ) # Services - services = Service.objects.filter(device=device) + services = device.services.all() # Secrets secrets = device.secrets.all() diff --git a/netbox/templates/dcim/inc/consoleport.html b/netbox/templates/dcim/inc/consoleport.html index 184d596dd..eecfc6735 100644 --- a/netbox/templates/dcim/inc/consoleport.html +++ b/netbox/templates/dcim/inc/consoleport.html @@ -7,14 +7,11 @@ {# Cable #} - {% with cable=cp.get_connected_cable %} - {% if cable %} - Cable {{ cable }} - {% if cable.far_end != cp.connected_endpoint %} - to {{ cable.far_end.device }} {{ cable.far_end }} - {% endif %} - {% endif %} - {% endwith %} + {% if cp.cable %} + {{ cp.cable }} + {% else %} + — + {% endif %} {# Connection #} diff --git a/netbox/templates/dcim/inc/consoleserverport.html b/netbox/templates/dcim/inc/consoleserverport.html index ab06d0b84..47345ef22 100644 --- a/netbox/templates/dcim/inc/consoleserverport.html +++ b/netbox/templates/dcim/inc/consoleserverport.html @@ -14,14 +14,11 @@ {# Cable #} - {% with cable=csp.get_connected_cable %} - {% if cable %} - {{ cable }} - {% if cable.far_end != csp.connected_endpoint %} - to {{ cable.far_end.device }} {{ cable.far_end }} - {% endif %} - {% endif %} - {% endwith %} + {% if csp.cable %} + {{ csp.cable }} + {% else %} + — + {% endif %} {# Connection #} diff --git a/netbox/templates/dcim/inc/interface.html b/netbox/templates/dcim/inc/interface.html index bbb37f517..3c584ba76 100644 --- a/netbox/templates/dcim/inc/interface.html +++ b/netbox/templates/dcim/inc/interface.html @@ -26,18 +26,15 @@ {{ iface.description|default:"—" }} {# 802.1Q mode #} - {{ iface.get_mode_display }} + {{ iface.get_mode_display|default:"—" }} {# Cable #} - {% with cable=iface.get_connected_cable %} - {% if cable %} - {{ cable }} - {% if cable.far_end != iface.connected_endpoint %} - to {{ cable.far_end.device }} {{ cable.far_end }} - {% endif %} - {% endif %} - {% endwith %} + {% if iface.cable %} + {{ iface.cable }} + {% else %} + — + {% endif %} {# Connection or type #} diff --git a/netbox/templates/dcim/inc/poweroutlet.html b/netbox/templates/dcim/inc/poweroutlet.html index 4a949ccd2..04b60a785 100644 --- a/netbox/templates/dcim/inc/poweroutlet.html +++ b/netbox/templates/dcim/inc/poweroutlet.html @@ -14,14 +14,11 @@ {# Cable #} - {% with cable=po.get_connected_cable %} - {% if cable %} - {{ cable }} - {% if cable.far_end != po.connected_endpoint %} - to {{ cable.far_end.device }} {{ cable.far_end }} - {% endif %} - {% endif %} - {% endwith %} + {% if po.cable %} + {{ po.cable }} + {% else %} + — + {% endif %} {# Connection #} diff --git a/netbox/templates/dcim/inc/powerport.html b/netbox/templates/dcim/inc/powerport.html index 8bffef2ae..3479505e2 100644 --- a/netbox/templates/dcim/inc/powerport.html +++ b/netbox/templates/dcim/inc/powerport.html @@ -7,14 +7,11 @@ {# Cable #} - {% with cable=pp.get_connected_cable %} - {% if cable %} - Cable {{ cable }} - {% if cable.far_end != pp.connected_endpoint %} - to {{ cable.far_end.device }} {{ cable.far_end }} - {% endif %} - {% endif %} - {% endwith %} + {% if pp.cable %} + {{ pp.cable }} + {% else %} + — + {% endif %} {# Connection #}