Browse Source

Improved cable tracing

Jeremy Stretch 7 years ago
parent
commit
e79a156e1f
2 changed files with 38 additions and 33 deletions
  1. 29 29
      netbox/dcim/models.py
  2. 9 4
      netbox/dcim/signals.py

+ 29 - 29
netbox/dcim/models.py

@@ -2377,44 +2377,44 @@ class Cable(ChangeLoggedModel):
         Traverse both ends of a cable path and return its connected endpoints. Note that one or both endpoints may be
         Traverse both ends of a cable path and return its connected endpoints. Note that one or both endpoints may be
         None.
         None.
         """
         """
-        def trace_cable(termination, position=None):
+        def trace_cable(termination, position=1):
 
 
             # Given a front port, follow the cable connected to the corresponding rear port/position
             # Given a front port, follow the cable connected to the corresponding rear port/position
             if isinstance(termination, FrontPanelPort):
             if isinstance(termination, FrontPanelPort):
-                rear_port = termination.rear_port
-                port_type = ContentType.objects.get_for_model(rear_port)
-                next_cable = Cable.objects.filter(
-                    Q(termination_a_type=port_type, termination_a_id=rear_port.pk) |
-                    Q(termination_b_type=port_type, termination_b_id=rear_port.pk)
-                ).first()
-                if next_cable is None:
-                    return None
-                if next_cable.termination_a == termination.rear_port:
-                    return trace_cable(next_cable.termination_b, termination.rear_port_position)
-                else:
-                    return trace_cable(next_cable.termination_a, termination.rear_port_position)
+                peer_port = termination.rear_port
+                position = termination.rear_port_position
 
 
             # Given a rear port/position, follow the cable connected to the corresponding front port
             # Given a rear port/position, follow the cable connected to the corresponding front port
-            if isinstance(termination, RearPanelPort):
-                if position is None:
-                    raise Exception("Must specify a position when tracing a path from a rear panel port")
-                front_port = FrontPanelPort.objects.get(
+            elif isinstance(termination, RearPanelPort):
+                if position not in range(1, termination.positions + 1):
+                    raise Exception("Invalid position for {} ({} positions): {})".format(
+                        termination, termination.positions, position
+                    ))
+                peer_port = FrontPanelPort.objects.get(
                     rear_port=termination,
                     rear_port=termination,
                     rear_port_position=position,
                     rear_port_position=position,
                 )
                 )
-                port_type = ContentType.objects.get_for_model(front_port)
-                next_cable = Cable.objects.filter(
-                    Q(termination_a_type=port_type, termination_a_id=front_port.pk) |
-                    Q(termination_b_type=port_type, termination_b_id=front_port.pk)
-                ).first()
-                if next_cable is None:
-                    return None
-                if next_cable.termination_a == front_port:
-                    return trace_cable(next_cable.termination_b)
-                else:
-                    return trace_cable(next_cable.termination_a)
+                position=1
 
 
             # Termination is not a panel port, so we've reached the end of the path
             # Termination is not a panel port, so we've reached the end of the path
-            return termination
+            else:
+                return termination
+
+            # Find the cable (if any) attached to the peer port
+            port_type = ContentType.objects.get_for_model(peer_port)
+            next_cable = Cable.objects.filter(
+                Q(termination_a_type=port_type, termination_a_id=peer_port.pk) |
+                Q(termination_b_type=port_type, termination_b_id=peer_port.pk)
+            ).first()
+
+            # If no cable exists, return None
+            if next_cable is None:
+                return None
+
+            # Return the far side termination of the cable
+            if next_cable.termination_a == peer_port:
+                return trace_cable(next_cable.termination_b, position)
+            else:
+                return trace_cable(next_cable.termination_a, position)
 
 
         return trace_cable(self.termination_a), trace_cable(self.termination_b)
         return trace_cable(self.termination_a), trace_cable(self.termination_b)

+ 9 - 4
netbox/dcim/signals.py

@@ -29,8 +29,10 @@ def update_connected_endpoints(instance, **kwargs):
     termination_a, termination_b = instance.get_path_endpoints()
     termination_a, termination_b = instance.get_path_endpoints()
     if termination_a is not None and termination_b is not None:
     if termination_a is not None and termination_b is not None:
         termination_a.connected_endpoint = termination_b
         termination_a.connected_endpoint = termination_b
+        termination_a.connection_status = True
         termination_a.save()
         termination_a.save()
         termination_b.connected_endpoint = termination_a
         termination_b.connected_endpoint = termination_a
+        termination_a.connection_status = True
         termination_b.save()
         termination_b.save()
 
 
 
 
@@ -40,7 +42,10 @@ def nullify_connected_endpoints(instance, **kwargs):
     When a Cable is deleted, nullify its connected endpoints.
     When a Cable is deleted, nullify its connected endpoints.
     """
     """
     termination_a, termination_b = instance.get_path_endpoints()
     termination_a, termination_b = instance.get_path_endpoints()
-    termination_a.connected_endpoint = None
-    termination_a.save()
-    termination_b.connected_endpoint = None
-    termination_b.save()
+    if termination_a is not None and termination_b is not None:
+        termination_a.connected_endpoint = None
+        termination_a.connection_status = None
+        termination_a.save()
+        termination_b.connected_endpoint = None
+        termination_b.connection_status = None
+        termination_b.save()