1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Add mark_utilized to IPRange

This commit is contained in:
jeremystretch
2023-02-28 10:09:09 -05:00
committed by Jeremy Stretch
parent 8a08d3621b
commit 536b46158a
12 changed files with 61 additions and 10 deletions

View File

@ -28,3 +28,7 @@ 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 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

@ -26,6 +26,7 @@ A new ASN range model has been introduced to facilitate the provisioning of new
### Enhancements
* [#7947](https://github.com/netbox-community/netbox/issues/7947) - Enable marking IP ranges as fully utilized
* [#9073](https://github.com/netbox-community/netbox/issues/9073) - Enable syncing config context data from remote sources
* [#9653](https://github.com/netbox-community/netbox/issues/9653) - Enable setting a default platform for device types
* [#10374](https://github.com/netbox-community/netbox/issues/10374) - Require unique tenant names & slugs per group (not globally)

View File

@ -377,7 +377,7 @@ class IPRangeSerializer(NetBoxModelSerializer):
model = IPRange
fields = [
'id', 'url', 'display', 'family', 'start_address', 'end_address', 'size', 'vrf', 'tenant', 'status', 'role',
'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'children',
'mark_utilized', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'children',
]
read_only_fields = ['family']

View File

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

View File

@ -282,6 +282,11 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
queryset=Role.objects.all(),
required=False
)
mark_utilized = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),
label=_('Treat as 100% utilized')
)
description = forms.CharField(
max_length=200,
required=False
@ -293,7 +298,7 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
model = IPRange
fieldsets = (
(None, ('status', 'role', 'vrf', 'tenant', 'description')),
(None, ('status', 'role', 'vrf', 'tenant', 'mark_utilized', 'description')),
)
nullable_fields = (
'vrf', 'tenant', 'role', 'description', 'comments',

View File

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

View File

@ -253,7 +253,7 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = IPRange
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
('Attriubtes', ('family', 'vrf_id', 'status', 'role_id')),
('Attriubtes', ('family', 'vrf_id', 'status', 'role_id', 'mark_utilized')),
('Tenant', ('tenant_group_id', 'tenant_id')),
)
family = forms.ChoiceField(
@ -277,6 +277,13 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
null_option='None',
label=_('Role')
)
mark_utilized = forms.NullBooleanField(
required=False,
label=_('Marked as 100% utilized'),
widget=forms.Select(
choices=BOOLEAN_WITH_BLANK_CHOICES
)
)
tag = TagFilterField(model)

View File

@ -288,15 +288,15 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
comments = CommentField()
fieldsets = (
('IP Range', ('vrf', 'start_address', 'end_address', 'role', 'status', 'description', 'tags')),
('IP Range', ('vrf', 'start_address', 'end_address', 'role', 'status', 'mark_utilized', 'description', 'tags')),
('Tenancy', ('tenant_group', 'tenant')),
)
class Meta:
model = IPRange
fields = [
'vrf', 'start_address', 'end_address', 'status', 'role', 'tenant_group', 'tenant', 'description',
'comments', 'tags',
'vrf', 'start_address', 'end_address', 'status', 'role', 'tenant_group', 'tenant', 'mark_utilized',
'description', 'comments', 'tags',
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.1.7 on 2023-02-28 14:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ipam', '0064_asnrange'),
]
operations = [
migrations.AddField(
model_name='iprange',
name='mark_utilized',
field=models.BooleanField(default=False),
),
]

View File

@ -511,6 +511,10 @@ class IPRange(PrimaryModel):
null=True,
help_text=_('The primary function of this range')
)
mark_utilized = models.BooleanField(
default=False,
help_text=_("Treat as 100% utilized")
)
clone_fields = (
'vrf', 'tenant', 'status', 'role', 'description',
@ -652,6 +656,9 @@ class IPRange(PrimaryModel):
"""
Determine the utilization of the range and return it as a percentage.
"""
if self.mark_utilized:
return 100
# Compile an IPSet to avoid counting duplicate IPs
child_count = netaddr.IPSet([
ip.address.ip for ip in self.get_child_ips()

View File

@ -275,6 +275,9 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
role = tables.Column(
linkify=True
)
mark_utilized = columns.BooleanColumn(
verbose_name='Marked Utilized'
)
utilization = columns.UtilizationColumn(
accessor='utilization',
orderable=False
@ -288,7 +291,7 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
model = IPRange
fields = (
'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'tenant_group',
'utilization', 'description', 'comments', 'tags', 'created', 'last_updated',
'mark_utilized', 'utilization', 'description', 'comments', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',

View File

@ -30,7 +30,12 @@
<tr>
<th scope="row">Utilization</th>
<td>
{% if object.mark_utilized %}
{% utilization_graph 100 warning_threshold=0 danger_threshold=0 %}
<small>(Marked fully utilized)</small>
{% else %}
{% utilization_graph object.utilization %}
{% endif %}
</td>
</tr>
<tr>