xref: /openbmc/bmcweb/features/redfish/lib/power_supply.hpp (revision 34dfcb94afa2447965c7dd5b89274325ee2d0b88)
1a7210020SGeorge Liu #pragma once
2a7210020SGeorge Liu 
3a7210020SGeorge Liu #include "app.hpp"
4a7210020SGeorge Liu #include "dbus_utility.hpp"
5a7210020SGeorge Liu #include "query.hpp"
6a7210020SGeorge Liu #include "registries/privilege_registry.hpp"
7a7210020SGeorge Liu #include "utils/chassis_utils.hpp"
8a7210020SGeorge Liu 
9*34dfcb94SGeorge Liu #include <boost/system/error_code.hpp>
10ef4c65b7SEd Tanous #include <boost/url/format.hpp>
11ef4c65b7SEd Tanous 
12a7210020SGeorge Liu #include <memory>
13a7210020SGeorge Liu #include <optional>
14a7210020SGeorge Liu #include <string>
15a7210020SGeorge Liu 
16a7210020SGeorge Liu namespace redfish
17a7210020SGeorge Liu {
18a7210020SGeorge Liu 
1900ef5dc6SGeorge Liu inline void
2000ef5dc6SGeorge Liu     updatePowerSupplyList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2100ef5dc6SGeorge Liu                           const std::string& chassisId,
2200ef5dc6SGeorge Liu                           const std::string& powerSupplyPath)
23a7210020SGeorge Liu {
2400ef5dc6SGeorge Liu     std::string powerSupplyName =
2500ef5dc6SGeorge Liu         sdbusplus::message::object_path(powerSupplyPath).filename();
2600ef5dc6SGeorge Liu     if (powerSupplyName.empty())
2700ef5dc6SGeorge Liu     {
2800ef5dc6SGeorge Liu         return;
2900ef5dc6SGeorge Liu     }
3000ef5dc6SGeorge Liu 
3100ef5dc6SGeorge Liu     nlohmann::json item = nlohmann::json::object();
3200ef5dc6SGeorge Liu     item["@odata.id"] = boost::urls::format(
3300ef5dc6SGeorge Liu         "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
3400ef5dc6SGeorge Liu         powerSupplyName);
3500ef5dc6SGeorge Liu 
3600ef5dc6SGeorge Liu     nlohmann::json& powerSupplyList = asyncResp->res.jsonValue["Members"];
3700ef5dc6SGeorge Liu     powerSupplyList.emplace_back(std::move(item));
3800ef5dc6SGeorge Liu     asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size();
39a7210020SGeorge Liu }
40a7210020SGeorge Liu 
41a7210020SGeorge Liu inline void
42a7210020SGeorge Liu     doPowerSupplyCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
43a7210020SGeorge Liu                             const std::string& chassisId,
44a7210020SGeorge Liu                             const std::optional<std::string>& validChassisPath)
45a7210020SGeorge Liu {
46a7210020SGeorge Liu     if (!validChassisPath)
47a7210020SGeorge Liu     {
48a7210020SGeorge Liu         messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
49a7210020SGeorge Liu         return;
50a7210020SGeorge Liu     }
51a7210020SGeorge Liu 
52a7210020SGeorge Liu     asyncResp->res.addHeader(
53a7210020SGeorge Liu         boost::beast::http::field::link,
54a7210020SGeorge Liu         "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
55a7210020SGeorge Liu     asyncResp->res.jsonValue["@odata.type"] =
56a7210020SGeorge Liu         "#PowerSupplyCollection.PowerSupplyCollection";
57a7210020SGeorge Liu     asyncResp->res.jsonValue["Name"] = "Power Supply Collection";
58ef4c65b7SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
59ef4c65b7SEd Tanous         "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId);
60a7210020SGeorge Liu     asyncResp->res.jsonValue["Description"] =
61a7210020SGeorge Liu         "The collection of PowerSupply resource instances.";
627a2bb2c9SGeorge Liu     asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
637a2bb2c9SGeorge Liu     asyncResp->res.jsonValue["Members@odata.count"] = 0;
64a7210020SGeorge Liu 
65a7210020SGeorge Liu     std::string powerPath = *validChassisPath + "/powered_by";
66a7210020SGeorge Liu     dbus::utility::getAssociationEndPoints(
67a7210020SGeorge Liu         powerPath, [asyncResp, chassisId](
68a7210020SGeorge Liu                        const boost::system::error_code& ec,
69a7210020SGeorge Liu                        const dbus::utility::MapperEndPoints& endpoints) {
70a7210020SGeorge Liu             if (ec)
71a7210020SGeorge Liu             {
72a7210020SGeorge Liu                 if (ec.value() != EBADR)
73a7210020SGeorge Liu                 {
74a7210020SGeorge Liu                     BMCWEB_LOG_ERROR << "DBUS response error" << ec.value();
75a7210020SGeorge Liu                     messages::internalError(asyncResp->res);
76a7210020SGeorge Liu                 }
77a7210020SGeorge Liu                 return;
78a7210020SGeorge Liu             }
79a7210020SGeorge Liu 
80a7210020SGeorge Liu             for (const auto& endpoint : endpoints)
81a7210020SGeorge Liu             {
82a7210020SGeorge Liu                 updatePowerSupplyList(asyncResp, chassisId, endpoint);
83a7210020SGeorge Liu             }
84a7210020SGeorge Liu         });
85a7210020SGeorge Liu }
86a7210020SGeorge Liu 
87a7210020SGeorge Liu inline void handlePowerSupplyCollectionHead(
88a7210020SGeorge Liu     App& app, const crow::Request& req,
89a7210020SGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
90a7210020SGeorge Liu     const std::string& chassisId)
91a7210020SGeorge Liu {
92a7210020SGeorge Liu     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
93a7210020SGeorge Liu     {
94a7210020SGeorge Liu         return;
95a7210020SGeorge Liu     }
96a7210020SGeorge Liu 
97a7210020SGeorge Liu     redfish::chassis_utils::getValidChassisPath(
98a7210020SGeorge Liu         asyncResp, chassisId,
99a7210020SGeorge Liu         [asyncResp,
100a7210020SGeorge Liu          chassisId](const std::optional<std::string>& validChassisPath) {
101a7210020SGeorge Liu         if (!validChassisPath)
102a7210020SGeorge Liu         {
103a7210020SGeorge Liu             messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
104a7210020SGeorge Liu             return;
105a7210020SGeorge Liu         }
106a7210020SGeorge Liu         asyncResp->res.addHeader(
107a7210020SGeorge Liu             boost::beast::http::field::link,
108a7210020SGeorge Liu             "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
109a7210020SGeorge Liu         });
110a7210020SGeorge Liu }
111a7210020SGeorge Liu 
112a7210020SGeorge Liu inline void handlePowerSupplyCollectionGet(
113a7210020SGeorge Liu     App& app, const crow::Request& req,
114a7210020SGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
115a7210020SGeorge Liu     const std::string& chassisId)
116a7210020SGeorge Liu {
117a7210020SGeorge Liu     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
118a7210020SGeorge Liu     {
119a7210020SGeorge Liu         return;
120a7210020SGeorge Liu     }
121a7210020SGeorge Liu 
122a7210020SGeorge Liu     redfish::chassis_utils::getValidChassisPath(
123a7210020SGeorge Liu         asyncResp, chassisId,
124a7210020SGeorge Liu         std::bind_front(doPowerSupplyCollection, asyncResp, chassisId));
125a7210020SGeorge Liu }
126a7210020SGeorge Liu 
127a7210020SGeorge Liu inline void requestRoutesPowerSupplyCollection(App& app)
128a7210020SGeorge Liu {
129a7210020SGeorge Liu     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
130a7210020SGeorge Liu         .privileges(redfish::privileges::headPowerSupplyCollection)
131a7210020SGeorge Liu         .methods(boost::beast::http::verb::head)(
132a7210020SGeorge Liu             std::bind_front(handlePowerSupplyCollectionHead, std::ref(app)));
133a7210020SGeorge Liu 
134a7210020SGeorge Liu     BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
135a7210020SGeorge Liu         .privileges(redfish::privileges::getPowerSupplyCollection)
136a7210020SGeorge Liu         .methods(boost::beast::http::verb::get)(
137a7210020SGeorge Liu             std::bind_front(handlePowerSupplyCollectionGet, std::ref(app)));
138a7210020SGeorge Liu }
139a7210020SGeorge Liu 
14000ef5dc6SGeorge Liu inline bool checkPowerSupplyId(const std::string& powerSupplyPath,
14100ef5dc6SGeorge Liu                                const std::string& powerSupplyId)
14200ef5dc6SGeorge Liu {
14300ef5dc6SGeorge Liu     std::string powerSupplyName =
14400ef5dc6SGeorge Liu         sdbusplus::message::object_path(powerSupplyPath).filename();
14500ef5dc6SGeorge Liu 
14600ef5dc6SGeorge Liu     return !(powerSupplyName.empty() || powerSupplyName != powerSupplyId);
14700ef5dc6SGeorge Liu }
14800ef5dc6SGeorge Liu 
149*34dfcb94SGeorge Liu inline void getValidPowerSupplyPath(
150*34dfcb94SGeorge Liu     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
151*34dfcb94SGeorge Liu     const std::string& validChassisPath, const std::string& powerSupplyId,
152*34dfcb94SGeorge Liu     std::function<void(const std::string& powerSupplyPath)>&& callback)
15300ef5dc6SGeorge Liu {
15400ef5dc6SGeorge Liu     std::string powerPath = validChassisPath + "/powered_by";
15500ef5dc6SGeorge Liu     dbus::utility::getAssociationEndPoints(
15600ef5dc6SGeorge Liu         powerPath, [asyncResp, powerSupplyId, callback{std::move(callback)}](
15700ef5dc6SGeorge Liu                        const boost::system::error_code& ec,
15800ef5dc6SGeorge Liu                        const dbus::utility::MapperEndPoints& endpoints) {
15900ef5dc6SGeorge Liu             if (ec)
16000ef5dc6SGeorge Liu             {
16100ef5dc6SGeorge Liu                 if (ec.value() != EBADR)
16200ef5dc6SGeorge Liu                 {
16300ef5dc6SGeorge Liu                     BMCWEB_LOG_ERROR
16400ef5dc6SGeorge Liu                         << "DBUS response error for getAssociationEndPoints"
16500ef5dc6SGeorge Liu                         << ec.value();
16600ef5dc6SGeorge Liu                     messages::internalError(asyncResp->res);
16700ef5dc6SGeorge Liu                     return;
16800ef5dc6SGeorge Liu                 }
16900ef5dc6SGeorge Liu                 messages::resourceNotFound(asyncResp->res, "PowerSupplies",
17000ef5dc6SGeorge Liu                                            powerSupplyId);
17100ef5dc6SGeorge Liu                 return;
17200ef5dc6SGeorge Liu             }
17300ef5dc6SGeorge Liu 
17400ef5dc6SGeorge Liu             for (const auto& endpoint : endpoints)
17500ef5dc6SGeorge Liu             {
17600ef5dc6SGeorge Liu                 if (checkPowerSupplyId(endpoint, powerSupplyId))
17700ef5dc6SGeorge Liu                 {
178*34dfcb94SGeorge Liu                     callback(endpoint);
17900ef5dc6SGeorge Liu                     return;
18000ef5dc6SGeorge Liu                 }
18100ef5dc6SGeorge Liu             }
18200ef5dc6SGeorge Liu 
18300ef5dc6SGeorge Liu             if (!endpoints.empty())
18400ef5dc6SGeorge Liu             {
18500ef5dc6SGeorge Liu                 BMCWEB_LOG_WARNING << "Power supply not found: "
18600ef5dc6SGeorge Liu                                    << powerSupplyId;
18700ef5dc6SGeorge Liu                 messages::resourceNotFound(asyncResp->res, "PowerSupplies",
18800ef5dc6SGeorge Liu                                            powerSupplyId);
18900ef5dc6SGeorge Liu                 return;
19000ef5dc6SGeorge Liu             }
19100ef5dc6SGeorge Liu         });
19200ef5dc6SGeorge Liu }
19300ef5dc6SGeorge Liu 
19400ef5dc6SGeorge Liu inline void
195*34dfcb94SGeorge Liu     getPowerSupplyState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
196*34dfcb94SGeorge Liu                         const std::string& service, const std::string& path)
197*34dfcb94SGeorge Liu {
198*34dfcb94SGeorge Liu     sdbusplus::asio::getProperty<bool>(
199*34dfcb94SGeorge Liu         *crow::connections::systemBus, service, path,
200*34dfcb94SGeorge Liu         "xyz.openbmc_project.Inventory.Item", "Present",
201*34dfcb94SGeorge Liu         [asyncResp](const boost::system::error_code& ec, const bool value) {
202*34dfcb94SGeorge Liu         if (ec)
203*34dfcb94SGeorge Liu         {
204*34dfcb94SGeorge Liu             if (ec.value() != EBADR)
205*34dfcb94SGeorge Liu             {
206*34dfcb94SGeorge Liu                 BMCWEB_LOG_ERROR << "DBUS response error for State "
207*34dfcb94SGeorge Liu                                  << ec.value();
208*34dfcb94SGeorge Liu                 messages::internalError(asyncResp->res);
209*34dfcb94SGeorge Liu             }
210*34dfcb94SGeorge Liu             return;
211*34dfcb94SGeorge Liu         }
212*34dfcb94SGeorge Liu 
213*34dfcb94SGeorge Liu         if (!value)
214*34dfcb94SGeorge Liu         {
215*34dfcb94SGeorge Liu             asyncResp->res.jsonValue["Status"]["State"] = "Absent";
216*34dfcb94SGeorge Liu         }
217*34dfcb94SGeorge Liu         });
218*34dfcb94SGeorge Liu }
219*34dfcb94SGeorge Liu 
220*34dfcb94SGeorge Liu inline void
221*34dfcb94SGeorge Liu     getPowerSupplyHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
222*34dfcb94SGeorge Liu                          const std::string& service, const std::string& path)
223*34dfcb94SGeorge Liu {
224*34dfcb94SGeorge Liu     sdbusplus::asio::getProperty<bool>(
225*34dfcb94SGeorge Liu         *crow::connections::systemBus, service, path,
226*34dfcb94SGeorge Liu         "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
227*34dfcb94SGeorge Liu         [asyncResp](const boost::system::error_code& ec, const bool value) {
228*34dfcb94SGeorge Liu         if (ec)
229*34dfcb94SGeorge Liu         {
230*34dfcb94SGeorge Liu             if (ec.value() != EBADR)
231*34dfcb94SGeorge Liu             {
232*34dfcb94SGeorge Liu                 BMCWEB_LOG_ERROR << "DBUS response error for Health "
233*34dfcb94SGeorge Liu                                  << ec.value();
234*34dfcb94SGeorge Liu                 messages::internalError(asyncResp->res);
235*34dfcb94SGeorge Liu             }
236*34dfcb94SGeorge Liu             return;
237*34dfcb94SGeorge Liu         }
238*34dfcb94SGeorge Liu 
239*34dfcb94SGeorge Liu         if (!value)
240*34dfcb94SGeorge Liu         {
241*34dfcb94SGeorge Liu             asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
242*34dfcb94SGeorge Liu         }
243*34dfcb94SGeorge Liu         });
244*34dfcb94SGeorge Liu }
245*34dfcb94SGeorge Liu 
246*34dfcb94SGeorge Liu inline void
24700ef5dc6SGeorge Liu     doPowerSupplyGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
24800ef5dc6SGeorge Liu                      const std::string& chassisId,
24900ef5dc6SGeorge Liu                      const std::string& powerSupplyId,
25000ef5dc6SGeorge Liu                      const std::optional<std::string>& validChassisPath)
25100ef5dc6SGeorge Liu {
25200ef5dc6SGeorge Liu     if (!validChassisPath)
25300ef5dc6SGeorge Liu     {
25400ef5dc6SGeorge Liu         messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
25500ef5dc6SGeorge Liu         return;
25600ef5dc6SGeorge Liu     }
25700ef5dc6SGeorge Liu 
25800ef5dc6SGeorge Liu     // Get the correct Path and Service that match the input parameters
25900ef5dc6SGeorge Liu     getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
260*34dfcb94SGeorge Liu                             [asyncResp, chassisId, powerSupplyId](
261*34dfcb94SGeorge Liu                                 const std::string& powerSupplyPath) {
26200ef5dc6SGeorge Liu         asyncResp->res.addHeader(
26300ef5dc6SGeorge Liu             boost::beast::http::field::link,
26400ef5dc6SGeorge Liu             "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
26500ef5dc6SGeorge Liu         asyncResp->res.jsonValue["@odata.type"] =
26600ef5dc6SGeorge Liu             "#PowerSupply.v1_5_0.PowerSupply";
26700ef5dc6SGeorge Liu         asyncResp->res.jsonValue["Name"] = "Power Supply";
26800ef5dc6SGeorge Liu         asyncResp->res.jsonValue["Id"] = powerSupplyId;
26900ef5dc6SGeorge Liu         asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
27000ef5dc6SGeorge Liu             "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
27100ef5dc6SGeorge Liu             powerSupplyId);
272*34dfcb94SGeorge Liu 
273*34dfcb94SGeorge Liu         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
274*34dfcb94SGeorge Liu         asyncResp->res.jsonValue["Status"]["Health"] = "OK";
275*34dfcb94SGeorge Liu 
276*34dfcb94SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces = {
277*34dfcb94SGeorge Liu             "xyz.openbmc_project.Inventory.Item.PowerSupply"};
278*34dfcb94SGeorge Liu         dbus::utility::getDbusObject(
279*34dfcb94SGeorge Liu             powerSupplyPath, interfaces,
280*34dfcb94SGeorge Liu             [asyncResp,
281*34dfcb94SGeorge Liu              powerSupplyPath](const boost::system::error_code& ec,
282*34dfcb94SGeorge Liu                               const dbus::utility::MapperGetObject& object) {
283*34dfcb94SGeorge Liu             if (ec || object.empty())
284*34dfcb94SGeorge Liu             {
285*34dfcb94SGeorge Liu                 messages::internalError(asyncResp->res);
286*34dfcb94SGeorge Liu                 return;
287*34dfcb94SGeorge Liu             }
288*34dfcb94SGeorge Liu 
289*34dfcb94SGeorge Liu             getPowerSupplyState(asyncResp, object.begin()->first,
290*34dfcb94SGeorge Liu                                 powerSupplyPath);
291*34dfcb94SGeorge Liu             getPowerSupplyHealth(asyncResp, object.begin()->first,
292*34dfcb94SGeorge Liu                                  powerSupplyPath);
293*34dfcb94SGeorge Liu             });
29400ef5dc6SGeorge Liu     });
29500ef5dc6SGeorge Liu }
29600ef5dc6SGeorge Liu 
29700ef5dc6SGeorge Liu inline void
29800ef5dc6SGeorge Liu     handlePowerSupplyHead(App& app, const crow::Request& req,
29900ef5dc6SGeorge Liu                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
30000ef5dc6SGeorge Liu                           const std::string& chassisId,
30100ef5dc6SGeorge Liu                           const std::string& powerSupplyId)
30200ef5dc6SGeorge Liu {
30300ef5dc6SGeorge Liu     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
30400ef5dc6SGeorge Liu     {
30500ef5dc6SGeorge Liu         return;
30600ef5dc6SGeorge Liu     }
30700ef5dc6SGeorge Liu 
30800ef5dc6SGeorge Liu     redfish::chassis_utils::getValidChassisPath(
30900ef5dc6SGeorge Liu         asyncResp, chassisId,
31000ef5dc6SGeorge Liu         [asyncResp, chassisId,
31100ef5dc6SGeorge Liu          powerSupplyId](const std::optional<std::string>& validChassisPath) {
31200ef5dc6SGeorge Liu         if (!validChassisPath)
31300ef5dc6SGeorge Liu         {
31400ef5dc6SGeorge Liu             messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
31500ef5dc6SGeorge Liu             return;
31600ef5dc6SGeorge Liu         }
31700ef5dc6SGeorge Liu 
31800ef5dc6SGeorge Liu         // Get the correct Path and Service that match the input parameters
31900ef5dc6SGeorge Liu         getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
320*34dfcb94SGeorge Liu                                 [asyncResp](const std::string&) {
32100ef5dc6SGeorge Liu             asyncResp->res.addHeader(
32200ef5dc6SGeorge Liu                 boost::beast::http::field::link,
32300ef5dc6SGeorge Liu                 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
32400ef5dc6SGeorge Liu         });
32500ef5dc6SGeorge Liu         });
32600ef5dc6SGeorge Liu }
32700ef5dc6SGeorge Liu 
32800ef5dc6SGeorge Liu inline void
32900ef5dc6SGeorge Liu     handlePowerSupplyGet(App& app, const crow::Request& req,
33000ef5dc6SGeorge Liu                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
33100ef5dc6SGeorge Liu                          const std::string& chassisId,
33200ef5dc6SGeorge Liu                          const std::string& powerSupplyId)
33300ef5dc6SGeorge Liu {
33400ef5dc6SGeorge Liu     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
33500ef5dc6SGeorge Liu     {
33600ef5dc6SGeorge Liu         return;
33700ef5dc6SGeorge Liu     }
33800ef5dc6SGeorge Liu 
33900ef5dc6SGeorge Liu     redfish::chassis_utils::getValidChassisPath(
34000ef5dc6SGeorge Liu         asyncResp, chassisId,
34100ef5dc6SGeorge Liu         std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId));
34200ef5dc6SGeorge Liu }
34300ef5dc6SGeorge Liu 
34400ef5dc6SGeorge Liu inline void requestRoutesPowerSupply(App& app)
34500ef5dc6SGeorge Liu {
34600ef5dc6SGeorge Liu     BMCWEB_ROUTE(
34700ef5dc6SGeorge Liu         app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
34800ef5dc6SGeorge Liu         .privileges(redfish::privileges::headPowerSupply)
34900ef5dc6SGeorge Liu         .methods(boost::beast::http::verb::head)(
35000ef5dc6SGeorge Liu             std::bind_front(handlePowerSupplyHead, std::ref(app)));
35100ef5dc6SGeorge Liu 
35200ef5dc6SGeorge Liu     BMCWEB_ROUTE(
35300ef5dc6SGeorge Liu         app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
35400ef5dc6SGeorge Liu         .privileges(redfish::privileges::getPowerSupply)
35500ef5dc6SGeorge Liu         .methods(boost::beast::http::verb::get)(
35600ef5dc6SGeorge Liu             std::bind_front(handlePowerSupplyGet, std::ref(app)));
35700ef5dc6SGeorge Liu }
35800ef5dc6SGeorge Liu 
359a7210020SGeorge Liu } // namespace redfish
360