blob: ebc61c50abf35fbeb168a77ba489d6cd0a9f391a [file] [log] [blame]
George Liua7210022022-10-05 15:44:11 +08001#pragma once
2
3#include "app.hpp"
4#include "dbus_utility.hpp"
5#include "query.hpp"
6#include "registries/privilege_registry.hpp"
7#include "utils/chassis_utils.hpp"
8
Ed Tanousef4c65b2023-04-24 15:28:50 -07009#include <boost/url/format.hpp>
10
George Liua7210022022-10-05 15:44:11 +080011#include <memory>
12#include <optional>
13#include <string>
14
15namespace redfish
16{
17
George Liu00ef5dc2022-10-05 16:27:52 +080018inline void
19 updatePowerSupplyList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
20 const std::string& chassisId,
21 const std::string& powerSupplyPath)
George Liua7210022022-10-05 15:44:11 +080022{
George Liu00ef5dc2022-10-05 16:27:52 +080023 std::string powerSupplyName =
24 sdbusplus::message::object_path(powerSupplyPath).filename();
25 if (powerSupplyName.empty())
26 {
27 return;
28 }
29
30 nlohmann::json item = nlohmann::json::object();
31 item["@odata.id"] = boost::urls::format(
32 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
33 powerSupplyName);
34
35 nlohmann::json& powerSupplyList = asyncResp->res.jsonValue["Members"];
36 powerSupplyList.emplace_back(std::move(item));
37 asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size();
George Liua7210022022-10-05 15:44:11 +080038}
39
40inline void
41 doPowerSupplyCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
42 const std::string& chassisId,
43 const std::optional<std::string>& validChassisPath)
44{
45 if (!validChassisPath)
46 {
47 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
48 return;
49 }
50
51 asyncResp->res.addHeader(
52 boost::beast::http::field::link,
53 "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
54 asyncResp->res.jsonValue["@odata.type"] =
55 "#PowerSupplyCollection.PowerSupplyCollection";
56 asyncResp->res.jsonValue["Name"] = "Power Supply Collection";
Ed Tanousef4c65b2023-04-24 15:28:50 -070057 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
58 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId);
George Liua7210022022-10-05 15:44:11 +080059 asyncResp->res.jsonValue["Description"] =
60 "The collection of PowerSupply resource instances.";
George Liu7a2bb2c2023-04-11 10:44:33 +080061 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
62 asyncResp->res.jsonValue["Members@odata.count"] = 0;
George Liua7210022022-10-05 15:44:11 +080063
64 std::string powerPath = *validChassisPath + "/powered_by";
65 dbus::utility::getAssociationEndPoints(
66 powerPath, [asyncResp, chassisId](
67 const boost::system::error_code& ec,
68 const dbus::utility::MapperEndPoints& endpoints) {
69 if (ec)
70 {
71 if (ec.value() != EBADR)
72 {
73 BMCWEB_LOG_ERROR << "DBUS response error" << ec.value();
74 messages::internalError(asyncResp->res);
75 }
76 return;
77 }
78
79 for (const auto& endpoint : endpoints)
80 {
81 updatePowerSupplyList(asyncResp, chassisId, endpoint);
82 }
83 });
84}
85
86inline void handlePowerSupplyCollectionHead(
87 App& app, const crow::Request& req,
88 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
89 const std::string& chassisId)
90{
91 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
92 {
93 return;
94 }
95
96 redfish::chassis_utils::getValidChassisPath(
97 asyncResp, chassisId,
98 [asyncResp,
99 chassisId](const std::optional<std::string>& validChassisPath) {
100 if (!validChassisPath)
101 {
102 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
103 return;
104 }
105 asyncResp->res.addHeader(
106 boost::beast::http::field::link,
107 "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
108 });
109}
110
111inline void handlePowerSupplyCollectionGet(
112 App& app, const crow::Request& req,
113 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
114 const std::string& chassisId)
115{
116 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
117 {
118 return;
119 }
120
121 redfish::chassis_utils::getValidChassisPath(
122 asyncResp, chassisId,
123 std::bind_front(doPowerSupplyCollection, asyncResp, chassisId));
124}
125
126inline void requestRoutesPowerSupplyCollection(App& app)
127{
128 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
129 .privileges(redfish::privileges::headPowerSupplyCollection)
130 .methods(boost::beast::http::verb::head)(
131 std::bind_front(handlePowerSupplyCollectionHead, std::ref(app)));
132
133 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
134 .privileges(redfish::privileges::getPowerSupplyCollection)
135 .methods(boost::beast::http::verb::get)(
136 std::bind_front(handlePowerSupplyCollectionGet, std::ref(app)));
137}
138
George Liu00ef5dc2022-10-05 16:27:52 +0800139inline bool checkPowerSupplyId(const std::string& powerSupplyPath,
140 const std::string& powerSupplyId)
141{
142 std::string powerSupplyName =
143 sdbusplus::message::object_path(powerSupplyPath).filename();
144
145 return !(powerSupplyName.empty() || powerSupplyName != powerSupplyId);
146}
147
148inline void
149 getValidPowerSupplyPath(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
150 const std::string& validChassisPath,
151 const std::string& powerSupplyId,
152 std::function<void()>&& callback)
153{
154 std::string powerPath = validChassisPath + "/powered_by";
155 dbus::utility::getAssociationEndPoints(
156 powerPath, [asyncResp, powerSupplyId, callback{std::move(callback)}](
157 const boost::system::error_code& ec,
158 const dbus::utility::MapperEndPoints& endpoints) {
159 if (ec)
160 {
161 if (ec.value() != EBADR)
162 {
163 BMCWEB_LOG_ERROR
164 << "DBUS response error for getAssociationEndPoints"
165 << ec.value();
166 messages::internalError(asyncResp->res);
167 return;
168 }
169 messages::resourceNotFound(asyncResp->res, "PowerSupplies",
170 powerSupplyId);
171 return;
172 }
173
174 for (const auto& endpoint : endpoints)
175 {
176 if (checkPowerSupplyId(endpoint, powerSupplyId))
177 {
178 callback();
179 return;
180 }
181 }
182
183 if (!endpoints.empty())
184 {
185 BMCWEB_LOG_WARNING << "Power supply not found: "
186 << powerSupplyId;
187 messages::resourceNotFound(asyncResp->res, "PowerSupplies",
188 powerSupplyId);
189 return;
190 }
191 });
192}
193
194inline void
195 doPowerSupplyGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
196 const std::string& chassisId,
197 const std::string& powerSupplyId,
198 const std::optional<std::string>& validChassisPath)
199{
200 if (!validChassisPath)
201 {
202 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
203 return;
204 }
205
206 // Get the correct Path and Service that match the input parameters
207 getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
208 [asyncResp, chassisId, powerSupplyId]() {
209 asyncResp->res.addHeader(
210 boost::beast::http::field::link,
211 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
212 asyncResp->res.jsonValue["@odata.type"] =
213 "#PowerSupply.v1_5_0.PowerSupply";
214 asyncResp->res.jsonValue["Name"] = "Power Supply";
215 asyncResp->res.jsonValue["Id"] = powerSupplyId;
216 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
217 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
218 powerSupplyId);
219 });
220}
221
222inline void
223 handlePowerSupplyHead(App& app, const crow::Request& req,
224 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
225 const std::string& chassisId,
226 const std::string& powerSupplyId)
227{
228 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
229 {
230 return;
231 }
232
233 redfish::chassis_utils::getValidChassisPath(
234 asyncResp, chassisId,
235 [asyncResp, chassisId,
236 powerSupplyId](const std::optional<std::string>& validChassisPath) {
237 if (!validChassisPath)
238 {
239 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
240 return;
241 }
242
243 // Get the correct Path and Service that match the input parameters
244 getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
245 [asyncResp]() {
246 asyncResp->res.addHeader(
247 boost::beast::http::field::link,
248 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
249 });
250 });
251}
252
253inline void
254 handlePowerSupplyGet(App& app, const crow::Request& req,
255 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
256 const std::string& chassisId,
257 const std::string& powerSupplyId)
258{
259 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
260 {
261 return;
262 }
263
264 redfish::chassis_utils::getValidChassisPath(
265 asyncResp, chassisId,
266 std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId));
267}
268
269inline void requestRoutesPowerSupply(App& app)
270{
271 BMCWEB_ROUTE(
272 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
273 .privileges(redfish::privileges::headPowerSupply)
274 .methods(boost::beast::http::verb::head)(
275 std::bind_front(handlePowerSupplyHead, std::ref(app)));
276
277 BMCWEB_ROUTE(
278 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
279 .privileges(redfish::privileges::getPowerSupply)
280 .methods(boost::beast::http::verb::get)(
281 std::bind_front(handlePowerSupplyGet, std::ref(app)));
282}
283
George Liua7210022022-10-05 15:44:11 +0800284} // namespace redfish