xref: /openbmc/bmcweb/redfish-core/lib/aggregation_service.hpp (revision 89492a157c9cf972b342421e24d41fd382510251)
1 #pragma once
2 
3 #include "app.hpp"
4 #include "error_messages.hpp"
5 #include "http_request.hpp"
6 #include "http_response.hpp"
7 #include "query.hpp"
8 #include "redfish_aggregator.hpp"
9 #include "registries/privilege_registry.hpp"
10 
11 #include <nlohmann/json.hpp>
12 
13 #include <functional>
14 #include <memory>
15 
16 namespace redfish
17 {
18 
19 inline void handleAggregationServiceHead(
20     App& app, const crow::Request& req,
21     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
22 {
23     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
24     {
25         return;
26     }
27     asyncResp->res.addHeader(
28         boost::beast::http::field::link,
29         "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
30 }
31 
32 inline void handleAggregationServiceGet(
33     App& app, const crow::Request& req,
34     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
35 {
36     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
37     {
38         return;
39     }
40     asyncResp->res.addHeader(
41         boost::beast::http::field::link,
42         "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
43     nlohmann::json& json = asyncResp->res.jsonValue;
44     json["@odata.id"] = "/redfish/v1/AggregationService";
45     json["@odata.type"] = "#AggregationService.v1_0_1.AggregationService";
46     json["Id"] = "AggregationService";
47     json["Name"] = "Aggregation Service";
48     json["Description"] = "Aggregation Service";
49     json["ServiceEnabled"] = true;
50     json["AggregationSources"]["@odata.id"] =
51         "/redfish/v1/AggregationService/AggregationSources";
52 }
53 
54 inline void requestRoutesAggregationService(App& app)
55 {
56     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
57         .privileges(redfish::privileges::headAggregationService)
58         .methods(boost::beast::http::verb::head)(
59             std::bind_front(handleAggregationServiceHead, std::ref(app)));
60     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
61         .privileges(redfish::privileges::getAggregationService)
62         .methods(boost::beast::http::verb::get)(
63             std::bind_front(handleAggregationServiceGet, std::ref(app)));
64 }
65 
66 inline void populateAggregationSourceCollection(
67     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
68     const boost::system::error_code ec,
69     const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
70 {
71     // Something went wrong while querying dbus
72     if (ec)
73     {
74         messages::internalError(asyncResp->res);
75         return;
76     }
77     nlohmann::json::array_t members = nlohmann::json::array();
78     for (const auto& sat : satelliteInfo)
79     {
80         nlohmann::json::object_t member;
81         member["@odata.id"] =
82             crow::utility::urlFromPieces("redfish", "v1", "AggregationService",
83                                          "AggregationSources", sat.first);
84         members.push_back(std::move(member));
85     }
86     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
87     asyncResp->res.jsonValue["Members"] = std::move(members);
88 }
89 
90 inline void handleAggregationSourceCollectionGet(
91     App& app, const crow::Request& req,
92     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
93 {
94     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
95     {
96         return;
97     }
98     asyncResp->res.addHeader(
99         boost::beast::http::field::link,
100         "</redfish/v1/JsonSchemas/AggregationSourceCollection/AggregationSourceCollection.json>; rel=describedby");
101     nlohmann::json& json = asyncResp->res.jsonValue;
102     json["@odata.id"] = "/redfish/v1/AggregationService/AggregationSources";
103     json["@odata.type"] =
104         "#AggregationSourceCollection.AggregationSourceCollection";
105     json["Name"] = "Aggregation Source Collection";
106 
107     // Query D-Bus for satellite configs and add them to the Members array
108     RedfishAggregator::getSatelliteConfigs(
109         std::bind_front(populateAggregationSourceCollection, asyncResp));
110 }
111 
112 inline void handleAggregationSourceCollectionHead(
113     App& app, const crow::Request& req,
114     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
115 {
116     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
117     {
118         return;
119     }
120     asyncResp->res.addHeader(
121         boost::beast::http::field::link,
122         "</redfish/v1/JsonSchemas/AggregationService/AggregationSourceCollection.json>; rel=describedby");
123 }
124 
125 inline void requestRoutesAggregationSourceCollection(App& app)
126 {
127     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
128         .privileges(redfish::privileges::getAggregationSourceCollection)
129         .methods(boost::beast::http::verb::get)(std::bind_front(
130             handleAggregationSourceCollectionGet, std::ref(app)));
131 
132     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
133         .privileges(redfish::privileges::getAggregationSourceCollection)
134         .methods(boost::beast::http::verb::head)(std::bind_front(
135             handleAggregationSourceCollectionHead, std::ref(app)));
136 }
137 
138 inline void populateAggregationSource(
139     const std::string& aggregationSourceId,
140     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
141     const boost::system::error_code ec,
142     const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
143 {
144     asyncResp->res.addHeader(
145         boost::beast::http::field::link,
146         "</redfish/v1/JsonSchemas/AggregationSource/AggregationSource.json>; rel=describedby");
147 
148     // Something went wrong while querying dbus
149     if (ec)
150     {
151         messages::internalError(asyncResp->res);
152         return;
153     }
154 
155     const auto& sat = satelliteInfo.find(aggregationSourceId);
156     if (sat == satelliteInfo.end())
157     {
158         messages::resourceNotFound(asyncResp->res, "AggregationSource",
159                                    aggregationSourceId);
160         return;
161     }
162 
163     asyncResp->res.jsonValue["@odata.id"] =
164         crow::utility::urlFromPieces("redfish", "v1", "AggregationService",
165                                      "AggregationSources", aggregationSourceId);
166     asyncResp->res.jsonValue["@odata.type"] =
167         "#AggregationSource.v1_3_1.AggregationSource";
168     asyncResp->res.jsonValue["Id"] = aggregationSourceId;
169 
170     // TODO: We may want to change this whenever we support aggregating multiple
171     // satellite BMCs.  Otherwise all AggregationSource resources will have the
172     // same "Name".
173     // TODO: We should use the "Name" from the satellite config whenever we add
174     // support for including it in the data returned in satelliteInfo.
175     asyncResp->res.jsonValue["Name"] = "Aggregation source";
176     std::string hostName(sat->second.encoded_origin());
177     asyncResp->res.jsonValue["HostName"] = std::move(hostName);
178 
179     // The Redfish spec requires Password to be null in responses
180     asyncResp->res.jsonValue["Password"] = nullptr;
181 }
182 
183 inline void handleAggregationSourceGet(
184     App& app, const crow::Request& req,
185     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
186     const std::string& aggregationSourceId)
187 {
188     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
189     {
190         return;
191     }
192 
193     // Query D-Bus for satellite config corresponding to the specified
194     // AggregationSource
195     RedfishAggregator::getSatelliteConfigs(std::bind_front(
196         populateAggregationSource, aggregationSourceId, asyncResp));
197 }
198 
199 inline void handleAggregationSourceHead(
200     App& app, const crow::Request& req,
201     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
202     const std::string& aggregationSourceId)
203 {
204     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
205     {
206         return;
207     }
208     asyncResp->res.addHeader(
209         boost::beast::http::field::link,
210         "</redfish/v1/JsonSchemas/AggregationService/AggregationSource.json>; rel=describedby");
211 
212     // Needed to prevent unused variable error
213     BMCWEB_LOG_DEBUG << "Added link header to response from "
214                      << aggregationSourceId;
215 }
216 
217 inline void requestRoutesAggregationSource(App& app)
218 {
219     BMCWEB_ROUTE(app,
220                  "/redfish/v1/AggregationService/AggregationSources/<str>/")
221         .privileges(redfish::privileges::getAggregationSource)
222         .methods(boost::beast::http::verb::get)(
223             std::bind_front(handleAggregationSourceGet, std::ref(app)));
224 }
225 
226 } // namespace redfish
227