Jelajahi Sumber

review fixes

Arthur 4 hari lalu
induk
melakukan
46373981af
2 mengubah file dengan 36 tambahan dan 2 penghapusan
  1. 10 2
      netbox/dcim/models/devices.py
  2. 26 0
      netbox/dcim/tests/test_models.py

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

@@ -1033,13 +1033,21 @@ class Device(
         if self.virtual_chassis_id:
             lag_members = lag_members.exclude(lag__device__virtual_chassis=self.virtual_chassis_id)
             lag_peers = lag_peers.exclude(device__virtual_chassis=self.virtual_chassis_id)
-        interfaces = [*lag_members.select_related('lag__device'), *lag_peers.select_related('device', 'lag')]
+        interfaces = [
+            *lag_members.select_related('device', 'lag__device'),
+            *lag_peers.select_related('device', 'lag__device'),
+        ]
         if interfaces:
+            # Cap the listed interfaces to keep the message readable
+            max_listed = 5
+            listed = ', '.join(f'{i.device}:{i} ({i.lag.device}:{i.lag})' for i in interfaces[:max_listed])
+            if len(interfaces) > max_listed:
+                listed += _(' (and {count} more)').format(count=len(interfaces) - max_listed)
             raise ValidationError({
                 'virtual_chassis': _(
                     'Virtual chassis membership cannot be changed while interfaces form a LAG with another device '
                     'outside the virtual chassis: {interfaces}'
-                ).format(interfaces=', '.join(f'{i.device}:{i} ({i.lag.device}:{i.lag})' for i in interfaces))
+                ).format(interfaces=listed)
             })
 
     def _check_duplicate_component_names(self, components):

+ 26 - 0
netbox/dcim/tests/test_models.py

@@ -3728,6 +3728,32 @@ class VirtualChassisTestCase(TestCase):
             device1.full_clean()
         self.assertIn('eth0', str(cm.exception.error_dict['virtual_chassis']))
 
+    def test_member_removal_error_lists_at_most_five_interfaces(self):
+        """
+        The cross-chassis LAG error names at most five interfaces and summarizes the rest.
+        """
+        device1 = Device.objects.get(name='TestDevice1')
+        device2 = Device.objects.get(name='TestDevice2')
+
+        vc = VirtualChassis.objects.create(name='Test VC', master=device1)
+        Device.objects.filter(pk=device1.pk).update(virtual_chassis=vc, vc_position=1)
+        Device.objects.filter(pk=device2.pk).update(virtual_chassis=vc, vc_position=2)
+        device2.refresh_from_db()
+
+        lag = Interface.objects.create(device=device1, name='lag0', type=InterfaceTypeChoices.TYPE_LAG)
+        Interface.objects.bulk_create([
+            Interface(device=device2, name=f'eth{i}', type=InterfaceTypeChoices.TYPE_1GE_FIXED, lag=lag)
+            for i in range(7)
+        ])
+
+        device2.virtual_chassis = None
+        device2.vc_position = None
+        with self.assertRaises(ValidationError) as cm:
+            device2.full_clean()
+        message = str(cm.exception.error_dict['virtual_chassis'])
+        self.assertEqual(message.count('lag0'), 5)
+        self.assertIn('(and 2 more)', message)
+
     def test_unrelated_edit_allowed_with_existing_cross_chassis_lag(self):
         """
         Pre-existing cross-chassis LAG data must not block edits that leave VC membership unchanged.