blob: 2b4b4aefba4f306de97fd5e8e25936c001f69c60 [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
36 BMCWEB_LOG_ERROR << "DBus method call failed with error " << ec.value();
37 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 {
53 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 {
79 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 {
136 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 {
163 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 }
243 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 }
258
259 getValidFabricAdapterPath(
Ed Tanousac106bf2023-06-07 09:24:59 -0700260 adapterId, systemName, asyncResp,
261 [asyncResp, systemName, adapterId](const std::string& fabricAdapterPath,
262 const std::string& serviceName) {
263 doAdapterGet(asyncResp, systemName, adapterId, fabricAdapterPath,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600264 serviceName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600265 });
266}
267
268inline void handleFabricAdapterCollectionGet(
269 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700270 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600271 const std::string& systemName)
272{
Ed Tanousac106bf2023-06-07 09:24:59 -0700273 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Sunny Srivastava31791052021-03-12 10:39:16 -0600274 {
275 return;
276 }
277 if (systemName != "system")
278 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700279 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
280 systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600281 return;
282 }
283
Ed Tanousac106bf2023-06-07 09:24:59 -0700284 asyncResp->res.addHeader(
Sunny Srivastava31791052021-03-12 10:39:16 -0600285 boost::beast::http::field::link,
286 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700287 asyncResp->res.jsonValue["@odata.type"] =
Sunny Srivastava31791052021-03-12 10:39:16 -0600288 "#FabricAdapterCollection.FabricAdapterCollection";
Ed Tanousac106bf2023-06-07 09:24:59 -0700289 asyncResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
290 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
Ed Tanousef4c65b2023-04-24 15:28:50 -0700291 "/redfish/v1/Systems/{}/FabricAdapters", systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600292
293 constexpr std::array<std::string_view, 1> interfaces{
294 "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
295 collection_util::getCollectionMembers(
Ed Tanousac106bf2023-06-07 09:24:59 -0700296 asyncResp,
297 boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"),
Sunny Srivastava31791052021-03-12 10:39:16 -0600298 interfaces);
299}
300
301inline void handleFabricAdapterCollectionHead(
302 crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700303 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600304 const std::string& systemName)
305{
Ed Tanousac106bf2023-06-07 09:24:59 -0700306 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Sunny Srivastava31791052021-03-12 10:39:16 -0600307 {
308 return;
309 }
310 if (systemName != "system")
311 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700312 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
313 systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600314 return;
315 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700316 asyncResp->res.addHeader(
Sunny Srivastava31791052021-03-12 10:39:16 -0600317 boost::beast::http::field::link,
318 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
319}
320
321inline void
322 handleFabricAdapterHead(crow::App& app, const crow::Request& req,
Ed Tanousac106bf2023-06-07 09:24:59 -0700323 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Sunny Srivastava31791052021-03-12 10:39:16 -0600324 const std::string& systemName,
325 const std::string& adapterId)
326{
Ed Tanousac106bf2023-06-07 09:24:59 -0700327 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Sunny Srivastava31791052021-03-12 10:39:16 -0600328 {
329 return;
330 }
331
Ed Tanousac106bf2023-06-07 09:24:59 -0700332 getValidFabricAdapterPath(adapterId, systemName, asyncResp,
333 [asyncResp, systemName, adapterId](
334 const std::string&, const std::string&) {
335 asyncResp->res.addHeader(
Sunny Srivastava31791052021-03-12 10:39:16 -0600336 boost::beast::http::field::link,
337 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
Ed Tanousac106bf2023-06-07 09:24:59 -0700338 });
Sunny Srivastava31791052021-03-12 10:39:16 -0600339}
340
341inline void requestRoutesFabricAdapterCollection(App& app)
342{
343 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
344 .privileges(redfish::privileges::getFabricAdapterCollection)
345 .methods(boost::beast::http::verb::get)(
346 std::bind_front(handleFabricAdapterCollectionGet, std::ref(app)));
347
348 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
349 .privileges(redfish::privileges::headFabricAdapterCollection)
350 .methods(boost::beast::http::verb::head)(
351 std::bind_front(handleFabricAdapterCollectionHead, std::ref(app)));
352}
353
354inline void requestRoutesFabricAdapters(App& app)
355{
356 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
357 .privileges(redfish::privileges::getFabricAdapter)
358 .methods(boost::beast::http::verb::get)(
359 std::bind_front(handleFabricAdapterGet, std::ref(app)));
360
361 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
362 .privileges(redfish::privileges::headFabricAdapter)
363 .methods(boost::beast::http::verb::head)(
364 std::bind_front(handleFabricAdapterHead, std::ref(app)));
365}
366} // namespace redfish