diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index cb46d0222..30e6d20cd 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -1602,6 +1602,26 @@ class PowerOutletFilterSet( class MACAddressFilterSet(NetBoxModelFilterSet): mac_address = MultiValueMACAddressFilter() + device = MultiValueCharFilter( + method='filter_device', + field_name='name', + label=_('Device (name)'), + ) + device_id = MultiValueNumberFilter( + method='filter_device', + field_name='pk', + label=_('Device (ID)'), + ) + virtual_machine = MultiValueCharFilter( + method='filter_virtual_machine', + field_name='name', + label=_('Virtual machine (name)'), + ) + virtual_machine_id = MultiValueNumberFilter( + method='filter_virtual_machine', + field_name='pk', + label=_('Virtual machine (ID)'), + ) interface = django_filters.ModelMultipleChoiceFilter( field_name='interface__name', queryset=Interface.objects.all(), @@ -1638,6 +1658,28 @@ class MACAddressFilterSet(NetBoxModelFilterSet): ) return queryset.filter(qs_filter) + def filter_device(self, queryset, name, value): + devices = Device.objects.filter(**{'{}__in'.format(name): value}) + if not devices.exists(): + return queryset.none() + interface_ids = [] + for device in devices: + interface_ids.extend(device.vc_interfaces().values_list('id', flat=True)) + return queryset.filter( + interface__in=interface_ids + ) + + def filter_virtual_machine(self, queryset, name, value): + virtual_machines = VirtualMachine.objects.filter(**{'{}__in'.format(name): value}) + if not virtual_machines.exists(): + return queryset.none() + interface_ids = [] + for vm in virtual_machines: + interface_ids.extend(vm.interfaces.values_list('id', flat=True)) + return queryset.filter( + vminterface__in=interface_ids + ) + class CommonInterfaceFilterSet(django_filters.FilterSet): vlan_id = django_filters.CharFilter( diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 5fb1b9012..0b7c11db7 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -15,7 +15,7 @@ from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_ch from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField from utilities.forms.rendering import FieldSet from utilities.forms.widgets import NumberWithOptions -from virtualization.models import Cluster, ClusterGroup +from virtualization.models import Cluster, ClusterGroup, VirtualMachine from vpn.models import L2VPN from wireless.choices import * @@ -1211,12 +1211,23 @@ class MACAddressFilterForm(NetBoxModelFilterSetForm): fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('mac_address', name=_('Addressing')), + FieldSet('device_id', 'virtual_machine_id', name=_('Device/VM')), ) - selector_fields = ('filter_id', 'q', 'device_id') + selector_fields = ('filter_id', 'q', 'device_id', 'virtual_machine_id') mac_address = forms.CharField( required=False, label=_('MAC address') ) + device_id = DynamicModelMultipleChoiceField( + queryset=Device.objects.all(), + required=False, + label=_('Assigned Device'), + ) + virtual_machine_id = DynamicModelMultipleChoiceField( + queryset=VirtualMachine.objects.all(), + required=False, + label=_('Assigned VM'), + ) tag = TagFilterField(model)