Require vlan_id_ranges & set default value

This commit is contained in:
Jeremy Stretch 2024-07-15 10:13:34 -04:00
parent e039ba474a
commit f6c2396a30
5 changed files with 24 additions and 21 deletions

View File

@ -413,7 +413,7 @@ class VLANGroupImportForm(NetBoxModelImportForm):
label=_('Scope type (app & model)') label=_('Scope type (app & model)')
) )
vlan_id_ranges = NumericRangeArrayField( vlan_id_ranges = NumericRangeArrayField(
required=False, required=False
) )
class Meta: class Meta:

View File

@ -634,8 +634,7 @@ class VLANGroupForm(NetBoxModelForm):
) )
slug = SlugField() slug = SlugField()
vlan_id_ranges = NumericRangeArrayField( vlan_id_ranges = NumericRangeArrayField(
label=_('VLAN IDs'), label=_('VLAN IDs')
required=False
) )
fieldsets = ( fieldsets = (

View File

@ -3,6 +3,8 @@ import django.contrib.postgres.fields.ranges
from django.db import migrations, models from django.db import migrations, models
from django.db.backends.postgresql.psycopg_any import NumericRange from django.db.backends.postgresql.psycopg_any import NumericRange
import ipam.models.vlans
def move_min_max(apps, schema_editor): def move_min_max(apps, schema_editor):
VLANGroup = apps.get_model('ipam', 'VLANGroup') VLANGroup = apps.get_model('ipam', 'VLANGroup')
@ -29,9 +31,8 @@ class Migration(migrations.Migration):
name='vlan_id_ranges', name='vlan_id_ranges',
field=django.contrib.postgres.fields.ArrayField( field=django.contrib.postgres.fields.ArrayField(
base_field=django.contrib.postgres.fields.ranges.IntegerRangeField(), base_field=django.contrib.postgres.fields.ranges.IntegerRangeField(),
blank=True, default=ipam.models.vlans.default_vland_id_ranges,
null=True, size=None
size=None,
), ),
), ),
migrations.AddField( migrations.AddField(

View File

@ -3,6 +3,7 @@ from django.contrib.postgres.fields import ArrayField, IntegerRangeField
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models
from django.db.backends.postgresql.psycopg_any import NumericRange
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -20,6 +21,12 @@ __all__ = (
) )
def default_vland_id_ranges():
return [
NumericRange(VLAN_VID_MIN, VLAN_VID_MAX, bounds='[]')
]
class VLANGroup(OrganizationalModel): class VLANGroup(OrganizationalModel):
""" """
A VLAN group is an arbitrary collection of VLANs within which VLAN IDs and names must be unique. A VLAN group is an arbitrary collection of VLANs within which VLAN IDs and names must be unique.
@ -50,8 +57,7 @@ class VLANGroup(OrganizationalModel):
vlan_id_ranges = ArrayField( vlan_id_ranges = ArrayField(
IntegerRangeField(), IntegerRangeField(),
verbose_name=_('VLAN ID ranges'), verbose_name=_('VLAN ID ranges'),
blank=True, default=default_vland_id_ranges
null=True
) )
_total_vlan_ids = models.PositiveBigIntegerField( _total_vlan_ids = models.PositiveBigIntegerField(
default=VLAN_VID_MAX - VLAN_VID_MIN + 1 default=VLAN_VID_MAX - VLAN_VID_MIN + 1
@ -93,21 +99,18 @@ class VLANGroup(OrganizationalModel):
if self.vlan_id_ranges and check_ranges_overlap(self.vlan_id_ranges): if self.vlan_id_ranges and check_ranges_overlap(self.vlan_id_ranges):
raise ValidationError({'vlan_id_ranges': _("Ranges cannot overlap.")}) raise ValidationError({'vlan_id_ranges': _("Ranges cannot overlap.")})
for ranges in self.vlan_id_ranges: for vid_range in self.vlan_id_ranges:
if ranges.lower >= ranges.upper: if vid_range.lower >= vid_range.upper:
raise ValidationError({ raise ValidationError({
'vlan_id_ranges': _( 'vlan_id_ranges': _(
"Maximum child VID must be greater than or equal to minimum child VID Invalid range ({value})" "Maximum child VID must be greater than or equal to minimum child VID ({value})"
).format(value=ranges) ).format(value=vid_range)
}) })
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.vlan_id_ranges: self._total_vlan_ids = 0
self._total_vlan_ids = 0 for vid_range in self.vlan_id_ranges:
for vlan_range in self.vlan_id_ranges: self._total_vlan_ids += vid_range.upper - vid_range.lower + 1
self._total_vlan_ids += vlan_range.upper - vlan_range.lower + 1
else:
self._total_vlan_ids = VLAN_VID_MAX - VLAN_VID_MIN + 1
super().save(*args, **kwargs) super().save(*args, **kwargs)
@ -249,8 +252,8 @@ class VLAN(PrimaryModel):
# Validate group min/max VIDs # Validate group min/max VIDs
if self.group and self.group.vlan_id_ranges: if self.group and self.group.vlan_id_ranges:
in_bounds = False in_bounds = False
for ranges in self.group.vlan_id_ranges: for vid_range in self.group.vlan_id_ranges:
if ranges.lower <= self.vid <= ranges.upper: if vid_range.lower <= self.vid <= vid_range.upper:
in_bounds = True in_bounds = True
if not in_bounds: if not in_bounds:

View File

@ -9,7 +9,6 @@ from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site, Inte
from ipam.choices import * from ipam.choices import *
from ipam.models import * from ipam.models import *
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.data import string_to_range_array
from utilities.testing import ViewTestCases, create_tags from utilities.testing import ViewTestCases, create_tags
@ -766,6 +765,7 @@ class VLANGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
'name': 'VLAN Group X', 'name': 'VLAN Group X',
'slug': 'vlan-group-x', 'slug': 'vlan-group-x',
'description': 'A new VLAN group', 'description': 'A new VLAN group',
'vlan_id_ranges': '100-199,300-399',
'tags': [t.pk for t in tags], 'tags': [t.pk for t in tags],
} }