From 1025c227ce8fbf16c352366e983d0eb21c241b7c Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Wed, 6 Aug 2025 21:16:19 -0500 Subject: [PATCH] Fixes: #19645 - Correct Interface selection for Cable add when VC master is the selected device --- netbox/dcim/filtersets.py | 17 +++++++++++++++-- netbox/dcim/forms/connections.py | 7 ++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 814be356c..beecb7116 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -1885,6 +1885,16 @@ class InterfaceFilterSet( PathEndpointFilterSet, CommonInterfaceFilterSet ): + virtual_chassis_member_or_master = MultiValueCharFilter( + method='filter_virtual_chassis_member_or_master', + field_name='name', + label=_('Virtual Chassis Interfaces for Device') + ) + virtual_chassis_member_or_master_id = MultiValueNumberFilter( + method='filter_virtual_chassis_member_or_master', + field_name='pk', + label=_('Virtual Chassis Interfaces for Device (ID)') + ) virtual_chassis_member = MultiValueCharFilter( method='filter_virtual_chassis_member', field_name='name', @@ -1995,11 +2005,14 @@ class InterfaceFilterSet( 'cable_id', 'cable_end', ) - def filter_virtual_chassis_member(self, queryset, name, value): + def filter_virtual_chassis_member_or_master(self, queryset, name, value): + return self.filter_virtual_chassis_member(queryset, name, value, if_master=True) + + def filter_virtual_chassis_member(self, queryset, name, value, if_master=False): try: vc_interface_ids = [] for device in Device.objects.filter(**{f'{name}__in': value}): - vc_interface_ids.extend(device.vc_interfaces(if_master=False).values_list('id', flat=True)) + vc_interface_ids.extend(device.vc_interfaces(if_master=if_master).values_list('id', flat=True)) return queryset.filter(pk__in=vc_interface_ids) except Device.DoesNotExist: return queryset.none() diff --git a/netbox/dcim/forms/connections.py b/netbox/dcim/forms/connections.py index 5e5d83b0b..d3588da39 100644 --- a/netbox/dcim/forms/connections.py +++ b/netbox/dcim/forms/connections.py @@ -19,6 +19,11 @@ def get_cable_form(a_type, b_type): # Device component if hasattr(term_cls, 'device'): + # Dynamically change the param field for interfaces to use virtual_chassis filter + query_param_device_field = 'device_id' + if term_cls == Interface: + query_param_device_field = 'virtual_chassis_member_or_master_id' + attrs[f'termination_{cable_end}_device'] = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), label=_('Device'), @@ -36,7 +41,7 @@ def get_cable_form(a_type, b_type): 'parent': 'device', }, query_params={ - 'device_id': f'$termination_{cable_end}_device', + query_param_device_field: f'$termination_{cable_end}_device', 'kind': 'physical', # Exclude virtual interfaces } )