mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 17:08:41 -06:00
Device.face to slug (#3569)
This commit is contained in:
parent
c79c29e769
commit
a8db07e0a8
@ -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)
|
||||||
|
@ -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
|
||||||
#
|
#
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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'
|
||||||
)
|
)
|
||||||
|
@ -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
netbox/dcim/migrations/0079_device_choicefields_to_slugs.py
Normal file
31
netbox/dcim/migrations/0079_device_choicefields_to_slugs.py
Normal file
@ -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
|
||||||
|
),
|
||||||
|
]
|
@ -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=DeviceFaceChoices,
|
||||||
choices=RACK_FACE_CHOICES,
|
|
||||||
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.",
|
||||||
})
|
})
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user