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