From 8c7f6c62b0379402945c1eadaf5aed20caf50129 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 25 Nov 2019 21:21:35 -0500 Subject: [PATCH] PowerFeed.status to slug (#3569) --- netbox/dcim/api/serializers.py | 4 ++-- netbox/dcim/choices.py | 22 ++++++++++++++++++ netbox/dcim/constants.py | 21 ----------------- netbox/dcim/forms.py | 6 ++--- .../migrations/0084_3569_powerfeed_fields.py | 23 +++++++++++++++++++ netbox/dcim/models.py | 23 +++++++++++++++---- 6 files changed, 68 insertions(+), 31 deletions(-) diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index d03d3f5a9..eb640914e 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -695,8 +695,8 @@ class PowerFeedSerializer(TaggitSerializer, CustomFieldModelSerializer): default=PowerFeedTypeChoices.TYPE_PRIMARY ) status = ChoiceField( - choices=POWERFEED_STATUS_CHOICES, - default=POWERFEED_STATUS_ACTIVE + choices=PowerFeedStatusChoices, + default=PowerFeedStatusChoices.STATUS_ACTIVE ) supply = ChoiceField( choices=PowerFeedSupplyChoices, diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index cd4124518..4ac4ecde0 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -878,6 +878,28 @@ class CableLengthUnitChoices(ChoiceSet): # PowerFeeds # +class PowerFeedStatusChoices(ChoiceSet): + + STATUS_OFFLINE = 'offline' + STATUS_ACTIVE = 'active' + STATUS_PLANNED = 'planned' + STATUS_FAILED = 'failed' + + CHOICES = ( + (STATUS_OFFLINE, 'Offline'), + (STATUS_ACTIVE, 'Active'), + (STATUS_PLANNED, 'Planned'), + (STATUS_FAILED, 'Failed'), + ) + + LEGACY_MAP = { + STATUS_OFFLINE: 0, + STATUS_ACTIVE: 1, + STATUS_PLANNED: 2, + STATUS_FAILED: 4, + } + + class PowerFeedTypeChoices(ChoiceSet): TYPE_PRIMARY = 'primary' diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 79ad5229d..fb119286a 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -20,17 +20,6 @@ WIRELESS_IFACE_TYPES = [ NONCONNECTABLE_IFACE_TYPES = VIRTUAL_IFACE_TYPES + WIRELESS_IFACE_TYPES -# Bootstrap CSS classes for device/rack statuses -STATUS_CLASSES = { - 0: 'warning', - 1: 'success', - 2: 'info', - 3: 'primary', - 4: 'danger', - 5: 'default', - 6: 'warning', -} - # Console/power/interface connection statuses CONNECTION_STATUS_PLANNED = False CONNECTION_STATUS_CONNECTED = True @@ -68,16 +57,6 @@ COMPATIBLE_TERMINATION_TYPES = { } # Power feeds -POWERFEED_STATUS_OFFLINE = 0 -POWERFEED_STATUS_ACTIVE = 1 -POWERFEED_STATUS_PLANNED = 2 -POWERFEED_STATUS_FAILED = 4 -POWERFEED_STATUS_CHOICES = ( - (POWERFEED_STATUS_ACTIVE, 'Active'), - (POWERFEED_STATUS_OFFLINE, 'Offline'), - (POWERFEED_STATUS_PLANNED, 'Planned'), - (POWERFEED_STATUS_FAILED, 'Failed'), -) POWERFEED_LEG_A = 1 POWERFEED_LEG_B = 2 POWERFEED_LEG_C = 3 diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index fb9467397..6350b5045 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -3855,7 +3855,7 @@ class PowerFeedCSVForm(forms.ModelForm): help_text="Rack name (optional)" ) status = CSVChoiceField( - choices=POWERFEED_STATUS_CHOICES, + choices=PowerFeedStatusChoices, required=False, help_text='Operational status' ) @@ -3930,7 +3930,7 @@ class PowerFeedBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd ) ) status = forms.ChoiceField( - choices=add_blank_choice(POWERFEED_STATUS_CHOICES), + choices=add_blank_choice(PowerFeedStatusChoices), required=False, initial='', widget=StaticSelect2() @@ -4009,7 +4009,7 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm): ) ) status = forms.MultipleChoiceField( - choices=POWERFEED_STATUS_CHOICES, + choices=PowerFeedStatusChoices, required=False, widget=StaticSelect2Multiple() ) diff --git a/netbox/dcim/migrations/0084_3569_powerfeed_fields.py b/netbox/dcim/migrations/0084_3569_powerfeed_fields.py index 5dafa4f3a..6a3ba1ce5 100644 --- a/netbox/dcim/migrations/0084_3569_powerfeed_fields.py +++ b/netbox/dcim/migrations/0084_3569_powerfeed_fields.py @@ -1,6 +1,13 @@ from django.db import migrations, models +POWERFEED_STATUS_CHOICES = ( + (0, 'offline'), + (1, 'active'), + (2, 'planned'), + (4, 'failed'), +) + POWERFEED_TYPE_CHOICES = ( (1, 'primary'), (2, 'redundant'), @@ -17,6 +24,12 @@ POWERFEED_PHASE_CHOICES = ( ) +def powerfeed_status_to_slug(apps, schema_editor): + PowerFeed = apps.get_model('dcim', 'PowerFeed') + for id, slug in POWERFEED_STATUS_CHOICES: + PowerFeed.objects.filter(status=id).update(status=slug) + + def powerfeed_type_to_slug(apps, schema_editor): PowerFeed = apps.get_model('dcim', 'PowerFeed') for id, slug in POWERFEED_TYPE_CHOICES: @@ -44,6 +57,16 @@ class Migration(migrations.Migration): operations = [ + # PowerFeed.status + migrations.AlterField( + model_name='powerfeed', + name='status', + field=models.CharField(blank=True, max_length=50), + ), + migrations.RunPython( + code=powerfeed_status_to_slug + ), + # PowerFeed.type migrations.AlterField( model_name='powerfeed', diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 1510c7bea..b38adb479 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -3107,9 +3107,10 @@ class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): name = models.CharField( max_length=50 ) - status = models.PositiveSmallIntegerField( - choices=POWERFEED_STATUS_CHOICES, - default=POWERFEED_STATUS_ACTIVE + status = models.CharField( + max_length=50, + choices=PowerFeedStatusChoices, + default=PowerFeedStatusChoices.STATUS_ACTIVE ) type = models.CharField( max_length=50, @@ -3159,6 +3160,18 @@ class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): 'amperage', 'max_utilization', 'comments', ] + STATUS_CLASS_MAP = { + PowerFeedStatusChoices.STATUS_OFFLINE: 'warning', + PowerFeedStatusChoices.STATUS_ACTIVE: 'success', + PowerFeedStatusChoices.STATUS_PLANNED: 'info', + PowerFeedStatusChoices.STATUS_FAILED: 'danger', + } + + TYPE_CLASS_MAP = { + PowerFeedTypeChoices.TYPE_PRIMARY: 'success', + PowerFeedTypeChoices.TYPE_REDUNDANT: 'info', + } + class Meta: ordering = ['power_panel', 'name'] unique_together = ['power_panel', 'name'] @@ -3206,7 +3219,7 @@ class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): super().save(*args, **kwargs) def get_type_class(self): - return STATUS_CLASSES[self.type] + return self.TYPE_CLASS_MAP.get(self.type) def get_status_class(self): - return STATUS_CLASSES[self.status] + return self.STATUS_CLASS_MAP.get(self.status)