diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index 894219c64..d62250b80 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -610,6 +610,11 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet): field_name='pk', label=_('Device (ID)'), ) + device_role = MultiValueCharFilter( + method='filter_device', + field_name='role', + label=_('Device (role)'), + ) virtual_machine = MultiValueCharFilter( method='filter_virtual_machine', field_name='name', @@ -620,6 +625,11 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet): field_name='pk', label=_('Virtual machine (ID)'), ) + virtual_machine_role = MultiValueCharFilter( + method='filter_virtual_machine', + field_name='role', + label=_('Virtual machine (role)'), + ) interface = django_filters.ModelMultipleChoiceFilter( field_name='interface__name', queryset=Interface.objects.all(), diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py index a32694321..9b55d9450 100644 --- a/netbox/ipam/forms/filtersets.py +++ b/netbox/ipam/forms/filtersets.py @@ -1,7 +1,7 @@ from django import forms from django.utils.translation import gettext_lazy as _ -from dcim.models import Location, Rack, Region, Site, SiteGroup, Device +from dcim.models import Location, Rack, Region, Site, SiteGroup, Device, DeviceRole from ipam.choices import * from ipam.constants import * from ipam.models import * @@ -308,7 +308,7 @@ class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): ), FieldSet('vrf_id', 'present_in_vrf_id', name=_('VRF')), FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), - FieldSet('device_id', 'virtual_machine_id', name=_('Device/VM')), + FieldSet('device_id', 'virtual_machine_id', 'virtual_machine_role', name=_('Device/VM')), ) selector_fields = ('filter_id', 'q', 'region_id', 'group_id', 'parent', 'status', 'role') parent = forms.CharField( @@ -346,11 +346,21 @@ class IPAddressFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): required=False, label=_('Assigned Device'), ) + device_role = DynamicModelMultipleChoiceField( + queryset=DeviceRole.objects.all(), + required=False, + label=_('Assigned Device Role'), + ) virtual_machine_id = DynamicModelMultipleChoiceField( queryset=VirtualMachine.objects.all(), required=False, label=_('Assigned VM'), ) + virtual_machine_role = DynamicModelMultipleChoiceField( + queryset=DeviceRole.objects.all(), + required=False, + label=_('Assigned VM Role') + ) status = forms.MultipleChoiceField( label=_('Status'), choices=IPAddressStatusChoices, diff --git a/netbox/ipam/tests/test_filtersets.py b/netbox/ipam/tests/test_filtersets.py index 4e38b1450..4d5b6b55c 100644 --- a/netbox/ipam/tests/test_filtersets.py +++ b/netbox/ipam/tests/test_filtersets.py @@ -1020,8 +1020,8 @@ class IPAddressTestCase(TestCase, ChangeLoggedFilterSetTests): cluster = Cluster.objects.create(type=clustertype, name='Cluster 1') virtual_machines = ( - VirtualMachine(name='Virtual Machine 1', cluster=cluster), - VirtualMachine(name='Virtual Machine 2', cluster=cluster), + VirtualMachine(name='Virtual Machine 1', cluster=cluster, role=role), + VirtualMachine(name='Virtual Machine 2', cluster=cluster, role=role), VirtualMachine(name='Virtual Machine 3', cluster=cluster), ) VirtualMachine.objects.bulk_create(virtual_machines) @@ -1244,6 +1244,8 @@ class IPAddressTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) params = {'device': [devices[0].name, devices[1].name]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device_role': [devices[0].role.pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) def test_virtual_machine(self): vms = VirtualMachine.objects.all()[:2] @@ -1251,6 +1253,8 @@ class IPAddressTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) params = {'virtual_machine': [vms[0].name, vms[1].name]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'virtual_machine_role': [vms[0].role.pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_interface(self): interfaces = Interface.objects.all()[:2]