common/recipes-rest/rest-api/files/redfish_chassis.py (122 lines of code) (raw):
import typing as t
import pal
import redfish_chassis_helper
import redfish_sensors
import rest_pal_legacy
from aiohttp import web
from common_utils import dumps_bytestr, parse_expand_level
from redfish_base import validate_keys
class FruNotFoundError(Exception):
pass
def _get_fru_name_from_server_id(server_name: str) -> t.Optional[str]:
"Returns the server name for an fru that their routes include"
slot_name = None
# if server_name is 1, we return None, as
# get_fru_info_helper handles None as all non slot_ frus
if server_name != "1":
if rest_pal_legacy.pal_get_num_slots() > 1:
if server_name.startswith("accelerator"):
accel_index = int(server_name.replace("accelerator", ""))
accelerators = redfish_chassis_helper._get_accelerator_list()
return accelerators[accel_index]
else:
# replace server with slot
slot_name = server_name.replace("server", "slot")
else:
raise ValueError(
"{server_name} server_name is invalid for slingle slot servers".format(
server_name=server_name
)
)
return slot_name
async def get_chassis(request: web.Request) -> web.Response:
expand_level = parse_expand_level(request)
members_json = await get_chassis_members_json(expand_level)
body = {
"@odata.context": "/redfish/v1/$metadata#ChassisCollection.ChassisCollection",
"@odata.id": "/redfish/v1/Chassis",
"@odata.type": "#ChassisCollection.ChassisCollection",
"Name": "Chassis Collection",
"Members@odata.count": len(members_json),
"Members": members_json,
}
await validate_keys(body)
return web.json_response(body, dumps=dumps_bytestr)
def get_chassis_url_for_server_name(server_name: str) -> t.Dict[str, str]:
return {"@odata.id": "/redfish/v1/Chassis/" + server_name}
async def _get_chassis_child_for_server_name(
server_name: str, expand_level: int
) -> t.Dict[str, t.Any]:
if expand_level > 0:
return await get_chassis_member_for_fru(server_name, expand_level - 1)
else:
return get_chassis_url_for_server_name(server_name)
async def get_chassis_members_json(expand_level: int) -> t.List[t.Dict[str, t.Any]]:
chassis_members = [await _get_chassis_child_for_server_name("1", expand_level)]
if (
redfish_chassis_helper.is_libpal_supported()
and "slot4" in pal.pal_fru_name_map()
):
# return chassis members for a multisled platform
fru_name_map = pal.pal_fru_name_map()
asics = 0
for fru_name, fruid in fru_name_map.items():
if pal.pal_is_fru_prsnt(fruid):
child_name = None
fru_capabilities = pal.pal_get_fru_capability(fruid)
if (
pal.FruCapability.FRU_CAPABILITY_SERVER in fru_capabilities
and "slot" in fru_name
):
child_name = fru_name.replace("slot", "server")
if (
pal.FruCapability.FRU_CAPABILITY_HAS_DEVICE in fru_capabilities
and pal.FruCapability.FRU_CAPABILITY_SERVER not in fru_capabilities
):
child_name = "accelerator" + str(asics)
asics += 1
if child_name:
chassis_members.append(
await _get_chassis_child_for_server_name(
child_name, expand_level
)
)
return chassis_members
async def get_chassis_member(request: web.Request) -> web.Response:
server_name = request.match_info["fru_name"]
expand_level = parse_expand_level(request)
try:
body = await get_chassis_member_for_fru(server_name, expand_level)
return web.json_response(body, dumps=dumps_bytestr)
except FruNotFoundError:
return web.json_response(status=404)
async def get_chassis_member_for_fru(
server_name: str, expand_level: int
) -> web.Response:
try:
fru_name = _get_fru_name_from_server_id(server_name)
except ValueError:
raise FruNotFoundError()
frus_info_list = await redfish_chassis_helper.get_fru_info_helper(fru_name)
fru = frus_info_list[0]
if expand_level > 0:
sensors = await redfish_sensors.get_redfish_sensors_for_server_name(
server_name, expand_level - 1
)
else:
sensors = {"@odata.id": "/redfish/v1/Chassis/{}/Sensors".format(server_name)}
if fru_name is None:
fru_name = "Computer System Chassis"
body = {
"@odata.context": "/redfish/v1/$metadata#Chassis.Chassis",
"@odata.id": "/redfish/v1/Chassis/{}".format(server_name),
"@odata.type": "#Chassis.v1_15_0.Chassis",
"Id": "1",
"Name": fru_name,
"ChassisType": "RackMount",
"PowerState": "On",
"Manufacturer": fru.manufacturer,
"Model": fru.model,
"SerialNumber": fru.serial_number,
"Status": {"State": "Enabled", "Health": "OK"},
"Sensors": sensors,
"Links": {"ManagedBy": [{"@odata.id": "/redfish/v1/Managers/1"}]},
}
await validate_keys(body)
return body