jeremystretch 3 лет назад
Родитель
Сommit
b44bfa1aa6
3 измененных файлов с 25 добавлено и 14 удалено
  1. 11 4
      netbox/dcim/models/cables.py
  2. 9 7
      netbox/dcim/signals.py
  3. 5 3
      netbox/dcim/utils.py

+ 11 - 4
netbox/dcim/models/cables.py

@@ -330,6 +330,8 @@ class CablePath(models.Model):
     def from_origin(cls, terminations):
         """
         Create a new CablePath instance as traced from the given path origin.
+
+        :param terminations: An iterable of one or more CableTermination objects.
         """
         from circuits.models import CircuitTermination
 
@@ -348,7 +350,7 @@ class CablePath(models.Model):
         ])
 
         node = terminations[0].termination
-        while node.link is not None:
+        while terminations and node.link is not None:
             if hasattr(node.link, 'status') and node.link.status != LinkStatusChoices.STATUS_CONNECTED:
                 is_active = False
 
@@ -371,9 +373,10 @@ class CablePath(models.Model):
                     termination_id__in=[t.termination_id for t in peer_terminations]
                 )
                 rear_ports = RearPort.objects.filter(pk__in=[t.termination.rear_port_id for t in peer_terminations])
+                # TODO: We're assuming that each of the front-to-rear mapping use equivalent positions.
                 node = rear_ports[0]
-                if node.positions > 1:
-                    position_stack.append(node.rear_port_position)
+                if rear_ports[0].positions > 1:
+                    position_stack.append(peer_terminations[0].termination.rear_port_position)
                 path.append([
                     object_to_path_node(rp) for rp in rear_ports
                 ])
@@ -395,10 +398,14 @@ class CablePath(models.Model):
                     break
 
                 # Map FrontPorts to their corresponding RearPorts
-                terminations = FrontPort.objects.filter(
+                front_ports = FrontPort.objects.filter(
                     rear_port_id__in=[t.rear_port_id for t in peer_terminations],
                     rear_port_position=position
                 )
+                terminations = CableTermination.objects.filter(
+                    termination_type=ContentType.objects.get_for_model(FrontPort),
+                    termination_id__in=[fp.pk for fp in front_ports]
+                )
                 if terminations:
                     path.append([
                         object_to_path_node(t.termination) for t in terminations

+ 9 - 7
netbox/dcim/signals.py

@@ -1,3 +1,4 @@
+from collections import defaultdict
 import logging
 
 from django.contrib.contenttypes.models import ContentType
@@ -84,25 +85,26 @@ def update_connected_endpoints(instance, created, raw=False, **kwargs):
         term for term in instance.terminations if not term.pk
     ])
 
+    # Split terminations into A/B sets
+    _terms = defaultdict(list)
+    for term in instance.terminations:
+        _terms[term.cable_end].append(term)
+
     # TODO: Update link peers
     # Set cable on terminating endpoints
-    _terms = {
-        'A': [],
-        'B': [],
-    }
     for term in instance.terminations:
         if term.termination.cable != instance:
             term.termination.cable = instance
             term.termination.save()
-        _terms[term.cable_end].append(term)
 
     # Create/update cable paths
     if created:
         for terms in _terms.values():
+            # Examine type of first termination to determine object type (all must be the same)
             if isinstance(terms[0].termination, PathEndpoint):
                 create_cablepath(terms)
-            else:
-                rebuild_paths(terms)
+            # else:
+            #     rebuild_paths(terms)
     # elif instance.status != instance._orig_status:
     #     # We currently don't support modifying either termination of an existing Cable. (This
     #     # may change in the future.) However, we do need to capture status changes and update

+ 5 - 3
netbox/dcim/utils.py

@@ -39,13 +39,15 @@ def flatten_path(path):
     return ret
 
 
-def create_cablepath(node):
+def create_cablepath(terminations):
     """
-    Create CablePaths for all paths originating from the specified node.
+    Create CablePaths for all paths originating from the specified set of nodes.
+
+    :param terminations: Iterable of CableTermination objects
     """
     from dcim.models import CablePath
 
-    cp = CablePath.from_origin(node)
+    cp = CablePath.from_origin(terminations)
     if cp:
         cp.save()