xref: /openbmc/bmcweb/features/redfish/lib/fabric_adapters.hpp (revision 3179105b5d9be791d79302d27ceb8e94f8670a6c)
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