mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #9778: Fix exception during cable deletion after deleting a connected termination
This commit is contained in:
@ -104,6 +104,7 @@ Custom field UI visibility has no impact on API operation.
|
|||||||
* [#9730](https://github.com/netbox-community/netbox/issues/9730) - Fix validation error when creating a new cable via UI form
|
* [#9730](https://github.com/netbox-community/netbox/issues/9730) - Fix validation error when creating a new cable via UI form
|
||||||
* [#9733](https://github.com/netbox-community/netbox/issues/9733) - Handle split paths during trace when fanning out to front ports with differing cables
|
* [#9733](https://github.com/netbox-community/netbox/issues/9733) - Handle split paths during trace when fanning out to front ports with differing cables
|
||||||
* [#9765](https://github.com/netbox-community/netbox/issues/9765) - Report correct segment count under cable trace UI view
|
* [#9765](https://github.com/netbox-community/netbox/issues/9765) - Report correct segment count under cable trace UI view
|
||||||
|
* [#9778](https://github.com/netbox-community/netbox/issues/9778) - Fix exception during cable deletion after deleting a connected termination
|
||||||
* [#9788](https://github.com/netbox-community/netbox/issues/9788) - Ensure denormalized fields on CableTermination are kept in sync with related objects
|
* [#9788](https://github.com/netbox-community/netbox/issues/9788) - Ensure denormalized fields on CableTermination are kept in sync with related objects
|
||||||
* [#9789](https://github.com/netbox-community/netbox/issues/9789) - Fix rendering of cable traces ending at provider networks
|
* [#9789](https://github.com/netbox-community/netbox/issues/9789) - Fix rendering of cable traces ending at provider networks
|
||||||
* [#9794](https://github.com/netbox-community/netbox/issues/9794) - Fix link to connect a rear port to a circuit termination
|
* [#9794](https://github.com/netbox-community/netbox/issues/9794) - Fix link to connect a rear port to a circuit termination
|
||||||
|
@ -431,11 +431,7 @@ class CablePath(models.Model):
|
|||||||
"""
|
"""
|
||||||
Return the list of originating objects.
|
Return the list of originating objects.
|
||||||
"""
|
"""
|
||||||
if hasattr(self, '_path_objects'):
|
return self.path_objects[0]
|
||||||
return self.path_objects[0]
|
|
||||||
return [
|
|
||||||
path_node_to_object(node) for node in self.path[0]
|
|
||||||
]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def destinations(self):
|
def destinations(self):
|
||||||
@ -444,11 +440,7 @@ class CablePath(models.Model):
|
|||||||
"""
|
"""
|
||||||
if not self.is_complete:
|
if not self.is_complete:
|
||||||
return []
|
return []
|
||||||
if hasattr(self, '_path_objects'):
|
return self.path_objects[-1]
|
||||||
return self.path_objects[-1]
|
|
||||||
return [
|
|
||||||
path_node_to_object(node) for node in self.path[-1]
|
|
||||||
]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def segment_count(self):
|
def segment_count(self):
|
||||||
@ -463,6 +455,9 @@ class CablePath(models.Model):
|
|||||||
"""
|
"""
|
||||||
from circuits.models import CircuitTermination
|
from circuits.models import CircuitTermination
|
||||||
|
|
||||||
|
if not terminations:
|
||||||
|
return None
|
||||||
|
|
||||||
# Ensure all originating terminations are attached to the same link
|
# Ensure all originating terminations are attached to the same link
|
||||||
if len(terminations) > 1:
|
if len(terminations) > 1:
|
||||||
assert all(t.link == terminations[0].link for t in terminations[1:])
|
assert all(t.link == terminations[0].link for t in terminations[1:])
|
||||||
@ -529,6 +524,9 @@ class CablePath(models.Model):
|
|||||||
])
|
])
|
||||||
|
|
||||||
# Step 6: Determine the "next hop" terminations, if applicable
|
# Step 6: Determine the "next hop" terminations, if applicable
|
||||||
|
if not remote_terminations:
|
||||||
|
break
|
||||||
|
|
||||||
if isinstance(remote_terminations[0], FrontPort):
|
if isinstance(remote_terminations[0], FrontPort):
|
||||||
# Follow FrontPorts to their corresponding RearPorts
|
# Follow FrontPorts to their corresponding RearPorts
|
||||||
rear_ports = RearPort.objects.filter(
|
rear_ports = RearPort.objects.filter(
|
||||||
@ -640,7 +638,11 @@ class CablePath(models.Model):
|
|||||||
nodes = []
|
nodes = []
|
||||||
for node in step:
|
for node in step:
|
||||||
ct_id, object_id = decompile_path_node(node)
|
ct_id, object_id = decompile_path_node(node)
|
||||||
nodes.append(prefetched[ct_id][object_id])
|
try:
|
||||||
|
nodes.append(prefetched[ct_id][object_id])
|
||||||
|
except KeyError:
|
||||||
|
# Ignore stale (deleted) object IDs
|
||||||
|
pass
|
||||||
path.append(nodes)
|
path.append(nodes)
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
@ -116,7 +116,10 @@ def retrace_cable_paths(instance, **kwargs):
|
|||||||
@receiver(post_delete, sender=CableTermination)
|
@receiver(post_delete, sender=CableTermination)
|
||||||
def nullify_connected_endpoints(instance, **kwargs):
|
def nullify_connected_endpoints(instance, **kwargs):
|
||||||
"""
|
"""
|
||||||
Disassociate the Cable from the termination object.
|
Disassociate the Cable from the termination object, and retrace any affected CablePaths.
|
||||||
"""
|
"""
|
||||||
model = instance.termination_type.model_class()
|
model = instance.termination_type.model_class()
|
||||||
model.objects.filter(pk=instance.termination_id).update(cable=None, cable_end='')
|
model.objects.filter(pk=instance.termination_id).update(cable=None, cable_end='')
|
||||||
|
|
||||||
|
for cablepath in CablePath.objects.filter(_nodes__contains=instance.cable):
|
||||||
|
cablepath.retrace()
|
||||||
|
@ -362,8 +362,11 @@ class CableTraceSVG:
|
|||||||
terminations = self.draw_terminations(far_ends)
|
terminations = self.draw_terminations(far_ends)
|
||||||
for term in terminations:
|
for term in terminations:
|
||||||
self.draw_fanout(term, cable)
|
self.draw_fanout(term, cable)
|
||||||
else:
|
elif far_ends:
|
||||||
self.draw_terminations(far_ends)
|
self.draw_terminations(far_ends)
|
||||||
|
else:
|
||||||
|
# Link is not connected to anything
|
||||||
|
break
|
||||||
|
|
||||||
# Far end parent
|
# Far end parent
|
||||||
parent_objects = set(end.parent_object for end in far_ends)
|
parent_objects = set(end.parent_object for end in far_ends)
|
||||||
|
@ -24,11 +24,12 @@ def object_to_path_node(obj):
|
|||||||
|
|
||||||
def path_node_to_object(repr):
|
def path_node_to_object(repr):
|
||||||
"""
|
"""
|
||||||
Given the string representation of a path node, return the corresponding instance.
|
Given the string representation of a path node, return the corresponding instance. If the object no longer
|
||||||
|
exists, return None.
|
||||||
"""
|
"""
|
||||||
ct_id, object_id = decompile_path_node(repr)
|
ct_id, object_id = decompile_path_node(repr)
|
||||||
ct = ContentType.objects.get_for_id(ct_id)
|
ct = ContentType.objects.get_for_id(ct_id)
|
||||||
return ct.model_class().objects.get(pk=object_id)
|
return ct.model_class().objects.filter(pk=object_id).first()
|
||||||
|
|
||||||
|
|
||||||
def create_cablepath(terminations):
|
def create_cablepath(terminations):
|
||||||
|
@ -219,7 +219,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Path Status</th>
|
<th scope="row">Path Status</th>
|
||||||
<td>
|
<td>
|
||||||
{% if object.path.is_active %}
|
{% if object.path.is_complete and object.path.is_active %}
|
||||||
<span class="badge bg-success">Reachable</span>
|
<span class="badge bg-success">Reachable</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge bg-danger">Not Reachable</span>
|
<span class="badge bg-danger">Not Reachable</span>
|
||||||
|
Reference in New Issue
Block a user