xref: /openbmc/bmcweb/features/redfish/lib/fabric_adapters.hpp (revision 37937d515e98beff1807438eb3c95329dfb035ab)
140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
33179105bSSunny Srivastava #pragma once
43179105bSSunny Srivastava 
5d7857201SEd Tanous #include "bmcweb_config.h"
6d7857201SEd Tanous 
73179105bSSunny Srivastava #include "app.hpp"
8d7857201SEd Tanous #include "async_resp.hpp"
93179105bSSunny Srivastava #include "dbus_utility.hpp"
10d7857201SEd Tanous #include "error_messages.hpp"
11539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
12d7857201SEd Tanous #include "http_request.hpp"
13be1384e3SMyung Bae #include "led.hpp"
14d7857201SEd Tanous #include "logging.hpp"
15a8e884fcSEd Tanous #include "query.hpp"
16a8e884fcSEd Tanous #include "registries/privilege_registry.hpp"
173179105bSSunny Srivastava #include "utils/collection.hpp"
186177a301SLakshmi Yadlapati #include "utils/dbus_utils.hpp"
19be1384e3SMyung Bae #include "utils/json_utils.hpp"
203179105bSSunny Srivastava 
21d7857201SEd Tanous #include <asm-generic/errno.h>
22d7857201SEd Tanous 
23d7857201SEd Tanous #include <boost/beast/http/field.hpp>
24d7857201SEd Tanous #include <boost/beast/http/verb.hpp>
253179105bSSunny Srivastava #include <boost/system/error_code.hpp>
26ef4c65b7SEd Tanous #include <boost/url/format.hpp>
276177a301SLakshmi Yadlapati #include <sdbusplus/unpack_properties.hpp>
283179105bSSunny Srivastava 
293179105bSSunny Srivastava #include <array>
303179105bSSunny Srivastava #include <functional>
313179105bSSunny Srivastava #include <memory>
32be1384e3SMyung Bae #include <optional>
333179105bSSunny Srivastava #include <string>
343179105bSSunny Srivastava #include <string_view>
35d7857201SEd Tanous #include <utility>
363179105bSSunny Srivastava 
373179105bSSunny Srivastava namespace redfish
383179105bSSunny Srivastava {
393179105bSSunny Srivastava 
40ac106bf6SEd Tanous inline void getFabricAdapterLocation(
41ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
42ac106bf6SEd Tanous     const std::string& serviceName, const std::string& fabricAdapterPath)
4353ffeca5SLakshmi Yadlapati {
44deae6a78SEd Tanous     dbus::utility::getProperty<std::string>(
45deae6a78SEd Tanous         serviceName, fabricAdapterPath,
4653ffeca5SLakshmi Yadlapati         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
47ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
4853ffeca5SLakshmi Yadlapati                     const std::string& property) {
4953ffeca5SLakshmi Yadlapati             if (ec)
5053ffeca5SLakshmi Yadlapati             {
5153ffeca5SLakshmi Yadlapati                 if (ec.value() != EBADR)
5253ffeca5SLakshmi Yadlapati                 {
5362598e31SEd Tanous                     BMCWEB_LOG_ERROR("DBUS response error for Location");
54ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
5553ffeca5SLakshmi Yadlapati                 }
5653ffeca5SLakshmi Yadlapati                 return;
5753ffeca5SLakshmi Yadlapati             }
5853ffeca5SLakshmi Yadlapati 
59bd79bce8SPatrick Williams             asyncResp->res
60bd79bce8SPatrick Williams                 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
6153ffeca5SLakshmi Yadlapati                 property;
6253ffeca5SLakshmi Yadlapati         });
6353ffeca5SLakshmi Yadlapati }
6453ffeca5SLakshmi Yadlapati 
65bd79bce8SPatrick Williams inline void getFabricAdapterAsset(
66bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
67bd79bce8SPatrick Williams     const std::string& serviceName, const std::string& fabricAdapterPath)
686369421dSLakshmi Yadlapati {
69deae6a78SEd Tanous     dbus::utility::getAllProperties(
70deae6a78SEd Tanous         serviceName, fabricAdapterPath,
716369421dSLakshmi Yadlapati         "xyz.openbmc_project.Inventory.Decorator.Asset",
72ac106bf6SEd Tanous         [fabricAdapterPath, asyncResp{asyncResp}](
73ac106bf6SEd Tanous             const boost::system::error_code& ec,
746369421dSLakshmi Yadlapati             const dbus::utility::DBusPropertiesMap& propertiesList) {
756369421dSLakshmi Yadlapati             if (ec)
766369421dSLakshmi Yadlapati             {
776369421dSLakshmi Yadlapati                 if (ec.value() != EBADR)
786369421dSLakshmi Yadlapati                 {
7962598e31SEd Tanous                     BMCWEB_LOG_ERROR("DBUS response error for Properties");
80ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
816369421dSLakshmi Yadlapati                 }
826369421dSLakshmi Yadlapati                 return;
836369421dSLakshmi Yadlapati             }
846369421dSLakshmi Yadlapati 
856369421dSLakshmi Yadlapati             const std::string* serialNumber = nullptr;
866369421dSLakshmi Yadlapati             const std::string* model = nullptr;
876369421dSLakshmi Yadlapati             const std::string* partNumber = nullptr;
886369421dSLakshmi Yadlapati             const std::string* sparePartNumber = nullptr;
896369421dSLakshmi Yadlapati 
906369421dSLakshmi Yadlapati             const bool success = sdbusplus::unpackPropertiesNoThrow(
91bd79bce8SPatrick Williams                 dbus_utils::UnpackErrorPrinter(), propertiesList,
92bd79bce8SPatrick Williams                 "SerialNumber", serialNumber, "Model", model, "PartNumber",
93bd79bce8SPatrick Williams                 partNumber, "SparePartNumber", sparePartNumber);
946369421dSLakshmi Yadlapati 
956369421dSLakshmi Yadlapati             if (!success)
966369421dSLakshmi Yadlapati             {
97ac106bf6SEd Tanous                 messages::internalError(asyncResp->res);
986369421dSLakshmi Yadlapati                 return;
996369421dSLakshmi Yadlapati             }
1006369421dSLakshmi Yadlapati 
1016369421dSLakshmi Yadlapati             if (serialNumber != nullptr)
1026369421dSLakshmi Yadlapati             {
103ac106bf6SEd Tanous                 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
1046369421dSLakshmi Yadlapati             }
1056369421dSLakshmi Yadlapati 
1066369421dSLakshmi Yadlapati             if (model != nullptr)
1076369421dSLakshmi Yadlapati             {
108ac106bf6SEd Tanous                 asyncResp->res.jsonValue["Model"] = *model;
1096369421dSLakshmi Yadlapati             }
1106369421dSLakshmi Yadlapati 
1116369421dSLakshmi Yadlapati             if (partNumber != nullptr)
1126369421dSLakshmi Yadlapati             {
113ac106bf6SEd Tanous                 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
1146369421dSLakshmi Yadlapati             }
1156369421dSLakshmi Yadlapati 
1166369421dSLakshmi Yadlapati             if (sparePartNumber != nullptr && !sparePartNumber->empty())
1176369421dSLakshmi Yadlapati             {
118ac106bf6SEd Tanous                 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
1196369421dSLakshmi Yadlapati             }
1206369421dSLakshmi Yadlapati         });
1216369421dSLakshmi Yadlapati }
1226369421dSLakshmi Yadlapati 
123bd79bce8SPatrick Williams inline void getFabricAdapterState(
124bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
125bd79bce8SPatrick Williams     const std::string& serviceName, const std::string& fabricAdapterPath)
126cd7af44fSLakshmi Yadlapati {
127deae6a78SEd Tanous     dbus::utility::getProperty<bool>(
128deae6a78SEd Tanous         serviceName, fabricAdapterPath, "xyz.openbmc_project.Inventory.Item",
129deae6a78SEd Tanous         "Present",
130ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec, const bool present) {
131cd7af44fSLakshmi Yadlapati             if (ec)
132cd7af44fSLakshmi Yadlapati             {
133cd7af44fSLakshmi Yadlapati                 if (ec.value() != EBADR)
134cd7af44fSLakshmi Yadlapati                 {
13562598e31SEd Tanous                     BMCWEB_LOG_ERROR("DBUS response error for State");
136ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
137cd7af44fSLakshmi Yadlapati                 }
138cd7af44fSLakshmi Yadlapati                 return;
139cd7af44fSLakshmi Yadlapati             }
140cd7af44fSLakshmi Yadlapati 
141cd7af44fSLakshmi Yadlapati             if (!present)
142cd7af44fSLakshmi Yadlapati             {
143539d8c6bSEd Tanous                 asyncResp->res.jsonValue["Status"]["State"] =
144539d8c6bSEd Tanous                     resource::State::Absent;
145cd7af44fSLakshmi Yadlapati             }
146cd7af44fSLakshmi Yadlapati         });
147cd7af44fSLakshmi Yadlapati }
148cd7af44fSLakshmi Yadlapati 
149bd79bce8SPatrick Williams inline void getFabricAdapterHealth(
150bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
151bd79bce8SPatrick Williams     const std::string& serviceName, const std::string& fabricAdapterPath)
1527da847b6SLakshmi Yadlapati {
153deae6a78SEd Tanous     dbus::utility::getProperty<bool>(
154deae6a78SEd Tanous         serviceName, fabricAdapterPath,
1557da847b6SLakshmi Yadlapati         "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
156ac106bf6SEd Tanous         [asyncResp](const boost::system::error_code& ec,
157ac106bf6SEd Tanous                     const bool functional) {
1587da847b6SLakshmi Yadlapati             if (ec)
1597da847b6SLakshmi Yadlapati             {
1607da847b6SLakshmi Yadlapati                 if (ec.value() != EBADR)
1617da847b6SLakshmi Yadlapati                 {
16262598e31SEd Tanous                     BMCWEB_LOG_ERROR("DBUS response error for Health");
163ac106bf6SEd Tanous                     messages::internalError(asyncResp->res);
1647da847b6SLakshmi Yadlapati                 }
1657da847b6SLakshmi Yadlapati                 return;
1667da847b6SLakshmi Yadlapati             }
1677da847b6SLakshmi Yadlapati 
1687da847b6SLakshmi Yadlapati             if (!functional)
1697da847b6SLakshmi Yadlapati             {
170539d8c6bSEd Tanous                 asyncResp->res.jsonValue["Status"]["Health"] =
171539d8c6bSEd Tanous                     resource::Health::Critical;
1727da847b6SLakshmi Yadlapati             }
1737da847b6SLakshmi Yadlapati         });
1747da847b6SLakshmi Yadlapati }
1757da847b6SLakshmi Yadlapati 
176bd79bce8SPatrick Williams inline void doAdapterGet(
177bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
178bd79bce8SPatrick Williams     const std::string& systemName, const std::string& adapterId,
179bd79bce8SPatrick Williams     const std::string& fabricAdapterPath, const std::string& serviceName)
1803179105bSSunny Srivastava {
181ac106bf6SEd Tanous     asyncResp->res.addHeader(
1823179105bSSunny Srivastava         boost::beast::http::field::link,
1833179105bSSunny Srivastava         "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
184ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
185ac106bf6SEd Tanous         "#FabricAdapter.v1_4_0.FabricAdapter";
186ac106bf6SEd Tanous     asyncResp->res.jsonValue["Name"] = "Fabric Adapter";
187ac106bf6SEd Tanous     asyncResp->res.jsonValue["Id"] = adapterId;
188ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
189ef4c65b7SEd Tanous         "/redfish/v1/Systems/{}/FabricAdapters/{}", systemName, adapterId);
19053ffeca5SLakshmi Yadlapati 
191539d8c6bSEd Tanous     asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
192539d8c6bSEd Tanous     asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
193cd7af44fSLakshmi Yadlapati 
194*37937d51SGeorge Liu     asyncResp->res.jsonValue["Ports"]["@odata.id"] =
195*37937d51SGeorge Liu         boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters/{}/Ports",
196*37937d51SGeorge Liu                             systemName, adapterId);
197*37937d51SGeorge Liu 
198ac106bf6SEd Tanous     getFabricAdapterLocation(asyncResp, serviceName, fabricAdapterPath);
199ac106bf6SEd Tanous     getFabricAdapterAsset(asyncResp, serviceName, fabricAdapterPath);
200ac106bf6SEd Tanous     getFabricAdapterState(asyncResp, serviceName, fabricAdapterPath);
201ac106bf6SEd Tanous     getFabricAdapterHealth(asyncResp, serviceName, fabricAdapterPath);
202be1384e3SMyung Bae     getLocationIndicatorActive(asyncResp, fabricAdapterPath);
2033179105bSSunny Srivastava }
2043179105bSSunny Srivastava 
20578c90203SMyung Bae inline void afterGetValidFabricAdapterPath(
20678c90203SMyung Bae     const std::string& adapterId,
20778c90203SMyung Bae     std::function<void(const boost::system::error_code&,
20878c90203SMyung Bae                        const std::string& fabricAdapterPath,
20978c90203SMyung Bae                        const std::string& serviceName)>& callback,
21078c90203SMyung Bae     const boost::system::error_code& ec,
21178c90203SMyung Bae     const dbus::utility::MapperGetSubTreeResponse& subtree)
21278c90203SMyung Bae {
21378c90203SMyung Bae     std::string fabricAdapterPath;
21478c90203SMyung Bae     std::string serviceName;
21578c90203SMyung Bae     if (ec)
21678c90203SMyung Bae     {
21778c90203SMyung Bae         callback(ec, fabricAdapterPath, serviceName);
21878c90203SMyung Bae         return;
21978c90203SMyung Bae     }
22078c90203SMyung Bae 
22178c90203SMyung Bae     for (const auto& [adapterPath, serviceMap] : subtree)
2223179105bSSunny Srivastava     {
2233179105bSSunny Srivastava         std::string fabricAdapterName =
2243179105bSSunny Srivastava             sdbusplus::message::object_path(adapterPath).filename();
22578c90203SMyung Bae         if (fabricAdapterName == adapterId)
22678c90203SMyung Bae         {
22778c90203SMyung Bae             fabricAdapterPath = adapterPath;
22878c90203SMyung Bae             serviceName = serviceMap.begin()->first;
22978c90203SMyung Bae             break;
23078c90203SMyung Bae         }
23178c90203SMyung Bae     }
23278c90203SMyung Bae     callback(ec, fabricAdapterPath, serviceName);
2333179105bSSunny Srivastava }
2343179105bSSunny Srivastava 
2353179105bSSunny Srivastava inline void getValidFabricAdapterPath(
23678c90203SMyung Bae     const std::string& adapterId,
23778c90203SMyung Bae     std::function<void(const boost::system::error_code& ec,
23878c90203SMyung Bae                        const std::string& fabricAdapterPath,
2393179105bSSunny Srivastava                        const std::string& serviceName)>&& callback)
2403179105bSSunny Srivastava {
2413179105bSSunny Srivastava     constexpr std::array<std::string_view, 1> interfaces{
2423179105bSSunny Srivastava         "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
24378c90203SMyung Bae     dbus::utility::getSubTree("/xyz/openbmc_project/inventory", 0, interfaces,
24478c90203SMyung Bae                               std::bind_front(afterGetValidFabricAdapterPath,
24578c90203SMyung Bae                                               adapterId, std::move(callback)));
24678c90203SMyung Bae }
2473179105bSSunny Srivastava 
24878c90203SMyung Bae inline void afterHandleFabricAdapterGet(
24978c90203SMyung Bae     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
25078c90203SMyung Bae     const std::string& systemName, const std::string& adapterId,
25178c90203SMyung Bae     const boost::system::error_code& ec, const std::string& fabricAdapterPath,
25278c90203SMyung Bae     const std::string& serviceName)
25378c90203SMyung Bae {
2543179105bSSunny Srivastava     if (ec)
2553179105bSSunny Srivastava     {
25678c90203SMyung Bae         if (ec.value() == boost::system::errc::io_error)
25778c90203SMyung Bae         {
25878c90203SMyung Bae             messages::resourceNotFound(asyncResp->res, "FabricAdapter",
25978c90203SMyung Bae                                        adapterId);
2603179105bSSunny Srivastava             return;
2613179105bSSunny Srivastava         }
26278c90203SMyung Bae 
26378c90203SMyung Bae         BMCWEB_LOG_ERROR("DBus method call failed with error {}", ec.value());
26478c90203SMyung Bae         messages::internalError(asyncResp->res);
2653179105bSSunny Srivastava         return;
2663179105bSSunny Srivastava     }
26778c90203SMyung Bae     if (fabricAdapterPath.empty() || serviceName.empty())
26878c90203SMyung Bae     {
26962598e31SEd Tanous         BMCWEB_LOG_WARNING("Adapter not found");
270ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "FabricAdapter", adapterId);
27178c90203SMyung Bae         return;
27278c90203SMyung Bae     }
27378c90203SMyung Bae     doAdapterGet(asyncResp, systemName, adapterId, fabricAdapterPath,
27478c90203SMyung Bae                  serviceName);
2753179105bSSunny Srivastava }
2763179105bSSunny Srivastava 
277bd79bce8SPatrick Williams inline void handleFabricAdapterGet(
278bd79bce8SPatrick Williams     App& app, const crow::Request& req,
279ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
280bd79bce8SPatrick Williams     const std::string& systemName, const std::string& adapterId)
2813179105bSSunny Srivastava {
282ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2833179105bSSunny Srivastava     {
2843179105bSSunny Srivastava         return;
2853179105bSSunny Srivastava     }
28625b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2877f3e84a1SEd Tanous     {
2887f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
2897f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2907f3e84a1SEd Tanous                                    systemName);
2917f3e84a1SEd Tanous         return;
2927f3e84a1SEd Tanous     }
293253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
29478c90203SMyung Bae     {
29578c90203SMyung Bae         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
29678c90203SMyung Bae                                    systemName);
29778c90203SMyung Bae         return;
29878c90203SMyung Bae     }
2993179105bSSunny Srivastava     getValidFabricAdapterPath(
30078c90203SMyung Bae         adapterId, std::bind_front(afterHandleFabricAdapterGet, asyncResp,
30178c90203SMyung Bae                                    systemName, adapterId));
3023179105bSSunny Srivastava }
3033179105bSSunny Srivastava 
304be1384e3SMyung Bae inline void afterHandleFabricAdapterPatch(
305be1384e3SMyung Bae     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
306be1384e3SMyung Bae     const std::string& adapterId, std::optional<bool> locationIndicatorActive,
307be1384e3SMyung Bae     const boost::system::error_code& ec, const std::string& fabricAdapterPath,
308be1384e3SMyung Bae     const std::string& serviceName)
309be1384e3SMyung Bae {
310be1384e3SMyung Bae     if (ec)
311be1384e3SMyung Bae     {
312be1384e3SMyung Bae         if (ec.value() == boost::system::errc::io_error)
313be1384e3SMyung Bae         {
314be1384e3SMyung Bae             messages::resourceNotFound(asyncResp->res, "FabricAdapter",
315be1384e3SMyung Bae                                        adapterId);
316be1384e3SMyung Bae             return;
317be1384e3SMyung Bae         }
318be1384e3SMyung Bae 
319be1384e3SMyung Bae         BMCWEB_LOG_ERROR("DBus method call failed with error {}", ec.value());
320be1384e3SMyung Bae         messages::internalError(asyncResp->res);
321be1384e3SMyung Bae         return;
322be1384e3SMyung Bae     }
323be1384e3SMyung Bae     if (fabricAdapterPath.empty() || serviceName.empty())
324be1384e3SMyung Bae     {
325be1384e3SMyung Bae         BMCWEB_LOG_WARNING("Adapter {} not found", adapterId);
326be1384e3SMyung Bae         messages::resourceNotFound(asyncResp->res, "FabricAdapter", adapterId);
327be1384e3SMyung Bae         return;
328be1384e3SMyung Bae     }
329be1384e3SMyung Bae 
330be1384e3SMyung Bae     if (locationIndicatorActive)
331be1384e3SMyung Bae     {
332be1384e3SMyung Bae         setLocationIndicatorActive(asyncResp, fabricAdapterPath,
333be1384e3SMyung Bae                                    *locationIndicatorActive);
334be1384e3SMyung Bae     }
335be1384e3SMyung Bae }
336be1384e3SMyung Bae 
337be1384e3SMyung Bae inline void handleFabricAdapterPatch(
338be1384e3SMyung Bae     App& app, const crow::Request& req,
339be1384e3SMyung Bae     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
340be1384e3SMyung Bae     const std::string& systemName, const std::string& adapterId)
341be1384e3SMyung Bae {
342be1384e3SMyung Bae     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
343be1384e3SMyung Bae     {
344be1384e3SMyung Bae         return;
345be1384e3SMyung Bae     }
346be1384e3SMyung Bae     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
347be1384e3SMyung Bae     {
348be1384e3SMyung Bae         // Option currently returns no systems.  TBD
349be1384e3SMyung Bae         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
350be1384e3SMyung Bae                                    systemName);
351be1384e3SMyung Bae         return;
352be1384e3SMyung Bae     }
353be1384e3SMyung Bae     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
354be1384e3SMyung Bae     {
355be1384e3SMyung Bae         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
356be1384e3SMyung Bae                                    systemName);
357be1384e3SMyung Bae         return;
358be1384e3SMyung Bae     }
359be1384e3SMyung Bae 
360be1384e3SMyung Bae     std::optional<bool> locationIndicatorActive;
361be1384e3SMyung Bae 
362be1384e3SMyung Bae     if (!json_util::readJsonPatch(req, asyncResp->res,
363be1384e3SMyung Bae                                   "LocationIndicatorActive",
364be1384e3SMyung Bae                                   locationIndicatorActive))
365be1384e3SMyung Bae     {
366be1384e3SMyung Bae         return;
367be1384e3SMyung Bae     }
368be1384e3SMyung Bae 
369be1384e3SMyung Bae     getValidFabricAdapterPath(
370be1384e3SMyung Bae         adapterId, std::bind_front(afterHandleFabricAdapterPatch, asyncResp,
371be1384e3SMyung Bae                                    adapterId, locationIndicatorActive));
372be1384e3SMyung Bae }
373be1384e3SMyung Bae 
3743179105bSSunny Srivastava inline void handleFabricAdapterCollectionGet(
3753179105bSSunny Srivastava     crow::App& app, const crow::Request& req,
376ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3773179105bSSunny Srivastava     const std::string& systemName)
3783179105bSSunny Srivastava {
379ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3803179105bSSunny Srivastava     {
3813179105bSSunny Srivastava         return;
3823179105bSSunny Srivastava     }
38325b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3847f3e84a1SEd Tanous     {
3857f3e84a1SEd Tanous         // Option currently returns no systems. TBD
3867f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3877f3e84a1SEd Tanous                                    systemName);
3887f3e84a1SEd Tanous         return;
3897f3e84a1SEd Tanous     }
390253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3913179105bSSunny Srivastava     {
392ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
393ac106bf6SEd Tanous                                    systemName);
3943179105bSSunny Srivastava         return;
3953179105bSSunny Srivastava     }
3963179105bSSunny Srivastava 
397ac106bf6SEd Tanous     asyncResp->res.addHeader(
3983179105bSSunny Srivastava         boost::beast::http::field::link,
3993179105bSSunny Srivastava         "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
400ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
4013179105bSSunny Srivastava         "#FabricAdapterCollection.FabricAdapterCollection";
402ac106bf6SEd Tanous     asyncResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
403ac106bf6SEd Tanous     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
404ef4c65b7SEd Tanous         "/redfish/v1/Systems/{}/FabricAdapters", systemName);
4053179105bSSunny Srivastava 
4063179105bSSunny Srivastava     constexpr std::array<std::string_view, 1> interfaces{
4073179105bSSunny Srivastava         "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
4083179105bSSunny Srivastava     collection_util::getCollectionMembers(
409ac106bf6SEd Tanous         asyncResp,
410253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
411253f11b8SEd Tanous                             BMCWEB_REDFISH_SYSTEM_URI_NAME),
41236b5f1edSLakshmi Yadlapati         interfaces, "/xyz/openbmc_project/inventory");
4133179105bSSunny Srivastava }
4143179105bSSunny Srivastava 
4153179105bSSunny Srivastava inline void handleFabricAdapterCollectionHead(
4163179105bSSunny Srivastava     crow::App& app, const crow::Request& req,
417ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4183179105bSSunny Srivastava     const std::string& systemName)
4193179105bSSunny Srivastava {
420ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
4213179105bSSunny Srivastava     {
4223179105bSSunny Srivastava         return;
4233179105bSSunny Srivastava     }
42425b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
4257f3e84a1SEd Tanous     {
4267f3e84a1SEd Tanous         // Option currently returns no systems.  TBD
4277f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
4287f3e84a1SEd Tanous                                    systemName);
4297f3e84a1SEd Tanous         return;
4307f3e84a1SEd Tanous     }
431253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
4323179105bSSunny Srivastava     {
433ac106bf6SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
434ac106bf6SEd Tanous                                    systemName);
4353179105bSSunny Srivastava         return;
4363179105bSSunny Srivastava     }
437ac106bf6SEd Tanous     asyncResp->res.addHeader(
4383179105bSSunny Srivastava         boost::beast::http::field::link,
4393179105bSSunny Srivastava         "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
4403179105bSSunny Srivastava }
4413179105bSSunny Srivastava 
44278c90203SMyung Bae inline void afterHandleFabricAdapterHead(
44378c90203SMyung Bae     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
44478c90203SMyung Bae     const std::string& adapterId, const boost::system::error_code& ec,
44578c90203SMyung Bae     const std::string& fabricAdapterPath, const std::string& serviceName)
44678c90203SMyung Bae {
44778c90203SMyung Bae     if (ec)
44878c90203SMyung Bae     {
44978c90203SMyung Bae         if (ec.value() == boost::system::errc::io_error)
45078c90203SMyung Bae         {
45178c90203SMyung Bae             messages::resourceNotFound(asyncResp->res, "FabricAdapter",
45278c90203SMyung Bae                                        adapterId);
45378c90203SMyung Bae             return;
45478c90203SMyung Bae         }
45578c90203SMyung Bae 
45678c90203SMyung Bae         BMCWEB_LOG_ERROR("DBus method call failed with error {}", ec.value());
45778c90203SMyung Bae         messages::internalError(asyncResp->res);
45878c90203SMyung Bae         return;
45978c90203SMyung Bae     }
46078c90203SMyung Bae     if (fabricAdapterPath.empty() || serviceName.empty())
46178c90203SMyung Bae     {
46278c90203SMyung Bae         BMCWEB_LOG_WARNING("Adapter not found");
46378c90203SMyung Bae         messages::resourceNotFound(asyncResp->res, "FabricAdapter", adapterId);
46478c90203SMyung Bae         return;
46578c90203SMyung Bae     }
46678c90203SMyung Bae     asyncResp->res.addHeader(
46778c90203SMyung Bae         boost::beast::http::field::link,
46878c90203SMyung Bae         "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
46978c90203SMyung Bae }
47078c90203SMyung Bae 
471bd79bce8SPatrick Williams inline void handleFabricAdapterHead(
472bd79bce8SPatrick Williams     crow::App& app, const crow::Request& req,
473ac106bf6SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
474bd79bce8SPatrick Williams     const std::string& systemName, const std::string& adapterId)
4753179105bSSunny Srivastava {
476ac106bf6SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
4773179105bSSunny Srivastava     {
4783179105bSSunny Srivastava         return;
4793179105bSSunny Srivastava     }
4803179105bSSunny Srivastava 
48125b54dbaSEd Tanous     if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
4827f3e84a1SEd Tanous     {
4837f3e84a1SEd Tanous         // Option currently returns no systems. TBD
4847f3e84a1SEd Tanous         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
4857f3e84a1SEd Tanous                                    systemName);
4867f3e84a1SEd Tanous         return;
4877f3e84a1SEd Tanous     }
488253f11b8SEd Tanous     if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
48978c90203SMyung Bae     {
49078c90203SMyung Bae         messages::resourceNotFound(asyncResp->res, "ComputerSystem",
49178c90203SMyung Bae                                    systemName);
49278c90203SMyung Bae         return;
49378c90203SMyung Bae     }
49478c90203SMyung Bae     getValidFabricAdapterPath(
49578c90203SMyung Bae         adapterId,
49678c90203SMyung Bae         std::bind_front(afterHandleFabricAdapterHead, asyncResp, adapterId));
4973179105bSSunny Srivastava }
4983179105bSSunny Srivastava 
4993179105bSSunny Srivastava inline void requestRoutesFabricAdapterCollection(App& app)
5003179105bSSunny Srivastava {
5013179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
5023179105bSSunny Srivastava         .privileges(redfish::privileges::getFabricAdapterCollection)
5033179105bSSunny Srivastava         .methods(boost::beast::http::verb::get)(
5043179105bSSunny Srivastava             std::bind_front(handleFabricAdapterCollectionGet, std::ref(app)));
5053179105bSSunny Srivastava 
5063179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
5073179105bSSunny Srivastava         .privileges(redfish::privileges::headFabricAdapterCollection)
5083179105bSSunny Srivastava         .methods(boost::beast::http::verb::head)(
5093179105bSSunny Srivastava             std::bind_front(handleFabricAdapterCollectionHead, std::ref(app)));
5103179105bSSunny Srivastava }
5113179105bSSunny Srivastava 
5123179105bSSunny Srivastava inline void requestRoutesFabricAdapters(App& app)
5133179105bSSunny Srivastava {
5143179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
5153179105bSSunny Srivastava         .privileges(redfish::privileges::getFabricAdapter)
5163179105bSSunny Srivastava         .methods(boost::beast::http::verb::get)(
5173179105bSSunny Srivastava             std::bind_front(handleFabricAdapterGet, std::ref(app)));
5183179105bSSunny Srivastava 
5193179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
5203179105bSSunny Srivastava         .privileges(redfish::privileges::headFabricAdapter)
5213179105bSSunny Srivastava         .methods(boost::beast::http::verb::head)(
5223179105bSSunny Srivastava             std::bind_front(handleFabricAdapterHead, std::ref(app)));
523be1384e3SMyung Bae 
524be1384e3SMyung Bae     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
525be1384e3SMyung Bae         .privileges(redfish::privileges::patchFabricAdapter)
526be1384e3SMyung Bae         .methods(boost::beast::http::verb::patch)(
527be1384e3SMyung Bae             std::bind_front(handleFabricAdapterPatch, std::ref(app)));
5283179105bSSunny Srivastava }
5293179105bSSunny Srivastava } // namespace redfish
530