Prefix.status to slug (#3569)

This commit is contained in:
Jeremy Stretch 2019-11-27 21:46:53 -05:00
parent 21fe5902a8
commit 929c0648d0
9 changed files with 91 additions and 29 deletions

View File

@ -8,6 +8,7 @@ from taggit_serializer.serializers import TaggitSerializer, TagListSerializerFie
from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer
from dcim.models import Interface from dcim.models import Interface
from extras.api.customfields import CustomFieldModelSerializer from extras.api.customfields import CustomFieldModelSerializer
from ipam.choices import *
from ipam.constants import * from ipam.constants import *
from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
from tenancy.api.nested_serializers import NestedTenantSerializer from tenancy.api.nested_serializers import NestedTenantSerializer
@ -140,7 +141,7 @@ class PrefixSerializer(TaggitSerializer, CustomFieldModelSerializer):
vrf = NestedVRFSerializer(required=False, allow_null=True) vrf = NestedVRFSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True)
vlan = NestedVLANSerializer(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) role = NestedRoleSerializer(required=False, allow_null=True)
tags = TagListSerializerField(required=False) tags = TagListSerializerField(required=False)

27
netbox/ipam/choices.py Normal file
View 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,
}

View File

@ -4,18 +4,6 @@ AF_CHOICES = (
(6, 'IPv6'), (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 # IP address statuses
IPADDRESS_STATUS_ACTIVE = 1 IPADDRESS_STATUS_ACTIVE = 1
IPADDRESS_STATUS_RESERVED = 2 IPADDRESS_STATUS_RESERVED = 2

View File

@ -9,6 +9,7 @@ from extras.filters import CustomFieldFilterSet
from tenancy.filtersets import TenancyFilterSet from tenancy.filtersets import TenancyFilterSet
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .choices import *
from .constants import * from .constants import *
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
@ -178,7 +179,7 @@ class PrefixFilter(TenancyFilterSet, CustomFieldFilterSet):
label='Role (slug)', label='Role (slug)',
) )
status = django_filters.MultipleChoiceFilter( status = django_filters.MultipleChoiceFilter(
choices=PREFIX_STATUS_CHOICES, choices=PrefixStatusChoices,
null_value=None null_value=None
) )
tag = TagFilter() tag = TagFilter()

View File

@ -40,7 +40,7 @@
"site": 1, "site": 1,
"vrf": null, "vrf": null,
"vlan": null, "vlan": null,
"status": 1, "status": "active",
"role": 1, "role": 1,
"description": "" "description": ""
} }
@ -56,7 +56,7 @@
"site": 1, "site": 1,
"vrf": null, "vrf": null,
"vlan": null, "vlan": null,
"status": 1, "status": "active",
"role": 1, "role": 1,
"description": "" "description": ""
} }

View File

@ -13,6 +13,7 @@ from utilities.forms import (
StaticSelect2, StaticSelect2Multiple, BOOLEAN_WITH_BLANK_CHOICES StaticSelect2, StaticSelect2Multiple, BOOLEAN_WITH_BLANK_CHOICES
) )
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .choices import *
from .constants import * from .constants import *
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
@ -374,7 +375,7 @@ class PrefixCSVForm(forms.ModelForm):
required=False required=False
) )
status = CSVChoiceField( status = CSVChoiceField(
choices=PREFIX_STATUS_CHOICES, choices=PrefixStatusChoices,
help_text='Operational status' help_text='Operational status'
) )
role = forms.ModelChoiceField( role = forms.ModelChoiceField(
@ -459,7 +460,7 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
) )
) )
status = forms.ChoiceField( status = forms.ChoiceField(
choices=add_blank_choice(PREFIX_STATUS_CHOICES), choices=add_blank_choice(PrefixStatusChoices),
required=False, required=False,
widget=StaticSelect2() widget=StaticSelect2()
) )
@ -527,7 +528,7 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
) )
) )
status = forms.MultipleChoiceField( status = forms.MultipleChoiceField(
choices=PREFIX_STATUS_CHOICES, choices=PrefixStatusChoices,
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )

View 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
),
]

View File

@ -14,6 +14,7 @@ from extras.models import CustomFieldModel, ObjectChange, TaggedItem
from utilities.models import ChangeLoggedModel from utilities.models import ChangeLoggedModel
from utilities.utils import serialize_object from utilities.utils import serialize_object
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .choices import *
from .constants import * from .constants import *
from .fields import IPNetworkField, IPAddressField from .fields import IPNetworkField, IPAddressField
from .querysets import PrefixQuerySet from .querysets import PrefixQuerySet
@ -297,9 +298,10 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
null=True, null=True,
verbose_name='VLAN' verbose_name='VLAN'
) )
status = models.PositiveSmallIntegerField( status = models.CharField(
choices=PREFIX_STATUS_CHOICES, max_length=50,
default=PREFIX_STATUS_ACTIVE, choices=PrefixStatusChoices,
default=PrefixStatusChoices.STATUS_ACTIVE,
verbose_name='Status', verbose_name='Status',
help_text='Operational status of this prefix' 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', '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: class Meta:
ordering = [F('vrf').asc(nulls_first=True), 'family', 'prefix'] ordering = [F('vrf').asc(nulls_first=True), 'family', 'prefix']
verbose_name_plural = 'prefixes' verbose_name_plural = 'prefixes'
@ -404,7 +413,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
prefix_length = property(fset=_set_prefix_length) prefix_length = property(fset=_set_prefix_length)
def get_status_class(self): def get_status_class(self):
return STATUS_CHOICE_CLASSES[self.status] return self.STATUS_CLASS_MAP.get(self.status)
def get_duplicates(self): def get_duplicates(self):
return Prefix.objects.filter(vrf=self.vrf, prefix=str(self.prefix)).exclude(pk=self.pk) 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 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. 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)) return Prefix.objects.filter(prefix__net_contained=str(self.prefix))
else: else:
return Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf) 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 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. 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)) return IPAddress.objects.filter(address__net_host_contained=str(self.prefix))
else: else:
return IPAddress.objects.filter(address__net_host_contained=str(self.prefix), vrf=self.vrf) 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 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. "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) queryset = Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf)
child_prefixes = netaddr.IPSet([p.prefix for p in queryset]) child_prefixes = netaddr.IPSet([p.prefix for p in queryset])
return int(float(child_prefixes.size) / self.prefix.size * 100) return int(float(child_prefixes.size) / self.prefix.size * 100)

View File

@ -14,6 +14,7 @@ from utilities.views import (
) )
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from . import filters, forms, tables from . import filters, forms, tables
from .choices import PrefixStatusChoices
from .constants import * from .constants import *
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF 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). # Find all consumed space for each prefix status (we ignore containers for this purpose).
active_prefixes = netaddr.cidr_merge( 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( 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( 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. # Find all available prefixes by subtracting each of the existing prefix sets from the aggregate prefix.