From 5be20924e7aa8369cb8653decd5502fdd1d68de5 Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Thu, 31 Oct 2024 14:31:49 -0400 Subject: [PATCH] Fix filterset tests for VMInterface --- netbox/dcim/filtersets.py | 13 ++-- netbox/dcim/forms/filtersets.py | 10 +-- netbox/dcim/tests/test_filtersets.py | 4 ++ netbox/netbox/filtersets.py | 2 + netbox/templates/dcim/macaddress.html | 68 +++++++++---------- netbox/virtualization/filtersets.py | 9 +-- netbox/virtualization/forms/filtersets.py | 10 +-- .../virtualization/tests/test_filtersets.py | 16 +++-- 8 files changed, 75 insertions(+), 57 deletions(-) diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index a4ceefb72..645dc9c40 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -1099,10 +1099,10 @@ class DeviceFilterSet( field_name='device_type__is_full_depth', label=_('Is full depth'), ) - # mac_address = MultiValueMACAddressFilter( - # field_name='interfaces___mac_address', - # label=_('MAC address'), - # ) + mac_address = MultiValueMACAddressFilter( + field_name='interfaces__mac_addresses__mac_address', + label=_('MAC address'), + ) serial = MultiValueCharFilter( lookup_expr='iexact' ) @@ -1849,7 +1849,10 @@ class InterfaceFilterSet( duplex = django_filters.MultipleChoiceFilter( choices=InterfaceDuplexChoices ) - # mac_address = MultiValueMACAddressFilter() + mac_address = MultiValueMACAddressFilter( + field_name='mac_addresses__mac_address', + label=_('MAC Address') + ) wwn = MultiValueWWNFilter() poe_mode = django_filters.MultipleChoiceFilter( choices=InterfacePoEModeChoices diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 1816ef444..cdb7e2a71 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -1344,7 +1344,7 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('name', 'label', 'kind', 'type', 'speed', 'duplex', 'enabled', 'mgmt_only', name=_('Attributes')), - FieldSet('vrf_id', 'l2vpn_id', 'wwn', name=_('Addressing')), + FieldSet('vrf_id', 'l2vpn_id', 'mac_address', 'wwn', name=_('Addressing')), FieldSet('poe_mode', 'poe_type', name=_('PoE')), FieldSet('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power', name=_('Wireless')), FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), @@ -1399,10 +1399,10 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): choices=BOOLEAN_WITH_BLANK_CHOICES ) ) - # mac_address = forms.CharField( - # required=False, - # label=_('MAC address') - # ) + mac_address = forms.CharField( + required=False, + label=_('MAC address') + ) wwn = forms.CharField( required=False, label=_('WWN') diff --git a/netbox/dcim/tests/test_filtersets.py b/netbox/dcim/tests/test_filtersets.py index d3b62c232..ae3fbe049 100644 --- a/netbox/dcim/tests/test_filtersets.py +++ b/netbox/dcim/tests/test_filtersets.py @@ -3988,6 +3988,10 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil params = {'kind': 'virtual'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0) + def test_mac_address(self): + params = {'mac_address': ['00-00-00-00-00-01', '00-00-00-00-00-02']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_type(self): params = {'type': [InterfaceTypeChoices.TYPE_1GE_FIXED, InterfaceTypeChoices.TYPE_1GE_GBIC]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py index 637a40bf1..8be3db059 100644 --- a/netbox/netbox/filtersets.py +++ b/netbox/netbox/filtersets.py @@ -168,6 +168,8 @@ class BaseFilterSet(django_filters.FilterSet): # Get properties of the existing filter for later use field_name = existing_filter.field_name field = get_model_field(cls._meta.model, field_name) + if field is None: + raise ValueError('Invalid field name/lookup on {}: {}'.format(existing_filter_name, field_name)) # Create new filters for each lookup expression in the map for lookup_name, lookup_expr in lookup_map.items(): diff --git a/netbox/templates/dcim/macaddress.html b/netbox/templates/dcim/macaddress.html index b0cf1bb62..d62edd550 100644 --- a/netbox/templates/dcim/macaddress.html +++ b/netbox/templates/dcim/macaddress.html @@ -5,46 +5,46 @@ {% load i18n %} {% block content %} -
-
+
+
-

{% trans "MAC Address" %}

- - - - - - - - - - - - - -
{% trans "Description" %}{{ object.description|placeholder }}
{% trans "Assignment" %} - {% if object.assigned_object %} - {% if object.assigned_object.parent_object %} - {{ object.assigned_object.parent_object|linkify }} / - {% endif %} - {{ object.assigned_object|linkify }} - {% else %} - {{ ''|placeholder }} - {% endif %} -
{% trans "Primary MAC for Interface" %}{% checkmark object.is_primary %}
+

{% trans "MAC Address" %}

+ + + + + + + + + + + + + +
{% trans "Description" %}{{ object.description|placeholder }}
{% trans "Assignment" %} + {% if object.assigned_object %} + {% if object.assigned_object.parent_object %} + {{ object.assigned_object.parent_object|linkify }} / + {% endif %} + {{ object.assigned_object|linkify }} + {% else %} + {{ ''|placeholder }} + {% endif %} +
{% trans "Primary MAC for Interface" %}{% checkmark object.is_primary %}
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/custom_fields.html' %} {% plugin_left_page object %} -
-
+
+
{% include 'inc/panels/comments.html' %} {% plugin_right_page object %} -
-
-
-
- {% plugin_full_width_page object %} +
+
+
+
+ {% plugin_full_width_page object %} +
-
{% endblock %} diff --git a/netbox/virtualization/filtersets.py b/netbox/virtualization/filtersets.py index 17f574db9..84e828295 100644 --- a/netbox/virtualization/filtersets.py +++ b/netbox/virtualization/filtersets.py @@ -9,7 +9,7 @@ from extras.models import ConfigTemplate from ipam.filtersets import PrimaryIPFilterSet from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet -from utilities.filters import MultiValueCharFilter, TreeNodeMultipleChoiceFilter +from utilities.filters import MultiValueCharFilter, TreeNodeMultipleChoiceFilter, MultiValueMACAddressFilter from .choices import * from .models import * @@ -297,9 +297,10 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet, CommonInterfaceFilterSet): queryset=VMInterface.objects.all(), label=_('Bridged interface (ID)'), ) - # _mac_address = MultiValueMACAddressFilter( - # label=_('MAC address'), - # ) + mac_address = MultiValueMACAddressFilter( + field_name='mac_addresses__mac_address', + label=_('MAC address'), + ) class Meta: model = VMInterface diff --git a/netbox/virtualization/forms/filtersets.py b/netbox/virtualization/forms/filtersets.py index 70266cb5f..7c040d948 100644 --- a/netbox/virtualization/forms/filtersets.py +++ b/netbox/virtualization/forms/filtersets.py @@ -195,7 +195,7 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm): fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('cluster_id', 'virtual_machine_id', name=_('Virtual Machine')), - FieldSet('enabled', 'vrf_id', 'l2vpn_id', name=_('Attributes')), + FieldSet('enabled', 'mac_address', 'vrf_id', 'l2vpn_id', name=_('Attributes')), ) selector_fields = ('filter_id', 'q', 'virtual_machine_id') cluster_id = DynamicModelMultipleChoiceField( @@ -218,10 +218,10 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm): choices=BOOLEAN_WITH_BLANK_CHOICES ) ) - # mac_address = forms.CharField( - # required=False, - # label=_('MAC address') - # ) + mac_address = forms.CharField( + required=False, + label=_('MAC address') + ) vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, diff --git a/netbox/virtualization/tests/test_filtersets.py b/netbox/virtualization/tests/test_filtersets.py index cd598274f..0543121bf 100644 --- a/netbox/virtualization/tests/test_filtersets.py +++ b/netbox/virtualization/tests/test_filtersets.py @@ -1,6 +1,6 @@ from django.test import TestCase -from dcim.models import Device, DeviceRole, Platform, Region, Site, SiteGroup +from dcim.models import Device, DeviceRole, MACAddress, Platform, Region, Site, SiteGroup from ipam.models import IPAddress, VLANTranslationPolicy, VRF from tenancy.models import Tenant, TenantGroup from utilities.testing import ChangeLoggedFilterSetTests, create_test_device @@ -568,13 +568,19 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests): ) VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + mac_addresses = ( + MACAddress(mac_address='00-00-00-00-00-01'), + MACAddress(mac_address='00-00-00-00-00-02'), + MACAddress(mac_address='00-00-00-00-00-03'), + ) + MACAddress.objects.bulk_create(mac_addresses) + interfaces = ( VMInterface( virtual_machine=vms[0], name='Interface 1', enabled=True, mtu=100, - mac_address='00-00-00-00-00-01', vrf=vrfs[0], description='foobar1', vlan_translation_policy=vlan_translation_policies[0], @@ -584,7 +590,6 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests): name='Interface 2', enabled=True, mtu=200, - mac_address='00-00-00-00-00-02', vrf=vrfs[1], description='foobar2', vlan_translation_policy=vlan_translation_policies[0], @@ -594,13 +599,16 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests): name='Interface 3', enabled=False, mtu=300, - mac_address='00-00-00-00-00-03', vrf=vrfs[2], description='foobar3' ), ) VMInterface.objects.bulk_create(interfaces) + interfaces[0].mac_addresses.set([mac_addresses[0]]) + interfaces[1].mac_addresses.set([mac_addresses[1]]) + interfaces[2].mac_addresses.set([mac_addresses[2]]) + def test_q(self): params = {'q': 'foobar1'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)