summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Liu <liuxiwei@inspur.com>2022-10-05 11:27:52 +0300
committerLakshmi Yadlapati <lakshmiy@us.ibm.com>2023-05-18 17:10:08 +0300
commit00ef5dc6d410ab83302529f23919b3d91a35b5e3 (patch)
treec9fbcbb028401841bcebca9c1bee68afb2dace37
parent78e3900f9156f056d7f9f5c9e2b6ae0abd2c6b0f (diff)
downloadbmcweb-00ef5dc6d410ab83302529f23919b3d91a35b5e3.tar.xz
Implements PowerSupply schema
This commit implements the Redfish PowerSupply schema and populates the PowerSupplyCollection members. The PowerSupply is a grandchild of the PowerSubsystem. PowerSupply is part of the new PowerSubsystme/ThermalSubsystem schemas, released in Redfish Version 2020.4. This commit only displays the PowerSupplies in the chassis with common fields like odata.id, odata.type, Id, and Name. Future commits will add PowerSupply properties like FirmwareVersion, LocationIndicatorActive, Status, and Asset information like SerialNumber, PartNumber, Model. This commit looks at the powered_by association from Inventory.Item.Chassis to Inventory.Item.PowerSupply to find a PowerSupply [1]. [1] https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/58609 Tested: Validator passes 1. curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Chassis/chassis/PowerSubsystem/ PowerSupplies/powersupply0 { "@odata.id": "/redfish/v1/Chassis/chassis/PowerSubsystem/ PowerSupplies/powersupply0", "@odata.type": "#PowerSupply.v1_5_0.PowerSupply", "Id": "powersupply0", "Name": "powersupply0" } 2. Bad power supply name curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Chassis/chassis/PowerSubsystem/ PowerSupplies/ERROR { "error": { "@Message.ExtendedInfo": [ { "@odata.type": "#Message.v1_1_1.Message", "Message": "The requested resource of type PowerSupply named 'ERROR' was not found.", "MessageArgs": [ "PowerSupply", "ERROR" ], "MessageId": "Base.1.13.0.ResourceNotFound", "MessageSeverity": "Critical", "Resolution": "Provide a valid resource identifier and resubmit the request." } ], "code": "Base.1.13.0.ResourceNotFound", "message": "The requested resource of type PowerSupply named 'ERROR' was not found." } } Signed-off-by: George Liu <liuxiwei@inspur.com> Change-Id: I7b7c0e40c090a3f253f1a778edbe36be9b4317b0 Signed-off-by: Lakshmi Yadlapati <lakshmiy@us.ibm.com>
-rw-r--r--Redfish.md6
-rw-r--r--redfish-core/include/redfish.hpp1
-rw-r--r--redfish-core/lib/power_supply.hpp170
3 files changed, 171 insertions, 6 deletions
diff --git a/Redfish.md b/Redfish.md
index 9fec4ed4b6..1cdce980aa 100644
--- a/Redfish.md
+++ b/Redfish.md
@@ -371,6 +371,12 @@ Fields common to all schemas
##### PowerSupplies
- Description
+- Members
+- Members@odata.count
+
+#### /redfish/v1/Chassis/{ChassisId}/PowerSubsystem/PowerSupplies/{PowerSupplyId}
+
+##### PowerSupply
### /redfish/v1/EventService/
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index ce09531c42..2bf0f4578e 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -91,6 +91,7 @@ class RedfishService
#ifdef BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM
requestRoutesEnvironmentMetrics(app);
requestRoutesPowerSubsystem(app);
+ requestRoutesPowerSupply(app);
requestRoutesPowerSupplyCollection(app);
requestRoutesThermalSubsystem(app);
#endif
diff --git a/redfish-core/lib/power_supply.hpp b/redfish-core/lib/power_supply.hpp
index 430a29a632..ebc61c50ab 100644
--- a/redfish-core/lib/power_supply.hpp
+++ b/redfish-core/lib/power_supply.hpp
@@ -15,13 +15,26 @@
namespace redfish
{
-inline void updatePowerSupplyList(
- const std::shared_ptr<bmcweb::AsyncResp>& /* asyncResp */,
- const std::string& /* chassisId */,
- const std::string& /* powerSupplyPath */)
+inline void
+ updatePowerSupplyList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId,
+ const std::string& powerSupplyPath)
{
- // TODO In order for the validator to pass, the Members property will be
- // implemented on the next commit
+ std::string powerSupplyName =
+ sdbusplus::message::object_path(powerSupplyPath).filename();
+ if (powerSupplyName.empty())
+ {
+ return;
+ }
+
+ nlohmann::json item = nlohmann::json::object();
+ item["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
+ powerSupplyName);
+
+ nlohmann::json& powerSupplyList = asyncResp->res.jsonValue["Members"];
+ powerSupplyList.emplace_back(std::move(item));
+ asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size();
}
inline void
@@ -123,4 +136,149 @@ inline void requestRoutesPowerSupplyCollection(App& app)
std::bind_front(handlePowerSupplyCollectionGet, std::ref(app)));
}
+inline bool checkPowerSupplyId(const std::string& powerSupplyPath,
+ const std::string& powerSupplyId)
+{
+ std::string powerSupplyName =
+ sdbusplus::message::object_path(powerSupplyPath).filename();
+
+ return !(powerSupplyName.empty() || powerSupplyName != powerSupplyId);
+}
+
+inline void
+ getValidPowerSupplyPath(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& validChassisPath,
+ const std::string& powerSupplyId,
+ std::function<void()>&& callback)
+{
+ std::string powerPath = validChassisPath + "/powered_by";
+ dbus::utility::getAssociationEndPoints(
+ powerPath, [asyncResp, powerSupplyId, callback{std::move(callback)}](
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperEndPoints& endpoints) {
+ if (ec)
+ {
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR
+ << "DBUS response error for getAssociationEndPoints"
+ << ec.value();
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::resourceNotFound(asyncResp->res, "PowerSupplies",
+ powerSupplyId);
+ return;
+ }
+
+ for (const auto& endpoint : endpoints)
+ {
+ if (checkPowerSupplyId(endpoint, powerSupplyId))
+ {
+ callback();
+ return;
+ }
+ }
+
+ if (!endpoints.empty())
+ {
+ BMCWEB_LOG_WARNING << "Power supply not found: "
+ << powerSupplyId;
+ messages::resourceNotFound(asyncResp->res, "PowerSupplies",
+ powerSupplyId);
+ return;
+ }
+ });
+}
+
+inline void
+ doPowerSupplyGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId,
+ const std::string& powerSupplyId,
+ const std::optional<std::string>& validChassisPath)
+{
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+ return;
+ }
+
+ // Get the correct Path and Service that match the input parameters
+ getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
+ [asyncResp, chassisId, powerSupplyId]() {
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#PowerSupply.v1_5_0.PowerSupply";
+ asyncResp->res.jsonValue["Name"] = "Power Supply";
+ asyncResp->res.jsonValue["Id"] = powerSupplyId;
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
+ powerSupplyId);
+ });
+}
+
+inline void
+ handlePowerSupplyHead(App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId,
+ const std::string& powerSupplyId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ redfish::chassis_utils::getValidChassisPath(
+ asyncResp, chassisId,
+ [asyncResp, chassisId,
+ powerSupplyId](const std::optional<std::string>& validChassisPath) {
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+ return;
+ }
+
+ // Get the correct Path and Service that match the input parameters
+ getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
+ [asyncResp]() {
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
+ });
+ });
+}
+
+inline void
+ handlePowerSupplyGet(App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId,
+ const std::string& powerSupplyId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ redfish::chassis_utils::getValidChassisPath(
+ asyncResp, chassisId,
+ std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId));
+}
+
+inline void requestRoutesPowerSupply(App& app)
+{
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
+ .privileges(redfish::privileges::headPowerSupply)
+ .methods(boost::beast::http::verb::head)(
+ std::bind_front(handlePowerSupplyHead, std::ref(app)));
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
+ .privileges(redfish::privileges::getPowerSupply)
+ .methods(boost::beast::http::verb::get)(
+ std::bind_front(handlePowerSupplyGet, std::ref(app)));
+}
+
} // namespace redfish