Jeremy Stretch 6 лет назад
Родитель
Сommit
929c0648d0

+ 2 - 1
netbox/ipam/api/serializers.py

@@ -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 - 0
netbox/ipam/choices.py

@@ -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,
+    }

+ 0 - 12
netbox/ipam/constants.py

@@ -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

+ 2 - 1
netbox/ipam/filters.py

@@ -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()

+ 2 - 2
netbox/ipam/fixtures/ipam.json

@@ -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": ""
     }

+ 4 - 3
netbox/ipam/forms.py

@@ -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 - 0
netbox/ipam/migrations/0028_3569_prefix_fields.py

@@ -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
+        ),
+    ]

+ 16 - 7
netbox/ipam/models.py

@@ -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)

+ 4 - 3
netbox/ipam/views.py

@@ -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.