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 62*6369421dSLakshmi Yadlapati inline void 63*6369421dSLakshmi Yadlapati getFabricAdapterAsset(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 64*6369421dSLakshmi Yadlapati const std::string& serviceName, 65*6369421dSLakshmi Yadlapati const std::string& fabricAdapterPath) 66*6369421dSLakshmi Yadlapati { 67*6369421dSLakshmi Yadlapati sdbusplus::asio::getAllProperties( 68*6369421dSLakshmi Yadlapati *crow::connections::systemBus, serviceName, fabricAdapterPath, 69*6369421dSLakshmi Yadlapati "xyz.openbmc_project.Inventory.Decorator.Asset", 70*6369421dSLakshmi Yadlapati [fabricAdapterPath, 71*6369421dSLakshmi Yadlapati aResp{aResp}](const boost::system::error_code ec, 72*6369421dSLakshmi Yadlapati const dbus::utility::DBusPropertiesMap& propertiesList) { 73*6369421dSLakshmi Yadlapati if (ec) 74*6369421dSLakshmi Yadlapati { 75*6369421dSLakshmi Yadlapati if (ec.value() != EBADR) 76*6369421dSLakshmi Yadlapati { 77*6369421dSLakshmi Yadlapati BMCWEB_LOG_ERROR << "DBUS response error for Properties"; 78*6369421dSLakshmi Yadlapati messages::internalError(aResp->res); 79*6369421dSLakshmi Yadlapati } 80*6369421dSLakshmi Yadlapati return; 81*6369421dSLakshmi Yadlapati } 82*6369421dSLakshmi Yadlapati 83*6369421dSLakshmi Yadlapati const std::string* serialNumber = nullptr; 84*6369421dSLakshmi Yadlapati const std::string* model = nullptr; 85*6369421dSLakshmi Yadlapati const std::string* partNumber = nullptr; 86*6369421dSLakshmi Yadlapati const std::string* sparePartNumber = nullptr; 87*6369421dSLakshmi Yadlapati 88*6369421dSLakshmi Yadlapati const bool success = sdbusplus::unpackPropertiesNoThrow( 89*6369421dSLakshmi Yadlapati dbus_utils::UnpackErrorPrinter(), propertiesList, "SerialNumber", 90*6369421dSLakshmi Yadlapati serialNumber, "Model", model, "PartNumber", partNumber, 91*6369421dSLakshmi Yadlapati "SparePartNumber", sparePartNumber); 92*6369421dSLakshmi Yadlapati 93*6369421dSLakshmi Yadlapati if (!success) 94*6369421dSLakshmi Yadlapati { 95*6369421dSLakshmi Yadlapati messages::internalError(aResp->res); 96*6369421dSLakshmi Yadlapati return; 97*6369421dSLakshmi Yadlapati } 98*6369421dSLakshmi Yadlapati 99*6369421dSLakshmi Yadlapati if (serialNumber != nullptr) 100*6369421dSLakshmi Yadlapati { 101*6369421dSLakshmi Yadlapati aResp->res.jsonValue["SerialNumber"] = *serialNumber; 102*6369421dSLakshmi Yadlapati } 103*6369421dSLakshmi Yadlapati 104*6369421dSLakshmi Yadlapati if (model != nullptr) 105*6369421dSLakshmi Yadlapati { 106*6369421dSLakshmi Yadlapati aResp->res.jsonValue["Model"] = *model; 107*6369421dSLakshmi Yadlapati } 108*6369421dSLakshmi Yadlapati 109*6369421dSLakshmi Yadlapati if (partNumber != nullptr) 110*6369421dSLakshmi Yadlapati { 111*6369421dSLakshmi Yadlapati aResp->res.jsonValue["PartNumber"] = *partNumber; 112*6369421dSLakshmi Yadlapati } 113*6369421dSLakshmi Yadlapati 114*6369421dSLakshmi Yadlapati if (sparePartNumber != nullptr && !sparePartNumber->empty()) 115*6369421dSLakshmi Yadlapati { 116*6369421dSLakshmi Yadlapati aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 117*6369421dSLakshmi Yadlapati } 118*6369421dSLakshmi Yadlapati }); 119*6369421dSLakshmi Yadlapati } 120*6369421dSLakshmi Yadlapati 1213179105bSSunny Srivastava inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 1223179105bSSunny Srivastava const std::string& systemName, 12353ffeca5SLakshmi Yadlapati const std::string& adapterId, 12453ffeca5SLakshmi Yadlapati const std::string& fabricAdapterPath, 12553ffeca5SLakshmi Yadlapati const std::string& serviceName) 1263179105bSSunny Srivastava { 1273179105bSSunny Srivastava aResp->res.addHeader( 1283179105bSSunny Srivastava boost::beast::http::field::link, 1293179105bSSunny Srivastava "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby"); 13053ffeca5SLakshmi Yadlapati aResp->res.jsonValue["@odata.type"] = "#FabricAdapter.v1_4_0.FabricAdapter"; 1313179105bSSunny Srivastava aResp->res.jsonValue["Name"] = "Fabric Adapter"; 1323179105bSSunny Srivastava aResp->res.jsonValue["Id"] = adapterId; 1333179105bSSunny Srivastava aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( 1343179105bSSunny Srivastava "redfish", "v1", "Systems", systemName, "FabricAdapters", adapterId); 13553ffeca5SLakshmi Yadlapati 13653ffeca5SLakshmi Yadlapati getFabricAdapterLocation(aResp, serviceName, fabricAdapterPath); 137*6369421dSLakshmi Yadlapati getFabricAdapterAsset(aResp, serviceName, fabricAdapterPath); 1383179105bSSunny Srivastava } 1393179105bSSunny Srivastava 1403179105bSSunny Srivastava inline bool checkFabricAdapterId(const std::string& adapterPath, 1413179105bSSunny Srivastava const std::string& adapterId) 1423179105bSSunny Srivastava { 1433179105bSSunny Srivastava std::string fabricAdapterName = 1443179105bSSunny Srivastava sdbusplus::message::object_path(adapterPath).filename(); 1453179105bSSunny Srivastava 1463179105bSSunny Srivastava return !(fabricAdapterName.empty() || fabricAdapterName != adapterId); 1473179105bSSunny Srivastava } 1483179105bSSunny Srivastava 1493179105bSSunny Srivastava inline void getValidFabricAdapterPath( 1503179105bSSunny Srivastava const std::string& adapterId, const std::string& systemName, 1513179105bSSunny Srivastava const std::shared_ptr<bmcweb::AsyncResp>& aResp, 1523179105bSSunny Srivastava std::function<void(const std::string& fabricAdapterPath, 1533179105bSSunny Srivastava const std::string& serviceName)>&& callback) 1543179105bSSunny Srivastava { 1553179105bSSunny Srivastava if (systemName != "system") 1563179105bSSunny Srivastava { 1573179105bSSunny Srivastava messages::resourceNotFound(aResp->res, "ComputerSystem", systemName); 1583179105bSSunny Srivastava return; 1593179105bSSunny Srivastava } 1603179105bSSunny Srivastava constexpr std::array<std::string_view, 1> interfaces{ 1613179105bSSunny Srivastava "xyz.openbmc_project.Inventory.Item.FabricAdapter"}; 1623179105bSSunny Srivastava 1633179105bSSunny Srivastava dbus::utility::getSubTree( 1643179105bSSunny Srivastava "/xyz/openbmc_project/inventory", 0, interfaces, 1653179105bSSunny Srivastava [adapterId, aResp, 1663179105bSSunny Srivastava callback](const boost::system::error_code& ec, 1673179105bSSunny Srivastava const dbus::utility::MapperGetSubTreeResponse& subtree) { 1683179105bSSunny Srivastava if (ec) 1693179105bSSunny Srivastava { 1703179105bSSunny Srivastava handleAdapterError(ec, aResp->res, adapterId); 1713179105bSSunny Srivastava return; 1723179105bSSunny Srivastava } 1733179105bSSunny Srivastava for (const auto& [adapterPath, serviceMap] : subtree) 1743179105bSSunny Srivastava { 1753179105bSSunny Srivastava if (checkFabricAdapterId(adapterPath, adapterId)) 1763179105bSSunny Srivastava { 1773179105bSSunny Srivastava callback(adapterPath, serviceMap.begin()->first); 1783179105bSSunny Srivastava return; 1793179105bSSunny Srivastava } 1803179105bSSunny Srivastava } 1813179105bSSunny Srivastava BMCWEB_LOG_WARNING << "Adapter not found"; 1823179105bSSunny Srivastava messages::resourceNotFound(aResp->res, "FabricAdapter", adapterId); 1833179105bSSunny Srivastava }); 1843179105bSSunny Srivastava } 1853179105bSSunny Srivastava 1863179105bSSunny Srivastava inline void 1873179105bSSunny Srivastava handleFabricAdapterGet(App& app, const crow::Request& req, 1883179105bSSunny Srivastava const std::shared_ptr<bmcweb::AsyncResp>& aResp, 1893179105bSSunny Srivastava const std::string& systemName, 1903179105bSSunny Srivastava const std::string& adapterId) 1913179105bSSunny Srivastava { 1923179105bSSunny Srivastava if (!redfish::setUpRedfishRoute(app, req, aResp)) 1933179105bSSunny Srivastava { 1943179105bSSunny Srivastava return; 1953179105bSSunny Srivastava } 1963179105bSSunny Srivastava 1973179105bSSunny Srivastava getValidFabricAdapterPath( 1983179105bSSunny Srivastava adapterId, systemName, aResp, 19953ffeca5SLakshmi Yadlapati [aResp, systemName, adapterId](const std::string& fabricAdapterPath, 20053ffeca5SLakshmi Yadlapati const std::string& serviceName) { 20153ffeca5SLakshmi Yadlapati doAdapterGet(aResp, systemName, adapterId, fabricAdapterPath, 20253ffeca5SLakshmi Yadlapati serviceName); 2033179105bSSunny Srivastava }); 2043179105bSSunny Srivastava } 2053179105bSSunny Srivastava 2063179105bSSunny Srivastava inline void handleFabricAdapterCollectionGet( 2073179105bSSunny Srivastava crow::App& app, const crow::Request& req, 2083179105bSSunny Srivastava const std::shared_ptr<bmcweb::AsyncResp>& aResp, 2093179105bSSunny Srivastava const std::string& systemName) 2103179105bSSunny Srivastava { 2113179105bSSunny Srivastava if (!redfish::setUpRedfishRoute(app, req, aResp)) 2123179105bSSunny Srivastava { 2133179105bSSunny Srivastava return; 2143179105bSSunny Srivastava } 2153179105bSSunny Srivastava if (systemName != "system") 2163179105bSSunny Srivastava { 2173179105bSSunny Srivastava messages::resourceNotFound(aResp->res, "ComputerSystem", systemName); 2183179105bSSunny Srivastava return; 2193179105bSSunny Srivastava } 2203179105bSSunny Srivastava 2213179105bSSunny Srivastava aResp->res.addHeader( 2223179105bSSunny Srivastava boost::beast::http::field::link, 2233179105bSSunny Srivastava "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby"); 2243179105bSSunny Srivastava aResp->res.jsonValue["@odata.type"] = 2253179105bSSunny Srivastava "#FabricAdapterCollection.FabricAdapterCollection"; 2263179105bSSunny Srivastava aResp->res.jsonValue["Name"] = "Fabric Adapter Collection"; 2273179105bSSunny Srivastava aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( 2283179105bSSunny Srivastava "redfish", "v1", "Systems", systemName, "FabricAdapters"); 2293179105bSSunny Srivastava 2303179105bSSunny Srivastava constexpr std::array<std::string_view, 1> interfaces{ 2313179105bSSunny Srivastava "xyz.openbmc_project.Inventory.Item.FabricAdapter"}; 2323179105bSSunny Srivastava collection_util::getCollectionMembers( 2333179105bSSunny Srivastava aResp, boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"), 2343179105bSSunny Srivastava interfaces); 2353179105bSSunny Srivastava } 2363179105bSSunny Srivastava 2373179105bSSunny Srivastava inline void handleFabricAdapterCollectionHead( 2383179105bSSunny Srivastava crow::App& app, const crow::Request& req, 2393179105bSSunny Srivastava const std::shared_ptr<bmcweb::AsyncResp>& aResp, 2403179105bSSunny Srivastava const std::string& systemName) 2413179105bSSunny Srivastava { 2423179105bSSunny Srivastava if (!redfish::setUpRedfishRoute(app, req, aResp)) 2433179105bSSunny Srivastava { 2443179105bSSunny Srivastava return; 2453179105bSSunny Srivastava } 2463179105bSSunny Srivastava if (systemName != "system") 2473179105bSSunny Srivastava { 2483179105bSSunny Srivastava messages::resourceNotFound(aResp->res, "ComputerSystem", systemName); 2493179105bSSunny Srivastava return; 2503179105bSSunny Srivastava } 2513179105bSSunny Srivastava aResp->res.addHeader( 2523179105bSSunny Srivastava boost::beast::http::field::link, 2533179105bSSunny Srivastava "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby"); 2543179105bSSunny Srivastava } 2553179105bSSunny Srivastava 2563179105bSSunny Srivastava inline void 2573179105bSSunny Srivastava handleFabricAdapterHead(crow::App& app, const crow::Request& req, 2583179105bSSunny Srivastava const std::shared_ptr<bmcweb::AsyncResp>& aResp, 2593179105bSSunny Srivastava const std::string& systemName, 2603179105bSSunny Srivastava const std::string& adapterId) 2613179105bSSunny Srivastava { 2623179105bSSunny Srivastava if (!redfish::setUpRedfishRoute(app, req, aResp)) 2633179105bSSunny Srivastava { 2643179105bSSunny Srivastava return; 2653179105bSSunny Srivastava } 2663179105bSSunny Srivastava 2673179105bSSunny Srivastava getValidFabricAdapterPath( 2683179105bSSunny Srivastava adapterId, systemName, aResp, 2693179105bSSunny Srivastava [aResp, systemName, adapterId](const std::string&, const std::string&) { 2703179105bSSunny Srivastava aResp->res.addHeader( 2713179105bSSunny Srivastava boost::beast::http::field::link, 2723179105bSSunny Srivastava "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby"); 2733179105bSSunny Srivastava }); 2743179105bSSunny Srivastava } 2753179105bSSunny Srivastava 2763179105bSSunny Srivastava inline void requestRoutesFabricAdapterCollection(App& app) 2773179105bSSunny Srivastava { 2783179105bSSunny Srivastava BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/") 2793179105bSSunny Srivastava .privileges(redfish::privileges::getFabricAdapterCollection) 2803179105bSSunny Srivastava .methods(boost::beast::http::verb::get)( 2813179105bSSunny Srivastava std::bind_front(handleFabricAdapterCollectionGet, std::ref(app))); 2823179105bSSunny Srivastava 2833179105bSSunny Srivastava BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/") 2843179105bSSunny Srivastava .privileges(redfish::privileges::headFabricAdapterCollection) 2853179105bSSunny Srivastava .methods(boost::beast::http::verb::head)( 2863179105bSSunny Srivastava std::bind_front(handleFabricAdapterCollectionHead, std::ref(app))); 2873179105bSSunny Srivastava } 2883179105bSSunny Srivastava 2893179105bSSunny Srivastava inline void requestRoutesFabricAdapters(App& app) 2903179105bSSunny Srivastava { 2913179105bSSunny Srivastava BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/") 2923179105bSSunny Srivastava .privileges(redfish::privileges::getFabricAdapter) 2933179105bSSunny Srivastava .methods(boost::beast::http::verb::get)( 2943179105bSSunny Srivastava std::bind_front(handleFabricAdapterGet, std::ref(app))); 2953179105bSSunny Srivastava 2963179105bSSunny Srivastava BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/") 2973179105bSSunny Srivastava .privileges(redfish::privileges::headFabricAdapter) 2983179105bSSunny Srivastava .methods(boost::beast::http::verb::head)( 2993179105bSSunny Srivastava std::bind_front(handleFabricAdapterHead, std::ref(app))); 3003179105bSSunny Srivastava } 3013179105bSSunny Srivastava } // namespace redfish 302