From 7622d90c1de981e78d63f31b52505e0dd6689cd4 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 27 Jun 2022 15:22:09 -0400 Subject: [PATCH] Extend cable tracing to support terminations to different parent objects --- netbox/dcim/models/cables.py | 3 +-- netbox/dcim/svg/cables.py | 45 +++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index 55b1512d0..f13c77d15 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -444,9 +444,8 @@ class CablePath(models.Model): while terminations: - # Terminations must all be of the same type and belong to the same parent + # Terminations must all be of the same type assert all(isinstance(t, type(terminations[0])) for t in terminations[1:]) - assert all(t.parent_object == terminations[0].parent_object for t in terminations[1:]) # Step 1: Record the near-end termination object(s) path.append([ diff --git a/netbox/dcim/svg/cables.py b/netbox/dcim/svg/cables.py index 3a9b47b54..d26bc5ff5 100644 --- a/netbox/dcim/svg/cables.py +++ b/netbox/dcim/svg/cables.py @@ -18,7 +18,6 @@ PADDING = 10 LINE_HEIGHT = 20 FANOUT_HEIGHT = 35 FANOUT_LEG_HEIGHT = 15 -TERMINATION_WIDTH = 100 class Node(Hyperlink): @@ -174,32 +173,35 @@ class CableTraceSVG: # Other parent object return 'e0e0e0' - def draw_parent_object(self, obj): - node = Node( - position=(0, self.cursor), - width=self.width, - url=f'{self.base_url}{obj.get_absolute_url()}', - color=self._get_color(obj), - labels=self._get_labels(obj) - ) - self.parent_objects.append(node) - self.cursor += node.box['height'] - - return node + def draw_parent_objects(self, obj_list): + """ + Draw a set of parent objects. + """ + width = self.width / len(obj_list) + for i, obj in enumerate(obj_list): + node = Node( + position=(i * width, self.cursor), + width=width, + url=f'{self.base_url}{obj.get_absolute_url()}', + color=self._get_color(obj), + labels=self._get_labels(obj) + ) + self.parent_objects.append(node) + if i + 1 == len(obj_list): + self.cursor += node.box['height'] def draw_terminations(self, terminations): """ - Draw a row of terminating objects (e.g. interfaces) belonging to the same parent object, all of which - are attached to the same end of a cable. + Draw a row of terminating objects (e.g. interfaces), all of which are attached to the same end of a cable. """ nodes = [] nodes_height = 0 - x = self.width / 2 - len(terminations) * TERMINATION_WIDTH / 2 + width = self.width / len(terminations) for i, term in enumerate(terminations): node = Node( - position=(x + i * TERMINATION_WIDTH, self.cursor), - width=TERMINATION_WIDTH, + position=(i * width, self.cursor), + width=width, url=f'{self.base_url}{term.get_absolute_url()}', color=self._get_color(term), labels=self._get_labels(term), @@ -324,7 +326,7 @@ class CableTraceSVG: # Near end parent if i == 0: # If this is the first segment, draw the originating termination's parent object - self.draw_parent_object(near_ends[0].parent_object) + self.draw_parent_objects(set(end.parent_object for end in near_ends)) # Near end termination(s) terminations = self.draw_terminations(near_ends) @@ -363,7 +365,8 @@ class CableTraceSVG: self.draw_terminations(far_ends) # Far end parent - self.draw_parent_object(far_ends[0].parent_object) + parent_objects = set(end.parent_object for end in far_ends) + self.draw_parent_objects(parent_objects) elif far_ends: @@ -372,7 +375,7 @@ class CableTraceSVG: self.connectors.append(attachment) # ProviderNetwork - self.draw_parent_object(far_ends[0]) + self.draw_parent_objects(set(end.parent_object for end in far_ends)) # Determine drawing size self.drawing = svgwrite.Drawing(