* Fixes #22447: Pre-release QA Add the missing `cooling_outflow` GraphQL filter on CoolingIntake, so an intake can be filtered by its upstream outflow. CoolingOutflow already exposes the reverse `cooling_intake` filter and the REST filterset already carries `cooling_outflow_id`; the GraphQL intake filter was the only side missing it. Correct the CoolingIntake docstring, which referenced a direct CoolingFeed relationship that does not exist. The serving feed is derived from the device's rack, not stored on the intake. * Fixes #22447: Pre-release QA (filter form + table parity) Address the same-class gaps surfaced in review, all mirror images of the intake/outflow filter parity already fixed: Add the `cooling_intake_id` filter to CoolingOutflowFilterForm and CoolingOutflowTemplateFilterForm. The underlying filtersets already carried `cooling_intake_id` and GraphQL supported it, but the list-view filter panel did not expose it, so an outflow could not be filtered by its downstream intake from the UI. Add `cooling_outflow` to the default columns on CoolingIntakeTable and DeviceCoolingIntakeTable. The outflow tables already default-show `cooling_intake`; the intake tables hid the reverse, so the same relationship displayed inconsistently between the two sides. Note in the CoolingIntake docstring why CoolingIntakeTemplate has no upstream-outflow field: an intake's outflow normally lives on a different device (a CDU), which a device-type template cannot express.
This commit is contained in:
parent
bfb665ccb9
commit
feffda99d7
|
|
@ -1940,7 +1940,7 @@ class CoolingOutflowFilterForm(DeviceComponentFilterForm):
|
|||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet(
|
||||
'name', 'label', 'type', 'diameter', 'diameter_unit', name=_('Attributes')
|
||||
'name', 'label', 'type', 'diameter', 'diameter_unit', 'cooling_intake_id', name=_('Attributes')
|
||||
),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||
FieldSet(
|
||||
|
|
@ -1963,6 +1963,11 @@ class CoolingOutflowFilterForm(DeviceComponentFilterForm):
|
|||
choices=DiameterUnitChoices,
|
||||
required=False
|
||||
)
|
||||
cooling_intake_id = DynamicModelMultipleChoiceField(
|
||||
label=_('Cooling intake'),
|
||||
queryset=CoolingIntake.objects.all(),
|
||||
required=False
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
|
|
@ -1970,7 +1975,7 @@ class CoolingOutflowTemplateFilterForm(ModularDeviceComponentTemplateFilterForm)
|
|||
model = CoolingOutflowTemplate
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('name', 'label', 'type', 'diameter', 'diameter_unit', name=_('Attributes')),
|
||||
FieldSet('name', 'label', 'type', 'diameter', 'diameter_unit', 'cooling_intake_id', name=_('Attributes')),
|
||||
FieldSet('device_type_id', 'module_type_id', name=_('Device')),
|
||||
)
|
||||
type = forms.MultipleChoiceField(
|
||||
|
|
@ -1987,6 +1992,11 @@ class CoolingOutflowTemplateFilterForm(ModularDeviceComponentTemplateFilterForm)
|
|||
choices=DiameterUnitChoices,
|
||||
required=False
|
||||
)
|
||||
cooling_intake_id = DynamicModelMultipleChoiceField(
|
||||
label=_('Cooling intake'),
|
||||
queryset=CoolingIntakeTemplate.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
|
||||
class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
|
|
|
|||
|
|
@ -1068,6 +1068,10 @@ class CoolingIntakeFilter(ModularComponentFilterMixin, NetBoxModelFilter):
|
|||
max_flow_unit: BaseFilterLookup[
|
||||
Annotated['FlowRateUnitEnum', strawberry.lazy('dcim.graphql.enums')]
|
||||
] | None = strawberry_django.filter_field()
|
||||
cooling_outflow: Annotated['CoolingOutflowFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
|
||||
strawberry_django.filter_field()
|
||||
)
|
||||
cooling_outflow_id: ID | None = strawberry_django.filter_field()
|
||||
|
||||
|
||||
@register_filter(models.CoolingIntakeTemplate, lookups=True)
|
||||
|
|
|
|||
|
|
@ -700,7 +700,12 @@ class CoolingIntake(
|
|||
):
|
||||
"""
|
||||
A coolant intake port within a Device (e.g. a server cold-plate inlet or CDU intake). A
|
||||
CoolingIntake is supplied by an upstream CoolingOutflow or CoolingFeed.
|
||||
CoolingIntake is supplied by an upstream CoolingOutflow. The serving CoolingFeed is
|
||||
derived from the Device's Rack rather than referenced directly.
|
||||
|
||||
Unlike CoolingOutflow (whose parent intake is on the same Device and can therefore be
|
||||
templated), an intake's upstream outflow typically lives on a different Device (e.g. a
|
||||
CDU), so there is deliberately no upstream-outflow field on CoolingIntakeTemplate.
|
||||
"""
|
||||
type = models.CharField(
|
||||
verbose_name=_('type'),
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ class CoolingIntakeTable(ModularDeviceComponentTable):
|
|||
)
|
||||
default_columns = (
|
||||
'pk', 'name', 'device', 'label', 'type', 'diameter', 'max_flow',
|
||||
'description',
|
||||
'cooling_outflow', 'description',
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ class DeviceCoolingIntakeTable(CoolingIntakeTable):
|
|||
)
|
||||
default_columns = (
|
||||
'pk', 'name', 'label', 'type', 'diameter', 'max_flow',
|
||||
'description',
|
||||
'cooling_outflow', 'description',
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue