blob: 0336ddcee9500e347ac432ac657252f12d9177b1 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
George Liua7210022022-10-05 15:44:11 +08003#pragma once
4
5#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "async_resp.hpp"
George Liua7210022022-10-05 15:44:11 +08007#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08008#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -07009#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080010#include "http_request.hpp"
Myung Bae7066dc52024-08-20 11:01:57 -050011#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "logging.hpp"
George Liua7210022022-10-05 15:44:11 +080013#include "query.hpp"
14#include "registries/privilege_registry.hpp"
Myung Baef7e62c12025-09-07 14:02:08 -050015#include "utils/asset_utils.hpp"
George Liua7210022022-10-05 15:44:11 +080016#include "utils/chassis_utils.hpp"
George Liu2b45fb32022-10-05 17:00:00 +080017#include "utils/dbus_utils.hpp"
Myung Bae7066dc52024-08-20 11:01:57 -050018#include "utils/json_utils.hpp"
Hieu Huynhb5190062024-07-11 03:47:21 +000019#include "utils/time_utils.hpp"
George Liua7210022022-10-05 15:44:11 +080020
Ed Tanousd7857202025-01-28 15:32:26 -080021#include <asm-generic/errno.h>
22
23#include <boost/beast/http/field.hpp>
24#include <boost/beast/http/verb.hpp>
George Liu34dfcb92022-10-05 16:47:44 +080025#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070026#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080027#include <nlohmann/json.hpp>
28#include <sdbusplus/unpack_properties.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070029
Ed Tanousd7857202025-01-28 15:32:26 -080030#include <array>
31#include <cstdint>
32#include <functional>
George Liua7210022022-10-05 15:44:11 +080033#include <memory>
34#include <optional>
35#include <string>
Ed Tanousd7857202025-01-28 15:32:26 -080036#include <string_view>
37#include <utility>
George Liua7210022022-10-05 15:44:11 +080038
39namespace redfish
40{
41
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -050042static constexpr std::array<std::string_view, 1> powerSupplyInterface = {
43 "xyz.openbmc_project.Inventory.Item.PowerSupply"};
44
45inline void updatePowerSupplyList(
46 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
47 const std::string& chassisId,
48 const dbus::utility::MapperGetSubTreePathsResponse& powerSupplyPaths)
George Liua7210022022-10-05 15:44:11 +080049{
George Liu00ef5dc2022-10-05 16:27:52 +080050 nlohmann::json& powerSupplyList = asyncResp->res.jsonValue["Members"];
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -050051 for (const std::string& powerSupplyPath : powerSupplyPaths)
52 {
53 std::string powerSupplyName =
54 sdbusplus::message::object_path(powerSupplyPath).filename();
55 if (powerSupplyName.empty())
56 {
57 continue;
58 }
59
60 nlohmann::json item = nlohmann::json::object();
61 item["@odata.id"] = boost::urls::format(
62 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
63 powerSupplyName);
64
65 powerSupplyList.emplace_back(std::move(item));
66 }
George Liu00ef5dc2022-10-05 16:27:52 +080067 asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size();
George Liua7210022022-10-05 15:44:11 +080068}
69
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -050070inline void doPowerSupplyCollection(
71 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
72 const std::string& chassisId, const boost::system::error_code& ec,
73 const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths)
George Liua7210022022-10-05 15:44:11 +080074{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -050075 if (ec)
George Liua7210022022-10-05 15:44:11 +080076 {
Myung Bae193582b2025-03-31 07:21:31 -050077 if (ec.value() == boost::system::errc::io_error)
78 {
79 BMCWEB_LOG_WARNING("Chassis not found");
80 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
81 return;
82 }
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -050083 if (ec.value() != EBADR)
84 {
85 BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
86 messages::internalError(asyncResp->res);
87 }
George Liua7210022022-10-05 15:44:11 +080088 return;
89 }
George Liua7210022022-10-05 15:44:11 +080090 asyncResp->res.addHeader(
91 boost::beast::http::field::link,
92 "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
93 asyncResp->res.jsonValue["@odata.type"] =
94 "#PowerSupplyCollection.PowerSupplyCollection";
95 asyncResp->res.jsonValue["Name"] = "Power Supply Collection";
Ed Tanousef4c65b2023-04-24 15:28:50 -070096 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
97 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId);
George Liua7210022022-10-05 15:44:11 +080098 asyncResp->res.jsonValue["Description"] =
99 "The collection of PowerSupply resource instances.";
George Liu7a2bb2c2023-04-11 10:44:33 +0800100 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
101 asyncResp->res.jsonValue["Members@odata.count"] = 0;
George Liua7210022022-10-05 15:44:11 +0800102
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500103 updatePowerSupplyList(asyncResp, chassisId, subtreePaths);
George Liua7210022022-10-05 15:44:11 +0800104}
105
106inline void handlePowerSupplyCollectionHead(
107 App& app, const crow::Request& req,
108 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
109 const std::string& chassisId)
110{
111 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
112 {
113 return;
114 }
115
116 redfish::chassis_utils::getValidChassisPath(
117 asyncResp, chassisId,
118 [asyncResp,
119 chassisId](const std::optional<std::string>& validChassisPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400120 if (!validChassisPath)
121 {
Myung Bae193582b2025-03-31 07:21:31 -0500122 BMCWEB_LOG_WARNING("Chassis not found");
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400123 messages::resourceNotFound(asyncResp->res, "Chassis",
124 chassisId);
125 return;
126 }
127 asyncResp->res.addHeader(
128 boost::beast::http::field::link,
129 "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
130 });
George Liua7210022022-10-05 15:44:11 +0800131}
132
133inline void handlePowerSupplyCollectionGet(
134 App& app, const crow::Request& req,
135 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
136 const std::string& chassisId)
137{
138 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
139 {
140 return;
141 }
142
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500143 const std::string reqpath = "/xyz/openbmc_project/inventory";
144
145 dbus::utility::getAssociatedSubTreePathsById(
Myung Bae3f95a272024-03-13 07:32:02 -0700146 chassisId, reqpath, chassisInterfaces, "powered_by",
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500147 powerSupplyInterface,
148 [asyncResp, chassisId](
149 const boost::system::error_code& ec,
150 const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
151 doPowerSupplyCollection(asyncResp, chassisId, ec, subtreePaths);
152 });
George Liua7210022022-10-05 15:44:11 +0800153}
154
155inline void requestRoutesPowerSupplyCollection(App& app)
156{
157 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
158 .privileges(redfish::privileges::headPowerSupplyCollection)
159 .methods(boost::beast::http::verb::head)(
160 std::bind_front(handlePowerSupplyCollectionHead, std::ref(app)));
161
162 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
163 .privileges(redfish::privileges::getPowerSupplyCollection)
164 .methods(boost::beast::http::verb::get)(
165 std::bind_front(handlePowerSupplyCollectionGet, std::ref(app)));
166}
167
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500168inline void afterGetValidPowerSupplyPath(
169 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
170 const std::string& powerSupplyId, const boost::system::error_code& ec,
171 const dbus::utility::MapperGetSubTreeResponse& subtree,
172 const std::function<void(const std::string& powerSupplyPath,
173 const std::string& service)>& callback)
George Liu00ef5dc2022-10-05 16:27:52 +0800174{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500175 if (ec)
176 {
Myung Bae193582b2025-03-31 07:21:31 -0500177 if (ec.value() == boost::system::errc::io_error)
178 {
179 // Not found
180 callback(std::string(), std::string());
181 return;
182 }
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500183 if (ec.value() != EBADR)
184 {
185 BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
186 messages::internalError(asyncResp->res);
Myung Bae193582b2025-03-31 07:21:31 -0500187 return;
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500188 }
Myung Bae193582b2025-03-31 07:21:31 -0500189 callback(std::string(), std::string());
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500190 return;
191 }
192 for (const auto& [objectPath, service] : subtree)
193 {
194 sdbusplus::message::object_path path(objectPath);
Myung Baed8e2b612024-10-08 12:19:19 -0500195 if (path.filename() == powerSupplyId)
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500196 {
197 callback(path, service.begin()->first);
198 return;
199 }
200 }
George Liu00ef5dc2022-10-05 16:27:52 +0800201
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500202 BMCWEB_LOG_WARNING("Power supply not found: {}", powerSupplyId);
203 messages::resourceNotFound(asyncResp->res, "PowerSupplies", powerSupplyId);
George Liu00ef5dc2022-10-05 16:27:52 +0800204}
205
George Liu34dfcb92022-10-05 16:47:44 +0800206inline void getValidPowerSupplyPath(
207 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500208 const std::string& chassisId, const std::string& powerSupplyId,
209 std::function<void(const std::string& powerSupplyPath,
210 const std::string& service)>&& callback)
George Liu00ef5dc2022-10-05 16:27:52 +0800211{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500212 const std::string reqpath = "/xyz/openbmc_project/inventory";
213
214 dbus::utility::getAssociatedSubTreeById(
Myung Bae3f95a272024-03-13 07:32:02 -0700215 chassisId, reqpath, chassisInterfaces, "powered_by",
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -0500216 powerSupplyInterface,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500217 [asyncResp, chassisId, powerSupplyId, callback{std::move(callback)}](
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -0500218 const boost::system::error_code& ec,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500219 const dbus::utility::MapperGetSubTreeResponse& subtree) {
220 afterGetValidPowerSupplyPath(asyncResp, powerSupplyId, ec, subtree,
221 callback);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400222 });
George Liu00ef5dc2022-10-05 16:27:52 +0800223}
224
Patrick Williams504af5a2025-02-03 14:29:03 -0500225inline void getPowerSupplyState(
226 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
227 const std::string& service, const std::string& path)
George Liu34dfcb92022-10-05 16:47:44 +0800228{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800229 dbus::utility::getProperty<bool>(
230 service, path, "xyz.openbmc_project.Inventory.Item", "Present",
George Liu34dfcb92022-10-05 16:47:44 +0800231 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400232 if (ec)
George Liu34dfcb92022-10-05 16:47:44 +0800233 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400234 if (ec.value() != EBADR)
235 {
236 BMCWEB_LOG_ERROR("DBUS response error for State {}",
237 ec.value());
238 messages::internalError(asyncResp->res);
239 }
240 return;
George Liu34dfcb92022-10-05 16:47:44 +0800241 }
George Liu34dfcb92022-10-05 16:47:44 +0800242
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400243 if (!value)
244 {
245 asyncResp->res.jsonValue["Status"]["State"] =
246 resource::State::Absent;
247 }
248 });
George Liu34dfcb92022-10-05 16:47:44 +0800249}
250
Patrick Williams504af5a2025-02-03 14:29:03 -0500251inline void getPowerSupplyHealth(
252 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
253 const std::string& service, const std::string& path)
George Liu34dfcb92022-10-05 16:47:44 +0800254{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800255 dbus::utility::getProperty<bool>(
256 service, path, "xyz.openbmc_project.State.Decorator.OperationalStatus",
257 "Functional",
George Liu34dfcb92022-10-05 16:47:44 +0800258 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400259 if (ec)
George Liu34dfcb92022-10-05 16:47:44 +0800260 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400261 if (ec.value() != EBADR)
262 {
263 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
264 ec.value());
265 messages::internalError(asyncResp->res);
266 }
267 return;
George Liu34dfcb92022-10-05 16:47:44 +0800268 }
George Liu34dfcb92022-10-05 16:47:44 +0800269
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400270 if (!value)
271 {
272 asyncResp->res.jsonValue["Status"]["Health"] =
273 resource::Health::Critical;
274 }
275 });
George Liu34dfcb92022-10-05 16:47:44 +0800276}
277
Patrick Williams504af5a2025-02-03 14:29:03 -0500278inline void getPowerSupplyAsset(
279 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
280 const std::string& service, const std::string& path)
George Liu2b45fb32022-10-05 17:00:00 +0800281{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800282 dbus::utility::getAllProperties(
283 service, path, "xyz.openbmc_project.Inventory.Decorator.Asset",
George Liu2b45fb32022-10-05 17:00:00 +0800284 [asyncResp](const boost::system::error_code& ec,
285 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400286 if (ec)
George Liu2b45fb32022-10-05 17:00:00 +0800287 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400288 if (ec.value() != EBADR)
289 {
290 BMCWEB_LOG_ERROR("DBUS response error for Asset {}",
291 ec.value());
292 messages::internalError(asyncResp->res);
293 }
294 return;
George Liu2b45fb32022-10-05 17:00:00 +0800295 }
George Liu2b45fb32022-10-05 17:00:00 +0800296
Myung Baef7e62c12025-09-07 14:02:08 -0500297 asset_utils::extractAssetInfo(asyncResp, ""_json_pointer,
298 propertiesList, true);
299
Hieu Huynhb5190062024-07-11 03:47:21 +0000300 const std::string* buildDate = nullptr;
George Liu2b45fb32022-10-05 17:00:00 +0800301
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400302 const bool success = sdbusplus::unpackPropertiesNoThrow(
Myung Baef7e62c12025-09-07 14:02:08 -0500303 dbus_utils::UnpackErrorPrinter(), propertiesList, "BuildDate",
304 buildDate);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400305 if (!success)
306 {
307 messages::internalError(asyncResp->res);
308 return;
309 }
George Liu2b45fb32022-10-05 17:00:00 +0800310
Hieu Huynhb5190062024-07-11 03:47:21 +0000311 if (buildDate != nullptr)
312 {
313 time_utils::productionDateReport(asyncResp->res, *buildDate);
314 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400315 });
George Liu2b45fb32022-10-05 17:00:00 +0800316}
317
George Liua0dba872022-10-05 17:03:20 +0800318inline void getPowerSupplyFirmwareVersion(
319 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
320 const std::string& service, const std::string& path)
321{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800322 dbus::utility::getProperty<std::string>(
323 service, path, "xyz.openbmc_project.Software.Version", "Version",
George Liua0dba872022-10-05 17:03:20 +0800324 [asyncResp](const boost::system::error_code& ec,
325 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400326 if (ec)
George Liua0dba872022-10-05 17:03:20 +0800327 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400328 if (ec.value() != EBADR)
329 {
330 BMCWEB_LOG_ERROR(
331 "DBUS response error for FirmwareVersion {}",
332 ec.value());
333 messages::internalError(asyncResp->res);
334 }
335 return;
George Liua0dba872022-10-05 17:03:20 +0800336 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400337 asyncResp->res.jsonValue["FirmwareVersion"] = value;
338 });
George Liua0dba872022-10-05 17:03:20 +0800339}
340
Patrick Williams504af5a2025-02-03 14:29:03 -0500341inline void getPowerSupplyLocation(
342 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
343 const std::string& service, const std::string& path)
George Liu44845e52022-10-05 17:09:21 +0800344{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800345 dbus::utility::getProperty<std::string>(
346 service, path, "xyz.openbmc_project.Inventory.Decorator.LocationCode",
347 "LocationCode",
George Liu44845e52022-10-05 17:09:21 +0800348 [asyncResp](const boost::system::error_code& ec,
349 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400350 if (ec)
George Liu44845e52022-10-05 17:09:21 +0800351 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400352 if (ec.value() != EBADR)
353 {
354 BMCWEB_LOG_ERROR("DBUS response error for Location {}",
355 ec.value());
356 messages::internalError(asyncResp->res);
357 }
358 return;
George Liu44845e52022-10-05 17:09:21 +0800359 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400360 asyncResp->res
361 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = value;
362 });
George Liu44845e52022-10-05 17:09:21 +0800363}
364
George Liuddceee02022-10-06 08:57:11 +0800365inline void handleGetEfficiencyResponse(
366 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
367 const boost::system::error_code& ec, uint32_t value)
368{
369 if (ec)
370 {
371 if (ec.value() != EBADR)
372 {
Ed Tanous62598e32023-07-17 17:06:25 -0700373 BMCWEB_LOG_ERROR("DBUS response error for DeratingFactor {}",
374 ec.value());
George Liuddceee02022-10-06 08:57:11 +0800375 messages::internalError(asyncResp->res);
376 }
377 return;
378 }
379 // The PDI default value is 0, if it hasn't been set leave off
380 if (value == 0)
381 {
382 return;
383 }
384
385 nlohmann::json::array_t efficiencyRatings;
386 nlohmann::json::object_t efficiencyPercent;
387 efficiencyPercent["EfficiencyPercent"] = value;
388 efficiencyRatings.emplace_back(std::move(efficiencyPercent));
389 asyncResp->res.jsonValue["EfficiencyRatings"] =
390 std::move(efficiencyRatings);
391}
392
393inline void handlePowerSupplyAttributesSubTreeResponse(
394 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
395 const boost::system::error_code& ec,
396 const dbus::utility::MapperGetSubTreeResponse& subtree)
397{
398 if (ec)
399 {
400 if (ec.value() != EBADR)
401 {
Ed Tanous62598e32023-07-17 17:06:25 -0700402 BMCWEB_LOG_ERROR("DBUS response error for EfficiencyPercent {}",
403 ec.value());
George Liuddceee02022-10-06 08:57:11 +0800404 messages::internalError(asyncResp->res);
405 }
406 return;
407 }
408
409 if (subtree.empty())
410 {
Ed Tanous62598e32023-07-17 17:06:25 -0700411 BMCWEB_LOG_DEBUG("Can't find Power Supply Attributes!");
George Liuddceee02022-10-06 08:57:11 +0800412 return;
413 }
414
415 if (subtree.size() != 1)
416 {
Ed Tanous62598e32023-07-17 17:06:25 -0700417 BMCWEB_LOG_ERROR(
418 "Unexpected number of paths returned by getSubTree: {}",
419 subtree.size());
George Liuddceee02022-10-06 08:57:11 +0800420 messages::internalError(asyncResp->res);
421 return;
422 }
423
424 const auto& [path, serviceMap] = *subtree.begin();
425 const auto& [service, interfaces] = *serviceMap.begin();
Ed Tanousdeae6a72024-11-11 21:58:57 -0800426 dbus::utility::getProperty<uint32_t>(
427 service, path, "xyz.openbmc_project.Control.PowerSupplyAttributes",
428 "DeratingFactor",
George Liuddceee02022-10-06 08:57:11 +0800429 [asyncResp](const boost::system::error_code& ec1, uint32_t value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400430 handleGetEfficiencyResponse(asyncResp, ec1, value);
431 });
George Liuddceee02022-10-06 08:57:11 +0800432}
433
Patrick Williams504af5a2025-02-03 14:29:03 -0500434inline void getEfficiencyPercent(
435 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuddceee02022-10-06 08:57:11 +0800436{
437 constexpr std::array<std::string_view, 1> efficiencyIntf = {
438 "xyz.openbmc_project.Control.PowerSupplyAttributes"};
439
440 dbus::utility::getSubTree(
441 "/xyz/openbmc_project", 0, efficiencyIntf,
442 [asyncResp](const boost::system::error_code& ec,
443 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400444 handlePowerSupplyAttributesSubTreeResponse(asyncResp, ec, subtree);
445 });
George Liuddceee02022-10-06 08:57:11 +0800446}
447
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400448inline void doPowerSupplyGet(
449 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
450 const std::string& chassisId, const std::string& powerSupplyId,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500451 const std::string& powerSupplyPath, const std::string& service)
George Liu00ef5dc2022-10-05 16:27:52 +0800452{
Myung Bae193582b2025-03-31 07:21:31 -0500453 if (powerSupplyPath.empty() || service.empty())
454 {
455 BMCWEB_LOG_WARNING("PowerSupply not found");
456 messages::resourceNotFound(asyncResp->res, "PowerSupply",
457 powerSupplyId);
458 return;
459 }
460
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500461 asyncResp->res.addHeader(
462 boost::beast::http::field::link,
463 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
464 asyncResp->res.jsonValue["@odata.type"] = "#PowerSupply.v1_5_0.PowerSupply";
465 asyncResp->res.jsonValue["Name"] = "Power Supply";
466 asyncResp->res.jsonValue["Id"] = powerSupplyId;
467 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
468 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
469 powerSupplyId);
George Liu00ef5dc2022-10-05 16:27:52 +0800470
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500471 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
472 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
George Liu34dfcb92022-10-05 16:47:44 +0800473
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500474 getPowerSupplyState(asyncResp, service, powerSupplyPath);
475 getPowerSupplyHealth(asyncResp, service, powerSupplyPath);
476 getPowerSupplyAsset(asyncResp, service, powerSupplyPath);
477 getPowerSupplyFirmwareVersion(asyncResp, service, powerSupplyPath);
478 getPowerSupplyLocation(asyncResp, service, powerSupplyPath);
479 getEfficiencyPercent(asyncResp);
Myung Bae7066dc52024-08-20 11:01:57 -0500480 getLocationIndicatorActive(asyncResp, powerSupplyPath);
George Liu00ef5dc2022-10-05 16:27:52 +0800481}
482
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400483inline void handlePowerSupplyHead(
484 App& app, const crow::Request& req,
485 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
486 const std::string& chassisId, const std::string& powerSupplyId)
George Liu00ef5dc2022-10-05 16:27:52 +0800487{
488 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
489 {
490 return;
491 }
492
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500493 // Get the correct Path and Service that match the input parameters
494 getValidPowerSupplyPath(
495 asyncResp, chassisId, powerSupplyId,
Myung Bae193582b2025-03-31 07:21:31 -0500496 [asyncResp, powerSupplyId](const std::string& powerSupplyPath,
497 const std::string& service) {
498 if (powerSupplyPath.empty() || service.empty())
499 {
500 BMCWEB_LOG_WARNING("PowerSupply not found");
501 messages::resourceNotFound(asyncResp->res, "PowerSupply",
502 powerSupplyId);
503 return;
504 }
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500505 asyncResp->res.addHeader(
506 boost::beast::http::field::link,
507 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
George Liu00ef5dc2022-10-05 16:27:52 +0800508 });
George Liu00ef5dc2022-10-05 16:27:52 +0800509}
510
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400511inline void handlePowerSupplyGet(
512 App& app, const crow::Request& req,
513 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
514 const std::string& chassisId, const std::string& powerSupplyId)
George Liu00ef5dc2022-10-05 16:27:52 +0800515{
516 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
517 {
518 return;
519 }
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500520 getValidPowerSupplyPath(
521 asyncResp, chassisId, powerSupplyId,
George Liu00ef5dc2022-10-05 16:27:52 +0800522 std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId));
523}
524
Myung Bae7066dc52024-08-20 11:01:57 -0500525inline void doPatchPowerSupply(
526 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
527 const bool locationIndicatorActive, const std::string& powerSupplyPath,
528 const std::string& /*service*/)
529{
530 setLocationIndicatorActive(asyncResp, powerSupplyPath,
531 locationIndicatorActive);
532}
533
534inline void handlePowerSupplyPatch(
535 App& app, const crow::Request& req,
536 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
537 const std::string& chassisId, const std::string& powerSupplyId)
538{
539 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
540 {
541 return;
542 }
543
544 std::optional<bool> locationIndicatorActive;
545 if (!json_util::readJsonPatch( //
546 req, asyncResp->res, //
547 "LocationIndicatorActive", locationIndicatorActive //
548 ))
549 {
550 return;
551 }
552
553 if (locationIndicatorActive)
554 {
555 // Get the correct power supply Path that match the input parameters
556 getValidPowerSupplyPath(asyncResp, chassisId, powerSupplyId,
557 std::bind_front(doPatchPowerSupply, asyncResp,
558 *locationIndicatorActive));
559 }
560}
561
George Liu00ef5dc2022-10-05 16:27:52 +0800562inline void requestRoutesPowerSupply(App& app)
563{
564 BMCWEB_ROUTE(
565 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
566 .privileges(redfish::privileges::headPowerSupply)
567 .methods(boost::beast::http::verb::head)(
568 std::bind_front(handlePowerSupplyHead, std::ref(app)));
569
570 BMCWEB_ROUTE(
571 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
572 .privileges(redfish::privileges::getPowerSupply)
573 .methods(boost::beast::http::verb::get)(
574 std::bind_front(handlePowerSupplyGet, std::ref(app)));
Myung Bae7066dc52024-08-20 11:01:57 -0500575
576 BMCWEB_ROUTE(
577 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
578 .privileges(redfish::privileges::patchPowerSupply)
579 .methods(boost::beast::http::verb::patch)(
580 std::bind_front(handlePowerSupplyPatch, std::ref(app)));
George Liu00ef5dc2022-10-05 16:27:52 +0800581}
582
George Liua7210022022-10-05 15:44:11 +0800583} // namespace redfish