Add mark_reserved boolean field to IPRange

This commit is contained in:
Jeremy Stretch 2025-04-01 15:21:19 -04:00
parent 8d7889e2c0
commit 67615368b2
11 changed files with 58 additions and 11 deletions

View File

@ -29,6 +29,10 @@ The IP range's operational status. Note that the status of a range does _not_ ha
!!! tip
Additional statuses may be defined by setting `IPRange.status` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter.
### Mark Reserved
If enabled, NetBox will prevent the creation of IP addresses which fall within the declared range (and assigned VRF, if any).
### Mark Utilized
If enabled, the IP range will be considered 100% utilized regardless of how many IP addresses are defined within it. This is useful for documenting DHCP ranges, for example.

View File

@ -147,7 +147,8 @@ class IPRangeSerializer(NetBoxModelSerializer):
fields = [
'id', 'url', 'display_url', 'display', 'family', 'start_address', 'end_address', 'size', 'vrf', 'tenant',
'status', 'role', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
'mark_utilized', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
'mark_reserved', 'mark_utilized', 'description', 'comments', 'tags', 'custom_fields', 'created',
'last_updated',
]
brief_fields = ('id', 'url', 'display', 'family', 'start_address', 'end_address', 'description')

View File

@ -478,7 +478,7 @@ class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
class Meta:
model = IPRange
fields = ('id', 'mark_utilized', 'size', 'description')
fields = ('id', 'mark_reserved', 'mark_utilized', 'size', 'description')
def search(self, queryset, name, value):
if not value.strip():

View File

@ -296,6 +296,11 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
queryset=Role.objects.all(),
required=False
)
mark_reserved = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),
label=_('Treat as reserved')
)
mark_utilized = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),

View File

@ -268,8 +268,8 @@ class IPRangeImportForm(NetBoxModelImportForm):
class Meta:
model = IPRange
fields = (
'start_address', 'end_address', 'vrf', 'tenant', 'status', 'role', 'mark_utilized', 'description',
'comments', 'tags',
'start_address', 'end_address', 'vrf', 'tenant', 'status', 'role', 'mark_reserved', 'mark_utilized',
'description', 'comments', 'tags',
)

View File

@ -266,7 +266,7 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = IPRange
fieldsets = (
FieldSet('q', 'filter_id', 'tag'),
FieldSet('family', 'vrf_id', 'status', 'role_id', 'mark_utilized', name=_('Attributes')),
FieldSet('family', 'vrf_id', 'status', 'role_id', 'mark_reserved', 'mark_utilized', name=_('Attributes')),
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
)
family = forms.ChoiceField(
@ -291,6 +291,13 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
null_option='None',
label=_('Role')
)
mark_reserved = forms.NullBooleanField(
required=False,
label=_('Treat as reserved'),
widget=forms.Select(
choices=BOOLEAN_WITH_BLANK_CHOICES
)
)
mark_utilized = forms.NullBooleanField(
required=False,
label=_('Treat as fully utilized'),

View File

@ -257,8 +257,8 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
fieldsets = (
FieldSet(
'vrf', 'start_address', 'end_address', 'role', 'status', 'mark_utilized', 'description', 'tags',
name=_('IP Range')
'vrf', 'start_address', 'end_address', 'role', 'status', 'mark_reserved', 'mark_utilized', 'description',
'tags', name=_('IP Range')
),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
)
@ -266,8 +266,8 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
class Meta:
model = IPRange
fields = [
'vrf', 'start_address', 'end_address', 'status', 'role', 'tenant_group', 'tenant', 'mark_utilized',
'description', 'comments', 'tags',
'vrf', 'start_address', 'end_address', 'status', 'role', 'tenant_group', 'tenant', 'mark_reserved',
'mark_utilized', 'description', 'comments', 'tags',
]

View File

@ -0,0 +1,16 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ipam', '0077_vlangroup_tenant'),
]
operations = [
migrations.AddField(
model_name='iprange',
name='mark_reserved',
field=models.BooleanField(default=False),
),
]

View File

@ -519,6 +519,11 @@ class IPRange(ContactsMixin, PrimaryModel):
null=True,
help_text=_('The primary function of this range')
)
mark_reserved = models.BooleanField(
verbose_name=_('mark reserved'),
default=False,
help_text=_("Prevent the creation of IP addresses within this range")
)
mark_utilized = models.BooleanField(
verbose_name=_('mark utilized'),
default=False,
@ -526,7 +531,7 @@ class IPRange(ContactsMixin, PrimaryModel):
)
clone_fields = (
'vrf', 'tenant', 'status', 'role', 'description',
'vrf', 'tenant', 'status', 'role', 'description', 'mark_reserved', 'mark_utilized',
)
class Meta:

View File

@ -268,6 +268,10 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
verbose_name=_('Role'),
linkify=True
)
mark_reserved = columns.BooleanColumn(
verbose_name=_('Marked Reserved'),
false_mark=None
)
mark_utilized = columns.BooleanColumn(
verbose_name=_('Marked Utilized'),
false_mark=None
@ -288,7 +292,8 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
model = IPRange
fields = (
'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'tenant_group',
'mark_utilized', 'utilization', 'description', 'comments', 'tags', 'created', 'last_updated',
'mark_reserved', 'mark_utilized', 'utilization', 'description', 'comments', 'tags', 'created',
'last_updated',
)
default_columns = (
'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',

View File

@ -25,6 +25,10 @@
<th scope="row">{% trans "Size" %}</th>
<td>{{ object.size }}</td>
</tr>
<tr>
<th scope="row">{% trans "Reserved" %}</th>
<td>{% checkmark object.mark_reserved %}</td>
</tr>
<tr>
<th scope="row">{% trans "Utilization" %}</th>
<td>