Skip to content

Commit

Permalink
Closes netbox-community#901: Support for filtering prefixes and IP ad…
Browse files Browse the repository at this point in the history
…dresses by mask length
  • Loading branch information
jeremystretch committed Mar 1, 2017
1 parent ac4b92e commit 1fed9dd
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
4 changes: 3 additions & 1 deletion netbox/ipam/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from .formfields import IPFormField
from .lookups import (
EndsWith, IEndsWith, IRegex, IStartsWith, NetContained, NetContainedOrEqual, NetContains, NetContainsOrEquals,
NetHost, Regex, StartsWith,
NetHost, NetMaskLength, Regex, StartsWith,
)


Expand Down Expand Up @@ -67,6 +67,7 @@ def db_type(self, connection):
IPNetworkField.register_lookup(NetContains)
IPNetworkField.register_lookup(NetContainsOrEquals)
IPNetworkField.register_lookup(NetHost)
IPNetworkField.register_lookup(NetMaskLength)


class IPAddressField(BaseIPField):
Expand All @@ -90,3 +91,4 @@ def db_type(self, connection):
IPAddressField.register_lookup(NetContains)
IPAddressField.register_lookup(NetContainsOrEquals)
IPAddressField.register_lookup(NetHost)
IPAddressField.register_lookup(NetMaskLength)
18 changes: 18 additions & 0 deletions netbox/ipam/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet):
method='search_by_parent',
label='Parent prefix',
)
mask_length = django_filters.NumberFilter(
method='filter_mask_length',
label='Mask length',
)
vrf_id = NullableModelMultipleChoiceFilter(
name='vrf_id',
queryset=VRF.objects.all(),
Expand Down Expand Up @@ -171,6 +175,11 @@ def search_by_parent(self, queryset, name, value):
except AddrFormatError:
return queryset.none()

def filter_mask_length(self, queryset, name, value):
if not value:
return queryset
return queryset.filter(prefix__net_mask_length=value)


class IPAddressFilter(CustomFieldFilterSet, django_filters.FilterSet):
q = django_filters.CharFilter(
Expand All @@ -181,6 +190,10 @@ class IPAddressFilter(CustomFieldFilterSet, django_filters.FilterSet):
method='search_by_parent',
label='Parent prefix',
)
mask_length = django_filters.NumberFilter(
method='filter_mask_length',
label='Mask length',
)
vrf_id = NullableModelMultipleChoiceFilter(
name='vrf_id',
queryset=VRF.objects.all(),
Expand Down Expand Up @@ -245,6 +258,11 @@ def search_by_parent(self, queryset, name, value):
except AddrFormatError:
return queryset.none()

def filter_mask_length(self, queryset, name, value):
if not value:
return queryset
return queryset.filter(address__net_mask_length=value)


class VLANGroupFilter(django_filters.FilterSet):
site_id = NullableModelMultipleChoiceFilter(
Expand Down
10 changes: 9 additions & 1 deletion netbox/ipam/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
(6, 'IPv6'),
]

PREFIX_MASK_LENGTH_CHOICES = [
('', '---------'),
] + [(i, i) for i in range(1, 128)]

IPADDRESS_MASK_LENGTH_CHOICES = PREFIX_MASK_LENGTH_CHOICES + [(128, 128)]


#
# VRFs
Expand Down Expand Up @@ -266,6 +272,7 @@ class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
'placeholder': 'Prefix',
}))
family = forms.ChoiceField(required=False, choices=IP_FAMILY_CHOICES, label='Address family')
mask_length = forms.ChoiceField(required=False, choices=PREFIX_MASK_LENGTH_CHOICES, label='Mask length')
vrf = FilterChoiceField(
queryset=VRF.objects.annotate(filter_count=Count('prefixes')),
to_field_name='rd',
Expand Down Expand Up @@ -503,7 +510,8 @@ class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm):
parent = forms.CharField(required=False, label='Parent Prefix', widget=forms.TextInput(attrs={
'placeholder': 'Prefix',
}))
family = forms.ChoiceField(required=False, choices=IP_FAMILY_CHOICES, label='Address Family')
family = forms.ChoiceField(required=False, choices=IP_FAMILY_CHOICES, label='Address family')
mask_length = forms.ChoiceField(required=False, choices=IPADDRESS_MASK_LENGTH_CHOICES, label='Mask length')
vrf = FilterChoiceField(
queryset=VRF.objects.annotate(filter_count=Count('ip_addresses')),
to_field_name='rd',
Expand Down
11 changes: 10 additions & 1 deletion netbox/ipam/lookups.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from django.db.models import Lookup
from django.db.models import Lookup, Transform, IntegerField
from django.db.models.lookups import BuiltinLookup


Expand Down Expand Up @@ -87,3 +87,12 @@ def as_sql(self, qn, connection):
rhs_params[0] = rhs_params[0].split('/')[0]
params = lhs_params + rhs_params
return 'HOST(%s) = %s' % (lhs, rhs), params


class NetMaskLength(Transform):
lookup_name = 'net_mask_length'
function = 'MASKLEN'

@property
def output_field(self):
return IntegerField()

0 comments on commit 1fed9dd

Please sign in to comment.