Przeglądaj źródła

Device.face to slug (#3569)

Jeremy Stretch 6 lat temu
rodzic
commit
a8db07e0a8

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

@@ -324,7 +324,7 @@ class DeviceSerializer(TaggitSerializer, CustomFieldModelSerializer):
     platform = NestedPlatformSerializer(required=False, allow_null=True)
     platform = NestedPlatformSerializer(required=False, allow_null=True)
     site = NestedSiteSerializer()
     site = NestedSiteSerializer()
     rack = NestedRackSerializer(required=False, allow_null=True)
     rack = NestedRackSerializer(required=False, allow_null=True)
-    face = ChoiceField(choices=RACK_FACE_CHOICES, 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=DEVICE_STATUS_CHOICES, 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)

+ 20 - 0
netbox/dcim/choices.py

@@ -66,6 +66,26 @@ class RackStatusChoices(ChoiceSet):
     }
     }
 
 
 
 
+#
+# Devices
+#
+
+class DeviceFaceChoices(ChoiceSet):
+
+    FACE_FRONT = 'front'
+    FACE_REAR = 'rear'
+
+    CHOICES = (
+        (FACE_FRONT, 'Front'),
+        (FACE_REAR, 'Rear'),
+    )
+
+    LEGACY_MAP = {
+        FACE_FRONT: 0,
+        FACE_REAR: 1,
+    }
+
+
 #
 #
 # Console port type values
 # Console port type values
 #
 #

+ 0 - 14
netbox/dcim/constants.py

@@ -1,17 +1,3 @@
-# Device rack faces
-RACK_FACE_FRONT = 0
-RACK_FACE_REAR = 1
-RACK_FACE_CHOICES = [
-    [RACK_FACE_FRONT, 'Front'],
-    [RACK_FACE_REAR, 'Rear'],
-]
-
-# Device rack position
-DEVICE_POSITION_CHOICES = [
-    # Rack.u_height is limited to 100
-    (i, 'Unit {}'.format(i)) for i in range(1, 101)
-]
-
 # Parent/child device roles
 # Parent/child device roles
 SUBDEVICE_ROLE_PARENT = True
 SUBDEVICE_ROLE_PARENT = True
 SUBDEVICE_ROLE_CHILD = False
 SUBDEVICE_ROLE_CHILD = False

+ 11 - 11
netbox/dcim/fixtures/dcim.json

@@ -1910,7 +1910,7 @@
         "site": 1,
         "site": 1,
         "rack": 1,
         "rack": 1,
         "position": 1,
         "position": 1,
-        "face": 0,
+        "face": "front",
         "status": true,
         "status": true,
         "primary_ip4": 1,
         "primary_ip4": 1,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -1931,7 +1931,7 @@
         "site": 1,
         "site": 1,
         "rack": 1,
         "rack": 1,
         "position": 17,
         "position": 17,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": 5,
         "primary_ip4": 5,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -1952,7 +1952,7 @@
         "site": 1,
         "site": 1,
         "rack": 1,
         "rack": 1,
         "position": 33,
         "position": 33,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": null,
         "primary_ip4": null,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -1973,7 +1973,7 @@
         "site": 1,
         "site": 1,
         "rack": 1,
         "rack": 1,
         "position": 34,
         "position": 34,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": null,
         "primary_ip4": null,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -1994,7 +1994,7 @@
         "site": 1,
         "site": 1,
         "rack": 2,
         "rack": 2,
         "position": 34,
         "position": 34,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": null,
         "primary_ip4": null,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -2015,7 +2015,7 @@
         "site": 1,
         "site": 1,
         "rack": 2,
         "rack": 2,
         "position": 33,
         "position": 33,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": null,
         "primary_ip4": null,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -2036,7 +2036,7 @@
         "site": 1,
         "site": 1,
         "rack": 2,
         "rack": 2,
         "position": 1,
         "position": 1,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": 3,
         "primary_ip4": 3,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -2057,7 +2057,7 @@
         "site": 1,
         "site": 1,
         "rack": 2,
         "rack": 2,
         "position": 17,
         "position": 17,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": 19,
         "primary_ip4": 19,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -2078,7 +2078,7 @@
         "site": 1,
         "site": 1,
         "rack": 1,
         "rack": 1,
         "position": 42,
         "position": 42,
-        "face": 0,
+        "face": "rear",
         "status": true,
         "status": true,
         "primary_ip4": null,
         "primary_ip4": null,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -2099,7 +2099,7 @@
         "site": 1,
         "site": 1,
         "rack": 1,
         "rack": 1,
         "position": null,
         "position": null,
-        "face": null,
+        "face": "",
         "status": true,
         "status": true,
         "primary_ip4": null,
         "primary_ip4": null,
         "primary_ip6": null,
         "primary_ip6": null,
@@ -2120,7 +2120,7 @@
         "site": 1,
         "site": 1,
         "rack": 2,
         "rack": 2,
         "position": null,
         "position": null,
-        "face": null,
+        "face": "",
         "status": true,
         "status": true,
         "primary_ip4": null,
         "primary_ip4": null,
         "primary_ip6": null,
         "primary_ip6": null,

+ 1 - 1
netbox/dcim/forms.py

@@ -1716,7 +1716,7 @@ class DeviceCSVForm(BaseDeviceCSVForm):
         help_text='Name of parent rack'
         help_text='Name of parent rack'
     )
     )
     face = CSVChoiceField(
     face = CSVChoiceField(
-        choices=RACK_FACE_CHOICES,
+        choices=DeviceFaceChoices,
         required=False,
         required=False,
         help_text='Mounted rack face'
         help_text='Mounted rack face'
     )
     )

+ 1 - 1
netbox/dcim/migrations/0078_rack_choicefields_to_slugs.py

@@ -49,7 +49,7 @@ class Migration(migrations.Migration):
         migrations.AlterField(
         migrations.AlterField(
             model_name='rack',
             model_name='rack',
             name='status',
             name='status',
-            field=models.CharField(blank=True, max_length=50),
+            field=models.CharField(blank=True, default='active', max_length=50),
         ),
         ),
         migrations.RunPython(
         migrations.RunPython(
             code=rack_status_to_slug
             code=rack_status_to_slug

+ 31 - 0
netbox/dcim/migrations/0079_device_choicefields_to_slugs.py

@@ -0,0 +1,31 @@
+from django.db import migrations, models
+
+DEVICE_FACE_CHOICES = (
+    (0, 'front'),
+    (1, 'rear'),
+)
+
+
+def rack_type_to_slug(apps, schema_editor):
+    Device = apps.get_model('dcim', 'Device')
+    for id, slug in DEVICE_FACE_CHOICES:
+        Device.objects.filter(face=str(id)).update(face=slug)
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('dcim', '0078_rack_choicefields_to_slugs'),
+    ]
+
+    operations = [
+        # Device.face
+        migrations.AlterField(
+            model_name='device',
+            name='face',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.RunPython(
+            code=rack_type_to_slug
+        ),
+    ]

+ 8 - 8
netbox/dcim/models.py

@@ -655,7 +655,7 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
     def get_status_class(self):
     def get_status_class(self):
         return self.STATUS_CLASS_MAP.get(self.status)
         return self.STATUS_CLASS_MAP.get(self.status)
 
 
-    def get_rack_units(self, face=RACK_FACE_FRONT, exclude=None, remove_redundant=False):
+    def get_rack_units(self, face=DeviceFaceChoices.FACE_FRONT, exclude=None, remove_redundant=False):
         """
         """
         Return a list of rack units as dictionaries. Example: {'device': None, 'face': 0, 'id': 48, 'name': 'U48'}
         Return a list of rack units as dictionaries. Example: {'device': None, 'face': 0, 'id': 48, 'name': 'U48'}
         Each key 'device' is either a Device or None. By default, multi-U devices are repeated for each U they occupy.
         Each key 'device' is either a Device or None. By default, multi-U devices are repeated for each U they occupy.
@@ -687,10 +687,10 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
         return [u for u in elevation.values()]
         return [u for u in elevation.values()]
 
 
     def get_front_elevation(self):
     def get_front_elevation(self):
-        return self.get_rack_units(face=RACK_FACE_FRONT, remove_redundant=True)
+        return self.get_rack_units(face=DeviceFaceChoices.FACE_FRONT, remove_redundant=True)
 
 
     def get_rear_elevation(self):
     def get_rear_elevation(self):
-        return self.get_rack_units(face=RACK_FACE_REAR, remove_redundant=True)
+        return self.get_rack_units(face=DeviceFaceChoices.FACE_REAR, remove_redundant=True)
 
 
     def get_available_units(self, u_height=1, rack_face=None, exclude=list()):
     def get_available_units(self, u_height=1, rack_face=None, exclude=list()):
         """
         """
@@ -1535,10 +1535,10 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
         verbose_name='Position (U)',
         verbose_name='Position (U)',
         help_text='The lowest-numbered unit occupied by the device'
         help_text='The lowest-numbered unit occupied by the device'
     )
     )
-    face = models.PositiveSmallIntegerField(
+    face = models.CharField(
+        max_length=50,
         blank=True,
         blank=True,
-        null=True,
-        choices=RACK_FACE_CHOICES,
+        choices=DeviceFaceChoices,
         verbose_name='Rack face'
         verbose_name='Rack face'
     )
     )
     status = models.PositiveSmallIntegerField(
     status = models.PositiveSmallIntegerField(
@@ -1634,7 +1634,7 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
             })
             })
 
 
         if self.rack is None:
         if self.rack is None:
-            if self.face is not None:
+            if self.face:
                 raise ValidationError({
                 raise ValidationError({
                     'face': "Cannot select a rack face without assigning a rack.",
                     'face': "Cannot select a rack face without assigning a rack.",
                 })
                 })
@@ -1644,7 +1644,7 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
                 })
                 })
 
 
         # Validate position/face combination
         # Validate position/face combination
-        if self.position and self.face is None:
+        if self.position and not self.face:
             raise ValidationError({
             raise ValidationError({
                 'face': "Must specify rack face when defining rack position.",
                 'face': "Must specify rack face when defining rack position.",
             })
             })

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

@@ -21,7 +21,7 @@ class DeviceTestCase(TestCase):
             'device_type': get_id(DeviceType, 'qfx5100-48s'),
             'device_type': get_id(DeviceType, 'qfx5100-48s'),
             'site': get_id(Site, 'test1'),
             'site': get_id(Site, 'test1'),
             'rack': '1',
             'rack': '1',
-            'face': RACK_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': DEVICE_STATUS_ACTIVE,
@@ -38,7 +38,7 @@ class DeviceTestCase(TestCase):
             'device_type': get_id(DeviceType, 'qfx5100-48s'),
             'device_type': get_id(DeviceType, 'qfx5100-48s'),
             'site': get_id(Site, 'test1'),
             'site': get_id(Site, 'test1'),
             'rack': '1',
             'rack': '1',
-            'face': RACK_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': DEVICE_STATUS_ACTIVE,
@@ -54,7 +54,7 @@ class DeviceTestCase(TestCase):
             'device_type': get_id(DeviceType, 'cwg-24vym415c9'),
             'device_type': get_id(DeviceType, 'cwg-24vym415c9'),
             'site': get_id(Site, 'test1'),
             'site': get_id(Site, 'test1'),
             'rack': '1',
             'rack': '1',
-            'face': None,
+            'face': '',
             'position': None,
             'position': None,
             'platform': None,
             'platform': None,
             'status': DEVICE_STATUS_ACTIVE,
             'status': DEVICE_STATUS_ACTIVE,
@@ -71,7 +71,7 @@ class DeviceTestCase(TestCase):
             'device_type': get_id(DeviceType, 'cwg-24vym415c9'),
             'device_type': get_id(DeviceType, 'cwg-24vym415c9'),
             'site': get_id(Site, 'test1'),
             'site': get_id(Site, 'test1'),
             'rack': '1',
             'rack': '1',
-            'face': RACK_FACE_REAR,
+            'face': DeviceFaceChoices.FACE_REAR,
             'position': None,
             'position': None,
             'platform': None,
             'platform': None,
             'status': DEVICE_STATUS_ACTIVE,
             'status': DEVICE_STATUS_ACTIVE,

+ 3 - 3
netbox/dcim/tests/test_models.py

@@ -87,7 +87,7 @@ class RackTestCase(TestCase):
             site=self.site1,
             site=self.site1,
             rack=rack1,
             rack=rack1,
             position=43,
             position=43,
-            face=RACK_FACE_FRONT,
+            face=DeviceFaceChoices.FACE_FRONT,
         )
         )
         device1.save()
         device1.save()
 
 
@@ -117,7 +117,7 @@ class RackTestCase(TestCase):
             site=self.site1,
             site=self.site1,
             rack=self.rack,
             rack=self.rack,
             position=10,
             position=10,
-            face=RACK_FACE_REAR,
+            face=DeviceFaceChoices.FACE_REAR,
         )
         )
         device1.save()
         device1.save()
 
 
@@ -146,7 +146,7 @@ class RackTestCase(TestCase):
             site=self.site1,
             site=self.site1,
             rack=self.rack,
             rack=self.rack,
             position=None,
             position=None,
-            face=None,
+            face='',
         )
         )
         self.assertTrue(pdu)
         self.assertTrue(pdu)