xref: /openbmc/bmcweb/features/redfish/lib/fabric_adapters.hpp (revision cd7af44f12a56813a464b77828502138ed3eacf2)
13179105bSSunny Srivastava #pragma once
23179105bSSunny Srivastava 
33179105bSSunny Srivastava #include "app.hpp"
43179105bSSunny Srivastava #include "dbus_utility.hpp"
5a8e884fcSEd Tanous #include "query.hpp"
6a8e884fcSEd Tanous #include "registries/privilege_registry.hpp"
73179105bSSunny Srivastava #include "utils/collection.hpp"
83179105bSSunny Srivastava #include "utils/json_utils.hpp"
93179105bSSunny Srivastava 
103179105bSSunny Srivastava #include <boost/system/error_code.hpp>
113179105bSSunny Srivastava 
123179105bSSunny Srivastava #include <array>
133179105bSSunny Srivastava #include <functional>
143179105bSSunny Srivastava #include <memory>
153179105bSSunny Srivastava #include <string>
163179105bSSunny Srivastava #include <string_view>
173179105bSSunny Srivastava 
183179105bSSunny Srivastava namespace redfish
193179105bSSunny Srivastava {
203179105bSSunny Srivastava 
213179105bSSunny Srivastava inline void handleAdapterError(const boost::system::error_code& ec,
223179105bSSunny Srivastava                                crow::Response& res,
233179105bSSunny Srivastava                                const std::string& adapterId)
243179105bSSunny Srivastava {
253179105bSSunny Srivastava 
263179105bSSunny Srivastava     if (ec.value() == boost::system::errc::io_error)
273179105bSSunny Srivastava     {
2853ffeca5SLakshmi Yadlapati         messages::resourceNotFound(res, "#FabricAdapter.v1_4_0.FabricAdapter",
293179105bSSunny Srivastava                                    adapterId);
303179105bSSunny Srivastava         return;
313179105bSSunny Srivastava     }
323179105bSSunny Srivastava 
333179105bSSunny Srivastava     BMCWEB_LOG_ERROR << "DBus method call failed with error " << ec.value();
343179105bSSunny Srivastava     messages::internalError(res);
353179105bSSunny Srivastava }
363179105bSSunny Srivastava 
3753ffeca5SLakshmi Yadlapati inline void
3853ffeca5SLakshmi Yadlapati     getFabricAdapterLocation(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
3953ffeca5SLakshmi Yadlapati                              const std::string& serviceName,
4053ffeca5SLakshmi Yadlapati                              const std::string& fabricAdapterPath)
4153ffeca5SLakshmi Yadlapati {
4253ffeca5SLakshmi Yadlapati     sdbusplus::asio::getProperty<std::string>(
4353ffeca5SLakshmi Yadlapati         *crow::connections::systemBus, serviceName, fabricAdapterPath,
4453ffeca5SLakshmi Yadlapati         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
4553ffeca5SLakshmi Yadlapati         [aResp](const boost::system::error_code ec,
4653ffeca5SLakshmi Yadlapati                 const std::string& property) {
4753ffeca5SLakshmi Yadlapati         if (ec)
4853ffeca5SLakshmi Yadlapati         {
4953ffeca5SLakshmi Yadlapati             if (ec.value() != EBADR)
5053ffeca5SLakshmi Yadlapati             {
5153ffeca5SLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "DBUS response error for Location";
5253ffeca5SLakshmi Yadlapati                 messages::internalError(aResp->res);
5353ffeca5SLakshmi Yadlapati             }
5453ffeca5SLakshmi Yadlapati             return;
5553ffeca5SLakshmi Yadlapati         }
5653ffeca5SLakshmi Yadlapati 
5753ffeca5SLakshmi Yadlapati         aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
5853ffeca5SLakshmi Yadlapati             property;
5953ffeca5SLakshmi Yadlapati         });
6053ffeca5SLakshmi Yadlapati }
6153ffeca5SLakshmi Yadlapati 
626369421dSLakshmi Yadlapati inline void
636369421dSLakshmi Yadlapati     getFabricAdapterAsset(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
646369421dSLakshmi Yadlapati                           const std::string& serviceName,
656369421dSLakshmi Yadlapati                           const std::string& fabricAdapterPath)
666369421dSLakshmi Yadlapati {
676369421dSLakshmi Yadlapati     sdbusplus::asio::getAllProperties(
686369421dSLakshmi Yadlapati         *crow::connections::systemBus, serviceName, fabricAdapterPath,
696369421dSLakshmi Yadlapati         "xyz.openbmc_project.Inventory.Decorator.Asset",
706369421dSLakshmi Yadlapati         [fabricAdapterPath,
716369421dSLakshmi Yadlapati          aResp{aResp}](const boost::system::error_code ec,
726369421dSLakshmi Yadlapati                        const dbus::utility::DBusPropertiesMap& propertiesList) {
736369421dSLakshmi Yadlapati         if (ec)
746369421dSLakshmi Yadlapati         {
756369421dSLakshmi Yadlapati             if (ec.value() != EBADR)
766369421dSLakshmi Yadlapati             {
776369421dSLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "DBUS response error for Properties";
786369421dSLakshmi Yadlapati                 messages::internalError(aResp->res);
796369421dSLakshmi Yadlapati             }
806369421dSLakshmi Yadlapati             return;
816369421dSLakshmi Yadlapati         }
826369421dSLakshmi Yadlapati 
836369421dSLakshmi Yadlapati         const std::string* serialNumber = nullptr;
846369421dSLakshmi Yadlapati         const std::string* model = nullptr;
856369421dSLakshmi Yadlapati         const std::string* partNumber = nullptr;
866369421dSLakshmi Yadlapati         const std::string* sparePartNumber = nullptr;
876369421dSLakshmi Yadlapati 
886369421dSLakshmi Yadlapati         const bool success = sdbusplus::unpackPropertiesNoThrow(
896369421dSLakshmi Yadlapati             dbus_utils::UnpackErrorPrinter(), propertiesList, "SerialNumber",
906369421dSLakshmi Yadlapati             serialNumber, "Model", model, "PartNumber", partNumber,
916369421dSLakshmi Yadlapati             "SparePartNumber", sparePartNumber);
926369421dSLakshmi Yadlapati 
936369421dSLakshmi Yadlapati         if (!success)
946369421dSLakshmi Yadlapati         {
956369421dSLakshmi Yadlapati             messages::internalError(aResp->res);
966369421dSLakshmi Yadlapati             return;
976369421dSLakshmi Yadlapati         }
986369421dSLakshmi Yadlapati 
996369421dSLakshmi Yadlapati         if (serialNumber != nullptr)
1006369421dSLakshmi Yadlapati         {
1016369421dSLakshmi Yadlapati             aResp->res.jsonValue["SerialNumber"] = *serialNumber;
1026369421dSLakshmi Yadlapati         }
1036369421dSLakshmi Yadlapati 
1046369421dSLakshmi Yadlapati         if (model != nullptr)
1056369421dSLakshmi Yadlapati         {
1066369421dSLakshmi Yadlapati             aResp->res.jsonValue["Model"] = *model;
1076369421dSLakshmi Yadlapati         }
1086369421dSLakshmi Yadlapati 
1096369421dSLakshmi Yadlapati         if (partNumber != nullptr)
1106369421dSLakshmi Yadlapati         {
1116369421dSLakshmi Yadlapati             aResp->res.jsonValue["PartNumber"] = *partNumber;
1126369421dSLakshmi Yadlapati         }
1136369421dSLakshmi Yadlapati 
1146369421dSLakshmi Yadlapati         if (sparePartNumber != nullptr && !sparePartNumber->empty())
1156369421dSLakshmi Yadlapati         {
1166369421dSLakshmi Yadlapati             aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
1176369421dSLakshmi Yadlapati         }
1186369421dSLakshmi Yadlapati         });
1196369421dSLakshmi Yadlapati }
1206369421dSLakshmi Yadlapati 
121*cd7af44fSLakshmi Yadlapati inline void
122*cd7af44fSLakshmi Yadlapati     getFabricAdapterState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
123*cd7af44fSLakshmi Yadlapati                           const std::string& serviceName,
124*cd7af44fSLakshmi Yadlapati                           const std::string& fabricAdapterPath)
125*cd7af44fSLakshmi Yadlapati {
126*cd7af44fSLakshmi Yadlapati     sdbusplus::asio::getProperty<bool>(
127*cd7af44fSLakshmi Yadlapati         *crow::connections::systemBus, serviceName, fabricAdapterPath,
128*cd7af44fSLakshmi Yadlapati         "xyz.openbmc_project.Inventory.Item", "Present",
129*cd7af44fSLakshmi Yadlapati         [aResp](const boost::system::error_code ec, const bool present) {
130*cd7af44fSLakshmi Yadlapati         if (ec)
131*cd7af44fSLakshmi Yadlapati         {
132*cd7af44fSLakshmi Yadlapati             if (ec.value() != EBADR)
133*cd7af44fSLakshmi Yadlapati             {
134*cd7af44fSLakshmi Yadlapati                 BMCWEB_LOG_ERROR << "DBUS response error for State";
135*cd7af44fSLakshmi Yadlapati                 messages::internalError(aResp->res);
136*cd7af44fSLakshmi Yadlapati             }
137*cd7af44fSLakshmi Yadlapati             return;
138*cd7af44fSLakshmi Yadlapati         }
139*cd7af44fSLakshmi Yadlapati 
140*cd7af44fSLakshmi Yadlapati         if (!present)
141*cd7af44fSLakshmi Yadlapati         {
142*cd7af44fSLakshmi Yadlapati             aResp->res.jsonValue["Status"]["State"] = "Absent";
143*cd7af44fSLakshmi Yadlapati         }
144*cd7af44fSLakshmi Yadlapati         });
145*cd7af44fSLakshmi Yadlapati }
146*cd7af44fSLakshmi Yadlapati 
1473179105bSSunny Srivastava inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1483179105bSSunny Srivastava                          const std::string& systemName,
14953ffeca5SLakshmi Yadlapati                          const std::string& adapterId,
15053ffeca5SLakshmi Yadlapati                          const std::string& fabricAdapterPath,
15153ffeca5SLakshmi Yadlapati                          const std::string& serviceName)
1523179105bSSunny Srivastava {
1533179105bSSunny Srivastava     aResp->res.addHeader(
1543179105bSSunny Srivastava         boost::beast::http::field::link,
1553179105bSSunny Srivastava         "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
15653ffeca5SLakshmi Yadlapati     aResp->res.jsonValue["@odata.type"] = "#FabricAdapter.v1_4_0.FabricAdapter";
1573179105bSSunny Srivastava     aResp->res.jsonValue["Name"] = "Fabric Adapter";
1583179105bSSunny Srivastava     aResp->res.jsonValue["Id"] = adapterId;
1593179105bSSunny Srivastava     aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
1603179105bSSunny Srivastava         "redfish", "v1", "Systems", systemName, "FabricAdapters", adapterId);
16153ffeca5SLakshmi Yadlapati 
162*cd7af44fSLakshmi Yadlapati     aResp->res.jsonValue["Status"]["State"] = "Enabled";
163*cd7af44fSLakshmi Yadlapati 
16453ffeca5SLakshmi Yadlapati     getFabricAdapterLocation(aResp, serviceName, fabricAdapterPath);
1656369421dSLakshmi Yadlapati     getFabricAdapterAsset(aResp, serviceName, fabricAdapterPath);
166*cd7af44fSLakshmi Yadlapati     getFabricAdapterState(aResp, serviceName, fabricAdapterPath);
1673179105bSSunny Srivastava }
1683179105bSSunny Srivastava 
1693179105bSSunny Srivastava inline bool checkFabricAdapterId(const std::string& adapterPath,
1703179105bSSunny Srivastava                                  const std::string& adapterId)
1713179105bSSunny Srivastava {
1723179105bSSunny Srivastava     std::string fabricAdapterName =
1733179105bSSunny Srivastava         sdbusplus::message::object_path(adapterPath).filename();
1743179105bSSunny Srivastava 
1753179105bSSunny Srivastava     return !(fabricAdapterName.empty() || fabricAdapterName != adapterId);
1763179105bSSunny Srivastava }
1773179105bSSunny Srivastava 
1783179105bSSunny Srivastava inline void getValidFabricAdapterPath(
1793179105bSSunny Srivastava     const std::string& adapterId, const std::string& systemName,
1803179105bSSunny Srivastava     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1813179105bSSunny Srivastava     std::function<void(const std::string& fabricAdapterPath,
1823179105bSSunny Srivastava                        const std::string& serviceName)>&& callback)
1833179105bSSunny Srivastava {
1843179105bSSunny Srivastava     if (systemName != "system")
1853179105bSSunny Srivastava     {
1863179105bSSunny Srivastava         messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
1873179105bSSunny Srivastava         return;
1883179105bSSunny Srivastava     }
1893179105bSSunny Srivastava     constexpr std::array<std::string_view, 1> interfaces{
1903179105bSSunny Srivastava         "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
1913179105bSSunny Srivastava 
1923179105bSSunny Srivastava     dbus::utility::getSubTree(
1933179105bSSunny Srivastava         "/xyz/openbmc_project/inventory", 0, interfaces,
1943179105bSSunny Srivastava         [adapterId, aResp,
1953179105bSSunny Srivastava          callback](const boost::system::error_code& ec,
1963179105bSSunny Srivastava                    const dbus::utility::MapperGetSubTreeResponse& subtree) {
1973179105bSSunny Srivastava         if (ec)
1983179105bSSunny Srivastava         {
1993179105bSSunny Srivastava             handleAdapterError(ec, aResp->res, adapterId);
2003179105bSSunny Srivastava             return;
2013179105bSSunny Srivastava         }
2023179105bSSunny Srivastava         for (const auto& [adapterPath, serviceMap] : subtree)
2033179105bSSunny Srivastava         {
2043179105bSSunny Srivastava             if (checkFabricAdapterId(adapterPath, adapterId))
2053179105bSSunny Srivastava             {
2063179105bSSunny Srivastava                 callback(adapterPath, serviceMap.begin()->first);
2073179105bSSunny Srivastava                 return;
2083179105bSSunny Srivastava             }
2093179105bSSunny Srivastava         }
2103179105bSSunny Srivastava         BMCWEB_LOG_WARNING << "Adapter not found";
2113179105bSSunny Srivastava         messages::resourceNotFound(aResp->res, "FabricAdapter", adapterId);
2123179105bSSunny Srivastava         });
2133179105bSSunny Srivastava }
2143179105bSSunny Srivastava 
2153179105bSSunny Srivastava inline void
2163179105bSSunny Srivastava     handleFabricAdapterGet(App& app, const crow::Request& req,
2173179105bSSunny Srivastava                            const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2183179105bSSunny Srivastava                            const std::string& systemName,
2193179105bSSunny Srivastava                            const std::string& adapterId)
2203179105bSSunny Srivastava {
2213179105bSSunny Srivastava     if (!redfish::setUpRedfishRoute(app, req, aResp))
2223179105bSSunny Srivastava     {
2233179105bSSunny Srivastava         return;
2243179105bSSunny Srivastava     }
2253179105bSSunny Srivastava 
2263179105bSSunny Srivastava     getValidFabricAdapterPath(
2273179105bSSunny Srivastava         adapterId, systemName, aResp,
22853ffeca5SLakshmi Yadlapati         [aResp, systemName, adapterId](const std::string& fabricAdapterPath,
22953ffeca5SLakshmi Yadlapati                                        const std::string& serviceName) {
23053ffeca5SLakshmi Yadlapati         doAdapterGet(aResp, systemName, adapterId, fabricAdapterPath,
23153ffeca5SLakshmi Yadlapati                      serviceName);
2323179105bSSunny Srivastava         });
2333179105bSSunny Srivastava }
2343179105bSSunny Srivastava 
2353179105bSSunny Srivastava inline void handleFabricAdapterCollectionGet(
2363179105bSSunny Srivastava     crow::App& app, const crow::Request& req,
2373179105bSSunny Srivastava     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2383179105bSSunny Srivastava     const std::string& systemName)
2393179105bSSunny Srivastava {
2403179105bSSunny Srivastava     if (!redfish::setUpRedfishRoute(app, req, aResp))
2413179105bSSunny Srivastava     {
2423179105bSSunny Srivastava         return;
2433179105bSSunny Srivastava     }
2443179105bSSunny Srivastava     if (systemName != "system")
2453179105bSSunny Srivastava     {
2463179105bSSunny Srivastava         messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
2473179105bSSunny Srivastava         return;
2483179105bSSunny Srivastava     }
2493179105bSSunny Srivastava 
2503179105bSSunny Srivastava     aResp->res.addHeader(
2513179105bSSunny Srivastava         boost::beast::http::field::link,
2523179105bSSunny Srivastava         "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
2533179105bSSunny Srivastava     aResp->res.jsonValue["@odata.type"] =
2543179105bSSunny Srivastava         "#FabricAdapterCollection.FabricAdapterCollection";
2553179105bSSunny Srivastava     aResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
2563179105bSSunny Srivastava     aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
2573179105bSSunny Srivastava         "redfish", "v1", "Systems", systemName, "FabricAdapters");
2583179105bSSunny Srivastava 
2593179105bSSunny Srivastava     constexpr std::array<std::string_view, 1> interfaces{
2603179105bSSunny Srivastava         "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
2613179105bSSunny Srivastava     collection_util::getCollectionMembers(
2623179105bSSunny Srivastava         aResp, boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"),
2633179105bSSunny Srivastava         interfaces);
2643179105bSSunny Srivastava }
2653179105bSSunny Srivastava 
2663179105bSSunny Srivastava inline void handleFabricAdapterCollectionHead(
2673179105bSSunny Srivastava     crow::App& app, const crow::Request& req,
2683179105bSSunny Srivastava     const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2693179105bSSunny Srivastava     const std::string& systemName)
2703179105bSSunny Srivastava {
2713179105bSSunny Srivastava     if (!redfish::setUpRedfishRoute(app, req, aResp))
2723179105bSSunny Srivastava     {
2733179105bSSunny Srivastava         return;
2743179105bSSunny Srivastava     }
2753179105bSSunny Srivastava     if (systemName != "system")
2763179105bSSunny Srivastava     {
2773179105bSSunny Srivastava         messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
2783179105bSSunny Srivastava         return;
2793179105bSSunny Srivastava     }
2803179105bSSunny Srivastava     aResp->res.addHeader(
2813179105bSSunny Srivastava         boost::beast::http::field::link,
2823179105bSSunny Srivastava         "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby");
2833179105bSSunny Srivastava }
2843179105bSSunny Srivastava 
2853179105bSSunny Srivastava inline void
2863179105bSSunny Srivastava     handleFabricAdapterHead(crow::App& app, const crow::Request& req,
2873179105bSSunny Srivastava                             const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2883179105bSSunny Srivastava                             const std::string& systemName,
2893179105bSSunny Srivastava                             const std::string& adapterId)
2903179105bSSunny Srivastava {
2913179105bSSunny Srivastava     if (!redfish::setUpRedfishRoute(app, req, aResp))
2923179105bSSunny Srivastava     {
2933179105bSSunny Srivastava         return;
2943179105bSSunny Srivastava     }
2953179105bSSunny Srivastava 
2963179105bSSunny Srivastava     getValidFabricAdapterPath(
2973179105bSSunny Srivastava         adapterId, systemName, aResp,
2983179105bSSunny Srivastava         [aResp, systemName, adapterId](const std::string&, const std::string&) {
2993179105bSSunny Srivastava         aResp->res.addHeader(
3003179105bSSunny Srivastava             boost::beast::http::field::link,
3013179105bSSunny Srivastava             "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
3023179105bSSunny Srivastava         });
3033179105bSSunny Srivastava }
3043179105bSSunny Srivastava 
3053179105bSSunny Srivastava inline void requestRoutesFabricAdapterCollection(App& app)
3063179105bSSunny Srivastava {
3073179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
3083179105bSSunny Srivastava         .privileges(redfish::privileges::getFabricAdapterCollection)
3093179105bSSunny Srivastava         .methods(boost::beast::http::verb::get)(
3103179105bSSunny Srivastava             std::bind_front(handleFabricAdapterCollectionGet, std::ref(app)));
3113179105bSSunny Srivastava 
3123179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
3133179105bSSunny Srivastava         .privileges(redfish::privileges::headFabricAdapterCollection)
3143179105bSSunny Srivastava         .methods(boost::beast::http::verb::head)(
3153179105bSSunny Srivastava             std::bind_front(handleFabricAdapterCollectionHead, std::ref(app)));
3163179105bSSunny Srivastava }
3173179105bSSunny Srivastava 
3183179105bSSunny Srivastava inline void requestRoutesFabricAdapters(App& app)
3193179105bSSunny Srivastava {
3203179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
3213179105bSSunny Srivastava         .privileges(redfish::privileges::getFabricAdapter)
3223179105bSSunny Srivastava         .methods(boost::beast::http::verb::get)(
3233179105bSSunny Srivastava             std::bind_front(handleFabricAdapterGet, std::ref(app)));
3243179105bSSunny Srivastava 
3253179105bSSunny Srivastava     BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
3263179105bSSunny Srivastava         .privileges(redfish::privileges::headFabricAdapter)
3273179105bSSunny Srivastava         .methods(boost::beast::http::verb::head)(
3283179105bSSunny Srivastava             std::bind_front(handleFabricAdapterHead, std::ref(app)));
3293179105bSSunny Srivastava }
3303179105bSSunny Srivastava } // namespace redfish
331