Capture path end-to-end status in CablePath

This commit is contained in:
Jeremy Stretch 2020-10-01 16:42:57 -04:00
parent 610420c020
commit c974c5687c
5 changed files with 31 additions and 11 deletions

View File

@ -30,7 +30,7 @@ from .nested_serializers import *
class ConnectedEndpointSerializer(ValidatedModelSerializer): class ConnectedEndpointSerializer(ValidatedModelSerializer):
connected_endpoint_type = serializers.SerializerMethodField(read_only=True) connected_endpoint_type = serializers.SerializerMethodField(read_only=True)
connected_endpoint = serializers.SerializerMethodField(read_only=True) connected_endpoint = serializers.SerializerMethodField(read_only=True)
connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) connection_status = serializers.SerializerMethodField(read_only=True)
def get_connected_endpoint_type(self, obj): def get_connected_endpoint_type(self, obj):
if obj.path is not None: if obj.path is not None:
@ -49,6 +49,13 @@ class ConnectedEndpointSerializer(ValidatedModelSerializer):
return serializer(obj.path.destination, context=context).data return serializer(obj.path.destination, context=context).data
return None return None
# TODO: Tweak the representation for this field
@swagger_serializer_method(serializer_or_field=serializers.BooleanField)
def get_connection_status(self, obj):
if obj.path is not None:
return obj.path.is_connected
return None
# #
# Regions/sites # Regions/sites

View File

@ -1,5 +1,3 @@
# Generated by Django 3.1 on 2020-09-30 18:09
import dcim.fields import dcim.fields
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
@ -22,6 +20,7 @@ class Migration(migrations.Migration):
('path', dcim.fields.PathField(base_field=models.CharField(max_length=40), size=None)), ('path', dcim.fields.PathField(base_field=models.CharField(max_length=40), size=None)),
('destination_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')), ('destination_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')),
('origin_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')), ('origin_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')),
('is_connected', models.BooleanField(default=False)),
], ],
), ),
] ]

View File

@ -992,6 +992,8 @@ class Cable(ChangeLoggedModel, CustomFieldModel):
instance._orig_termination_b_type_id = instance.termination_b_type_id instance._orig_termination_b_type_id = instance.termination_b_type_id
instance._orig_termination_b_id = instance.termination_b_id instance._orig_termination_b_id = instance.termination_b_id
instance._orig_status = instance.status
return instance return instance
def __str__(self): def __str__(self):
@ -1188,6 +1190,9 @@ class CablePath(models.Model):
fk_field='destination_id' fk_field='destination_id'
) )
path = PathField() path = PathField()
is_connected = models.BooleanField(
default=False
)
objects = CablePathManager() objects = CablePathManager()

View File

@ -5,6 +5,7 @@ from django.db.models.signals import post_save, pre_delete
from django.db import transaction from django.db import transaction
from django.dispatch import receiver from django.dispatch import receiver
from .choices import CableStatusChoices
from .models import Cable, CablePath, Device, PathEndpoint, VirtualChassis from .models import Cable, CablePath, Device, PathEndpoint, VirtualChassis
from .utils import object_to_path_node, trace_path from .utils import object_to_path_node, trace_path
@ -13,9 +14,9 @@ def create_cablepath(node):
""" """
Create CablePaths for all paths originating from the specified node. Create CablePaths for all paths originating from the specified node.
""" """
path, destination = trace_path(node) path, destination, is_connected = trace_path(node)
if path: if path:
cp = CablePath(origin=node, path=path, destination=destination) cp = CablePath(origin=node, path=path, destination=destination, is_connected=is_connected)
cp.save() cp.save()
@ -80,10 +81,14 @@ def update_connected_endpoints(instance, created, **kwargs):
create_cablepath(termination) create_cablepath(termination)
else: else:
rebuild_paths(termination) rebuild_paths(termination)
else: elif instance.status != instance._orig_status:
# We currently don't support modifying either termination of an existing Cable. This # We currently don't support modifying either termination of an existing Cable. (This
# may change in the future. # may change in the future.) However, we do need to capture status changes and update
pass # any CablePaths accordingly.
if instance.status != CableStatusChoices.STATUS_CONNECTED:
CablePath.objects.filter(path__contains=object_to_path_node(instance)).update(is_connected=False)
else:
rebuild_paths(instance)
@receiver(pre_delete, sender=Cable) @receiver(pre_delete, sender=Cable)

View File

@ -1,5 +1,6 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from .choices import CableStatusChoices
from .exceptions import CableTraceSplit from .exceptions import CableTraceSplit
from .models import FrontPort, RearPort from .models import FrontPort, RearPort
@ -22,11 +23,14 @@ def trace_path(node):
destination = None destination = None
path = [] path = []
position_stack = [] position_stack = []
is_connected = True
if node.cable is None: if node.cable is None:
return [], None return [], None, False
while node.cable is not None: while node.cable is not None:
if node.cable.status != CableStatusChoices.STATUS_CONNECTED:
is_connected = False
# Follow the cable to its far-end termination # Follow the cable to its far-end termination
path.append(object_to_path_node(node.cable)) path.append(object_to_path_node(node.cable))
@ -59,4 +63,4 @@ def trace_path(node):
destination = peer_termination destination = peer_termination
break break
return path, destination return path, destination, is_connected