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