netbox/netbox/ipam/filters.py

536 lines
16 KiB
Python
Raw Normal View History

2016-03-01 11:23:03 -05:00
import django_filters
2018-11-02 15:20:08 -04:00
import netaddr
from django.core.exceptions import ValidationError
from django.db.models import Q
2016-03-01 11:23:03 -05:00
from netaddr.core import AddrFormatError
from dcim.models import Device, Interface, Region, Site
from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet
2019-05-09 14:32:49 -04:00
from tenancy.filtersets import TenancyFilterSet
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
from virtualization.models import VirtualMachine
2019-10-04 12:08:48 -04:00
from .constants import *
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
2016-03-01 11:23:03 -05:00
2020-01-08 17:20:31 -05:00
__all__ = (
'AggregateFilter',
'IPAddressFilter',
'PrefixFilter',
'RIRFilter',
'RoleFilter',
'ServiceFilter',
'VLANFilter',
'VLANGroupFilter',
'VRFFilter',
)
class VRFFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
id__in = NumericInFilter(
field_name='id',
lookup_expr='in'
)
q = django_filters.CharFilter(
method='search',
label='Search',
)
tag = TagFilter()
2016-03-01 11:23:03 -05:00
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(rd__icontains=value) |
Q(description__icontains=value)
)
class Meta:
model = VRF
fields = ['name', 'rd', 'enforce_unique']
2016-03-01 11:23:03 -05:00
class RIRFilter(NameSlugSearchFilterSet):
id__in = NumericInFilter(
field_name='id',
lookup_expr='in'
)
class Meta:
model = RIR
fields = ['name', 'slug', 'is_private']
class AggregateFilter(CustomFieldFilterSet, CreatedUpdatedFilterSet):
id__in = NumericInFilter(
field_name='id',
lookup_expr='in'
)
q = django_filters.CharFilter(
method='search',
label='Search',
)
prefix = django_filters.CharFilter(
method='filter_prefix',
label='Prefix',
)
2016-03-01 11:23:03 -05:00
rir_id = django_filters.ModelMultipleChoiceFilter(
queryset=RIR.objects.all(),
label='RIR (ID)',
)
rir = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='rir__slug',
2016-03-01 11:23:03 -05:00
queryset=RIR.objects.all(),
to_field_name='slug',
label='RIR (slug)',
)
tag = TagFilter()
2016-03-01 11:23:03 -05:00
class Meta:
model = Aggregate
fields = ['family', 'date_added']
2016-03-01 11:23:03 -05:00
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = Q(description__icontains=value)
try:
prefix = str(netaddr.IPNetwork(value.strip()).cidr)
qs_filter |= Q(prefix__net_contains_or_equals=prefix)
except (AddrFormatError, ValueError):
pass
return queryset.filter(qs_filter)
def filter_prefix(self, queryset, name, value):
if not value.strip():
return queryset
try:
query = str(netaddr.IPNetwork(value).cidr)
return queryset.filter(prefix=query)
except ValidationError:
return queryset.none()
2016-03-01 11:23:03 -05:00
class RoleFilter(NameSlugSearchFilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
class Meta:
model = Role
fields = ['id', 'name', 'slug']
class PrefixFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
id__in = NumericInFilter(
field_name='id',
lookup_expr='in'
)
q = django_filters.CharFilter(
method='search',
2016-03-01 11:23:03 -05:00
label='Search',
)
prefix = django_filters.CharFilter(
method='filter_prefix',
label='Prefix',
)
within = django_filters.CharFilter(
method='search_within',
label='Within prefix',
)
within_include = django_filters.CharFilter(
method='search_within_include',
label='Within and including prefix',
2016-03-01 11:23:03 -05:00
)
contains = django_filters.CharFilter(
method='search_contains',
label='Prefixes which contain this prefix or IP',
)
mask_length = django_filters.NumberFilter(
method='filter_mask_length',
label='Mask length',
)
vrf_id = django_filters.ModelMultipleChoiceFilter(
queryset=VRF.objects.all(),
label='VRF',
2016-03-01 11:23:03 -05:00
)
vrf = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='vrf__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
label='VRF (RD)',
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region__in',
label='Region (ID)',
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region__in',
to_field_name='slug',
label='Region (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter(
2016-03-01 11:23:03 -05:00
queryset=Site.objects.all(),
label='Site (ID)',
)
site = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='site__slug',
2016-03-01 11:23:03 -05:00
queryset=Site.objects.all(),
to_field_name='slug',
label='Site (slug)',
)
vlan_id = django_filters.ModelMultipleChoiceFilter(
2016-03-01 11:23:03 -05:00
queryset=VLAN.objects.all(),
label='VLAN (ID)',
)
vlan_vid = django_filters.NumberFilter(
2018-11-02 13:46:28 -04:00
field_name='vlan__vid',
2016-03-01 11:23:03 -05:00
label='VLAN number (1-4095)',
)
role_id = django_filters.ModelMultipleChoiceFilter(
2016-03-01 11:23:03 -05:00
queryset=Role.objects.all(),
label='Role (ID)',
)
role = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='role__slug',
2016-03-01 11:23:03 -05:00
queryset=Role.objects.all(),
to_field_name='slug',
label='Role (slug)',
)
status = django_filters.MultipleChoiceFilter(
choices=PREFIX_STATUS_CHOICES,
null_value=None
)
tag = TagFilter()
2016-03-01 11:23:03 -05:00
class Meta:
model = Prefix
fields = ['family', 'is_pool']
2016-03-01 11:23:03 -05:00
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = Q(description__icontains=value)
try:
prefix = str(netaddr.IPNetwork(value.strip()).cidr)
qs_filter |= Q(prefix__net_contains_or_equals=prefix)
except (AddrFormatError, ValueError):
pass
return queryset.filter(qs_filter)
def filter_prefix(self, queryset, name, value):
if not value.strip():
return queryset
try:
query = str(netaddr.IPNetwork(value).cidr)
return queryset.filter(prefix=query)
except ValidationError:
return queryset.none()
def search_within(self, queryset, name, value):
value = value.strip()
if not value:
return queryset
try:
query = str(netaddr.IPNetwork(value).cidr)
return queryset.filter(prefix__net_contained=query)
except (AddrFormatError, ValueError):
return queryset.none()
def search_within_include(self, queryset, name, value):
2016-03-01 11:23:03 -05:00
value = value.strip()
if not value:
return queryset
try:
query = str(netaddr.IPNetwork(value).cidr)
2016-03-01 11:23:03 -05:00
return queryset.filter(prefix__net_contained_or_equal=query)
except (AddrFormatError, ValueError):
2016-03-01 11:23:03 -05:00
return queryset.none()
def search_contains(self, queryset, name, value):
value = value.strip()
if not value:
return queryset
try:
# Searching by prefix
if '/' in value:
return queryset.filter(prefix__net_contains_or_equals=str(netaddr.IPNetwork(value).cidr))
# Searching by IP address
else:
return queryset.filter(prefix__net_contains=str(netaddr.IPAddress(value)))
except (AddrFormatError, ValueError):
return queryset.none()
def filter_mask_length(self, queryset, name, value):
if not value:
return queryset
return queryset.filter(prefix__net_mask_length=value)
2016-03-01 11:23:03 -05:00
class IPAddressFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
id__in = NumericInFilter(
field_name='id',
lookup_expr='in'
)
q = django_filters.CharFilter(
method='search',
2016-03-01 11:23:03 -05:00
label='Search',
)
parent = django_filters.CharFilter(
method='search_by_parent',
label='Parent prefix',
)
address = django_filters.CharFilter(
method='filter_address',
label='Address',
)
mask_length = django_filters.NumberFilter(
method='filter_mask_length',
label='Mask length',
)
vrf_id = django_filters.ModelMultipleChoiceFilter(
queryset=VRF.objects.all(),
label='VRF',
2016-03-01 11:23:03 -05:00
)
vrf = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='vrf__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
label='VRF (RD)',
)
device = django_filters.CharFilter(
method='filter_device',
2018-11-02 13:46:28 -04:00
field_name='name',
label='Device',
)
device_id = django_filters.NumberFilter(
method='filter_device',
2018-11-02 13:46:28 -04:00
field_name='pk',
2016-03-01 11:23:03 -05:00
label='Device (ID)',
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='interface__virtual_machine',
queryset=VirtualMachine.objects.all(),
label='Virtual machine (ID)',
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='interface__virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
label='Virtual machine (name)',
)
interface = django_filters.ModelMultipleChoiceFilter(
field_name='interface__name',
queryset=Interface.objects.all(),
to_field_name='name',
label='Interface (ID)',
)
2016-03-01 11:23:03 -05:00
interface_id = django_filters.ModelMultipleChoiceFilter(
queryset=Interface.objects.all(),
label='Interface (ID)',
)
assigned_to_interface = django_filters.BooleanFilter(
method='_assigned_to_interface',
label='Is assigned to an interface',
)
status = django_filters.MultipleChoiceFilter(
choices=IPADDRESS_STATUS_CHOICES,
null_value=None
)
role = django_filters.MultipleChoiceFilter(
choices=IPADDRESS_ROLE_CHOICES
)
tag = TagFilter()
2016-03-01 11:23:03 -05:00
class Meta:
model = IPAddress
fields = ['family', 'dns_name']
2016-03-01 11:23:03 -05:00
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = (
2019-04-22 18:10:28 -04:00
Q(dns_name__icontains=value) |
Q(description__icontains=value) |
Q(address__istartswith=value)
)
return queryset.filter(qs_filter)
2016-03-01 11:23:03 -05:00
def search_by_parent(self, queryset, name, value):
value = value.strip()
if not value:
return queryset
try:
query = str(netaddr.IPNetwork(value.strip()).cidr)
return queryset.filter(address__net_host_contained=query)
except (AddrFormatError, ValueError):
return queryset.none()
def filter_address(self, queryset, name, value):
if not value.strip():
return queryset
try:
# Match address and subnet mask
if '/' in value:
return queryset.filter(address=value)
return queryset.filter(address__net_host=value)
except ValidationError:
return queryset.none()
def filter_mask_length(self, queryset, name, value):
if not value:
return queryset
return queryset.filter(address__net_mask_length=value)
def filter_device(self, queryset, name, value):
try:
device = Device.objects.prefetch_related('device_type').get(**{name: value})
vc_interface_ids = [i['id'] for i in device.vc_interfaces.values('id')]
return queryset.filter(interface_id__in=vc_interface_ids)
except Device.DoesNotExist:
return queryset.none()
def _assigned_to_interface(self, queryset, name, value):
return queryset.exclude(interface__isnull=value)
2016-03-01 11:23:03 -05:00
class VLANGroupFilter(NameSlugSearchFilterSet):
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region__in',
label='Region (ID)',
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region__in',
to_field_name='slug',
label='Region (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter(
2016-07-15 13:26:54 -04:00
queryset=Site.objects.all(),
label='Site (ID)',
)
site = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='site__slug',
2016-07-15 13:26:54 -04:00
queryset=Site.objects.all(),
to_field_name='slug',
label='Site (slug)',
)
class Meta:
model = VLANGroup
fields = ['id', 'name', 'slug']
2016-07-15 13:26:54 -04:00
class VLANFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
id__in = NumericInFilter(
field_name='id',
lookup_expr='in'
)
q = django_filters.CharFilter(
method='search',
label='Search',
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region__in',
label='Region (ID)',
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region__in',
to_field_name='slug',
label='Region (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter(
2016-03-01 11:23:03 -05:00
queryset=Site.objects.all(),
label='Site (ID)',
)
site = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='site__slug',
2016-03-01 11:23:03 -05:00
queryset=Site.objects.all(),
to_field_name='slug',
label='Site (slug)',
)
group_id = django_filters.ModelMultipleChoiceFilter(
2016-07-15 13:26:54 -04:00
queryset=VLANGroup.objects.all(),
label='Group (ID)',
)
group = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='group__slug',
2016-07-15 13:26:54 -04:00
queryset=VLANGroup.objects.all(),
to_field_name='slug',
label='Group',
)
role_id = django_filters.ModelMultipleChoiceFilter(
2016-03-01 11:23:03 -05:00
queryset=Role.objects.all(),
label='Role (ID)',
)
role = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='role__slug',
2016-03-01 11:23:03 -05:00
queryset=Role.objects.all(),
to_field_name='slug',
label='Role (slug)',
)
status = django_filters.MultipleChoiceFilter(
choices=VLAN_STATUS_CHOICES,
null_value=None
)
tag = TagFilter()
2016-03-01 11:23:03 -05:00
class Meta:
model = VLAN
fields = ['vid', 'name']
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
try:
qs_filter |= Q(vid=int(value.strip()))
except ValueError:
pass
return queryset.filter(qs_filter)
class ServiceFilter(CreatedUpdatedFilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
2016-12-26 11:58:27 -05:00
device_id = django_filters.ModelMultipleChoiceFilter(
queryset=Device.objects.all(),
label='Device (ID)',
)
device = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='device__name',
2016-12-26 11:58:27 -05:00
queryset=Device.objects.all(),
to_field_name='name',
label='Device (name)',
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
queryset=VirtualMachine.objects.all(),
label='Virtual machine (ID)',
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
2018-11-02 13:46:28 -04:00
field_name='virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
label='Virtual machine (name)',
)
tag = TagFilter()
class Meta:
model = Service
fields = ['id', 'name', 'protocol', 'port']
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
return queryset.filter(qs_filter)