Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a010689
Initial work on #6732
DanSheps Oct 25, 2021
8b529ab
Initial work on #6732
DanSheps Oct 25, 2021
3185cd0
#6732 - Correct incorrect field definition in field order
DanSheps Oct 28, 2021
8235b33
#6732 - Revert some changes to legacy ASN field on site model
DanSheps Oct 28, 2021
0ad440f
#6732 - GraphQL support
DanSheps Oct 28, 2021
93de6c9
#6732 - Tests
DanSheps Oct 28, 2021
9b5f45a
#6732 - Serializers
DanSheps Oct 28, 2021
96565c3
#6732 - ASN should be unique
DanSheps Oct 28, 2021
1902e11
#6732 - Fix tests for utilities
DanSheps Oct 28, 2021
0f68ecd
#6732 - Fix hiding of ASN field in Site creation form
DanSheps Oct 28, 2021
ada81e3
#6732 - Fix CSV import form
DanSheps Oct 28, 2021
3c261b0
#6732 - Fix ASN tests
DanSheps Oct 28, 2021
de5c9ef
#6732 - Add graphql support for new ASN model and fix ASN overflow on…
DanSheps Oct 28, 2021
033db83
Merge branch 'feature' of https://github.com/netbox-community/netbox …
DanSheps Oct 28, 2021
fff124e
#6732 - Update migration file
DanSheps Oct 28, 2021
9565add
#6732 - Fix test failure when sending data
DanSheps Oct 28, 2021
0a8788e
#6732 - Fix Site form and ASN form
DanSheps Oct 28, 2021
7c147db
#6732 - Fix test exception in Site form
DanSheps Oct 28, 2021
d3364ef
#6732 - Restore resolve_field to the filterset
DanSheps Oct 29, 2021
43b9830
#6732 - Corrected model field definitions
DanSheps Oct 29, 2021
a30e7bf
#6732 - Add ASN field back to bulk edit
DanSheps Oct 29, 2021
3991115
#6732 - Fix imports and other small items
DanSheps Oct 29, 2021
87e07e7
#6732 - Removed ASN field hiding
DanSheps Oct 29, 2021
8c27ff3
#6732 - Add ASN back to filtersets
DanSheps Nov 2, 2021
5d0a7cb
#6732 - Remove migration
DanSheps Nov 2, 2021
330c498
Merge feature
DanSheps Nov 2, 2021
7625a2d
#6732 - Swap ASN M2M to Site model and update some templates/filters
DanSheps Nov 2, 2021
db2d71e
Merge branch 'feature' into 6732-asn-model
DanSheps Nov 3, 2021
25957bf
Fix migration issues
DanSheps Nov 3, 2021
0ec0185
Fix Migration
DanSheps Nov 3, 2021
76d73ab
Update ip.py
DanSheps Nov 3, 2021
cf9eaf2
Fix dcim/views.py merge error
DanSheps Nov 3, 2021
5fc373f
Merge feature -> develop
DanSheps Nov 3, 2021
c72f25c
#6732 - Add documentation
DanSheps Nov 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/core-functionality/ipam.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
{!models/ipam/vrf.md!}
{!models/ipam/routetarget.md!}

__
---

{!models/ipam/fhrpgroup.md!}

---

{!models/ipam/asn.md!}
15 changes: 15 additions & 0 deletions docs/models/ipam/asn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ASN

ASN is short for Autonomous System Number. This identifier is used in the BGP protocol to identify which "autonomous system" a particular prefix is originating and transiting through.

The AS number model within NetBox allows you to model some of this real-world relationship.

Within NetBox:

* AS numbers are globally unique
* Each AS number must be associated with a RIR (ARIN, RFC 6996, etc)
* Each AS number can be associated with many different sites
* Each site can have many different AS numbers
* Each AS number can be assigned to a single tenant


9 changes: 6 additions & 3 deletions netbox/dcim/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from dcim.choices import *
from dcim.constants import *
from dcim.models import *
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer
from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer, NestedASNSerializer
from ipam.models import VLAN
from netbox.api import ChoiceField, ContentTypeField, SerializedPKRelatedField
from netbox.api.serializers import (
Expand Down Expand Up @@ -113,21 +113,24 @@ class SiteSerializer(PrimaryModelSerializer):
region = NestedRegionSerializer(required=False, allow_null=True)
group = NestedSiteGroupSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
asns = NestedASNSerializer(many=True, required=False, allow_null=True)
time_zone = TimeZoneSerializerField(required=False)
circuit_count = serializers.IntegerField(read_only=True)
device_count = serializers.IntegerField(read_only=True)
prefix_count = serializers.IntegerField(read_only=True)
rack_count = serializers.IntegerField(read_only=True)
asn_count = serializers.IntegerField(read_only=True)
virtualmachine_count = serializers.IntegerField(read_only=True)
vlan_count = serializers.IntegerField(read_only=True)

class Meta:
model = Site
fields = [
'id', 'url', 'display', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'asn',
'id', 'url', 'display', 'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'asn', 'asns',
'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name',
'contact_phone', 'contact_email', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
'circuit_count', 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count',
'asn_count', 'circuit_count', 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count',
'vlan_count',
]


Expand Down
3 changes: 2 additions & 1 deletion netbox/dcim/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from dcim import filtersets
from dcim.models import *
from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet
from ipam.models import Prefix, VLAN
from ipam.models import Prefix, VLAN, ASN
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
from netbox.api.exceptions import ServiceUnavailable
from netbox.api.metadata import ContentTypeMetadata
Expand Down Expand Up @@ -139,6 +139,7 @@ class SiteViewSet(CustomFieldModelViewSet):
queryset = Site.objects.prefetch_related(
'region', 'tenant', 'tags'
).annotate(
asn_count=count_related(ASN, 'sites'),
device_count=count_related(Device, 'site'),
rack_count=count_related(Rack, 'site'),
prefix_count=count_related(Prefix, 'site'),
Expand Down
13 changes: 13 additions & 0 deletions netbox/dcim/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from extras.filters import TagFilter
from extras.filtersets import LocalConfigContextFilterSet
from ipam.models import ASN
from netbox.filtersets import (
BaseFilterSet, ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet,
)
Expand Down Expand Up @@ -130,6 +131,17 @@ class SiteFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
to_field_name='slug',
label='Group (slug)',
)
asns_id = django_filters.ModelMultipleChoiceFilter(
field_name='asns',
queryset=ASN.objects.all(),
label='AS (ID)',
)
asns = django_filters.ModelMultipleChoiceFilter(
field_name='asns__asn',
queryset=ASN.objects.all(),
to_field_name='asn',
label='AS (Number)',
)
tag = TagFilter()

class Meta:
Expand All @@ -155,6 +167,7 @@ def search(self, queryset, name, value):
)
try:
qs_filter |= Q(asn=int(value.strip()))
qs_filter |= Q(asns__asn=int(value.strip()))
except ValueError:
pass
return queryset.filter(qs_filter)
Expand Down
12 changes: 9 additions & 3 deletions netbox/dcim/forms/bulk_edit.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from django import forms
from django.utils.translation import gettext as _
from django.contrib.auth.models import User
from timezone_field import TimeZoneFormField

from dcim.choices import *
from dcim.constants import *
from dcim.models import *
from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm
from ipam.constants import BGP_ASN_MAX, BGP_ASN_MIN
from ipam.models import VLAN
from ipam.constants import BGP_ASN_MIN, BGP_ASN_MAX
from ipam.models import VLAN, ASN
from tenancy.models import Tenant
from utilities.forms import (
add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorField, CommentField,
Expand Down Expand Up @@ -116,6 +117,11 @@ class SiteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEd
required=False,
label='ASN'
)
asns = DynamicModelMultipleChoiceField(
queryset=ASN.objects.all(),
label=_('ASNs'),
required=False
)
description = forms.CharField(
max_length=100,
required=False
Expand All @@ -128,7 +134,7 @@ class SiteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEd

class Meta:
nullable_fields = [
'region', 'group', 'tenant', 'asn', 'description', 'time_zone',
'region', 'group', 'tenant', 'asn', 'asns', 'description', 'time_zone',
]


Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/forms/bulk_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class SiteCSVForm(CustomFieldModelCSVForm):
class Meta:
model = Site
fields = (
'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'asn', 'time_zone', 'description',
'name', 'slug', 'status', 'region', 'group', 'tenant', 'facility', 'time_zone', 'description',
'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone',
'contact_email', 'comments',
)
Expand Down
10 changes: 9 additions & 1 deletion netbox/dcim/forms/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from dcim.constants import *
from dcim.models import *
from extras.forms import CustomFieldModelFilterForm, LocalConfigContextFilterForm
from ipam.models import ASN
from tenancy.forms import TenancyFilterForm
from utilities.forms import (
APISelectMultiple, add_blank_choice, BootstrapMixin, ColorField, DynamicModelMultipleChoiceField, StaticSelect,
Expand Down Expand Up @@ -138,11 +139,12 @@ class SiteGroupFilterForm(BootstrapMixin, CustomFieldModelFilterForm):

class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterForm):
model = Site
field_order = ['q', 'status', 'region_id', 'tenant_group_id', 'tenant_id']
field_order = ['q', 'status', 'region_id', 'tenant_group_id', 'tenant_id', 'asn_id']
field_groups = [
['q', 'tag'],
['status', 'region_id', 'group_id'],
['tenant_group_id', 'tenant_id'],
['asn_id']
]
q = forms.CharField(
required=False,
Expand All @@ -166,6 +168,12 @@ class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilterFo
label=_('Site group'),
fetch_trigger='open'
)
asn_id = DynamicModelMultipleChoiceField(
queryset=ASN.objects.all(),
required=False,
label=_('ASNs'),
fetch_trigger='open'
)
tag = TagFilterField(model)


Expand Down
29 changes: 12 additions & 17 deletions netbox/dcim/forms/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django import forms
from django.utils.translation import gettext as _
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from timezone_field import TimeZoneFormField
Expand All @@ -8,7 +9,7 @@
from dcim.models import *
from extras.forms import CustomFieldModelForm
from extras.models import Tag
from ipam.models import IPAddress, VLAN, VLANGroup
from ipam.models import IPAddress, VLAN, VLANGroup, ASN
from tenancy.forms import TenancyForm
from utilities.forms import (
APISelect, add_blank_choice, BootstrapMixin, ClearableFileInput, CommentField, DynamicModelChoiceField,
Expand Down Expand Up @@ -110,6 +111,11 @@ class SiteForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
queryset=SiteGroup.objects.all(),
required=False
)
asns = DynamicModelMultipleChoiceField(
queryset=ASN.objects.all(),
label=_('ASNs'),
required=False
)
slug = SlugField()
time_zone = TimeZoneFormField(
choices=add_blank_choice(TimeZoneFormField().choices),
Expand All @@ -125,13 +131,14 @@ class SiteForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
class Meta:
model = Site
fields = [
'name', 'slug', 'status', 'region', 'group', 'tenant_group', 'tenant', 'facility', 'asn', 'time_zone',
'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name',
'name', 'slug', 'status', 'region', 'group', 'tenant_group', 'tenant', 'facility', 'asn', 'asns',
'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name',
'contact_phone', 'contact_email', 'comments', 'tags',
]
fieldsets = (
('Site', (
'name', 'slug', 'status', 'region', 'group', 'facility', 'asn', 'time_zone', 'description', 'tags',
'name', 'slug', 'status', 'region', 'group', 'facility', 'asn', 'asns', 'time_zone', 'description',
'tags',
)),
('Tenancy', ('tenant_group', 'tenant')),
('Contact Info', (
Expand All @@ -155,8 +162,8 @@ class Meta:
}
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)",
'asn': "BGP autonomous system number",
'time_zone': "Local time zone",
'description': "Short description (will appear in sites list)",
'physical_address': "Physical location of the building (e.g. for GPS)",
Expand Down Expand Up @@ -791,7 +798,6 @@ def __init__(self, *args, **kwargs):


class DeviceVCMembershipForm(forms.ModelForm):

class Meta:
model = Device
fields = [
Expand Down Expand Up @@ -887,7 +893,6 @@ def clean_device(self):


class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = ConsolePortTemplate
fields = [
Expand All @@ -899,7 +904,6 @@ class Meta:


class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = ConsoleServerPortTemplate
fields = [
Expand All @@ -911,7 +915,6 @@ class Meta:


class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = PowerPortTemplate
fields = [
Expand All @@ -923,7 +926,6 @@ class Meta:


class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = PowerOutletTemplate
fields = [
Expand All @@ -934,7 +936,6 @@ class Meta:
}

def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)

# Limit power_port choices to current DeviceType
Expand All @@ -945,7 +946,6 @@ def __init__(self, *args, **kwargs):


class InterfaceTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = InterfaceTemplate
fields = [
Expand All @@ -958,7 +958,6 @@ class Meta:


class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = FrontPortTemplate
fields = [
Expand All @@ -970,7 +969,6 @@ class Meta:
}

def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)

# Limit rear_port choices to current DeviceType
Expand All @@ -981,7 +979,6 @@ def __init__(self, *args, **kwargs):


class RearPortTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = RearPortTemplate
fields = [
Expand All @@ -994,7 +991,6 @@ class Meta:


class DeviceBayTemplateForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = DeviceBayTemplate
fields = [
Expand Down Expand Up @@ -1257,7 +1253,6 @@ class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
)

def __init__(self, device_bay, *args, **kwargs):

super().__init__(*args, **kwargs)

self.fields['installed_device'].queryset = Device.objects.filter(
Expand Down
4 changes: 4 additions & 0 deletions netbox/dcim/graphql/types.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import graphene

from dcim import filtersets, models
from extras.graphql.mixins import (
ChangelogMixin, ConfigContextMixin, CustomFieldsMixin, ImageAttachmentsMixin, TagsMixin,
)
from ipam.graphql.mixins import IPAddressesMixin, VLANGroupsMixin
from netbox.graphql.scalars import BigInt
from netbox.graphql.types import BaseObjectType, OrganizationalObjectType, PrimaryObjectType

__all__ = (
Expand Down Expand Up @@ -380,6 +383,7 @@ class Meta:


class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, PrimaryObjectType):
asn = graphene.Field(BigInt)

class Meta:
model = models.Site
Expand Down
19 changes: 19 additions & 0 deletions netbox/dcim/migrations/0141_asn_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.8 on 2021-11-02 16:16

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('ipam', '0053_asn_model'),
('dcim', '0140_wireless'),
]

operations = [
migrations.AddField(
model_name='site',
name='asns',
field=models.ManyToManyField(blank=True, related_name='sites', to='ipam.ASN'),
),
]
5 changes: 5 additions & 0 deletions netbox/dcim/models/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ class Site(PrimaryModel):
verbose_name='ASN',
help_text='32-bit autonomous system number'
)
asns = models.ManyToManyField(
to='ipam.ASN',
related_name='sites',
blank=True
)
time_zone = TimeZoneField(
blank=True
)
Expand Down
Loading