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