Add missing attribute of Thermal in RSD 2.2

Change-Id: Ie268a066716ab8b604e578e2558a59bb2fb24b65
This commit is contained in:
Lin Yang 2019-05-29 23:38:17 -07:00
parent bf06a290b4
commit 85afe50d6a
5 changed files with 254 additions and 0 deletions

View File

@ -17,6 +17,7 @@ from sushy import utils
from rsd_lib.resources.v2_1.chassis import chassis from rsd_lib.resources.v2_1.chassis import chassis
from rsd_lib.resources.v2_2.chassis import power from rsd_lib.resources.v2_2.chassis import power
from rsd_lib.resources.v2_2.chassis import thermal
class Chassis(chassis.Chassis): class Chassis(chassis.Chassis):
@ -43,3 +44,17 @@ class Chassis(chassis.Chassis):
utils.get_sub_resource_path_by(self, "Power"), utils.get_sub_resource_path_by(self, "Power"),
redfish_version=self.redfish_version, redfish_version=self.redfish_version,
) )
@property
@utils.cache_it
def thermal(self):
"""Property to provide reference to `Thermal` instance
It is calculated once when it is queried for the first time. On
refresh, this property is reset.
"""
return thermal.Thermal(
self._conn,
utils.get_sub_resource_path_by(self, "Thermal"),
redfish_version=self.redfish_version,
)

View File

@ -0,0 +1,55 @@
# Copyright 2019 Intel, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from sushy.resources import base
from rsd_lib.resources.v2_1.chassis import thermal
from rsd_lib import utils as rsd_lib_utils
class IntelRackScaleField(base.CompositeField):
"""Thermal field
Extended Thermal resource.
"""
volumetric_airflow_cfm = base.Field(
"VolumetricAirflowCfm", adapter=rsd_lib_utils.num_or_none
)
"""Volumetric Air Flow measured in Cubic Feet per Minute"""
desired_speed_pwm = base.Field(
"DesiredSpeedPwm", adapter=rsd_lib_utils.num_or_none
)
"""This property represent desired speed of all FANs in current chassis as
percentage of max speed.
"""
class OemField(base.CompositeField):
intel_rackscale = IntelRackScaleField("Intel_RackScale")
"""Intel Rack Scale Design specific properties."""
class Thermal(thermal.Thermal):
"""Thermal resource class
This is the schema definition for the Thermal properties. It
represents the properties for Temperature and Cooling.
"""
oem = OemField("Oem")
"""Oem specific properties."""

View File

@ -0,0 +1,92 @@
{
"@odata.context": "/redfish/v1/$metadata#Thermal.Thermal",
"@odata.id": "/redfish/v1/Chassis/Rack1/Thermal",
"@odata.type": "#Thermal.v1_1_0.Thermal",
"Id": "Thermal",
"Name": "ThermalName",
"Description": "Thermal Subsystem",
"Temperatures": [
{
"@odata.id": "/redfish/v1/Chassis/Rack1/Thermal#/Temperatures/0",
"MemberId": "0",
"Name": "Drawer inlet Temp",
"SensorNumber": 42,
"Status": {
"State": "Enabled",
"Health": "OK"
},
"ReadingCelsius": 21,
"UpperThresholdNonCritical": 42,
"UpperThresholdCritical": 42,
"UpperThresholdFatal": 42,
"LowerThresholdNonCritical": 42,
"LowerThresholdCritical": 5,
"LowerThresholdFatal": 42,
"MinReadingRangeTemp": 0,
"MaxReadingRangeTemp": 200,
"PhysicalContext": "Intake",
"RelatedItem": [
{"@odata.id": "/redfish/v1/Chassis/Drawer1" }
]
}
],
"Fans": [
{
"@odata.id": "/redfish/v1/Chassis/Rack1/Thermal#/Fans/0",
"MemberId": "0",
"Name": "BaseBoard System Fan",
"PhysicalContext": "Backplane",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"Reading": 2100,
"ReadingUnits": "RPM",
"UpperThresholdNonCritical": 42,
"UpperThresholdCritical": 4200,
"UpperThresholdFatal": 42,
"LowerThresholdNonCritical": 42,
"LowerThresholdCritical": 5,
"LowerThresholdFatal": 42,
"MinReadingRange": 0,
"MaxReadingRange": 5000,
"Redundancy" : [
{
"@odata.id": "/redfish/v1/Chassis/Rack1/Thermal#/Redundancy/0",
"Name": "Fans Redundancy Group 1"
}
],
"RelatedItem" : [
{
"@odata.id": "/redfish/v1/Chassis/Rack1"
}
]
}
],
"Redundancy": [
{
"@odata.id": "/redfish/v1/Chassis/Rack1/Thermal#/Redundancy/0",
"MemberId": "0",
"Name": "BaseBoard System Fans",
"RedundancyEnabled": false,
"RedundancySet": [
{
"@odata.id": "/redfish/v1/Chassis/1/Thermal#/Fans/0"
}
],
"Mode": "N+m",
"Status": {
"State": "Disabled",
"Health": "OK"
},
"MinNumNeeded": 1,
"MaxNumSupported": 2
}
],
"Oem": {
"Intel_RackScale": {
"VolumetricAirflowCfm": 12,
"DesiredSpeedPwm": 80
}
}
}

View File

@ -18,6 +18,7 @@ import testtools
from rsd_lib.resources.v2_2.chassis import chassis from rsd_lib.resources.v2_2.chassis import chassis
from rsd_lib.resources.v2_2.chassis import power from rsd_lib.resources.v2_2.chassis import power
from rsd_lib.resources.v2_2.chassis import thermal
class ChassisTestCase(testtools.TestCase): class ChassisTestCase(testtools.TestCase):
@ -73,3 +74,49 @@ class ChassisTestCase(testtools.TestCase):
self.conn.get.return_value.json.return_value = json.loads(f.read()) self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN | # | WHEN & THEN |
self.assertIsInstance(self.chassis_inst.power, power.Power) self.assertIsInstance(self.chassis_inst.power, power.Power)
def test_thermal(self):
# | GIVEN |
self.conn.get.return_value.json.reset_mock()
with open(
"rsd_lib/tests/unit/json_samples/v2_2/thermal.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN |
actual_thermal = self.chassis_inst.thermal
# | THEN |
self.assertIsInstance(actual_thermal, thermal.Thermal)
self.conn.get.return_value.json.assert_called_once_with()
# reset mock
self.conn.get.return_value.json.reset_mock()
# | WHEN & THEN |
# tests for same object on invoking subsequently
self.assertIs(actual_thermal, self.chassis_inst.thermal)
self.conn.get.return_value.json.assert_not_called()
def test_thermal_on_refresh(self):
# | GIVEN |
with open(
"rsd_lib/tests/unit/json_samples/v2_2/thermal.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(self.chassis_inst.thermal, thermal.Thermal)
# On refreshing the chassis instance...
with open(
"rsd_lib/tests/unit/json_samples/v2_2/chassis.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.chassis_inst.invalidate()
self.chassis_inst.refresh(force=False)
# | GIVEN |
with open(
"rsd_lib/tests/unit/json_samples/v2_2/thermal.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(self.chassis_inst.thermal, thermal.Thermal)

View File

@ -0,0 +1,45 @@
# Copyright 2019 Intel, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import mock
import testtools
from rsd_lib.resources.v2_2.chassis import thermal
class ThermalTestCase(testtools.TestCase):
def setUp(self):
super(ThermalTestCase, self).setUp()
self.conn = mock.Mock()
with open(
"rsd_lib/tests/unit/json_samples/v2_2/thermal.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.thermal = thermal.Thermal(
self.conn,
"/redfish/v1/Chassis/Rack1/Thermal",
redfish_version="1.1.0",
)
def test__parse_attributes(self):
self.thermal._parse_attributes()
self.assertEqual(
12, self.thermal.oem.intel_rackscale.volumetric_airflow_cfm
)
self.assertEqual(
80, self.thermal.oem.intel_rackscale.desired_speed_pwm
)