mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Fixes #4578: Prevent setting 0U height on device type with racked instances
This commit is contained in:
parent
6e2c68ef42
commit
0239be9be5
@ -18,6 +18,7 @@
|
|||||||
* [#4548](https://github.com/netbox-community/netbox/issues/4548) - Fix tracing cables through a single RearPort
|
* [#4548](https://github.com/netbox-community/netbox/issues/4548) - Fix tracing cables through a single RearPort
|
||||||
* [#4549](https://github.com/netbox-community/netbox/issues/4549) - Fix encoding unicode webhook body data
|
* [#4549](https://github.com/netbox-community/netbox/issues/4549) - Fix encoding unicode webhook body data
|
||||||
* [#4556](https://github.com/netbox-community/netbox/issues/4556) - Update form for adding devices to clusters
|
* [#4556](https://github.com/netbox-community/netbox/issues/4556) - Update form for adding devices to clusters
|
||||||
|
* [#4578](https://github.com/netbox-community/netbox/issues/4578) - Prevent setting 0U height on device type with racked instances
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Count, F, ProtectedError, Sum
|
from django.db.models import Count, F, ProtectedError, Sum
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from mptt.models import MPTTModel, TreeForeignKey
|
from mptt.models import MPTTModel, TreeForeignKey
|
||||||
from taggit.managers import TaggableManager
|
from taggit.managers import TaggableManager
|
||||||
from timezone_field import TimeZoneField
|
from timezone_field import TimeZoneField
|
||||||
@ -652,7 +653,8 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
|
|||||||
pk=exclude
|
pk=exclude
|
||||||
).filter(
|
).filter(
|
||||||
rack=self,
|
rack=self,
|
||||||
position__gt=0
|
position__gt=0,
|
||||||
|
device_type__u_height__gt=0
|
||||||
).filter(
|
).filter(
|
||||||
Q(face=face) | Q(device_type__is_full_depth=True)
|
Q(face=face) | Q(device_type__is_full_depth=True)
|
||||||
)
|
)
|
||||||
@ -1089,17 +1091,32 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel):
|
|||||||
# If editing an existing DeviceType to have a larger u_height, first validate that *all* instances of it have
|
# If editing an existing DeviceType to have a larger u_height, first validate that *all* instances of it have
|
||||||
# room to expand within their racks. This validation will impose a very high performance penalty when there are
|
# room to expand within their racks. This validation will impose a very high performance penalty when there are
|
||||||
# many instances to check, but increasing the u_height of a DeviceType should be a very rare occurrence.
|
# many instances to check, but increasing the u_height of a DeviceType should be a very rare occurrence.
|
||||||
if self.pk is not None and self.u_height > self._original_u_height:
|
if self.pk and self.u_height > self._original_u_height:
|
||||||
for d in Device.objects.filter(device_type=self, position__isnull=False):
|
for d in Device.objects.filter(device_type=self, position__isnull=False):
|
||||||
face_required = None if self.is_full_depth else d.face
|
face_required = None if self.is_full_depth else d.face
|
||||||
u_available = d.rack.get_available_units(u_height=self.u_height, rack_face=face_required,
|
u_available = d.rack.get_available_units(
|
||||||
exclude=[d.pk])
|
u_height=self.u_height,
|
||||||
|
rack_face=face_required,
|
||||||
|
exclude=[d.pk]
|
||||||
|
)
|
||||||
if d.position not in u_available:
|
if d.position not in u_available:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'u_height': "Device {} in rack {} does not have sufficient space to accommodate a height of "
|
'u_height': "Device {} in rack {} does not have sufficient space to accommodate a height of "
|
||||||
"{}U".format(d, d.rack, self.u_height)
|
"{}U".format(d, d.rack, self.u_height)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# If modifying the height of an existing DeviceType to 0U, check for any instances assigned to a rack position.
|
||||||
|
elif self.pk and self._original_u_height > 0 and self.u_height == 0:
|
||||||
|
racked_instance_count = Device.objects.filter(device_type=self, position__isnull=False).count()
|
||||||
|
if racked_instance_count:
|
||||||
|
url = f"{reverse('dcim:device_list')}?manufactuer_id={self.manufacturer_id}&device_type_id={self.pk}"
|
||||||
|
raise ValidationError({
|
||||||
|
'u_height': mark_safe(
|
||||||
|
f'Unable to set 0U height: Found <a href="{url}">{racked_instance_count} instances</a> already '
|
||||||
|
f'mounted within racks.'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT
|
self.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT
|
||||||
) and self.device_bay_templates.count():
|
) and self.device_bay_templates.count():
|
||||||
|
Loading…
Reference in New Issue
Block a user