diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 5a0b266f8..a92968bc9 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -8,15 +8,18 @@ ### Breaking Changes * Automatic redirection of legacy slug-based URL paths has been removed. +* The `asn` field has been removed from the site model. Please use the ASN model introduced in NetBox v3.1 to track ASN assignments for sites. +* The `asn` query filter for sites now matches against the AS number of assigned ASNs. * The `contact_name`, `contact_phone`, and `contact_email` fields have been removed from the site model. Please use the new contact model introduced in NetBox v3.1 to store contact information for sites. ### Other Changes * [#7731](https://github.com/netbox-community/netbox/issues/7731) - Require Python 3.8 or later +* [#7743](https://github.com/netbox-community/netbox/issues/7743) - Remove legacy ASN field from site model * [#7748](https://github.com/netbox-community/netbox/issues/7748) - Remove legacy contact fields from site model * [#8031](https://github.com/netbox-community/netbox/issues/8031) - Remove automatic redirection of legacy slug-based URLs ### REST API Changes * dcim.Site - * Removed the `contact_name`, `contact_phone`, and `contact_email` fields + * Removed the `asn`, `contact_name`, `contact_phone`, and `contact_email` fields diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 02c845091..113c71745 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -132,7 +132,7 @@ class SiteSerializer(PrimaryModelSerializer): class Meta: model = Site fields = [ - 'id', 'url', 'display', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'asn', 'asns', + 'id', 'url', 'display', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'asns', 'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count', 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count', diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 134a555f4..990c55115 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -131,6 +131,12 @@ class SiteFilterSet(PrimaryModelFilterSet, TenancyFilterSet): to_field_name='slug', label='Group (slug)', ) + asn = django_filters.ModelMultipleChoiceFilter( + field_name='asns__asn', + queryset=ASN.objects.all(), + to_field_name='asn', + label='AS (ID)', + ) asn_id = django_filters.ModelMultipleChoiceFilter( field_name='asns', queryset=ASN.objects.all(), @@ -141,7 +147,7 @@ class SiteFilterSet(PrimaryModelFilterSet, TenancyFilterSet): class Meta: model = Site fields = ( - 'id', 'name', 'slug', 'facility', 'asn', 'latitude', 'longitude', + 'id', 'name', 'slug', 'facility', 'latitude', 'longitude', ) def search(self, queryset, name, value): diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index 9127b072f..a40396e98 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -111,12 +111,6 @@ class SiteBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): queryset=Tenant.objects.all(), required=False ) - asn = forms.IntegerField( - min_value=BGP_ASN_MIN, - max_value=BGP_ASN_MAX, - required=False, - label='ASN' - ) asns = DynamicModelMultipleChoiceField( queryset=ASN.objects.all(), label=_('ASNs'), @@ -134,7 +128,7 @@ class SiteBulkEditForm(AddRemoveTagsForm, CustomFieldModelBulkEditForm): class Meta: nullable_fields = [ - 'region', 'group', 'tenant', 'asn', 'asns', 'description', 'time_zone', + 'region', 'group', 'tenant', 'asns', 'description', 'time_zone', ] diff --git a/netbox/dcim/forms/models.py b/netbox/dcim/forms/models.py index 309b203b1..d16cf3dd1 100644 --- a/netbox/dcim/forms/models.py +++ b/netbox/dcim/forms/models.py @@ -130,15 +130,13 @@ class SiteForm(TenancyForm, CustomFieldModelForm): class Meta: model = Site - fields = [ - 'name', 'slug', 'status', 'region', 'group', 'tenant_group', 'tenant', 'facility', 'asn', 'asns', - 'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', - 'tags', - ] + fields = ( + 'name', 'slug', 'status', 'region', 'group', 'tenant_group', 'tenant', 'facility', 'asns', 'time_zone', + 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', 'tags', + ) fieldsets = ( ('Site', ( - 'name', 'slug', 'status', 'region', 'group', 'facility', 'asn', 'asns', 'time_zone', 'description', - 'tags', + 'name', 'slug', 'status', 'region', 'group', 'facility', 'asns', 'time_zone', 'description', 'tags', )), ('Tenancy', ('tenant_group', 'tenant')), ('Contact Info', ('physical_address', 'shipping_address', 'latitude', 'longitude')), @@ -159,7 +157,6 @@ class SiteForm(TenancyForm, CustomFieldModelForm): } help_texts = { 'name': "Full name of the site", - 'asn': "BGP autonomous system number. This field is depreciated in favour of the ASN model", 'facility': "Data center provider and facility (e.g. Equinix NY7)", 'time_zone': "Local time zone", 'description': "Short description (will appear in sites list)", diff --git a/netbox/dcim/migrations/0144_site_remove_deprecated_fields.py b/netbox/dcim/migrations/0144_site_remove_deprecated_fields.py index 14554d0a0..1dcf4d43c 100644 --- a/netbox/dcim/migrations/0144_site_remove_deprecated_fields.py +++ b/netbox/dcim/migrations/0144_site_remove_deprecated_fields.py @@ -8,6 +8,10 @@ class Migration(migrations.Migration): ] operations = [ + migrations.RemoveField( + model_name='site', + name='asn', + ), migrations.RemoveField( model_name='site', name='contact_email', diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index 5dd05734c..0be7e4617 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -248,12 +248,6 @@ class Site(PrimaryModel): blank=True, help_text='Local facility ID or description' ) - asn = ASNField( - blank=True, - null=True, - verbose_name='ASN', - help_text='32-bit autonomous system number' - ) asns = models.ManyToManyField( to='ipam.ASN', related_name='sites', @@ -307,7 +301,7 @@ class Site(PrimaryModel): ) clone_fields = [ - 'status', 'region', 'group', 'tenant', 'facility', 'asn', 'time_zone', 'description', 'physical_address', + 'status', 'region', 'group', 'tenant', 'facility', 'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', ] diff --git a/netbox/dcim/tests/test_filtersets.py b/netbox/dcim/tests/test_filtersets.py index 396355ebb..a187c8881 100644 --- a/netbox/dcim/tests/test_filtersets.py +++ b/netbox/dcim/tests/test_filtersets.py @@ -151,9 +151,9 @@ class SiteTestCase(TestCase, ChangeLoggedFilterSetTests): ASN.objects.bulk_create(asns) sites = ( - Site(name='Site 1', slug='site-1', region=regions[0], group=groups[0], tenant=tenants[0], status=SiteStatusChoices.STATUS_ACTIVE, facility='Facility 1', asn=65001, latitude=10, longitude=10), - Site(name='Site 2', slug='site-2', region=regions[1], group=groups[1], tenant=tenants[1], status=SiteStatusChoices.STATUS_PLANNED, facility='Facility 2', asn=65002, latitude=20, longitude=20), - Site(name='Site 3', slug='site-3', region=regions[2], group=groups[2], tenant=tenants[2], status=SiteStatusChoices.STATUS_RETIRED, facility='Facility 3', asn=65003, latitude=30, longitude=30), + Site(name='Site 1', slug='site-1', region=regions[0], group=groups[0], tenant=tenants[0], status=SiteStatusChoices.STATUS_ACTIVE, facility='Facility 1', latitude=10, longitude=10), + Site(name='Site 2', slug='site-2', region=regions[1], group=groups[1], tenant=tenants[1], status=SiteStatusChoices.STATUS_PLANNED, facility='Facility 2', latitude=20, longitude=20), + Site(name='Site 3', slug='site-3', region=regions[2], group=groups[2], tenant=tenants[2], status=SiteStatusChoices.STATUS_RETIRED, facility='Facility 3', latitude=30, longitude=30), ) Site.objects.bulk_create(sites) sites[0].asns.set([asns[0]]) @@ -173,7 +173,7 @@ class SiteTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_asn(self): - params = {'asn': [65001, 65002]} + params = {'asn': ['64512', '64513']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_asn_id(self): diff --git a/netbox/extras/tests/test_customvalidator.py b/netbox/extras/tests/test_customvalidator.py index 89857b615..ce3b572d1 100644 --- a/netbox/extras/tests/test_customvalidator.py +++ b/netbox/extras/tests/test_customvalidator.py @@ -2,6 +2,7 @@ from django.conf import settings from django.core.exceptions import ValidationError from django.test import TestCase, override_settings +from circuits.models import Provider from dcim.models import Site from extras.validators import CustomValidator @@ -66,26 +67,26 @@ custom_validator = MyValidator() class CustomValidatorTest(TestCase): - @override_settings(CUSTOM_VALIDATORS={'dcim.site': [min_validator]}) + @override_settings(CUSTOM_VALIDATORS={'circuits.provider': [min_validator]}) def test_configuration(self): - self.assertIn('dcim.site', settings.CUSTOM_VALIDATORS) - validator = settings.CUSTOM_VALIDATORS['dcim.site'][0] + self.assertIn('circuits.provider', settings.CUSTOM_VALIDATORS) + validator = settings.CUSTOM_VALIDATORS['circuits.provider'][0] self.assertIsInstance(validator, CustomValidator) - @override_settings(CUSTOM_VALIDATORS={'dcim.site': [min_validator]}) + @override_settings(CUSTOM_VALIDATORS={'circuits.provider': [min_validator]}) def test_min(self): with self.assertRaises(ValidationError): - Site(name='abcdef123', slug='abcdefghijk', asn=1).clean() + Provider(name='Provider 1', slug='provider-1', asn=1).clean() - @override_settings(CUSTOM_VALIDATORS={'dcim.site': [max_validator]}) + @override_settings(CUSTOM_VALIDATORS={'circuits.provider': [max_validator]}) def test_max(self): with self.assertRaises(ValidationError): - Site(name='abcdef123', slug='abcdefghijk', asn=65535).clean() + Provider(name='Provider 1', slug='provider-1', asn=65535).clean() @override_settings(CUSTOM_VALIDATORS={'dcim.site': [min_length_validator]}) def test_min_length(self): with self.assertRaises(ValidationError): - Site(name='abc', slug='abc', asn=65000).clean() + Site(name='abc', slug='abc').clean() @override_settings(CUSTOM_VALIDATORS={'dcim.site': [max_length_validator]}) def test_max_length(self): diff --git a/netbox/templates/dcim/site.html b/netbox/templates/dcim/site.html index a8d39be40..539974b86 100644 --- a/netbox/templates/dcim/site.html +++ b/netbox/templates/dcim/site.html @@ -78,10 +78,6 @@