From e62a42286a5499fba50987fc8b3d2db6b4e52104 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Fri, 26 Jul 2024 02:14:02 +0700 Subject: [PATCH] 11969 airflow (#16967) * 11960 Add airflow * 11960 Add airflow * 11960 fix tests * 11960 fix racktype form * 11969 different choices type * 11969 update docs * 11969 fix racktype copy * 11969 fix * Misc cleanup & reordering of form fields --------- Co-authored-by: Jeremy Stretch --- docs/models/dcim/moduletype.md | 4 +++ docs/models/dcim/racktype.md | 3 ++ netbox/dcim/api/serializers_/devicetypes.py | 22 +++++++++++--- netbox/dcim/api/serializers_/racks.py | 16 ++++++++-- netbox/dcim/choices.py | 30 +++++++++++++++++++ netbox/dcim/filtersets.py | 7 +++-- netbox/dcim/forms/bulk_edit.py | 27 +++++++++++++---- netbox/dcim/forms/bulk_import.py | 28 +++++++++++++---- netbox/dcim/forms/filtersets.py | 16 ++++++++-- netbox/dcim/forms/model_forms.py | 15 +++++----- ...e_airflow_rack_airflow_racktype_airflow.py | 28 +++++++++++++++++ netbox/dcim/models/devices.py | 8 ++++- netbox/dcim/models/racks.py | 18 +++++++---- netbox/dcim/tables/modules.py | 2 +- netbox/dcim/tables/racks.py | 6 ++-- netbox/templates/dcim/moduletype.html | 6 ++++ netbox/templates/dcim/rack.html | 4 +++ netbox/templates/dcim/racktype.html | 4 +++ 18 files changed, 203 insertions(+), 41 deletions(-) create mode 100644 netbox/dcim/migrations/0189_moduletype_airflow_rack_airflow_racktype_airflow.py diff --git a/docs/models/dcim/moduletype.md b/docs/models/dcim/moduletype.md index 3122d2e00cd..7077e16c245 100644 --- a/docs/models/dcim/moduletype.md +++ b/docs/models/dcim/moduletype.md @@ -39,3 +39,7 @@ An alternative part number to uniquely identify the module type. ### Weight The numeric weight of the module, including a unit designation (e.g. 3 kilograms or 1 pound). + +### Airflow + +The direction in which air circulates through the device chassis for cooling. diff --git a/docs/models/dcim/racktype.md b/docs/models/dcim/racktype.md index d44e17b17fc..476dbe17863 100644 --- a/docs/models/dcim/racktype.md +++ b/docs/models/dcim/racktype.md @@ -54,4 +54,7 @@ The maximum total weight capacity for all installed devices, inclusive of the ra If selected, the rack's elevation will display unit 1 at the top of the rack. (Most racks use ascending numbering, with unit 1 assigned to the bottommost position.) +### Airflow + +The direction in which air circulates through the rack for cooling. diff --git a/netbox/dcim/api/serializers_/devicetypes.py b/netbox/dcim/api/serializers_/devicetypes.py index a755247db10..cda73886285 100644 --- a/netbox/dcim/api/serializers_/devicetypes.py +++ b/netbox/dcim/api/serializers_/devicetypes.py @@ -62,13 +62,27 @@ class Meta: class ModuleTypeSerializer(NetBoxModelSerializer): - manufacturer = ManufacturerSerializer(nested=True) - weight_unit = ChoiceField(choices=WeightUnitChoices, allow_blank=True, required=False, allow_null=True) + manufacturer = ManufacturerSerializer( + nested=True + ) + weight_unit = ChoiceField( + choices=WeightUnitChoices, + allow_blank=True, + required=False, + allow_null=True + ) + airflow = ChoiceField( + choices=ModuleAirflowChoices, + allow_blank=True, + required=False, + allow_null=True + ) class Meta: model = ModuleType fields = [ - 'id', 'url', 'display_url', 'display', 'manufacturer', 'model', 'part_number', 'weight', 'weight_unit', - 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', + 'id', 'url', 'display_url', 'display', 'manufacturer', 'model', 'part_number', 'airflow', + 'weight', 'weight_unit', 'description', 'comments', 'tags', 'custom_fields', + 'created', 'last_updated', ] brief_fields = ('id', 'url', 'display', 'manufacturer', 'model', 'description') diff --git a/netbox/dcim/api/serializers_/racks.py b/netbox/dcim/api/serializers_/racks.py index 4fb96e08c58..17c1c174e42 100644 --- a/netbox/dcim/api/serializers_/racks.py +++ b/netbox/dcim/api/serializers_/racks.py @@ -64,14 +64,19 @@ class RackTypeSerializer(RackBaseSerializer): manufacturer = ManufacturerSerializer( nested=True ) + airflow = ChoiceField( + choices=RackAirflowChoices, + allow_blank=True, + required=False + ) class Meta: model = RackType fields = [ 'id', 'url', 'display_url', 'display', 'manufacturer', 'name', 'slug', 'description', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'weight', - 'max_weight', 'weight_unit', 'mounting_depth', 'description', 'comments', 'tags', 'custom_fields', - 'created', 'last_updated', + 'max_weight', 'weight_unit', 'mounting_depth', 'airflow', 'description', 'comments', 'tags', + 'custom_fields', 'created', 'last_updated', ] brief_fields = ('id', 'url', 'display', 'manufacturer', 'name', 'slug', 'description') @@ -95,6 +100,11 @@ class RackSerializer(RackBaseSerializer): choices=RackStatusChoices, required=False ) + airflow = ChoiceField( + choices=RackAirflowChoices, + allow_blank=True, + required=False + ) role = RackRoleSerializer( nested=True, required=False, @@ -124,7 +134,7 @@ class Meta: 'id', 'url', 'display_url', 'display', 'name', 'facility_id', 'site', 'location', 'tenant', 'status', 'role', 'serial', 'asset_tag', 'rack_type', 'form_factor', 'width', 'u_height', 'starting_unit', 'weight', 'max_weight', 'weight_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', - 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', + 'airflow', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'powerfeed_count', ] brief_fields = ('id', 'url', 'display', 'name', 'description', 'device_count') diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 464c396ffaa..3575aeeec3b 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -127,6 +127,17 @@ class RackElevationDetailRenderChoices(ChoiceSet): ) +class RackAirflowChoices(ChoiceSet): + + AIRFLOW_FRONT_TO_REAR = 'front-to-rear' + AIRFLOW_REAR_TO_FRONT = 'rear-to-front' + + CHOICES = ( + (AIRFLOW_FRONT_TO_REAR, _('Front to rear')), + (AIRFLOW_REAR_TO_FRONT, _('Rear to front')), + ) + + # # DeviceTypes # @@ -224,6 +235,25 @@ class ModuleStatusChoices(ChoiceSet): ] +class ModuleAirflowChoices(ChoiceSet): + + AIRFLOW_FRONT_TO_REAR = 'front-to-rear' + AIRFLOW_REAR_TO_FRONT = 'rear-to-front' + AIRFLOW_LEFT_TO_RIGHT = 'left-to-right' + AIRFLOW_RIGHT_TO_LEFT = 'right-to-left' + AIRFLOW_SIDE_TO_REAR = 'side-to-rear' + AIRFLOW_PASSIVE = 'passive' + + CHOICES = ( + (AIRFLOW_FRONT_TO_REAR, _('Front to rear')), + (AIRFLOW_REAR_TO_FRONT, _('Rear to front')), + (AIRFLOW_LEFT_TO_RIGHT, _('Left to right')), + (AIRFLOW_RIGHT_TO_LEFT, _('Right to left')), + (AIRFLOW_SIDE_TO_REAR, _('Side to rear')), + (AIRFLOW_PASSIVE, _('Passive')), + ) + + # # ConsolePorts # diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 7159efb4003..b5f4cd65707 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -312,7 +312,7 @@ class Meta: model = RackType fields = ( 'id', 'name', 'slug', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', - 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description', + 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description', ) def search(self, queryset, name, value): @@ -413,7 +413,8 @@ class Meta: model = Rack fields = ( 'id', 'name', 'facility_id', 'asset_tag', 'u_height', 'starting_unit', 'desc_units', 'outer_width', - 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description', + 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', + 'description', ) def search(self, queryset, name, value): @@ -698,7 +699,7 @@ class ModuleTypeFilterSet(NetBoxModelFilterSet): class Meta: model = ModuleType - fields = ('id', 'model', 'part_number', 'weight', 'weight_unit', 'description') + fields = ('id', 'model', 'part_number', 'airflow', 'weight', 'weight_unit', 'description') def search(self, queryset, name, value): if not value.strip(): diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index 4a017dd4686..bc0f0bd71d7 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -268,6 +268,11 @@ class RackTypeBulkEditForm(NetBoxModelBulkEditForm): required=False, min_value=1 ) + airflow = forms.ChoiceField( + label=_('Airflow'), + choices=add_blank_choice(RackAirflowChoices), + required=False + ) weight = forms.DecimalField( label=_('Weight'), min_value=0, @@ -293,10 +298,8 @@ class RackTypeBulkEditForm(NetBoxModelBulkEditForm): model = RackType fieldsets = ( - FieldSet('manufacturer', 'description', 'form_factor', name=_('Rack Type')), + FieldSet('manufacturer', 'description', 'form_factor', 'width', 'u_height', 'airflow', name=_('Rack Type')), FieldSet( - 'width', - 'u_height', InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')), InlineFields('weight', 'max_weight', 'weight_unit', label=_('Weight')), 'mounting_depth', @@ -409,6 +412,11 @@ class RackBulkEditForm(NetBoxModelBulkEditForm): required=False, min_value=1 ) + airflow = forms.ChoiceField( + label=_('Airflow'), + choices=add_blank_choice(RackAirflowChoices), + required=False + ) weight = forms.DecimalField( label=_('Weight'), min_value=0, @@ -437,7 +445,7 @@ class RackBulkEditForm(NetBoxModelBulkEditForm): FieldSet('status', 'role', 'tenant', 'serial', 'asset_tag', 'description', name=_('Rack')), FieldSet('region', 'site_group', 'site', 'location', name=_('Location')), FieldSet( - 'form_factor', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', + 'form_factor', 'width', 'u_height', 'desc_units', 'airflow', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', name=_('Hardware') ), FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')), @@ -563,6 +571,11 @@ class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm): label=_('Part number'), required=False ) + airflow = forms.ChoiceField( + label=_('Airflow'), + choices=add_blank_choice(ModuleAirflowChoices), + required=False + ) weight = forms.DecimalField( label=_('Weight'), min_value=0, @@ -584,7 +597,11 @@ class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm): model = ModuleType fieldsets = ( FieldSet('manufacturer', 'part_number', 'description', name=_('Module Type')), - FieldSet('weight', 'weight_unit', name=_('Weight')), + FieldSet( + 'airflow', + InlineFields('weight', 'max_weight', 'weight_unit', label=_('Weight')), + name=_('Chassis') + ), ) nullable_fields = ('part_number', 'weight', 'weight_unit', 'description', 'comments') diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 7f7efecf61f..785b4fb42a6 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -206,6 +206,12 @@ class RackTypeImportForm(NetBoxModelImportForm): required=False, help_text=_('Unit for outer dimensions') ) + airflow = CSVChoiceField( + label=_('Airflow'), + choices=RackAirflowChoices, + required=False, + help_text=_('Airflow direction') + ) weight_unit = CSVChoiceField( label=_('Weight unit'), choices=WeightUnitChoices, @@ -217,8 +223,8 @@ class Meta: model = RackType fields = ( 'manufacturer', 'name', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', - 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', - 'description', 'comments', 'tags', + 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'weight', 'max_weight', + 'weight_unit', 'description', 'comments', 'tags', ) def __init__(self, data=None, *args, **kwargs): @@ -273,6 +279,12 @@ class RackImportForm(NetBoxModelImportForm): required=False, help_text=_('Unit for outer dimensions') ) + airflow = CSVChoiceField( + label=_('Airflow'), + choices=RackAirflowChoices, + required=False, + help_text=_('Airflow direction') + ) weight_unit = CSVChoiceField( label=_('Weight unit'), choices=WeightUnitChoices, @@ -284,8 +296,8 @@ class Meta: model = Rack fields = ( 'site', 'location', 'name', 'facility_id', 'tenant', 'status', 'role', 'form_factor', 'serial', 'asset_tag', - 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', - 'max_weight', 'weight_unit', 'description', 'comments', 'tags', + 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', + 'weight', 'max_weight', 'weight_unit', 'description', 'comments', 'tags', ) def __init__(self, data=None, *args, **kwargs): @@ -400,6 +412,12 @@ class ModuleTypeImportForm(NetBoxModelImportForm): queryset=Manufacturer.objects.all(), to_field_name='name' ) + airflow = CSVChoiceField( + label=_('Airflow'), + choices=ModuleAirflowChoices, + required=False, + help_text=_('Airflow direction') + ) weight = forms.DecimalField( label=_('Weight'), required=False, @@ -414,7 +432,7 @@ class ModuleTypeImportForm(NetBoxModelImportForm): class Meta: model = ModuleType - fields = ['manufacturer', 'model', 'part_number', 'description', 'weight', 'weight_unit', 'comments', 'tags'] + fields = ['manufacturer', 'model', 'part_number', 'description', 'airflow', 'weight', 'weight_unit', 'comments', 'tags'] class DeviceRoleImportForm(NetBoxModelImportForm): diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 5d16a7b39c8..c8124aa1112 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -267,6 +267,11 @@ class RackBaseFilterForm(NetBoxModelFilterSetForm): choices=BOOLEAN_WITH_BLANK_CHOICES ) ) + airflow = forms.MultipleChoiceField( + label=_('Airflow'), + choices=add_blank_choice(RackAirflowChoices), + required=False + ) weight = forms.DecimalField( label=_('Weight'), required=False, @@ -288,7 +293,7 @@ class RackTypeFilterForm(RackBaseFilterForm): model = RackType fieldsets = ( FieldSet('q', 'filter_id', 'tag'), - FieldSet('form_factor', 'width', 'u_height', name=_('Rack Type')), + FieldSet('form_factor', 'width', 'u_height', 'airflow', name=_('Rack Type')), FieldSet('starting_unit', 'desc_units', name=_('Numbering')), FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')), ) @@ -308,7 +313,7 @@ class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, RackBaseFilterFo FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')), FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), FieldSet('status', 'role_id', 'serial', 'asset_tag', name=_('Rack')), - FieldSet('form_factor', 'width', 'u_height', name=_('Rack Type')), + FieldSet('form_factor', 'width', 'u_height', 'airflow', name=_('Rack Type')), FieldSet('starting_unit', 'desc_units', name=_('Numbering')), FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')), FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), @@ -578,7 +583,7 @@ class ModuleTypeFilterForm(NetBoxModelFilterSetForm): model = ModuleType fieldsets = ( FieldSet('q', 'filter_id', 'tag'), - FieldSet('manufacturer_id', 'part_number', name=_('Hardware')), + FieldSet('manufacturer_id', 'part_number', 'airflow', name=_('Hardware')), FieldSet( 'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces', 'pass_through_ports', name=_('Components') @@ -638,6 +643,11 @@ class ModuleTypeFilterForm(NetBoxModelFilterSetForm): ) ) tag = TagFilterField(model) + airflow = forms.MultipleChoiceField( + label=_('Airflow'), + choices=add_blank_choice(ModuleAirflowChoices), + required=False + ) weight = forms.DecimalField( label=_('Weight'), required=False diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index bff0d8c462d..30c1cf3b99d 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -211,7 +211,7 @@ class RackTypeForm(NetBoxModelForm): slug = SlugField() fieldsets = ( - FieldSet('manufacturer', 'name', 'slug', 'description', 'form_factor', 'tags', name=_('Rack Type')), + FieldSet('manufacturer', 'name', 'slug', 'description', 'form_factor', 'airflow', 'tags', name=_('Rack Type')), FieldSet( 'width', 'u_height', InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')), @@ -226,7 +226,7 @@ class Meta: fields = [ 'manufacturer', 'name', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', - 'description', 'comments', 'tags', + 'airflow', 'description', 'comments', 'tags', ] @@ -268,8 +268,8 @@ class Meta: fields = [ 'site', 'location', 'name', 'facility_id', 'tenant_group', 'tenant', 'status', 'role', 'serial', 'asset_tag', 'rack_type', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', - 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description', - 'comments', 'tags', + 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', + 'description', 'comments', 'tags', ] def __init__(self, *args, **kwargs): @@ -290,7 +290,7 @@ def __init__(self, *args, **kwargs): self.fieldsets = ( *self.fieldsets, FieldSet( - 'form_factor', 'width', 'starting_unit', 'u_height', + 'form_factor', 'width', 'starting_unit', 'u_height', 'airflow', InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')), InlineFields('weight', 'max_weight', 'weight_unit', label=_('Weight')), 'mounting_depth', 'desc_units', name=_('Dimensions') @@ -398,13 +398,14 @@ class ModuleTypeForm(NetBoxModelForm): fieldsets = ( FieldSet('manufacturer', 'model', 'part_number', 'description', 'tags', name=_('Module Type')), - FieldSet('weight', 'weight_unit', name=_('Weight')) + FieldSet('airflow', 'weight', 'weight_unit', name=_('Chassis')) ) class Meta: model = ModuleType fields = [ - 'manufacturer', 'model', 'part_number', 'weight', 'weight_unit', 'description', 'comments', 'tags', + 'manufacturer', 'model', 'part_number', 'airflow', 'weight', 'weight_unit', 'description', + 'comments', 'tags', ] diff --git a/netbox/dcim/migrations/0189_moduletype_airflow_rack_airflow_racktype_airflow.py b/netbox/dcim/migrations/0189_moduletype_airflow_rack_airflow_racktype_airflow.py new file mode 100644 index 00000000000..370df90e863 --- /dev/null +++ b/netbox/dcim/migrations/0189_moduletype_airflow_rack_airflow_racktype_airflow.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0.7 on 2024-07-25 07:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0188_racktype'), + ] + + operations = [ + migrations.AddField( + model_name='moduletype', + name='airflow', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='rack', + name='airflow', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='racktype', + name='airflow', + field=models.CharField(blank=True, max_length=50), + ), + ] diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index abc9e0b0857..a790cceef8b 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -388,8 +388,14 @@ class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin): blank=True, help_text=_('Discrete part number (optional)') ) + airflow = models.CharField( + verbose_name=_('airflow'), + max_length=50, + choices=ModuleAirflowChoices, + blank=True + ) - clone_fields = ('manufacturer', 'weight', 'weight_unit',) + clone_fields = ('manufacturer', 'weight', 'weight_unit', 'airflow') prerequisite_models = ( 'dcim.Manufacturer', ) diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index e6487c7052e..cfa8f28bebd 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -53,6 +53,12 @@ class RackBase(WeightMixin, PrimaryModel): verbose_name=_('width'), help_text=_('Rail-to-rail width') ) + airflow = models.CharField( + verbose_name=_('airflow'), + max_length=50, + choices=RackAirflowChoices, + blank=True + ) # Numbering u_height = models.PositiveSmallIntegerField( @@ -232,10 +238,10 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): Each Rack is assigned to a Site and (optionally) a Location. """ # Fields which cannot be set locally if a RackType is assigned - RACKTYPE_FIELDS = [ - 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', - 'mounting_depth', 'weight', 'weight_unit', 'max_weight' - ] + RACKTYPE_FIELDS = ( + 'form_factor', 'width', 'airflow', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', + 'outer_unit', 'mounting_depth', 'weight', 'weight_unit', 'max_weight', + ) rack_type = models.ForeignKey( to='dcim.RackType', @@ -316,8 +322,8 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): ) clone_fields = ( - 'site', 'location', 'tenant', 'status', 'role', 'form_factor', 'width', 'u_height', 'desc_units', 'outer_width', - 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', + 'site', 'location', 'tenant', 'status', 'role', 'form_factor', 'width', 'airflow', 'u_height', 'desc_units', + 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', ) prerequisite_models = ( 'dcim.Site', diff --git a/netbox/dcim/tables/modules.py b/netbox/dcim/tables/modules.py index 0cd9e438ee9..5b06e08b28b 100644 --- a/netbox/dcim/tables/modules.py +++ b/netbox/dcim/tables/modules.py @@ -40,7 +40,7 @@ class ModuleTypeTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = ModuleType fields = ( - 'pk', 'id', 'model', 'manufacturer', 'part_number', 'weight', 'description', 'comments', 'tags', + 'pk', 'id', 'model', 'manufacturer', 'part_number', 'airflow', 'weight', 'description', 'comments', 'tags', ) default_columns = ( 'pk', 'model', 'manufacturer', 'part_number', diff --git a/netbox/dcim/tables/racks.py b/netbox/dcim/tables/racks.py index d269681c5dc..064a5a43df1 100644 --- a/netbox/dcim/tables/racks.py +++ b/netbox/dcim/tables/racks.py @@ -92,8 +92,8 @@ class Meta(NetBoxTable.Meta): model = RackType fields = ( 'pk', 'id', 'name', 'manufacturer', 'form_factor', 'u_height', 'starting_unit', 'width', 'outer_width', - 'outer_depth', 'mounting_depth', 'weight', 'max_weight', 'description', 'comments', 'tags', 'created', - 'last_updated', + 'outer_depth', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'description', 'comments', 'tags', + 'created', 'last_updated', ) default_columns = ( 'pk', 'name', 'manufacturer', 'type', 'u_height', 'description', @@ -171,7 +171,7 @@ class Meta(NetBoxTable.Meta): fields = ( 'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'tenant_group', 'role', 'serial', 'asset_tag', 'form_factor', 'u_height', 'starting_unit', 'width', 'outer_width', 'outer_depth', - 'mounting_depth', 'weight', 'max_weight', 'comments', 'device_count', 'get_utilization', + 'mounting_depth', 'airflow', 'weight', 'max_weight', 'comments', 'device_count', 'get_utilization', 'get_power_utilization', 'description', 'contacts', 'tags', 'created', 'last_updated', ) default_columns = ( diff --git a/netbox/templates/dcim/moduletype.html b/netbox/templates/dcim/moduletype.html index 77feece972b..3ddeea89e0b 100644 --- a/netbox/templates/dcim/moduletype.html +++ b/netbox/templates/dcim/moduletype.html @@ -26,6 +26,12 @@
{% trans "Module Type" %}
{% trans "Description" %} {{ object.description|placeholder }} + + {% trans "Airflow" %} + + {{ object.get_airflow_display|placeholder }} + + {% trans "Weight" %} diff --git a/netbox/templates/dcim/rack.html b/netbox/templates/dcim/rack.html index 9bf2f1827eb..f69abe77acb 100644 --- a/netbox/templates/dcim/rack.html +++ b/netbox/templates/dcim/rack.html @@ -61,6 +61,10 @@
{% trans "Rack" %}
{% trans "Asset Tag" %} {{ object.asset_tag|placeholder }} + + {% trans "Airflow" %} + {{ object.get_airflow_display|placeholder }} + {% trans "Space Utilization" %} {% utilization_graph object.get_utilization %} diff --git a/netbox/templates/dcim/racktype.html b/netbox/templates/dcim/racktype.html index 0c82b13d190..c4e44514602 100644 --- a/netbox/templates/dcim/racktype.html +++ b/netbox/templates/dcim/racktype.html @@ -24,6 +24,10 @@
{% trans "Rack Type" %}
{% trans "Description" %} {{ object.description|placeholder }} + + {% trans "Airflow" %} + {{ object.get_airflow_display|placeholder }} + {% include 'dcim/inc/panels/racktype_dimensions.html' %}