2
0
Эх сурвалжийг харах

Restore total length count on trace view

Jeremy Stretch 5 жил өмнө
parent
commit
44b842592a

+ 6 - 2
docs/release-notes/version-2.10.md

@@ -71,7 +71,9 @@ All end-to-end cable paths are now cached using the new CablePath model. This al
 * dcim.ConsoleServerPort:
 * dcim.ConsoleServerPort:
   * Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
   * Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
   * Added `cable_peer` and `cable_peer_type`
   * Added `cable_peer` and `cable_peer_type`
-* dcim.FrontPort: Added `cable_peer` and `cable_peer_type`
+* dcim.FrontPort:
+  * Removed the `/trace/` endpoint
+  * Added `cable_peer` and `cable_peer_type`
 * dcim.Interface:
 * dcim.Interface:
   * Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
   * Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
   * Added `cable_peer` and `cable_peer_type`
   * Added `cable_peer` and `cable_peer_type`
@@ -85,7 +87,9 @@ All end-to-end cable paths are now cached using the new CablePath model. This al
   * Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
   * Replaced `connection_status` with `connected_endpoint_reachable` (boolean)
   * Added `cable_peer` and `cable_peer_type`
   * Added `cable_peer` and `cable_peer_type`
 * dcim.RackReservation: Added `custom_fields`
 * dcim.RackReservation: Added `custom_fields`
-* dcim.RearPort: Added `cable_peer` and `cable_peer_type`
+* dcim.RearPort:
+  * Removed the `/trace/` endpoint
+  * Added `cable_peer` and `cable_peer_type`
 * dcim.VirtualChassis: Added `custom_fields`
 * dcim.VirtualChassis: Added `custom_fields`
 * extras.ExportTemplate: The `template_language` field has been removed
 * extras.ExportTemplate: The `template_language` field has been removed
 * extras.Graph: This API endpoint has been removed (see #4349)
 * extras.Graph: This API endpoint has been removed (see #4349)

+ 12 - 2
netbox/dcim/models/devices.py

@@ -7,7 +7,7 @@ from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ObjectDoesNotExist, ValidationError
 from django.core.exceptions import ObjectDoesNotExist, ValidationError
 from django.core.validators import MaxValueValidator, MinValueValidator
 from django.core.validators import MaxValueValidator, MinValueValidator
 from django.db import models
 from django.db import models
-from django.db.models import F, ProtectedError
+from django.db.models import F, ProtectedError, Sum
 from django.urls import reverse
 from django.urls import reverse
 from django.utils.safestring import mark_safe
 from django.utils.safestring import mark_safe
 from taggit.managers import TaggableManager
 from taggit.managers import TaggableManager
@@ -15,7 +15,7 @@ from taggit.managers import TaggableManager
 from dcim.choices import *
 from dcim.choices import *
 from dcim.constants import *
 from dcim.constants import *
 from dcim.fields import PathField
 from dcim.fields import PathField
-from dcim.utils import path_node_to_object
+from dcim.utils import decompile_path_node, path_node_to_object
 from extras.models import ChangeLoggedModel, ConfigContextModel, CustomFieldModel, TaggedItem
 from extras.models import ChangeLoggedModel, ConfigContextModel, CustomFieldModel, TaggedItem
 from extras.utils import extras_features
 from extras.utils import extras_features
 from utilities.choices import ColorChoices
 from utilities.choices import ColorChoices
@@ -1228,6 +1228,16 @@ class CablePath(models.Model):
         model = self.origin._meta.model
         model = self.origin._meta.model
         model.objects.filter(pk=self.origin.pk).update(_path=self.pk)
         model.objects.filter(pk=self.origin.pk).update(_path=self.pk)
 
 
+    def get_total_length(self):
+        """
+        Return the sum of the length of each cable in the path.
+        """
+        cable_ids = [
+            # Starting from the first element, every third element in the path should be a Cable
+            decompile_path_node(self.path[i])[1] for i in range(0, len(self.path), 3)
+        ]
+        return Cable.objects.filter(id__in=cable_ids).aggregate(total=Sum('_abs_length'))['total']
+
 
 
 #
 #
 # Virtual chassis
 # Virtual chassis

+ 11 - 2
netbox/dcim/utils.py

@@ -4,20 +4,29 @@ from .choices import CableStatusChoices
 from .exceptions import CableTraceSplit
 from .exceptions import CableTraceSplit
 
 
 
 
+def compile_path_node(ct_id, object_id):
+    return f'{ct_id}:{object_id}'
+
+
+def decompile_path_node(repr):
+    ct_id, object_id = repr.split(':')
+    return int(ct_id), int(object_id)
+
+
 def object_to_path_node(obj):
 def object_to_path_node(obj):
     """
     """
     Return a representation of an object suitable for inclusion in a CablePath path. Node representation is in the
     Return a representation of an object suitable for inclusion in a CablePath path. Node representation is in the
     form <ContentType ID>:<Object ID>.
     form <ContentType ID>:<Object ID>.
     """
     """
     ct = ContentType.objects.get_for_model(obj)
     ct = ContentType.objects.get_for_model(obj)
-    return f'{ct.pk}:{obj.pk}'
+    return compile_path_node(ct.pk, obj.pk)
 
 
 
 
 def path_node_to_object(repr):
 def path_node_to_object(repr):
     """
     """
     Given a path node representation, return the corresponding object.
     Given a path node representation, return the corresponding object.
     """
     """
-    ct_id, object_id = repr.split(':')
+    ct_id, object_id = decompile_path_node(repr)
     model_class = ContentType.objects.get(pk=ct_id).model_class()
     model_class = ContentType.objects.get(pk=ct_id).model_class()
     return model_class.objects.get(pk=int(object_id))
     return model_class.objects.get(pk=int(object_id))
 
 

+ 1 - 5
netbox/dcim/views.py

@@ -1984,15 +1984,11 @@ class PathTraceView(ObjectView):
             else:
             else:
                 path = related_paths.first()
                 path = related_paths.first()
 
 
-        # total_length = sum(
-        #     [entry[1]._abs_length for entry in path if entry[1] and entry[1]._abs_length]
-        # )
-
         return render(request, 'dcim/cable_trace.html', {
         return render(request, 'dcim/cable_trace.html', {
             'obj': obj,
             'obj': obj,
             'path': path,
             'path': path,
             'related_paths': related_paths,
             'related_paths': related_paths,
-            # 'total_length': total_length,
+            'total_length': path.get_total_length(),
         })
         })