blob: 16174bf4bd6520623f4b8646627ccd1ddc76eed9 [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
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060040inline void
41 getFabricAdapterLocation(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
42 const std::string& serviceName,
43 const std::string& fabricAdapterPath)
44{
45 sdbusplus::asio::getProperty<std::string>(
46 *crow::connections::systemBus, serviceName, fabricAdapterPath,
47 "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -060048 [aResp](const boost::system::error_code& ec,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -060049 const std::string& property) {
50 if (ec)
51 {
52 if (ec.value() != EBADR)
53 {
54 BMCWEB_LOG_ERROR << "DBUS response error for Location";
55 messages::internalError(aResp->res);
56 }
57 return;
58 }
59
60 aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
61 property;
62 });
63}
64
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060065inline void
66 getFabricAdapterAsset(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
67 const std::string& serviceName,
68 const std::string& fabricAdapterPath)
69{
70 sdbusplus::asio::getAllProperties(
71 *crow::connections::systemBus, serviceName, fabricAdapterPath,
72 "xyz.openbmc_project.Inventory.Decorator.Asset",
73 [fabricAdapterPath,
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -060074 aResp{aResp}](const boost::system::error_code& ec,
Lakshmi Yadlapati63694212023-01-27 16:35:22 -060075 const dbus::utility::DBusPropertiesMap& propertiesList) {
76 if (ec)
77 {
78 if (ec.value() != EBADR)
79 {
80 BMCWEB_LOG_ERROR << "DBUS response error for Properties";
81 messages::internalError(aResp->res);
82 }
83 return;
84 }
85
86 const std::string* serialNumber = nullptr;
87 const std::string* model = nullptr;
88 const std::string* partNumber = nullptr;
89 const std::string* sparePartNumber = nullptr;
90
91 const bool success = sdbusplus::unpackPropertiesNoThrow(
92 dbus_utils::UnpackErrorPrinter(), propertiesList, "SerialNumber",
93 serialNumber, "Model", model, "PartNumber", partNumber,
94 "SparePartNumber", sparePartNumber);
95
96 if (!success)
97 {
98 messages::internalError(aResp->res);
99 return;
100 }
101
102 if (serialNumber != nullptr)
103 {
104 aResp->res.jsonValue["SerialNumber"] = *serialNumber;
105 }
106
107 if (model != nullptr)
108 {
109 aResp->res.jsonValue["Model"] = *model;
110 }
111
112 if (partNumber != nullptr)
113 {
114 aResp->res.jsonValue["PartNumber"] = *partNumber;
115 }
116
117 if (sparePartNumber != nullptr && !sparePartNumber->empty())
118 {
119 aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
120 }
121 });
122}
123
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600124inline void
125 getFabricAdapterState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
126 const std::string& serviceName,
127 const std::string& fabricAdapterPath)
128{
129 sdbusplus::asio::getProperty<bool>(
130 *crow::connections::systemBus, serviceName, fabricAdapterPath,
131 "xyz.openbmc_project.Inventory.Item", "Present",
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -0600132 [aResp](const boost::system::error_code& ec, const bool present) {
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600133 if (ec)
134 {
135 if (ec.value() != EBADR)
136 {
137 BMCWEB_LOG_ERROR << "DBUS response error for State";
138 messages::internalError(aResp->res);
139 }
140 return;
141 }
142
143 if (!present)
144 {
145 aResp->res.jsonValue["Status"]["State"] = "Absent";
146 }
147 });
148}
149
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600150inline void
151 getFabricAdapterHealth(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
152 const std::string& serviceName,
153 const std::string& fabricAdapterPath)
154{
155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, serviceName, fabricAdapterPath,
157 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -0600158 [aResp](const boost::system::error_code& ec, 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";
164 messages::internalError(aResp->res);
165 }
166 return;
167 }
168
169 if (!functional)
170 {
171 aResp->res.jsonValue["Status"]["Health"] = "Critical";
172 }
173 });
174}
175
Sunny Srivastava31791052021-03-12 10:39:16 -0600176inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
177 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{
182 aResp->res.addHeader(
183 boost::beast::http::field::link,
184 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600185 aResp->res.jsonValue["@odata.type"] = "#FabricAdapter.v1_4_0.FabricAdapter";
Sunny Srivastava31791052021-03-12 10:39:16 -0600186 aResp->res.jsonValue["Name"] = "Fabric Adapter";
187 aResp->res.jsonValue["Id"] = adapterId;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700188 aResp->res.jsonValue["@odata.id"] = boost::urls::format(
189 "/redfish/v1/Systems/{}/FabricAdapters/{}", systemName, adapterId);
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600190
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600191 aResp->res.jsonValue["Status"]["State"] = "Enabled";
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600192 aResp->res.jsonValue["Status"]["Health"] = "OK";
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600193
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600194 getFabricAdapterLocation(aResp, serviceName, fabricAdapterPath);
Lakshmi Yadlapati63694212023-01-27 16:35:22 -0600195 getFabricAdapterAsset(aResp, serviceName, fabricAdapterPath);
Lakshmi Yadlapaticd7af442023-01-27 17:31:40 -0600196 getFabricAdapterState(aResp, serviceName, fabricAdapterPath);
Lakshmi Yadlapati7da847b2023-01-27 17:53:18 -0600197 getFabricAdapterHealth(aResp, serviceName, fabricAdapterPath);
Sunny Srivastava31791052021-03-12 10:39:16 -0600198}
199
200inline bool checkFabricAdapterId(const std::string& adapterPath,
201 const std::string& adapterId)
202{
203 std::string fabricAdapterName =
204 sdbusplus::message::object_path(adapterPath).filename();
205
206 return !(fabricAdapterName.empty() || fabricAdapterName != adapterId);
207}
208
209inline void getValidFabricAdapterPath(
210 const std::string& adapterId, const std::string& systemName,
211 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
212 std::function<void(const std::string& fabricAdapterPath,
213 const std::string& serviceName)>&& callback)
214{
215 if (systemName != "system")
216 {
217 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
218 return;
219 }
220 constexpr std::array<std::string_view, 1> interfaces{
221 "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
222
223 dbus::utility::getSubTree(
224 "/xyz/openbmc_project/inventory", 0, interfaces,
225 [adapterId, aResp,
226 callback](const boost::system::error_code& ec,
227 const dbus::utility::MapperGetSubTreeResponse& subtree) {
228 if (ec)
229 {
230 handleAdapterError(ec, aResp->res, adapterId);
231 return;
232 }
233 for (const auto& [adapterPath, serviceMap] : subtree)
234 {
235 if (checkFabricAdapterId(adapterPath, adapterId))
236 {
237 callback(adapterPath, serviceMap.begin()->first);
238 return;
239 }
240 }
241 BMCWEB_LOG_WARNING << "Adapter not found";
242 messages::resourceNotFound(aResp->res, "FabricAdapter", adapterId);
243 });
244}
245
246inline void
247 handleFabricAdapterGet(App& app, const crow::Request& req,
248 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
249 const std::string& systemName,
250 const std::string& adapterId)
251{
252 if (!redfish::setUpRedfishRoute(app, req, aResp))
253 {
254 return;
255 }
256
257 getValidFabricAdapterPath(
258 adapterId, systemName, aResp,
Lakshmi Yadlapati53ffeca2023-01-27 15:12:23 -0600259 [aResp, systemName, adapterId](const std::string& fabricAdapterPath,
260 const std::string& serviceName) {
261 doAdapterGet(aResp, systemName, adapterId, fabricAdapterPath,
262 serviceName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600263 });
264}
265
266inline void handleFabricAdapterCollectionGet(
267 crow::App& app, const crow::Request& req,
268 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
269 const std::string& systemName)
270{
271 if (!redfish::setUpRedfishRoute(app, req, aResp))
272 {
273 return;
274 }
275 if (systemName != "system")
276 {
277 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
278 return;
279 }
280
281 aResp->res.addHeader(
282 boost::beast::http::field::link,
283 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
284 aResp->res.jsonValue["@odata.type"] =
285 "#FabricAdapterCollection.FabricAdapterCollection";
286 aResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700287 aResp->res.jsonValue["@odata.id"] = boost::urls::format(
288 "/redfish/v1/Systems/{}/FabricAdapters", systemName);
Sunny Srivastava31791052021-03-12 10:39:16 -0600289
290 constexpr std::array<std::string_view, 1> interfaces{
291 "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
292 collection_util::getCollectionMembers(
293 aResp, boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"),
294 interfaces);
295}
296
297inline void handleFabricAdapterCollectionHead(
298 crow::App& app, const crow::Request& req,
299 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
300 const std::string& systemName)
301{
302 if (!redfish::setUpRedfishRoute(app, req, aResp))
303 {
304 return;
305 }
306 if (systemName != "system")
307 {
308 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
309 return;
310 }
311 aResp->res.addHeader(
312 boost::beast::http::field::link,
313 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
314}
315
316inline void
317 handleFabricAdapterHead(crow::App& app, const crow::Request& req,
318 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
319 const std::string& systemName,
320 const std::string& adapterId)
321{
322 if (!redfish::setUpRedfishRoute(app, req, aResp))
323 {
324 return;
325 }
326
327 getValidFabricAdapterPath(
328 adapterId, systemName, aResp,
329 [aResp, systemName, adapterId](const std::string&, const std::string&) {
330 aResp->res.addHeader(
331 boost::beast::http::field::link,
332 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
333 });
334}
335
336inline void requestRoutesFabricAdapterCollection(App& app)
337{
338 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
339 .privileges(redfish::privileges::getFabricAdapterCollection)
340 .methods(boost::beast::http::verb::get)(
341 std::bind_front(handleFabricAdapterCollectionGet, std::ref(app)));
342
343 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
344 .privileges(redfish::privileges::headFabricAdapterCollection)
345 .methods(boost::beast::http::verb::head)(
346 std::bind_front(handleFabricAdapterCollectionHead, std::ref(app)));
347}
348
349inline void requestRoutesFabricAdapters(App& app)
350{
351 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
352 .privileges(redfish::privileges::getFabricAdapter)
353 .methods(boost::beast::http::verb::get)(
354 std::bind_front(handleFabricAdapterGet, std::ref(app)));
355
356 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
357 .privileges(redfish::privileges::headFabricAdapter)
358 .methods(boost::beast::http::verb::head)(
359 std::bind_front(handleFabricAdapterHead, std::ref(app)));
360}
361} // namespace redfish