From 5811f9ecadaefbb9bd09315f47062047bfea62fd Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 15 Jul 2024 21:05:01 -0400 Subject: [PATCH] Create base classes for Rack & RackType models, serializers --- netbox/dcim/api/serializers_/racks.py | 61 +++++-- netbox/dcim/models/racks.py | 222 ++++++++++---------------- 2 files changed, 130 insertions(+), 153 deletions(-) diff --git a/netbox/dcim/api/serializers_/racks.py b/netbox/dcim/api/serializers_/racks.py index f2814cdd5..4fb96e08c 100644 --- a/netbox/dcim/api/serializers_/racks.py +++ b/netbox/dcim/api/serializers_/racks.py @@ -35,10 +35,7 @@ class RackRoleSerializer(NetBoxModelSerializer): brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'rack_count') -class RackTypeSerializer(NetBoxModelSerializer): - manufacturer = ManufacturerSerializer( - nested=True - ) +class RackBaseSerializer(NetBoxModelSerializer): form_factor = ChoiceField( choices=RackFormFactorChoices, allow_blank=True, @@ -62,6 +59,12 @@ class RackTypeSerializer(NetBoxModelSerializer): allow_null=True ) + +class RackTypeSerializer(RackBaseSerializer): + manufacturer = ManufacturerSerializer( + nested=True + ) + class Meta: model = RackType fields = [ @@ -73,19 +76,43 @@ class RackTypeSerializer(NetBoxModelSerializer): brief_fields = ('id', 'url', 'display', 'manufacturer', 'name', 'slug', 'description') -class RackSerializer(NetBoxModelSerializer): - site = SiteSerializer(nested=True) - location = LocationSerializer(nested=True, required=False, allow_null=True, default=None) - tenant = TenantSerializer(nested=True, required=False, allow_null=True) - status = ChoiceField(choices=RackStatusChoices, required=False) - role = RackRoleSerializer(nested=True, required=False, allow_null=True) - form_factor = ChoiceField(choices=RackFormFactorChoices, allow_blank=True, required=False, allow_null=True) - facility_id = serializers.CharField(max_length=50, allow_blank=True, allow_null=True, label=_('Facility ID'), - default=None) - rack_type = RackTypeSerializer(nested=True, required=False, allow_null=True, default=None) - width = ChoiceField(choices=RackWidthChoices, required=False) - outer_unit = ChoiceField(choices=RackDimensionUnitChoices, allow_blank=True, required=False, allow_null=True) - weight_unit = ChoiceField(choices=WeightUnitChoices, allow_blank=True, required=False, allow_null=True) +class RackSerializer(RackBaseSerializer): + site = SiteSerializer( + nested=True + ) + location = LocationSerializer( + nested=True, + required=False, + allow_null=True, + default=None + ) + tenant = TenantSerializer( + nested=True, + required=False, + allow_null=True + ) + status = ChoiceField( + choices=RackStatusChoices, + required=False + ) + role = RackRoleSerializer( + nested=True, + required=False, + allow_null=True + ) + facility_id = serializers.CharField( + max_length=50, + allow_blank=True, + allow_null=True, + label=_('Facility ID'), + default=None + ) + rack_type = RackTypeSerializer( + nested=True, + required=False, + allow_null=True, + default=None + ) # Related object counts device_count = RelatedObjectCountField('devices') diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 8b28fd905..6fe84fe04 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -37,7 +37,91 @@ __all__ = ( # Rack Types # -class RackType(WeightMixin, PrimaryModel): +class RackBase(WeightMixin, PrimaryModel): + """ + Base class for RackType & Rack. Holds + """ + # Rack type + form_factor = models.CharField( + choices=RackFormFactorChoices, + max_length=50, + blank=True, + verbose_name=_('form factor') + ) + width = models.PositiveSmallIntegerField( + choices=RackWidthChoices, + default=RackWidthChoices.WIDTH_19IN, + verbose_name=_('width'), + help_text=_('Rail-to-rail width') + ) + + # Numbering + u_height = models.PositiveSmallIntegerField( + default=RACK_U_HEIGHT_DEFAULT, + verbose_name=_('height (U)'), + validators=[MinValueValidator(1), MaxValueValidator(RACK_U_HEIGHT_MAX)], + help_text=_('Height in rack units') + ) + starting_unit = models.PositiveSmallIntegerField( + default=RACK_STARTING_UNIT_DEFAULT, + verbose_name=_('starting unit'), + validators=[MinValueValidator(1)], + help_text=_('Starting unit for rack') + ) + desc_units = models.BooleanField( + default=False, + verbose_name=_('descending units'), + help_text=_('Units are numbered top-to-bottom') + ) + + # Dimensions + outer_width = models.PositiveSmallIntegerField( + verbose_name=_('outer width'), + blank=True, + null=True, + help_text=_('Outer dimension of rack (width)') + ) + outer_depth = models.PositiveSmallIntegerField( + verbose_name=_('outer depth'), + blank=True, + null=True, + help_text=_('Outer dimension of rack (depth)') + ) + outer_unit = models.CharField( + verbose_name=_('outer unit'), + max_length=50, + choices=RackDimensionUnitChoices, + blank=True + ) + mounting_depth = models.PositiveSmallIntegerField( + verbose_name=_('mounting depth'), + blank=True, + null=True, + help_text=(_( + 'Maximum depth of a mounted device, in millimeters. For four-post racks, this is the distance between the ' + 'front and rear rails.' + )) + ) + + # Weight + # WeightMixin provides weight, weight_unit, and _abs_weight + max_weight = models.PositiveIntegerField( + verbose_name=_('max weight'), + blank=True, + null=True, + help_text=_('Maximum load capacity for the rack') + ) + # Stores the normalized max weight (in grams) for database ordering + _abs_max_weight = models.PositiveBigIntegerField( + blank=True, + null=True + ) + + class Meta: + abstract = True + + +class RackType(RackBase): """ Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face. Each Rack is assigned to a Site and (optionally) a Location. @@ -67,73 +151,6 @@ class RackType(WeightMixin, PrimaryModel): max_length=100, unique=True ) - form_factor = models.CharField( - choices=RackFormFactorChoices, - max_length=50, - blank=True, - verbose_name=_('form factor') - ) - width = models.PositiveSmallIntegerField( - choices=RackWidthChoices, - default=RackWidthChoices.WIDTH_19IN, - verbose_name=_('width'), - help_text=_('Rail-to-rail width') - ) - u_height = models.PositiveSmallIntegerField( - default=RACK_U_HEIGHT_DEFAULT, - verbose_name=_('height (U)'), - validators=[MinValueValidator(1), MaxValueValidator(RACK_U_HEIGHT_MAX)], - help_text=_('Height in rack units') - ) - starting_unit = models.PositiveSmallIntegerField( - default=RACK_STARTING_UNIT_DEFAULT, - verbose_name=_('starting unit'), - validators=[MinValueValidator(1)], - help_text=_('Starting unit for rack') - ) - desc_units = models.BooleanField( - default=False, - verbose_name=_('descending units'), - help_text=_('Units are numbered top-to-bottom') - ) - outer_width = models.PositiveSmallIntegerField( - verbose_name=_('outer width'), - blank=True, - null=True, - help_text=_('Outer dimension of rack (width)') - ) - outer_depth = models.PositiveSmallIntegerField( - verbose_name=_('outer depth'), - blank=True, - null=True, - help_text=_('Outer dimension of rack (depth)') - ) - outer_unit = models.CharField( - verbose_name=_('outer unit'), - max_length=50, - choices=RackDimensionUnitChoices, - blank=True - ) - max_weight = models.PositiveIntegerField( - verbose_name=_('max weight'), - blank=True, - null=True, - help_text=_('Maximum load capacity for the rack') - ) - # Stores the normalized max weight (in grams) for database ordering - _abs_max_weight = models.PositiveBigIntegerField( - blank=True, - null=True - ) - mounting_depth = models.PositiveSmallIntegerField( - verbose_name=_('mounting depth'), - blank=True, - null=True, - help_text=(_( - 'Maximum depth of a mounted device, in millimeters. For four-post racks, this is the distance between the ' - 'front and rear rails.' - )) - ) clone_fields = ( 'manufacturer', 'form_factor', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', @@ -228,7 +245,7 @@ class RackRole(OrganizationalModel): return reverse('dcim:rackrole', args=[self.pk]) -class Rack(ContactsMixin, ImageAttachmentsMixin, PrimaryModel, WeightMixin): +class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): """ Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face. Each Rack is assigned to a Site and (optionally) a Location. @@ -302,73 +319,6 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, PrimaryModel, WeightMixin): verbose_name=_('asset tag'), help_text=_('A unique tag used to identify this rack') ) - form_factor = models.CharField( - choices=RackFormFactorChoices, - max_length=50, - blank=True, - verbose_name=_('form factor') - ) - width = models.PositiveSmallIntegerField( - choices=RackWidthChoices, - default=RackWidthChoices.WIDTH_19IN, - verbose_name=_('width'), - help_text=_('Rail-to-rail width') - ) - u_height = models.PositiveSmallIntegerField( - default=RACK_U_HEIGHT_DEFAULT, - verbose_name=_('height (U)'), - validators=[MinValueValidator(1), MaxValueValidator(RACK_U_HEIGHT_MAX)], - help_text=_('Height in rack units') - ) - starting_unit = models.PositiveSmallIntegerField( - default=RACK_STARTING_UNIT_DEFAULT, - verbose_name=_('starting unit'), - validators=[MinValueValidator(1),], - help_text=_('Starting unit for rack') - ) - desc_units = models.BooleanField( - default=False, - verbose_name=_('descending units'), - help_text=_('Units are numbered top-to-bottom') - ) - outer_width = models.PositiveSmallIntegerField( - verbose_name=_('outer width'), - blank=True, - null=True, - help_text=_('Outer dimension of rack (width)') - ) - outer_depth = models.PositiveSmallIntegerField( - verbose_name=_('outer depth'), - blank=True, - null=True, - help_text=_('Outer dimension of rack (depth)') - ) - outer_unit = models.CharField( - verbose_name=_('outer unit'), - max_length=50, - choices=RackDimensionUnitChoices, - blank=True, - ) - max_weight = models.PositiveIntegerField( - verbose_name=_('max weight'), - blank=True, - null=True, - help_text=_('Maximum load capacity for the rack') - ) - # Stores the normalized max weight (in grams) for database ordering - _abs_max_weight = models.PositiveBigIntegerField( - blank=True, - null=True - ) - mounting_depth = models.PositiveSmallIntegerField( - verbose_name=_('mounting depth'), - blank=True, - null=True, - help_text=( - _('Maximum depth of a mounted device, in millimeters. For four-post racks, this is the ' - 'distance between the front and rear rails.') - ) - ) # Generic relations vlan_groups = GenericRelation(