From ba8f324b12a7d7e8b5452cc309c86a07e2b6a74e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 27 Nov 2019 21:54:01 -0500 Subject: [PATCH] IPAddress.status to slug (#3569) --- netbox/ipam/api/serializers.py | 2 +- netbox/ipam/choices.py | 26 +++++++++++++ netbox/ipam/constants.py | 12 ------ netbox/ipam/filters.py | 2 +- netbox/ipam/forms.py | 6 +-- .../migrations/0029_3569_ipaddress_fields.py | 37 +++++++++++++++++++ netbox/ipam/models.py | 17 ++++++--- 7 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 netbox/ipam/migrations/0029_3569_ipaddress_fields.py diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index fa9269584..4c49dbf57 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -201,7 +201,7 @@ class IPAddressSerializer(TaggitSerializer, CustomFieldModelSerializer): family = ChoiceField(choices=AF_CHOICES, read_only=True) vrf = NestedVRFSerializer(required=False, allow_null=True) tenant = NestedTenantSerializer(required=False, allow_null=True) - status = ChoiceField(choices=IPADDRESS_STATUS_CHOICES, required=False) + status = ChoiceField(choices=IPAddressStatusChoices, required=False) role = ChoiceField(choices=IPADDRESS_ROLE_CHOICES, required=False, allow_null=True) interface = IPAddressInterfaceSerializer(required=False, allow_null=True) nat_inside = NestedIPAddressSerializer(required=False, allow_null=True) diff --git a/netbox/ipam/choices.py b/netbox/ipam/choices.py index fc9874bb4..2cdda3731 100644 --- a/netbox/ipam/choices.py +++ b/netbox/ipam/choices.py @@ -25,3 +25,29 @@ class PrefixStatusChoices(ChoiceSet): STATUS_RESERVED: 2, STATUS_DEPRECATED: 3, } + + +# +# IPAddresses +# + +class IPAddressStatusChoices(ChoiceSet): + + STATUS_ACTIVE = 'active' + STATUS_RESERVED = 'reserved' + STATUS_DEPRECATED = 'deprecated' + STATUS_DHCP = 'dhcp' + + CHOICES = ( + (STATUS_ACTIVE, 'Active'), + (STATUS_RESERVED, 'Reserved'), + (STATUS_DEPRECATED, 'Deprecated'), + (STATUS_DHCP, 'DHCP'), + ) + + LEGACY_MAP = { + STATUS_ACTIVE: 1, + STATUS_RESERVED: 2, + STATUS_DEPRECATED: 3, + STATUS_DHCP: 5, + } diff --git a/netbox/ipam/constants.py b/netbox/ipam/constants.py index 93521e77d..6a95e247c 100644 --- a/netbox/ipam/constants.py +++ b/netbox/ipam/constants.py @@ -4,18 +4,6 @@ AF_CHOICES = ( (6, 'IPv6'), ) -# IP address statuses -IPADDRESS_STATUS_ACTIVE = 1 -IPADDRESS_STATUS_RESERVED = 2 -IPADDRESS_STATUS_DEPRECATED = 3 -IPADDRESS_STATUS_DHCP = 5 -IPADDRESS_STATUS_CHOICES = ( - (IPADDRESS_STATUS_ACTIVE, 'Active'), - (IPADDRESS_STATUS_RESERVED, 'Reserved'), - (IPADDRESS_STATUS_DEPRECATED, 'Deprecated'), - (IPADDRESS_STATUS_DHCP, 'DHCP') -) - # IP address roles IPADDRESS_ROLE_LOOPBACK = 10 IPADDRESS_ROLE_SECONDARY = 20 diff --git a/netbox/ipam/filters.py b/netbox/ipam/filters.py index d75d312cd..c4be858fa 100644 --- a/netbox/ipam/filters.py +++ b/netbox/ipam/filters.py @@ -311,7 +311,7 @@ class IPAddressFilter(TenancyFilterSet, CustomFieldFilterSet): label='Interface (ID)', ) status = django_filters.MultipleChoiceFilter( - choices=IPADDRESS_STATUS_CHOICES, + choices=IPAddressStatusChoices, null_value=None ) role = django_filters.MultipleChoiceFilter( diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 0c7108f41..e2f5140d2 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -765,7 +765,7 @@ class IPAddressCSVForm(forms.ModelForm): } ) status = CSVChoiceField( - choices=IPADDRESS_STATUS_CHOICES, + choices=IPAddressStatusChoices, help_text='Operational status' ) role = CSVChoiceField( @@ -894,7 +894,7 @@ class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd ) ) status = forms.ChoiceField( - choices=add_blank_choice(IPADDRESS_STATUS_CHOICES), + choices=add_blank_choice(IPAddressStatusChoices), required=False, widget=StaticSelect2() ) @@ -973,7 +973,7 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo ) ) status = forms.MultipleChoiceField( - choices=IPADDRESS_STATUS_CHOICES, + choices=IPAddressStatusChoices, required=False, widget=StaticSelect2Multiple() ) diff --git a/netbox/ipam/migrations/0029_3569_ipaddress_fields.py b/netbox/ipam/migrations/0029_3569_ipaddress_fields.py new file mode 100644 index 000000000..ae5ede5e9 --- /dev/null +++ b/netbox/ipam/migrations/0029_3569_ipaddress_fields.py @@ -0,0 +1,37 @@ +from django.db import migrations, models + + +IPADDRESS_STATUS_CHOICES = ( + (0, 'container'), + (1, 'active'), + (2, 'reserved'), + (3, 'deprecated'), +) + + +def ipaddress_status_to_slug(apps, schema_editor): + IPAddress = apps.get_model('ipam', 'IPAddress') + for id, slug in IPADDRESS_STATUS_CHOICES: + IPAddress.objects.filter(status=str(id)).update(status=slug) + + +class Migration(migrations.Migration): + atomic = False + + dependencies = [ + ('ipam', '0028_3569_prefix_fields'), + ] + + operations = [ + + # IPAddress.status + migrations.AlterField( + model_name='ipaddress', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=ipaddress_status_to_slug + ), + + ] diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index bb922c287..631805cb1 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -559,10 +559,10 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): blank=True, null=True ) - status = models.PositiveSmallIntegerField( - choices=IPADDRESS_STATUS_CHOICES, - default=IPADDRESS_STATUS_ACTIVE, - verbose_name='Status', + status = models.CharField( + max_length=50, + choices=IPAddressStatusChoices, + default=IPAddressStatusChoices.STATUS_ACTIVE, help_text='The operational status of this IP' ) role = models.PositiveSmallIntegerField( @@ -613,6 +613,13 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): 'dns_name', 'description', ] + STATUS_CLASS_MAP = { + 'active': 'primary', + 'reserved': 'info', + 'deprecated': 'danger', + 'dhcp': 'success', + } + class Meta: ordering = ['family', 'address'] verbose_name = 'IP address' @@ -746,7 +753,7 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): return None def get_status_class(self): - return STATUS_CHOICE_CLASSES[self.status] + return self.STATUS_CLASS_MAP.get(self.status) def get_role_class(self): return ROLE_CHOICE_CLASSES[self.role]