Introduced 'cable' field on CableTermination to cache connected Cable

This commit is contained in:
Jeremy Stretch 2018-10-29 12:24:16 -04:00
parent dc67028bd9
commit e21b23cd98
9 changed files with 110 additions and 55 deletions

View File

@ -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),

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -7,14 +7,11 @@
{# Cable #}
<td>
{% with cable=cp.get_connected_cable %}
{% if cable %}
Cable <a href="{{ cable.get_absolute_url }}">{{ cable }}</a>
{% if cable.far_end != cp.connected_endpoint %}
to <a href="{{ cable.far_end.device.get_absolute_url }}">{{ cable.far_end.device }}</a> {{ cable.far_end }}
{% endif %}
{% endif %}
{% endwith %}
{% if cp.cable %}
<a href="{{ cp.cable.get_absolute_url }}">{{ cp.cable }}</a>
{% else %}
&mdash;
{% endif %}
</td>
{# Connection #}

View File

@ -14,14 +14,11 @@
{# Cable #}
<td>
{% with cable=csp.get_connected_cable %}
{% if cable %}
<a href="{{ cable.get_absolute_url }}">{{ cable }}</a>
{% if cable.far_end != csp.connected_endpoint %}
to <a href="{{ cable.far_end.device.get_absolute_url }}">{{ cable.far_end.device }}</a> {{ cable.far_end }}
{% endif %}
{% endif %}
{% endwith %}
{% if csp.cable %}
<a href="{{ csp.cable.get_absolute_url }}">{{ csp.cable }}</a>
{% else %}
&mdash;
{% endif %}
</td>
{# Connection #}

View File

@ -26,18 +26,15 @@
<td>{{ iface.description|default:"&mdash;" }}</td>
{# 802.1Q mode #}
<td>{{ iface.get_mode_display }}</td>
<td>{{ iface.get_mode_display|default:"&mdash;" }}</td>
{# Cable #}
<td>
{% with cable=iface.get_connected_cable %}
{% if cable %}
<a href="{{ cable.get_absolute_url }}">{{ cable }}</a>
{% if cable.far_end != iface.connected_endpoint %}
to <a href="{{ cable.far_end.device.get_absolute_url }}">{{ cable.far_end.device }}</a> {{ cable.far_end }}
{% endif %}
{% endif %}
{% endwith %}
{% if iface.cable %}
<a href="{{ iface.cable.get_absolute_url }}">{{ iface.cable }}</a>
{% else %}
&mdash;
{% endif %}
</td>
{# Connection or type #}

View File

@ -14,14 +14,11 @@
{# Cable #}
<td>
{% with cable=po.get_connected_cable %}
{% if cable %}
<a href="{{ cable.get_absolute_url }}">{{ cable }}</a>
{% if cable.far_end != po.connected_endpoint %}
to <a href="{{ cable.far_end.device.get_absolute_url }}">{{ cable.far_end.device }}</a> {{ cable.far_end }}
{% endif %}
{% endif %}
{% endwith %}
{% if po.cable %}
<a href="{{ po.cable.get_absolute_url }}">{{ po.cable }}</a>
{% else %}
&mdash;
{% endif %}
</td>
{# Connection #}

View File

@ -7,14 +7,11 @@
{# Cable #}
<td>
{% with cable=pp.get_connected_cable %}
{% if cable %}
Cable <a href="{{ cable.get_absolute_url }}">{{ cable }}</a>
{% if cable.far_end != pp.connected_endpoint %}
to <a href="{{ cable.far_end.device.get_absolute_url }}">{{ cable.far_end.device }}</a> {{ cable.far_end }}
{% endif %}
{% endif %}
{% endwith %}
{% if pp.cable %}
<a href="{{ pp.cable.get_absolute_url }}">{{ pp.cable }}</a>
{% else %}
&mdash;
{% endif %}
</td>
{# Connection #}