mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 09:51:22 -06:00
Add mark_utilized to IPRange
This commit is contained in:
parent
8a08d3621b
commit
536b46158a
@ -28,3 +28,7 @@ The IP range's operational status. Note that the status of a range does _not_ ha
|
|||||||
|
|
||||||
!!! tip
|
!!! tip
|
||||||
Additional statuses may be defined by setting `IPRange.status` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter.
|
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.
|
||||||
|
@ -26,6 +26,7 @@ A new ASN range model has been introduced to facilitate the provisioning of new
|
|||||||
|
|
||||||
### Enhancements
|
### 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
|
* [#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
|
* [#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)
|
* [#10374](https://github.com/netbox-community/netbox/issues/10374) - Require unique tenant names & slugs per group (not globally)
|
||||||
|
@ -377,7 +377,7 @@ class IPRangeSerializer(NetBoxModelSerializer):
|
|||||||
model = IPRange
|
model = IPRange
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'url', 'display', 'family', 'start_address', 'end_address', 'size', 'vrf', 'tenant', 'status', 'role',
|
'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']
|
read_only_fields = ['family']
|
||||||
|
|
||||||
|
@ -468,7 +468,7 @@ class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IPRange
|
model = IPRange
|
||||||
fields = ['id', 'description']
|
fields = ['id', 'mark_utilized', 'description']
|
||||||
|
|
||||||
def search(self, queryset, name, value):
|
def search(self, queryset, name, value):
|
||||||
if not value.strip():
|
if not value.strip():
|
||||||
|
@ -282,6 +282,11 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
|
|||||||
queryset=Role.objects.all(),
|
queryset=Role.objects.all(),
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
mark_utilized = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect(),
|
||||||
|
label=_('Treat as 100% utilized')
|
||||||
|
)
|
||||||
description = forms.CharField(
|
description = forms.CharField(
|
||||||
max_length=200,
|
max_length=200,
|
||||||
required=False
|
required=False
|
||||||
@ -293,7 +298,7 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
|
|||||||
|
|
||||||
model = IPRange
|
model = IPRange
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, ('status', 'role', 'vrf', 'tenant', 'description')),
|
(None, ('status', 'role', 'vrf', 'tenant', 'mark_utilized', 'description')),
|
||||||
)
|
)
|
||||||
nullable_fields = (
|
nullable_fields = (
|
||||||
'vrf', 'tenant', 'role', 'description', 'comments',
|
'vrf', 'tenant', 'role', 'description', 'comments',
|
||||||
|
@ -223,7 +223,8 @@ class IPRangeImportForm(NetBoxModelImportForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = IPRange
|
model = IPRange
|
||||||
fields = (
|
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',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|||||||
model = IPRange
|
model = IPRange
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, ('q', 'filter_id', 'tag')),
|
(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')),
|
('Tenant', ('tenant_group_id', 'tenant_id')),
|
||||||
)
|
)
|
||||||
family = forms.ChoiceField(
|
family = forms.ChoiceField(
|
||||||
@ -277,6 +277,13 @@ class IPRangeFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|||||||
null_option='None',
|
null_option='None',
|
||||||
label=_('Role')
|
label=_('Role')
|
||||||
)
|
)
|
||||||
|
mark_utilized = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
label=_('Marked as 100% utilized'),
|
||||||
|
widget=forms.Select(
|
||||||
|
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||||
|
)
|
||||||
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,15 +288,15 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
|
|||||||
comments = CommentField()
|
comments = CommentField()
|
||||||
|
|
||||||
fieldsets = (
|
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')),
|
('Tenancy', ('tenant_group', 'tenant')),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IPRange
|
model = IPRange
|
||||||
fields = [
|
fields = [
|
||||||
'vrf', 'start_address', 'end_address', 'status', 'role', 'tenant_group', 'tenant', 'description',
|
'vrf', 'start_address', 'end_address', 'status', 'role', 'tenant_group', 'tenant', 'mark_utilized',
|
||||||
'comments', 'tags',
|
'description', 'comments', 'tags',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
18
netbox/ipam/migrations/0065_iprange_mark_utilized.py
Normal file
18
netbox/ipam/migrations/0065_iprange_mark_utilized.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
@ -511,6 +511,10 @@ class IPRange(PrimaryModel):
|
|||||||
null=True,
|
null=True,
|
||||||
help_text=_('The primary function of this range')
|
help_text=_('The primary function of this range')
|
||||||
)
|
)
|
||||||
|
mark_utilized = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text=_("Treat as 100% utilized")
|
||||||
|
)
|
||||||
|
|
||||||
clone_fields = (
|
clone_fields = (
|
||||||
'vrf', 'tenant', 'status', 'role', 'description',
|
'vrf', 'tenant', 'status', 'role', 'description',
|
||||||
@ -652,6 +656,9 @@ class IPRange(PrimaryModel):
|
|||||||
"""
|
"""
|
||||||
Determine the utilization of the range and return it as a percentage.
|
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
|
# Compile an IPSet to avoid counting duplicate IPs
|
||||||
child_count = netaddr.IPSet([
|
child_count = netaddr.IPSet([
|
||||||
ip.address.ip for ip in self.get_child_ips()
|
ip.address.ip for ip in self.get_child_ips()
|
||||||
|
@ -275,6 +275,9 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
|
|||||||
role = tables.Column(
|
role = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
mark_utilized = columns.BooleanColumn(
|
||||||
|
verbose_name='Marked Utilized'
|
||||||
|
)
|
||||||
utilization = columns.UtilizationColumn(
|
utilization = columns.UtilizationColumn(
|
||||||
accessor='utilization',
|
accessor='utilization',
|
||||||
orderable=False
|
orderable=False
|
||||||
@ -288,7 +291,7 @@ class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
|
|||||||
model = IPRange
|
model = IPRange
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'tenant_group',
|
'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 = (
|
default_columns = (
|
||||||
'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',
|
'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',
|
||||||
|
@ -30,7 +30,12 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Utilization</th>
|
<th scope="row">Utilization</th>
|
||||||
<td>
|
<td>
|
||||||
|
{% if object.mark_utilized %}
|
||||||
|
{% utilization_graph 100 warning_threshold=0 danger_threshold=0 %}
|
||||||
|
<small>(Marked fully utilized)</small>
|
||||||
|
{% else %}
|
||||||
{% utilization_graph object.utilization %}
|
{% utilization_graph object.utilization %}
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
Loading…
Reference in New Issue
Block a user