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

+ 1 - 1
netbox/dcim/api/serializers.py

@@ -325,7 +325,7 @@ class DeviceSerializer(TaggitSerializer, CustomFieldModelSerializer):
     site = NestedSiteSerializer()
     site = NestedSiteSerializer()
     rack = NestedRackSerializer(required=False, allow_null=True)
     rack = NestedRackSerializer(required=False, allow_null=True)
     face = ChoiceField(choices=DeviceFaceChoices, required=False, allow_null=True)
     face = ChoiceField(choices=DeviceFaceChoices, required=False, allow_null=True)
-    status = ChoiceField(choices=DEVICE_STATUS_CHOICES, required=False)
+    status = ChoiceField(choices=DeviceStatusChoices, required=False)
     primary_ip = NestedIPAddressSerializer(read_only=True)
     primary_ip = NestedIPAddressSerializer(read_only=True)
     primary_ip4 = NestedIPAddressSerializer(required=False, allow_null=True)
     primary_ip4 = NestedIPAddressSerializer(required=False, allow_null=True)
     primary_ip6 = NestedIPAddressSerializer(required=False, allow_null=True)
     primary_ip6 = NestedIPAddressSerializer(required=False, allow_null=True)

+ 31 - 0
netbox/dcim/choices.py

@@ -129,6 +129,37 @@ class DeviceFaceChoices(ChoiceSet):
     }
     }
 
 
 
 
+class DeviceStatusChoices(ChoiceSet):
+
+    STATUS_OFFLINE = 'offline'
+    STATUS_ACTIVE = 'active'
+    STATUS_PLANNED = 'planned'
+    STATUS_STAGED = 'staged'
+    STATUS_FAILED = 'failed'
+    STATUS_INVENTORY = 'inventory'
+    STATUS_DECOMMISSIONING = 'decommissioning'
+
+    CHOICES = (
+        (STATUS_OFFLINE, 'Offline'),
+        (STATUS_ACTIVE, 'Active'),
+        (STATUS_PLANNED, 'Planned'),
+        (STATUS_STAGED, 'Staged'),
+        (STATUS_FAILED, 'Failed'),
+        (STATUS_INVENTORY, 'Inventory'),
+        (STATUS_DECOMMISSIONING, 'Decommissioning'),
+    )
+
+    LEGACY_MAP = {
+        STATUS_OFFLINE: 0,
+        STATUS_ACTIVE: 1,
+        STATUS_PLANNED: 2,
+        STATUS_STAGED: 3,
+        STATUS_FAILED: 4,
+        STATUS_INVENTORY: 5,
+        STATUS_DECOMMISSIONING: 6,
+    }
+
+
 #
 #
 # ConsolePorts
 # ConsolePorts
 #
 #

+ 0 - 18
netbox/dcim/constants.py

@@ -61,24 +61,6 @@ PORT_TYPE_CHOICES = [
     ]
     ]
 ]
 ]
 
 
-# Device statuses
-DEVICE_STATUS_OFFLINE = 0
-DEVICE_STATUS_ACTIVE = 1
-DEVICE_STATUS_PLANNED = 2
-DEVICE_STATUS_STAGED = 3
-DEVICE_STATUS_FAILED = 4
-DEVICE_STATUS_INVENTORY = 5
-DEVICE_STATUS_DECOMMISSIONING = 6
-DEVICE_STATUS_CHOICES = [
-    [DEVICE_STATUS_ACTIVE, 'Active'],
-    [DEVICE_STATUS_OFFLINE, 'Offline'],
-    [DEVICE_STATUS_PLANNED, 'Planned'],
-    [DEVICE_STATUS_STAGED, 'Staged'],
-    [DEVICE_STATUS_FAILED, 'Failed'],
-    [DEVICE_STATUS_INVENTORY, 'Inventory'],
-    [DEVICE_STATUS_DECOMMISSIONING, 'Decommissioning'],
-]
-
 # Bootstrap CSS classes for device/rack statuses
 # Bootstrap CSS classes for device/rack statuses
 STATUS_CLASSES = {
 STATUS_CLASSES = {
     0: 'warning',
     0: 'warning',

+ 1 - 1
netbox/dcim/filters.py

@@ -511,7 +511,7 @@ class DeviceFilter(LocalConfigContextFilter, TenancyFilterSet, CustomFieldFilter
         label='Device model (slug)',
         label='Device model (slug)',
     )
     )
     status = django_filters.MultipleChoiceFilter(
     status = django_filters.MultipleChoiceFilter(
-        choices=DEVICE_STATUS_CHOICES,
+        choices=DeviceStatusChoices,
         null_value=None
         null_value=None
     )
     )
     is_full_depth = django_filters.BooleanFilter(
     is_full_depth = django_filters.BooleanFilter(

+ 3 - 3
netbox/dcim/forms.py

@@ -1665,7 +1665,7 @@ class BaseDeviceCSVForm(forms.ModelForm):
         }
         }
     )
     )
     status = CSVChoiceField(
     status = CSVChoiceField(
-        choices=DEVICE_STATUS_CHOICES,
+        choices=DeviceStatusChoices,
         help_text='Operational status'
         help_text='Operational status'
     )
     )
 
 
@@ -1833,7 +1833,7 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
         )
         )
     )
     )
     status = forms.ChoiceField(
     status = forms.ChoiceField(
-        choices=add_blank_choice(DEVICE_STATUS_CHOICES),
+        choices=add_blank_choice(DeviceStatusChoices),
         required=False,
         required=False,
         initial='',
         initial='',
         widget=StaticSelect2()
         widget=StaticSelect2()
@@ -1944,7 +1944,7 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt
         )
         )
     )
     )
     status = forms.MultipleChoiceField(
     status = forms.MultipleChoiceField(
-        choices=DEVICE_STATUS_CHOICES,
+        choices=DeviceStatusChoices,
         required=False,
         required=False,
         widget=StaticSelect2Multiple()
         widget=StaticSelect2Multiple()
     )
     )

+ 29 - 0
netbox/dcim/migrations/0081_3569_device_fields.py

@@ -5,6 +5,16 @@ DEVICE_FACE_CHOICES = (
     (1, 'rear'),
     (1, 'rear'),
 )
 )
 
 
+DEVICE_STATUS_CHOICES = (
+    (0, 'offline'),
+    (1, 'active'),
+    (2, 'planned'),
+    (3, 'staged'),
+    (4, 'failed'),
+    (5, 'inventory'),
+    (6, 'decommissioning'),
+)
+
 
 
 def device_face_to_slug(apps, schema_editor):
 def device_face_to_slug(apps, schema_editor):
     Device = apps.get_model('dcim', 'Device')
     Device = apps.get_model('dcim', 'Device')
@@ -12,6 +22,12 @@ def device_face_to_slug(apps, schema_editor):
         Device.objects.filter(face=str(id)).update(face=slug)
         Device.objects.filter(face=str(id)).update(face=slug)
 
 
 
 
+def device_status_to_slug(apps, schema_editor):
+    Device = apps.get_model('dcim', 'Device')
+    for id, slug in DEVICE_STATUS_CHOICES:
+        Device.objects.filter(status=str(id)).update(status=slug)
+
+
 class Migration(migrations.Migration):
 class Migration(migrations.Migration):
     atomic = False
     atomic = False
 
 
@@ -20,6 +36,8 @@ class Migration(migrations.Migration):
     ]
     ]
 
 
     operations = [
     operations = [
+
+        # Device.face
         migrations.AlterField(
         migrations.AlterField(
             model_name='device',
             model_name='device',
             name='face',
             name='face',
@@ -33,4 +51,15 @@ class Migration(migrations.Migration):
             name='face',
             name='face',
             field=models.CharField(blank=True, max_length=50),
             field=models.CharField(blank=True, max_length=50),
         ),
         ),
+
+        # Device.status
+        migrations.AlterField(
+            model_name='device',
+            name='status',
+            field=models.CharField(default='active', max_length=50),
+        ),
+        migrations.RunPython(
+            code=device_status_to_slug
+        ),
+
     ]
     ]

+ 15 - 5
netbox/dcim/models.py

@@ -1551,10 +1551,10 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
         choices=DeviceFaceChoices,
         choices=DeviceFaceChoices,
         verbose_name='Rack face'
         verbose_name='Rack face'
     )
     )
-    status = models.PositiveSmallIntegerField(
-        choices=DEVICE_STATUS_CHOICES,
-        default=DEVICE_STATUS_ACTIVE,
-        verbose_name='Status'
+    status = models.CharField(
+        max_length=50,
+        choices=DeviceStatusChoices,
+        default=DeviceStatusChoices.STATUS_ACTIVE
     )
     )
     primary_ip4 = models.OneToOneField(
     primary_ip4 = models.OneToOneField(
         to='ipam.IPAddress',
         to='ipam.IPAddress',
@@ -1616,6 +1616,16 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
         'site', 'rack_group', 'rack_name', 'position', 'face', 'comments',
         'site', 'rack_group', 'rack_name', 'position', 'face', 'comments',
     ]
     ]
 
 
+    STATUS_CLASS_MAP = {
+        DeviceStatusChoices.STATUS_OFFLINE: 'warning',
+        DeviceStatusChoices.STATUS_ACTIVE: 'success',
+        DeviceStatusChoices.STATUS_PLANNED: 'info',
+        DeviceStatusChoices.STATUS_STAGED: 'primary',
+        DeviceStatusChoices.STATUS_FAILED: 'danger',
+        DeviceStatusChoices.STATUS_INVENTORY: 'default',
+        DeviceStatusChoices.STATUS_DECOMMISSIONING: 'warning',
+    }
+
     class Meta:
     class Meta:
         ordering = ['name']
         ordering = ['name']
         unique_together = [
         unique_together = [
@@ -1869,7 +1879,7 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
         return Device.objects.filter(parent_bay__device=self.pk)
         return Device.objects.filter(parent_bay__device=self.pk)
 
 
     def get_status_class(self):
     def get_status_class(self):
-        return STATUS_CLASSES[self.status]
+        return self.STATUS_CLASS_MAP.get(self.status)
 
 
 
 
 #
 #

+ 4 - 4
netbox/dcim/tests/test_forms.py

@@ -24,7 +24,7 @@ class DeviceTestCase(TestCase):
             'face': DeviceFaceChoices.FACE_FRONT,
             'face': DeviceFaceChoices.FACE_FRONT,
             'position': 41,
             'position': 41,
             'platform': get_id(Platform, 'juniper-junos'),
             'platform': get_id(Platform, 'juniper-junos'),
-            'status': DEVICE_STATUS_ACTIVE,
+            'status': DeviceStatusChoices.STATUS_ACTIVE,
         })
         })
         self.assertTrue(test.is_valid(), test.fields['position'].choices)
         self.assertTrue(test.is_valid(), test.fields['position'].choices)
         self.assertTrue(test.save())
         self.assertTrue(test.save())
@@ -41,7 +41,7 @@ class DeviceTestCase(TestCase):
             'face': DeviceFaceChoices.FACE_FRONT,
             'face': DeviceFaceChoices.FACE_FRONT,
             'position': 1,
             'position': 1,
             'platform': get_id(Platform, 'juniper-junos'),
             'platform': get_id(Platform, 'juniper-junos'),
-            'status': DEVICE_STATUS_ACTIVE,
+            'status': DeviceStatusChoices.STATUS_ACTIVE,
         })
         })
         self.assertFalse(test.is_valid())
         self.assertFalse(test.is_valid())
 
 
@@ -57,7 +57,7 @@ class DeviceTestCase(TestCase):
             'face': '',
             'face': '',
             'position': None,
             'position': None,
             'platform': None,
             'platform': None,
-            'status': DEVICE_STATUS_ACTIVE,
+            'status': DeviceStatusChoices.STATUS_ACTIVE,
         })
         })
         self.assertTrue(test.is_valid())
         self.assertTrue(test.is_valid())
         self.assertTrue(test.save())
         self.assertTrue(test.save())
@@ -74,7 +74,7 @@ class DeviceTestCase(TestCase):
             'face': DeviceFaceChoices.FACE_REAR,
             'face': DeviceFaceChoices.FACE_REAR,
             'position': None,
             'position': None,
             'platform': None,
             'platform': None,
-            'status': DEVICE_STATUS_ACTIVE,
+            'status': DeviceStatusChoices.STATUS_ACTIVE,
         })
         })
         self.assertTrue(test.is_valid())
         self.assertTrue(test.is_valid())
         self.assertTrue(test.save())
         self.assertTrue(test.save())

+ 4 - 4
netbox/virtualization/constants.py

@@ -1,10 +1,10 @@
-from dcim.constants import DEVICE_STATUS_ACTIVE, DEVICE_STATUS_OFFLINE, DEVICE_STATUS_STAGED
+from dcim.choices import DeviceStatusChoices
 
 
 # VirtualMachine statuses (replicated from Device statuses)
 # VirtualMachine statuses (replicated from Device statuses)
 VM_STATUS_CHOICES = [
 VM_STATUS_CHOICES = [
-    [DEVICE_STATUS_ACTIVE, 'Active'],
-    [DEVICE_STATUS_OFFLINE, 'Offline'],
-    [DEVICE_STATUS_STAGED, 'Staged'],
+    [1, 'Active'],
+    [0, 'Offline'],
+    [3, 'Staged'],
 ]
 ]
 
 
 # Bootstrap CSS classes for VirtualMachine statuses
 # Bootstrap CSS classes for VirtualMachine statuses

+ 1 - 1
netbox/virtualization/models.py

@@ -195,7 +195,7 @@ class VirtualMachine(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
     )
     )
     status = models.PositiveSmallIntegerField(
     status = models.PositiveSmallIntegerField(
         choices=VM_STATUS_CHOICES,
         choices=VM_STATUS_CHOICES,
-        default=DEVICE_STATUS_ACTIVE,
+        default=1,  # TODO: Replace with ChoiceSet value
         verbose_name='Status'
         verbose_name='Status'
     )
     )
     role = models.ForeignKey(
     role = models.ForeignKey(