From 0a9887b42fbbe37c5f43a2318f0bf08e4c487e5b Mon Sep 17 00:00:00 2001 From: Jason Novinger Date: Tue, 24 Jun 2025 13:37:16 -0400 Subject: [PATCH] Fixes #19745: properly check IP assignment to FHRPGroup - Expands the logic in ServiceImportForm.clean() to handle properly validation of FHRPGroup assignments and maintain the existing [VM]Interface validation checks. - Includes an extension to ServiceTestCase.csv_data to act as a regression test for this behavior. --- netbox/ipam/forms/bulk_import.py | 5 ++++- netbox/ipam/tests/test_views.py | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py index d17944674..c0aa43461 100644 --- a/netbox/ipam/forms/bulk_import.py +++ b/netbox/ipam/forms/bulk_import.py @@ -633,7 +633,10 @@ class ServiceImportForm(NetBoxModelImportForm): # triggered parent = self.cleaned_data.get('parent') for ip_address in self.cleaned_data.get('ipaddresses', []): - if not ip_address.assigned_object or getattr(ip_address.assigned_object, 'parent_object') != parent: + if not (assigned := ip_address.assigned_object) or ( # no assigned object + (isinstance(parent, FHRPGroup) and assigned != parent) # assigned to FHRPGroup + and getattr(assigned, 'parent_object') != parent # assigned to [VM]Interface + ): raise forms.ValidationError( _("{ip} is not assigned to this parent.").format(ip=ip_address) ) diff --git a/netbox/ipam/tests/test_views.py b/netbox/ipam/tests/test_views.py index 8ba011d1d..0b4f3b740 100644 --- a/netbox/ipam/tests/test_views.py +++ b/netbox/ipam/tests/test_views.py @@ -1068,6 +1068,9 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase): role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') device = Device.objects.create(name='Device 1', site=site, device_type=devicetype, role=role) interface = Interface.objects.create(device=device, name='Interface 1', type=InterfaceTypeChoices.TYPE_VIRTUAL) + fhrp_group = FHRPGroup.objects.create( + name='Group 1', group_id=1234, protocol=FHRPGroupProtocolChoices.PROTOCOL_CARP + ) services = ( Service(parent=device, name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[101]), @@ -1079,6 +1082,7 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase): ip_addresses = ( IPAddress(assigned_object=interface, address='192.0.2.1/24'), IPAddress(assigned_object=interface, address='192.0.2.2/24'), + IPAddress(assigned_object=fhrp_group, address='192.0.2.3/24'), ) IPAddress.objects.bulk_create(ip_addresses) @@ -1100,6 +1104,7 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase): "dcim.device,Device 1,Service 1,tcp,1,192.0.2.1/24,First service", "dcim.device,Device 1,Service 2,tcp,2,192.0.2.2/24,Second service", "dcim.device,Device 1,Service 3,udp,3,,Third service", + "ipam.fhrpgroup,Group 1,Service 4,udp,4,192.0.2.3/24,Fourth service", ) cls.csv_update_data = (