diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index de06bfd68..c155c7663 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -38,6 +38,7 @@ class ASNRangeSerializer(NetBoxModelSerializer): class ASNSerializer(NetBoxModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:asn-detail') + range = NestedASNRangeSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True) site_count = serializers.IntegerField(read_only=True) provider_count = serializers.IntegerField(read_only=True) @@ -45,7 +46,7 @@ class ASNSerializer(NetBoxModelSerializer): class Meta: model = ASN fields = [ - 'id', 'url', 'display', 'asn', 'rir', 'tenant', 'description', 'comments', 'tags', 'custom_fields', + 'id', 'url', 'display', 'asn', 'rir', 'range', 'tenant', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'site_count', 'provider_count', ] diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index 82f9178b1..811ff7223 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -192,6 +192,16 @@ class ASNFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): to_field_name='slug', label=_('RIR (slug)'), ) + range_id = django_filters.ModelMultipleChoiceFilter( + queryset=ASNRange.objects.all(), + label=_('Range (ID)'), + ) + range = django_filters.ModelMultipleChoiceFilter( + field_name='range__slug', + queryset=ASNRange.objects.all(), + to_field_name='slug', + label=_('Range (slug)'), + ) site_id = django_filters.ModelMultipleChoiceFilter( field_name='sites', queryset=Site.objects.all(), diff --git a/netbox/ipam/forms/bulk_edit.py b/netbox/ipam/forms/bulk_edit.py index a879d1236..1ef6bf911 100644 --- a/netbox/ipam/forms/bulk_edit.py +++ b/netbox/ipam/forms/bulk_edit.py @@ -125,6 +125,10 @@ class ASNBulkEditForm(NetBoxModelBulkEditForm): required=False, label=_('RIR') ) + range = DynamicModelChoiceField( + queryset=ASNRange.objects.all(), + required=False + ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), required=False @@ -140,9 +144,9 @@ class ASNBulkEditForm(NetBoxModelBulkEditForm): model = ASN fieldsets = ( - (None, ('sites', 'rir', 'tenant', 'description')), + (None, ('sites', 'rir', 'range', 'tenant', 'description')), ) - nullable_fields = ('date_added', 'description', 'comments') + nullable_fields = ('range', 'description', 'comments') class AggregateBulkEditForm(NetBoxModelBulkEditForm): diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py index 46266d6d7..1fc1bf962 100644 --- a/netbox/ipam/forms/bulk_import.py +++ b/netbox/ipam/forms/bulk_import.py @@ -107,6 +107,11 @@ class ASNImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Assigned RIR') ) + range = CSVModelChoiceField( + queryset=ASNRange.objects.all(), + to_field_name='name', + help_text=_('ASN range') + ) tenant = CSVModelChoiceField( queryset=Tenant.objects.all(), required=False, @@ -116,7 +121,7 @@ class ASNImportForm(NetBoxModelImportForm): class Meta: model = ASN - fields = ('asn', 'rir', 'tenant', 'description', 'comments', 'tags') + fields = ('asn', 'rir', 'range', 'tenant', 'description', 'comments', 'tags') class RoleImportForm(NetBoxModelImportForm): diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py index ce2f762a4..491fd9be1 100644 --- a/netbox/ipam/forms/filtersets.py +++ b/netbox/ipam/forms/filtersets.py @@ -135,7 +135,7 @@ class ASNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = ASN fieldsets = ( (None, ('q', 'filter_id', 'tag')), - ('Assignment', ('rir_id', 'site_id')), + ('Assignment', ('rir_id', 'range_id', 'site_id')), ('Tenant', ('tenant_group_id', 'tenant_id')), ) rir_id = DynamicModelMultipleChoiceField( @@ -143,6 +143,11 @@ class ASNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): required=False, label=_('RIR') ) + range_id = DynamicModelMultipleChoiceField( + queryset=ASNRange.objects.all(), + required=False, + label=_('Range') + ) site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, diff --git a/netbox/ipam/models/asns.py b/netbox/ipam/models/asns.py index 9f7433a43..a2ea59fa6 100644 --- a/netbox/ipam/models/asns.py +++ b/netbox/ipam/models/asns.py @@ -106,7 +106,7 @@ class ASNRange(OrganizationalModel): verbose_name_plural = 'ASN ranges' def __str__(self): - return f'ASNs {self.range_as_string()}' + return f'{self.name} ({self.range_as_string()})' def get_absolute_url(self): return reverse('ipam:asnrange', args=[self.pk]) diff --git a/netbox/ipam/tables/asn.py b/netbox/ipam/tables/asn.py index c42add017..9d860ad6b 100644 --- a/netbox/ipam/tables/asn.py +++ b/netbox/ipam/tables/asn.py @@ -37,6 +37,12 @@ class ASNTable(TenancyColumnsMixin, NetBoxTable): asn = tables.Column( linkify=True ) + rir = tables.Column( + linkify=True + ) + range = tables.Column( + linkify=True + ) asn_asdot = tables.Column( accessor=tables.A('asn_asdot'), linkify=True, @@ -63,7 +69,9 @@ class ASNTable(TenancyColumnsMixin, NetBoxTable): class Meta(NetBoxTable.Meta): model = ASN fields = ( - 'pk', 'asn', 'asn_asdot', 'rir', 'site_count', 'provider_count', 'tenant', 'tenant_group', 'description', - 'comments', 'sites', 'tags', 'created', 'last_updated', 'actions', + 'pk', 'asn', 'asn_asdot', 'rir', 'range', 'site_count', 'provider_count', 'tenant', 'tenant_group', + 'description', 'comments', 'sites', 'tags', 'created', 'last_updated', 'actions', + ) + default_columns = ( + 'pk', 'asn', 'rir', 'range', 'site_count', 'provider_count', 'sites', 'description', 'tenant', ) - default_columns = ('pk', 'asn', 'rir', 'site_count', 'provider_count', 'sites', 'description', 'tenant') diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 07d5598f8..b6e717464 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -213,7 +213,7 @@ class ASNRangeView(generic.ObjectView): def get_extra_context(self, request, instance): related_models = ( - (ASN.objects.restrict(request.user, 'view').filter(range=instance), 'asn_id'), + (ASN.objects.restrict(request.user, 'view').filter(range=instance), 'range_id'), ) return { diff --git a/netbox/templates/ipam/asn.html b/netbox/templates/ipam/asn.html index a54a0aee5..f45e087d8 100644 --- a/netbox/templates/ipam/asn.html +++ b/netbox/templates/ipam/asn.html @@ -7,6 +7,9 @@ {% block breadcrumbs %} {{ block.super }} + {% if object.range %} + + {% endif %} {% endblock breadcrumbs %} {% block content %} @@ -26,6 +29,10 @@ {{ object.rir }} + + Range + {{ object.range|linkify|placeholder }} + Tenant diff --git a/netbox/templates/ipam/asnrange.html b/netbox/templates/ipam/asnrange.html index 07f826d9f..a2194e96d 100644 --- a/netbox/templates/ipam/asnrange.html +++ b/netbox/templates/ipam/asnrange.html @@ -46,6 +46,13 @@
+
+
ASNs
+
+
{% plugin_full_width_page object %}