blob: be89fbc3c2a4a5b98e3d79f246c11430a2cfab0f [file] [log] [blame]
Sunny Srivastava31791052021-03-12 10:39:16 -06001#pragma once
2
3#include "app.hpp"
4#include "dbus_utility.hpp"
Ed Tanousa8e884f2023-01-13 17:40:03 -08005#include "query.hpp"
6#include "registries/privilege_registry.hpp"
Sunny Srivastava31791052021-03-12 10:39:16 -06007#include "utils/collection.hpp"
Lakshmi Yadlapati6177a302023-02-17 10:29:34 -06008#include "utils/dbus_utils.hpp"
Sunny Srivastava31791052021-03-12 10:39:16 -06009#include "utils/json_utils.hpp"
10
11#include <boost/system/error_code.hpp>
Gunnar Millsf05e9162023-02-16 20:23:30 -060012#include <sdbusplus/asio/property.hpp>
Lakshmi Yadlapati6177a302023-02-17 10:29:34 -060013#include <sdbusplus/unpack_properties.hpp>
Sunny Srivastava31791052021-03-12 10:39:16 -060014
15#include <array>
16#include <functional>
17#include <memory>
18#include <string>
19#include <string_view>
20
21namespace redfish
22{
23
24inline void handleAdapterError(const boost::system::error_code& ec,
25 crow::Response& res,
26 const std::string& adapterId)
27{
Sunny Srivastava31791052021-03-12 10:39:16 -060028 if (ec.value() == boost::system::errc::io_error)
29 {
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060030 messages::resourceNotFound(res, "#FabricAdapter.v1_4_0.FabricAdapter",
Sunny Srivastava31791052021-03-12 10:39:16 -060031 adapterId);
32 return;
33 }
34
35 BMCWEB_LOG_ERROR << "DBus method call failed with error " << ec.value();
36 messages::internalError(res);
37}
38
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060039inline void
40 getFabricAdapterLocation(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
41 const std::string& serviceName,
42 const std::string& fabricAdapterPath)
43{
44 sdbusplus::asio::getProperty<std::string>(
45 *crow::connections::systemBus, serviceName, fabricAdapterPath,
46 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -060047 [aResp](const boost::system::error_code& ec,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060048 const std::string& property) {
49 if (ec)
50 {
51 if (ec.value() != EBADR)
52 {
53 BMCWEB_LOG_ERROR << "DBUS response error for Location";
54 messages::internalError(aResp->res);
55 }
56 return;
57 }
58
59 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
60 property;
61 });
62}
63
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060064inline void
65 getFabricAdapterAsset(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
66 const std::string& serviceName,
67 const std::string& fabricAdapterPath)
68{
69 sdbusplus::asio::getAllProperties(
70 *crow::connections::systemBus, serviceName, fabricAdapterPath,
71 "xyz.openbmc_project.Inventory.Decorator.Asset",
72 [fabricAdapterPath,
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -060073 aResp{aResp}](const boost::system::error_code& ec,
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060074 const dbus::utility::DBusPropertiesMap& propertiesList) {
75 if (ec)
76 {
77 if (ec.value() != EBADR)
78 {
79 BMCWEB_LOG_ERROR << "DBUS response error for Properties";
80 messages::internalError(aResp->res);
81 }
82 return;
83 }
84
85 const std::string* serialNumber = nullptr;
86 const std::string* model = nullptr;
87 const std::string* partNumber = nullptr;
88 const std::string* sparePartNumber = nullptr;
89
90 const bool success = sdbusplus::unpackPropertiesNoThrow(
91 dbus_utils::UnpackErrorPrinter(), propertiesList, "SerialNumber",
92 serialNumber, "Model", model, "PartNumber", partNumber,
93 "SparePartNumber", sparePartNumber);
94
95 if (!success)
96 {
97 messages::internalError(aResp->res);
98 return;
99 }
100
101 if (serialNumber != nullptr)
102 {
103 aResp->res.jsonValue["SerialNumber"] = *serialNumber;
104 }
105
106 if (model != nullptr)
107 {
108 aResp->res.jsonValue["Model"] = *model;
109 }
110
111 if (partNumber != nullptr)
112 {
113 aResp->res.jsonValue["PartNumber"] = *partNumber;
114 }
115
116 if (sparePartNumber != nullptr && !sparePartNumber->empty())
117 {
118 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
119 }
120 });
121}
122
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600123inline void
124 getFabricAdapterState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
125 const std::string& serviceName,
126 const std::string& fabricAdapterPath)
127{
128 sdbusplus::asio::getProperty<bool>(
129 *crow::connections::systemBus, serviceName, fabricAdapterPath,
130 "xyz.openbmc_project.Inventory.Item", "Present",
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -0600131 [aResp](const boost::system::error_code& ec, const bool present) {
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600132 if (ec)
133 {
134 if (ec.value() != EBADR)
135 {
136 BMCWEB_LOG_ERROR << "DBUS response error for State";
137 messages::internalError(aResp->res);
138 }
139 return;
140 }
141
142 if (!present)
143 {
144 aResp->res.jsonValue["Status"]["State"] = "Absent";
145 }
146 });
147}
148
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600149inline void
150 getFabricAdapterHealth(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
151 const std::string& serviceName,
152 const std::string& fabricAdapterPath)
153{
154 sdbusplus::asio::getProperty<bool>(
155 *crow::connections::systemBus, serviceName, fabricAdapterPath,
156 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -0600157 [aResp](const boost::system::error_code& ec, const bool functional) {
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600158 if (ec)
159 {
160 if (ec.value() != EBADR)
161 {
162 BMCWEB_LOG_ERROR << "DBUS response error for Health";
163 messages::internalError(aResp->res);
164 }
165 return;
166 }
167
168 if (!functional)
169 {
170 aResp->res.jsonValue["Status"]["Health"] = "Critical";
171 }
172 });
173}
174
Sunny Srivastava31791052021-03-12 10:39:16 -0600175inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
176 const std::string& systemName,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600177 const std::string& adapterId,
178 const std::string& fabricAdapterPath,
179 const std::string& serviceName)
Sunny Srivastava31791052021-03-12 10:39:16 -0600180{
181 aResp->res.addHeader(
182 boost::beast::http::field::link,
183 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600184 aResp->res.jsonValue["@odata.type"] = "#FabricAdapter.v1_4_0.FabricAdapter";
Sunny Srivastava31791052021-03-12 10:39:16 -0600185 aResp->res.jsonValue["Name"] = "Fabric Adapter";
186 aResp->res.jsonValue["Id"] = adapterId;
187 aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
188 "redfish", "v1", "Systems", systemName, "FabricAdapters", adapterId);
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600189
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600190 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600191 aResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600192
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600193 getFabricAdapterLocation(aResp, serviceName, fabricAdapterPath);
Lakshmi Yadlapati63694212023-01-27 16:35:22 -0600194 getFabricAdapterAsset(aResp, serviceName, fabricAdapterPath);
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600195 getFabricAdapterState(aResp, serviceName, fabricAdapterPath);
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600196 getFabricAdapterHealth(aResp, serviceName, fabricAdapterPath);
Sunny Srivastava31791052021-03-12 10:39:16 -0600197}
198
199inline bool checkFabricAdapterId(const std::string& adapterPath,
200 const std::string& adapterId)
201{
202 std::string fabricAdapterName =
203 sdbusplus::message::object_path(adapterPath).filename();
204
205 return !(fabricAdapterName.empty() || fabricAdapterName != adapterId);
206}
207
208inline void getValidFabricAdapterPath(
209 const std::string& adapterId, const std::string& systemName,
210 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
211 std::function<void(const std::string& fabricAdapterPath,
212 const std::string& serviceName)>&& callback)
213{
214 if (systemName != "system")
215 {
216 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
217 return;
218 }
219 constexpr std::array<std::string_view, 1> interfaces{
220 "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
221
222 dbus::utility::getSubTree(
223 "/xyz/openbmc_project/inventory", 0, interfaces,
224 [adapterId, aResp,
225 callback](const boost::system::error_code& ec,
226 const dbus::utility::MapperGetSubTreeResponse& subtree) {
227 if (ec)
228 {
229 handleAdapterError(ec, aResp->res, adapterId);
230 return;
231 }
232 for (const auto& [adapterPath, serviceMap] : subtree)
233 {
234 if (checkFabricAdapterId(adapterPath, adapterId))
235 {
236 callback(adapterPath, serviceMap.begin()->first);
237 return;
238 }
239 }
240 BMCWEB_LOG_WARNING << "Adapter not found";
241 messages::resourceNotFound(aResp->res, "FabricAdapter", adapterId);
242 });
243}
244
245inline void
246 handleFabricAdapterGet(App& app, const crow::Request& req,
247 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
248 const std::string& systemName,
249 const std::string& adapterId)
250{
251 if (!redfish::setUpRedfishRoute(app, req, aResp))
252 {
253 return;
254 }
255
256 getValidFabricAdapterPath(
257 adapterId, systemName, aResp,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600258 [aResp, systemName, adapterId](const std::string& fabricAdapterPath,
259 const std::string& serviceName) {
260 doAdapterGet(aResp, systemName, adapterId, fabricAdapterPath,
261 serviceName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600262 });
263}
264
265inline void handleFabricAdapterCollectionGet(
266 crow::App& app, const crow::Request& req,
267 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
268 const std::string& systemName)
269{
270 if (!redfish::setUpRedfishRoute(app, req, aResp))
271 {
272 return;
273 }
274 if (systemName != "system")
275 {
276 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
277 return;
278 }
279
280 aResp->res.addHeader(
281 boost::beast::http::field::link,
282 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
283 aResp->res.jsonValue["@odata.type"] =
284 "#FabricAdapterCollection.FabricAdapterCollection";
285 aResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
286 aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
287 "redfish", "v1", "Systems", systemName, "FabricAdapters");
288
289 constexpr std::array<std::string_view, 1> interfaces{
290 "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
291 collection_util::getCollectionMembers(
292 aResp, boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"),
293 interfaces);
294}
295
296inline void handleFabricAdapterCollectionHead(
297 crow::App& app, const crow::Request& req,
298 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
299 const std::string& systemName)
300{
301 if (!redfish::setUpRedfishRoute(app, req, aResp))
302 {
303 return;
304 }
305 if (systemName != "system")
306 {
307 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
308 return;
309 }
310 aResp->res.addHeader(
311 boost::beast::http::field::link,
312 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
313}
314
315inline void
316 handleFabricAdapterHead(crow::App& app, const crow::Request& req,
317 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
318 const std::string& systemName,
319 const std::string& adapterId)
320{
321 if (!redfish::setUpRedfishRoute(app, req, aResp))
322 {
323 return;
324 }
325
326 getValidFabricAdapterPath(
327 adapterId, systemName, aResp,
328 [aResp, systemName, adapterId](const std::string&, const std::string&) {
329 aResp->res.addHeader(
330 boost::beast::http::field::link,
331 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
332 });
333}
334
335inline void requestRoutesFabricAdapterCollection(App& app)
336{
337 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
338 .privileges(redfish::privileges::getFabricAdapterCollection)
339 .methods(boost::beast::http::verb::get)(
340 std::bind_front(handleFabricAdapterCollectionGet, std::ref(app)));
341
342 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
343 .privileges(redfish::privileges::headFabricAdapterCollection)
344 .methods(boost::beast::http::verb::head)(
345 std::bind_front(handleFabricAdapterCollectionHead, std::ref(app)));
346}
347
348inline void requestRoutesFabricAdapters(App& app)
349{
350 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
351 .privileges(redfish::privileges::getFabricAdapter)
352 .methods(boost::beast::http::verb::get)(
353 std::bind_front(handleFabricAdapterGet, std::ref(app)));
354
355 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
356 .privileges(redfish::privileges::headFabricAdapter)
357 .methods(boost::beast::http::verb::head)(
358 std::bind_front(handleFabricAdapterHead, std::ref(app)));
359}
360} // namespace redfish