blob: 317348f760af9c84e2b2a6968cebdb659cb1e3b0 [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>
Ed Tanousef4c65b2023-04-24 15:28:50 -070012#include <boost/url/format.hpp>
Gunnar Millsf05e9162023-02-16 20:23:30 -060013#include <sdbusplus/asio/property.hpp>
Lakshmi Yadlapati6177a302023-02-17 10:29:34 -060014#include <sdbusplus/unpack_properties.hpp>
Sunny Srivastava31791052021-03-12 10:39:16 -060015
16#include <array>
17#include <functional>
18#include <memory>
19#include <string>
20#include <string_view>
21
22namespace redfish
23{
24
25inline void handleAdapterError(const boost::system::error_code& ec,
26 crow::Response& res,
27 const std::string& adapterId)
28{
Sunny Srivastava31791052021-03-12 10:39:16 -060029 if (ec.value() == boost::system::errc::io_error)
30 {
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060031 messages::resourceNotFound(res, "#FabricAdapter.v1_4_0.FabricAdapter",
Sunny Srivastava31791052021-03-12 10:39:16 -060032 adapterId);
33 return;
34 }
35
Ed Tanous62598e32023-07-17 17:06:25 -070036 BMCWEB_LOG_ERROR("DBus method call failed with error {}", ec.value());
Sunny Srivastava31791052021-03-12 10:39:16 -060037 messages::internalError(res);
38}
39
Ed Tanousac106bf2023-06-07 09:24:59 -070040inline void getFabricAdapterLocation(
41 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
42 const std::string& serviceName, const std::string& fabricAdapterPath)
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060043{
44 sdbusplus::asio::getProperty<std::string>(
45 *crow::connections::systemBus, serviceName, fabricAdapterPath,
46 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Ed Tanousac106bf2023-06-07 09:24:59 -070047 [asyncResp](const boost::system::error_code& ec,
48 const std::string& property) {
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060049 if (ec)
50 {
51 if (ec.value() != EBADR)
52 {
Ed Tanous62598e32023-07-17 17:06:25 -070053 BMCWEB_LOG_ERROR("DBUS response error for Location");
Ed Tanousac106bf2023-06-07 09:24:59 -070054 messages::internalError(asyncResp->res);
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060055 }
56 return;
57 }
58
Ed Tanousac106bf2023-06-07 09:24:59 -070059 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060060 property;
61 });
62}
63
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060064inline void
Ed Tanousac106bf2023-06-07 09:24:59 -070065 getFabricAdapterAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060066 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",
Ed Tanousac106bf2023-06-07 09:24:59 -070072 [fabricAdapterPath, asyncResp{asyncResp}](
73 const boost::system::error_code& ec,
74 const dbus::utility::DBusPropertiesMap& propertiesList) {
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060075 if (ec)
76 {
77 if (ec.value() != EBADR)
78 {
Ed Tanous62598e32023-07-17 17:06:25 -070079 BMCWEB_LOG_ERROR("DBUS response error for Properties");
Ed Tanousac106bf2023-06-07 09:24:59 -070080 messages::internalError(asyncResp->res);
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060081 }
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 {
Ed Tanousac106bf2023-06-07 09:24:59 -070097 messages::internalError(asyncResp->res);
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060098 return;
99 }
100
101 if (serialNumber != nullptr)
102 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700103 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
Lakshmi Yadlapati63694212023-01-27 16:35:22 -0600104 }
105
106 if (model != nullptr)
107 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700108 asyncResp->res.jsonValue["Model"] = *model;
Lakshmi Yadlapati63694212023-01-27 16:35:22 -0600109 }
110
111 if (partNumber != nullptr)
112 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700113 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
Lakshmi Yadlapati63694212023-01-27 16:35:22 -0600114 }
115
116 if (sparePartNumber != nullptr && !sparePartNumber->empty())
117 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700118 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
Lakshmi Yadlapati63694212023-01-27 16:35:22 -0600119 }
120 });
121}
122
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600123inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700124 getFabricAdapterState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600125 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",
Ed Tanousac106bf2023-06-07 09:24:59 -0700131 [asyncResp](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 {
Ed Tanous62598e32023-07-17 17:06:25 -0700136 BMCWEB_LOG_ERROR("DBUS response error for State");
Ed Tanousac106bf2023-06-07 09:24:59 -0700137 messages::internalError(asyncResp->res);
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600138 }
139 return;
140 }
141
142 if (!present)
143 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700144 asyncResp->res.jsonValue["Status"]["State"] = "Absent";
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600145 }
146 });
147}
148
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600149inline void
Ed Tanousac106bf2023-06-07 09:24:59 -0700150 getFabricAdapterHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600151 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",
Ed Tanousac106bf2023-06-07 09:24:59 -0700157 [asyncResp](const boost::system::error_code& ec,
158 const bool functional) {
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600159 if (ec)
160 {
161 if (ec.value() != EBADR)
162 {
Ed Tanous62598e32023-07-17 17:06:25 -0700163 BMCWEB_LOG_ERROR("DBUS response error for Health");
Ed Tanousac106bf2023-06-07 09:24:59 -0700164 messages::internalError(asyncResp->res);
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600165 }
166 return;
167 }
168
169 if (!functional)
170 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700171 asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600172 }
173 });
174}
175
Ed Tanousac106bf2023-06-07 09:24:59 -0700176inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600177 const std::string& systemName,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600178 const std::string& adapterId,
179 const std::string& fabricAdapterPath,
180 const std::string& serviceName)
Sunny Srivastava31791052021-03-12 10:39:16 -0600181{
Ed Tanousac106bf2023-06-07 09:24:59 -0700182 asyncResp->res.addHeader(
Sunny Srivastava31791052021-03-12 10:39:16 -0600183 boost::beast::http::field::link,
184 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700185 asyncResp->res.jsonValue["@odata.type"] =
186 "#FabricAdapter.v1_4_0.FabricAdapter";
187 asyncResp->res.jsonValue["Name"] = "Fabric Adapter";
188 asyncResp->res.jsonValue["Id"] = adapterId;
189 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700190 "/redfish/v1/Systems/{}/FabricAdapters/{}", systemName, adapterId);
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600191
Ed Tanousac106bf2023-06-07 09:24:59 -0700192 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
193 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600194
Ed Tanousac106bf2023-06-07 09:24:59 -0700195 getFabricAdapterLocation(asyncResp, serviceName, fabricAdapterPath);
196 getFabricAdapterAsset(asyncResp, serviceName, fabricAdapterPath);
197 getFabricAdapterState(asyncResp, serviceName, fabricAdapterPath);
198 getFabricAdapterHealth(asyncResp, serviceName, fabricAdapterPath);
Sunny Srivastava31791052021-03-12 10:39:16 -0600199}
200
201inline bool checkFabricAdapterId(const std::string& adapterPath,
202 const std::string& adapterId)
203{
204 std::string fabricAdapterName =
205 sdbusplus::message::object_path(adapterPath).filename();
206
207 return !(fabricAdapterName.empty() || fabricAdapterName != adapterId);
208}
209
210inline void getValidFabricAdapterPath(
211 const std::string& adapterId, const std::string& systemName,
Ed Tanousac106bf2023-06-07 09:24:59 -0700212 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600213 std::function<void(const std::string& fabricAdapterPath,
214 const std::string& serviceName)>&& callback)
215{
216 if (systemName != "system")
217 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700218 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
219 systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600220 return;
221 }
222 constexpr std::array<std::string_view, 1> interfaces{
223 "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
224
225 dbus::utility::getSubTree(
226 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -0700227 [adapterId, asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600228 callback](const boost::system::error_code& ec,
229 const dbus::utility::MapperGetSubTreeResponse& subtree) {
230 if (ec)
231 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700232 handleAdapterError(ec, asyncResp->res, adapterId);
Sunny Srivastava31791052021-03-12 10:39:16 -0600233 return;
234 }
235 for (const auto& [adapterPath, serviceMap] : subtree)
236 {
237 if (checkFabricAdapterId(adapterPath, adapterId))
238 {
239 callback(adapterPath, serviceMap.begin()->first);
240 return;
241 }
242 }
Ed Tanous62598e32023-07-17 17:06:25 -0700243 BMCWEB_LOG_WARNING("Adapter not found");
Ed Tanousac106bf2023-06-07 09:24:59 -0700244 messages::resourceNotFound(asyncResp->res, "FabricAdapter", adapterId);
Sunny Srivastava31791052021-03-12 10:39:16 -0600245 });
246}
247
248inline void
249 handleFabricAdapterGet(App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700250 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600251 const std::string& systemName,
252 const std::string& adapterId)
253{
Ed Tanousac106bf2023-06-07 09:24:59 -0700254 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Sunny Srivastava31791052021-03-12 10:39:16 -0600255 {
256 return;
257 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800258 if constexpr (bmcwebEnableMultiHost)
259 {
260 // Option currently returns no systems. TBD
261 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
262 systemName);
263 return;
264 }
Sunny Srivastava31791052021-03-12 10:39:16 -0600265
266 getValidFabricAdapterPath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700267 adapterId, systemName, asyncResp,
268 [asyncResp, systemName, adapterId](const std::string& fabricAdapterPath,
269 const std::string& serviceName) {
270 doAdapterGet(asyncResp, systemName, adapterId, fabricAdapterPath,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600271 serviceName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600272 });
273}
274
275inline void handleFabricAdapterCollectionGet(
276 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700277 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600278 const std::string& systemName)
279{
Ed Tanousac106bf2023-06-07 09:24:59 -0700280 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Sunny Srivastava31791052021-03-12 10:39:16 -0600281 {
282 return;
283 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800284 if constexpr (bmcwebEnableMultiHost)
285 {
286 // Option currently returns no systems. TBD
287 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
288 systemName);
289 return;
290 }
Sunny Srivastava31791052021-03-12 10:39:16 -0600291 if (systemName != "system")
292 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700293 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
294 systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600295 return;
296 }
297
Ed Tanousac106bf2023-06-07 09:24:59 -0700298 asyncResp->res.addHeader(
Sunny Srivastava31791052021-03-12 10:39:16 -0600299 boost::beast::http::field::link,
300 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700301 asyncResp->res.jsonValue["@odata.type"] =
Sunny Srivastava31791052021-03-12 10:39:16 -0600302 "#FabricAdapterCollection.FabricAdapterCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700303 asyncResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
304 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700305 "/redfish/v1/Systems/{}/FabricAdapters", systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600306
307 constexpr std::array<std::string_view, 1> interfaces{
308 "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
309 collection_util::getCollectionMembers(
Ed Tanousac106bf2023-06-07 09:24:59 -0700310 asyncResp,
311 boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"),
Lakshmi Yadlapati36b5f1e2023-09-26 23:53:28 -0500312 interfaces, "/xyz/openbmc_project/inventory");
Sunny Srivastava31791052021-03-12 10:39:16 -0600313}
314
315inline void handleFabricAdapterCollectionHead(
316 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700317 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600318 const std::string& systemName)
319{
Ed Tanousac106bf2023-06-07 09:24:59 -0700320 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Sunny Srivastava31791052021-03-12 10:39:16 -0600321 {
322 return;
323 }
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800324 if constexpr (bmcwebEnableMultiHost)
325 {
326 // Option currently returns no systems. TBD
327 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
328 systemName);
329 return;
330 }
Sunny Srivastava31791052021-03-12 10:39:16 -0600331 if (systemName != "system")
332 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700333 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
334 systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600335 return;
336 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700337 asyncResp->res.addHeader(
Sunny Srivastava31791052021-03-12 10:39:16 -0600338 boost::beast::http::field::link,
339 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
340}
341
342inline void
343 handleFabricAdapterHead(crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700344 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600345 const std::string& systemName,
346 const std::string& adapterId)
347{
Ed Tanousac106bf2023-06-07 09:24:59 -0700348 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Sunny Srivastava31791052021-03-12 10:39:16 -0600349 {
350 return;
351 }
352
Ed Tanous7f3e84a2022-12-28 16:22:54 -0800353 if constexpr (bmcwebEnableMultiHost)
354 {
355 // Option currently returns no systems. TBD
356 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
357 systemName);
358 return;
359 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700360 getValidFabricAdapterPath(adapterId, systemName, asyncResp,
361 [asyncResp, systemName, adapterId](
362 const std::string&, const std::string&) {
363 asyncResp->res.addHeader(
Sunny Srivastava31791052021-03-12 10:39:16 -0600364 boost::beast::http::field::link,
365 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700366 });
Sunny Srivastava31791052021-03-12 10:39:16 -0600367}
368
369inline void requestRoutesFabricAdapterCollection(App& app)
370{
371 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
372 .privileges(redfish::privileges::getFabricAdapterCollection)
373 .methods(boost::beast::http::verb::get)(
374 std::bind_front(handleFabricAdapterCollectionGet, std::ref(app)));
375
376 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
377 .privileges(redfish::privileges::headFabricAdapterCollection)
378 .methods(boost::beast::http::verb::head)(
379 std::bind_front(handleFabricAdapterCollectionHead, std::ref(app)));
380}
381
382inline void requestRoutesFabricAdapters(App& app)
383{
384 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
385 .privileges(redfish::privileges::getFabricAdapter)
386 .methods(boost::beast::http::verb::get)(
387 std::bind_front(handleFabricAdapterGet, std::ref(app)));
388
389 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
390 .privileges(redfish::privileges::headFabricAdapter)
391 .methods(boost::beast::http::verb::head)(
392 std::bind_front(handleFabricAdapterHead, std::ref(app)));
393}
394} // namespace redfish