mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Prefix.status to slug (#3569)
This commit is contained in:
@ -8,6 +8,7 @@ from taggit_serializer.serializers import TaggitSerializer, TagListSerializerFie
|
||||
from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer
|
||||
from dcim.models import Interface
|
||||
from extras.api.customfields import CustomFieldModelSerializer
|
||||
from ipam.choices import *
|
||||
from ipam.constants import *
|
||||
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||
from tenancy.api.nested_serializers import NestedTenantSerializer
|
||||
@ -140,7 +141,7 @@ class PrefixSerializer(TaggitSerializer, CustomFieldModelSerializer):
|
||||
vrf = NestedVRFSerializer(required=False, allow_null=True)
|
||||
tenant = NestedTenantSerializer(required=False, allow_null=True)
|
||||
vlan = NestedVLANSerializer(required=False, allow_null=True)
|
||||
status = ChoiceField(choices=PREFIX_STATUS_CHOICES, required=False)
|
||||
status = ChoiceField(choices=PrefixStatusChoices, required=False)
|
||||
role = NestedRoleSerializer(required=False, allow_null=True)
|
||||
tags = TagListSerializerField(required=False)
|
||||
|
||||
|
27
netbox/ipam/choices.py
Normal file
27
netbox/ipam/choices.py
Normal file
@ -0,0 +1,27 @@
|
||||
from utilities.choices import ChoiceSet
|
||||
|
||||
|
||||
#
|
||||
# Prefixes
|
||||
#
|
||||
|
||||
class PrefixStatusChoices(ChoiceSet):
|
||||
|
||||
STATUS_CONTAINER = 'container'
|
||||
STATUS_ACTIVE = 'active'
|
||||
STATUS_RESERVED = 'reserved'
|
||||
STATUS_DEPRECATED = 'deprecated'
|
||||
|
||||
CHOICES = (
|
||||
(STATUS_CONTAINER, 'Container'),
|
||||
(STATUS_ACTIVE, 'Active'),
|
||||
(STATUS_RESERVED, 'Reserved'),
|
||||
(STATUS_DEPRECATED, 'Deprecated'),
|
||||
)
|
||||
|
||||
LEGACY_MAP = {
|
||||
STATUS_CONTAINER: 0,
|
||||
STATUS_ACTIVE: 1,
|
||||
STATUS_RESERVED: 2,
|
||||
STATUS_DEPRECATED: 3,
|
||||
}
|
@ -4,18 +4,6 @@ AF_CHOICES = (
|
||||
(6, 'IPv6'),
|
||||
)
|
||||
|
||||
# Prefix statuses
|
||||
PREFIX_STATUS_CONTAINER = 0
|
||||
PREFIX_STATUS_ACTIVE = 1
|
||||
PREFIX_STATUS_RESERVED = 2
|
||||
PREFIX_STATUS_DEPRECATED = 3
|
||||
PREFIX_STATUS_CHOICES = (
|
||||
(PREFIX_STATUS_CONTAINER, 'Container'),
|
||||
(PREFIX_STATUS_ACTIVE, 'Active'),
|
||||
(PREFIX_STATUS_RESERVED, 'Reserved'),
|
||||
(PREFIX_STATUS_DEPRECATED, 'Deprecated')
|
||||
)
|
||||
|
||||
# IP address statuses
|
||||
IPADDRESS_STATUS_ACTIVE = 1
|
||||
IPADDRESS_STATUS_RESERVED = 2
|
||||
|
@ -9,6 +9,7 @@ from extras.filters import CustomFieldFilterSet
|
||||
from tenancy.filtersets import TenancyFilterSet
|
||||
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
|
||||
from virtualization.models import VirtualMachine
|
||||
from .choices import *
|
||||
from .constants import *
|
||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||
|
||||
@ -178,7 +179,7 @@ class PrefixFilter(TenancyFilterSet, CustomFieldFilterSet):
|
||||
label='Role (slug)',
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=PREFIX_STATUS_CHOICES,
|
||||
choices=PrefixStatusChoices,
|
||||
null_value=None
|
||||
)
|
||||
tag = TagFilter()
|
||||
|
@ -40,7 +40,7 @@
|
||||
"site": 1,
|
||||
"vrf": null,
|
||||
"vlan": null,
|
||||
"status": 1,
|
||||
"status": "active",
|
||||
"role": 1,
|
||||
"description": ""
|
||||
}
|
||||
@ -56,7 +56,7 @@
|
||||
"site": 1,
|
||||
"vrf": null,
|
||||
"vlan": null,
|
||||
"status": 1,
|
||||
"status": "active",
|
||||
"role": 1,
|
||||
"description": ""
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ from utilities.forms import (
|
||||
StaticSelect2, StaticSelect2Multiple, BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
from virtualization.models import VirtualMachine
|
||||
from .choices import *
|
||||
from .constants import *
|
||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||
|
||||
@ -374,7 +375,7 @@ class PrefixCSVForm(forms.ModelForm):
|
||||
required=False
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=PREFIX_STATUS_CHOICES,
|
||||
choices=PrefixStatusChoices,
|
||||
help_text='Operational status'
|
||||
)
|
||||
role = forms.ModelChoiceField(
|
||||
@ -459,7 +460,7 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
|
||||
)
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
choices=add_blank_choice(PREFIX_STATUS_CHOICES),
|
||||
choices=add_blank_choice(PrefixStatusChoices),
|
||||
required=False,
|
||||
widget=StaticSelect2()
|
||||
)
|
||||
@ -527,7 +528,7 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
|
||||
)
|
||||
)
|
||||
status = forms.MultipleChoiceField(
|
||||
choices=PREFIX_STATUS_CHOICES,
|
||||
choices=PrefixStatusChoices,
|
||||
required=False,
|
||||
widget=StaticSelect2Multiple()
|
||||
)
|
||||
|
34
netbox/ipam/migrations/0028_3569_prefix_fields.py
Normal file
34
netbox/ipam/migrations/0028_3569_prefix_fields.py
Normal file
@ -0,0 +1,34 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
PREFIX_STATUS_CHOICES = (
|
||||
(0, 'container'),
|
||||
(1, 'active'),
|
||||
(2, 'reserved'),
|
||||
(3, 'deprecated'),
|
||||
)
|
||||
|
||||
|
||||
def prefix_status_to_slug(apps, schema_editor):
|
||||
Prefix = apps.get_model('ipam', 'Prefix')
|
||||
for id, slug in PREFIX_STATUS_CHOICES:
|
||||
Prefix.objects.filter(status=str(id)).update(status=slug)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
atomic = False
|
||||
|
||||
dependencies = [
|
||||
('ipam', '0027_ipaddress_add_dns_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='prefix',
|
||||
name='status',
|
||||
field=models.CharField(default='active', max_length=50),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=prefix_status_to_slug
|
||||
),
|
||||
]
|
@ -14,6 +14,7 @@ from extras.models import CustomFieldModel, ObjectChange, TaggedItem
|
||||
from utilities.models import ChangeLoggedModel
|
||||
from utilities.utils import serialize_object
|
||||
from virtualization.models import VirtualMachine
|
||||
from .choices import *
|
||||
from .constants import *
|
||||
from .fields import IPNetworkField, IPAddressField
|
||||
from .querysets import PrefixQuerySet
|
||||
@ -297,9 +298,10 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
|
||||
null=True,
|
||||
verbose_name='VLAN'
|
||||
)
|
||||
status = models.PositiveSmallIntegerField(
|
||||
choices=PREFIX_STATUS_CHOICES,
|
||||
default=PREFIX_STATUS_ACTIVE,
|
||||
status = models.CharField(
|
||||
max_length=50,
|
||||
choices=PrefixStatusChoices,
|
||||
default=PrefixStatusChoices.STATUS_ACTIVE,
|
||||
verbose_name='Status',
|
||||
help_text='Operational status of this prefix'
|
||||
)
|
||||
@ -333,6 +335,13 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
|
||||
'prefix', 'vrf', 'tenant', 'site', 'vlan_group', 'vlan_vid', 'status', 'role', 'is_pool', 'description',
|
||||
]
|
||||
|
||||
STATUS_CLASS_MAP = {
|
||||
'container': 'default',
|
||||
'active': 'primary',
|
||||
'reserved': 'info',
|
||||
'deprecated': 'danger',
|
||||
}
|
||||
|
||||
class Meta:
|
||||
ordering = [F('vrf').asc(nulls_first=True), 'family', 'prefix']
|
||||
verbose_name_plural = 'prefixes'
|
||||
@ -404,7 +413,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
|
||||
prefix_length = property(fset=_set_prefix_length)
|
||||
|
||||
def get_status_class(self):
|
||||
return STATUS_CHOICE_CLASSES[self.status]
|
||||
return self.STATUS_CLASS_MAP.get(self.status)
|
||||
|
||||
def get_duplicates(self):
|
||||
return Prefix.objects.filter(vrf=self.vrf, prefix=str(self.prefix)).exclude(pk=self.pk)
|
||||
@ -414,7 +423,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
|
||||
Return all Prefixes within this Prefix and VRF. If this Prefix is a container in the global table, return child
|
||||
Prefixes belonging to any VRF.
|
||||
"""
|
||||
if self.vrf is None and self.status == PREFIX_STATUS_CONTAINER:
|
||||
if self.vrf is None and self.status == PrefixStatusChoices.STATUS_CONTAINER:
|
||||
return Prefix.objects.filter(prefix__net_contained=str(self.prefix))
|
||||
else:
|
||||
return Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf)
|
||||
@ -424,7 +433,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
|
||||
Return all IPAddresses within this Prefix and VRF. If this Prefix is a container in the global table, return
|
||||
child IPAddresses belonging to any VRF.
|
||||
"""
|
||||
if self.vrf is None and self.status == PREFIX_STATUS_CONTAINER:
|
||||
if self.vrf is None and self.status == PrefixStatusChoices.STATUS_CONTAINER:
|
||||
return IPAddress.objects.filter(address__net_host_contained=str(self.prefix))
|
||||
else:
|
||||
return IPAddress.objects.filter(address__net_host_contained=str(self.prefix), vrf=self.vrf)
|
||||
@ -490,7 +499,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
|
||||
Determine the utilization of the prefix and return it as a percentage. For Prefixes with a status of
|
||||
"container", calculate utilization based on child prefixes. For all others, count child IP addresses.
|
||||
"""
|
||||
if self.status == PREFIX_STATUS_CONTAINER:
|
||||
if self.status == PrefixStatusChoices.STATUS_CONTAINER:
|
||||
queryset = Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf)
|
||||
child_prefixes = netaddr.IPSet([p.prefix for p in queryset])
|
||||
return int(float(child_prefixes.size) / self.prefix.size * 100)
|
||||
|
@ -14,6 +14,7 @@ from utilities.views import (
|
||||
)
|
||||
from virtualization.models import VirtualMachine
|
||||
from . import filters, forms, tables
|
||||
from .choices import PrefixStatusChoices
|
||||
from .constants import *
|
||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||
|
||||
@ -217,13 +218,13 @@ class RIRListView(PermissionRequiredMixin, ObjectListView):
|
||||
|
||||
# Find all consumed space for each prefix status (we ignore containers for this purpose).
|
||||
active_prefixes = netaddr.cidr_merge(
|
||||
[p.prefix for p in queryset.filter(status=PREFIX_STATUS_ACTIVE)]
|
||||
[p.prefix for p in queryset.filter(status=PrefixStatusChoices.STATUS_ACTIVE)]
|
||||
)
|
||||
reserved_prefixes = netaddr.cidr_merge(
|
||||
[p.prefix for p in queryset.filter(status=PREFIX_STATUS_RESERVED)]
|
||||
[p.prefix for p in queryset.filter(status=PrefixStatusChoices.STATUS_RESERVED)]
|
||||
)
|
||||
deprecated_prefixes = netaddr.cidr_merge(
|
||||
[p.prefix for p in queryset.filter(status=PREFIX_STATUS_DEPRECATED)]
|
||||
[p.prefix for p in queryset.filter(status=PrefixStatusChoices.STATUS_DEPRECATED)]
|
||||
)
|
||||
|
||||
# Find all available prefixes by subtracting each of the existing prefix sets from the aggregate prefix.
|
||||
|
Reference in New Issue
Block a user