1 #pragma once 2 3 #include "app.hpp" 4 #include "dbus_utility.hpp" 5 #include "utils/collection.hpp" 6 #include "utils/json_utils.hpp" 7 8 #include <boost/system/error_code.hpp> 9 10 #include <array> 11 #include <functional> 12 #include <memory> 13 #include <string> 14 #include <string_view> 15 16 namespace redfish 17 { 18 19 inline void handleAdapterError(const boost::system::error_code& ec, 20 crow::Response& res, 21 const std::string& adapterId) 22 { 23 24 if (ec.value() == boost::system::errc::io_error) 25 { 26 messages::resourceNotFound(res, "#FabricAdapter.v1_0_0.FabricAdapter", 27 adapterId); 28 return; 29 } 30 31 BMCWEB_LOG_ERROR << "DBus method call failed with error " << ec.value(); 32 messages::internalError(res); 33 } 34 35 inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 36 const std::string& systemName, 37 const std::string& adapterId) 38 { 39 aResp->res.addHeader( 40 boost::beast::http::field::link, 41 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby"); 42 aResp->res.jsonValue["@odata.type"] = "#FabricAdapter.v1_0_0.FabricAdapter"; 43 aResp->res.jsonValue["Name"] = "Fabric Adapter"; 44 aResp->res.jsonValue["Id"] = adapterId; 45 aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( 46 "redfish", "v1", "Systems", systemName, "FabricAdapters", adapterId); 47 } 48 49 inline bool checkFabricAdapterId(const std::string& adapterPath, 50 const std::string& adapterId) 51 { 52 std::string fabricAdapterName = 53 sdbusplus::message::object_path(adapterPath).filename(); 54 55 return !(fabricAdapterName.empty() || fabricAdapterName != adapterId); 56 } 57 58 inline void getValidFabricAdapterPath( 59 const std::string& adapterId, const std::string& systemName, 60 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 61 std::function<void(const std::string& fabricAdapterPath, 62 const std::string& serviceName)>&& callback) 63 { 64 if (systemName != "system") 65 { 66 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName); 67 return; 68 } 69 constexpr std::array<std::string_view, 1> interfaces{ 70 "xyz.openbmc_project.Inventory.Item.FabricAdapter"}; 71 72 dbus::utility::getSubTree( 73 "/xyz/openbmc_project/inventory", 0, interfaces, 74 [adapterId, aResp, 75 callback](const boost::system::error_code& ec, 76 const dbus::utility::MapperGetSubTreeResponse& subtree) { 77 if (ec) 78 { 79 handleAdapterError(ec, aResp->res, adapterId); 80 return; 81 } 82 for (const auto& [adapterPath, serviceMap] : subtree) 83 { 84 if (checkFabricAdapterId(adapterPath, adapterId)) 85 { 86 callback(adapterPath, serviceMap.begin()->first); 87 return; 88 } 89 } 90 BMCWEB_LOG_WARNING << "Adapter not found"; 91 messages::resourceNotFound(aResp->res, "FabricAdapter", adapterId); 92 }); 93 } 94 95 inline void 96 handleFabricAdapterGet(App& app, const crow::Request& req, 97 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 98 const std::string& systemName, 99 const std::string& adapterId) 100 { 101 if (!redfish::setUpRedfishRoute(app, req, aResp)) 102 { 103 return; 104 } 105 106 getValidFabricAdapterPath( 107 adapterId, systemName, aResp, 108 [aResp, systemName, adapterId](const std::string&, const std::string&) { 109 doAdapterGet(aResp, systemName, adapterId); 110 }); 111 } 112 113 inline void handleFabricAdapterCollectionGet( 114 crow::App& app, const crow::Request& req, 115 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 116 const std::string& systemName) 117 { 118 if (!redfish::setUpRedfishRoute(app, req, aResp)) 119 { 120 return; 121 } 122 if (systemName != "system") 123 { 124 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName); 125 return; 126 } 127 128 aResp->res.addHeader( 129 boost::beast::http::field::link, 130 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby"); 131 aResp->res.jsonValue["@odata.type"] = 132 "#FabricAdapterCollection.FabricAdapterCollection"; 133 aResp->res.jsonValue["Name"] = "Fabric Adapter Collection"; 134 aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( 135 "redfish", "v1", "Systems", systemName, "FabricAdapters"); 136 137 constexpr std::array<std::string_view, 1> interfaces{ 138 "xyz.openbmc_project.Inventory.Item.FabricAdapter"}; 139 collection_util::getCollectionMembers( 140 aResp, boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"), 141 interfaces); 142 } 143 144 inline void handleFabricAdapterCollectionHead( 145 crow::App& app, const crow::Request& req, 146 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 147 const std::string& systemName) 148 { 149 if (!redfish::setUpRedfishRoute(app, req, aResp)) 150 { 151 return; 152 } 153 if (systemName != "system") 154 { 155 messages::resourceNotFound(aResp->res, "ComputerSystem", systemName); 156 return; 157 } 158 aResp->res.addHeader( 159 boost::beast::http::field::link, 160 "</redfish/v1/JsonSchemas/FabricAdapterCollection/FabricAdapterCollection.json>; rel=describedby"); 161 } 162 163 inline void 164 handleFabricAdapterHead(crow::App& app, const crow::Request& req, 165 const std::shared_ptr<bmcweb::AsyncResp>& aResp, 166 const std::string& systemName, 167 const std::string& adapterId) 168 { 169 if (!redfish::setUpRedfishRoute(app, req, aResp)) 170 { 171 return; 172 } 173 174 getValidFabricAdapterPath( 175 adapterId, systemName, aResp, 176 [aResp, systemName, adapterId](const std::string&, const std::string&) { 177 aResp->res.addHeader( 178 boost::beast::http::field::link, 179 "</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby"); 180 }); 181 } 182 183 inline void requestRoutesFabricAdapterCollection(App& app) 184 { 185 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/") 186 .privileges(redfish::privileges::getFabricAdapterCollection) 187 .methods(boost::beast::http::verb::get)( 188 std::bind_front(handleFabricAdapterCollectionGet, std::ref(app))); 189 190 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/") 191 .privileges(redfish::privileges::headFabricAdapterCollection) 192 .methods(boost::beast::http::verb::head)( 193 std::bind_front(handleFabricAdapterCollectionHead, std::ref(app))); 194 } 195 196 inline void requestRoutesFabricAdapters(App& app) 197 { 198 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/") 199 .privileges(redfish::privileges::getFabricAdapter) 200 .methods(boost::beast::http::verb::get)( 201 std::bind_front(handleFabricAdapterGet, std::ref(app))); 202 203 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/") 204 .privileges(redfish::privileges::headFabricAdapter) 205 .methods(boost::beast::http::verb::head)( 206 std::bind_front(handleFabricAdapterHead, std::ref(app))); 207 } 208 } // namespace redfish 209