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
|
||||
* [#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
|
||||
* [#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
|
||||
* [#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
|
||||
|
@ -431,11 +431,7 @@ class CablePath(models.Model):
|
||||
"""
|
||||
Return the list of originating objects.
|
||||
"""
|
||||
if hasattr(self, '_path_objects'):
|
||||
return self.path_objects[0]
|
||||
return [
|
||||
path_node_to_object(node) for node in self.path[0]
|
||||
]
|
||||
return self.path_objects[0]
|
||||
|
||||
@property
|
||||
def destinations(self):
|
||||
@ -444,11 +440,7 @@ class CablePath(models.Model):
|
||||
"""
|
||||
if not self.is_complete:
|
||||
return []
|
||||
if hasattr(self, '_path_objects'):
|
||||
return self.path_objects[-1]
|
||||
return [
|
||||
path_node_to_object(node) for node in self.path[-1]
|
||||
]
|
||||
return self.path_objects[-1]
|
||||
|
||||
@property
|
||||
def segment_count(self):
|
||||
@ -463,6 +455,9 @@ class CablePath(models.Model):
|
||||
"""
|
||||
from circuits.models import CircuitTermination
|
||||
|
||||
if not terminations:
|
||||
return None
|
||||
|
||||
# Ensure all originating terminations are attached to the same link
|
||||
if len(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
|
||||
if not remote_terminations:
|
||||
break
|
||||
|
||||
if isinstance(remote_terminations[0], FrontPort):
|
||||
# Follow FrontPorts to their corresponding RearPorts
|
||||
rear_ports = RearPort.objects.filter(
|
||||
@ -640,7 +638,11 @@ class CablePath(models.Model):
|
||||
nodes = []
|
||||
for node in step:
|
||||
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)
|
||||
|
||||
return path
|
||||
|
@ -116,7 +116,10 @@ def retrace_cable_paths(instance, **kwargs):
|
||||
@receiver(post_delete, sender=CableTermination)
|
||||
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.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)
|
||||
for term in terminations:
|
||||
self.draw_fanout(term, cable)
|
||||
else:
|
||||
elif far_ends:
|
||||
self.draw_terminations(far_ends)
|
||||
else:
|
||||
# Link is not connected to anything
|
||||
break
|
||||
|
||||
# Far end parent
|
||||
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):
|
||||
"""
|
||||
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 = 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):
|
||||
|
@ -219,7 +219,7 @@
|
||||
<tr>
|
||||
<th scope="row">Path Status</th>
|
||||
<td>
|
||||
{% if object.path.is_active %}
|
||||
{% if object.path.is_complete and object.path.is_active %}
|
||||
<span class="badge bg-success">Reachable</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">Not Reachable</span>
|
||||
|
Reference in New Issue
Block a user