xref: /openbmc/bmcweb/features/redfish/lib/aggregation_service.hpp (revision 8b2521a5a3be479814beb316975bf3de0b4e378f)
16c068982SEd Tanous #pragma once
26c068982SEd Tanous 
36c068982SEd Tanous #include "app.hpp"
46c068982SEd Tanous #include "error_messages.hpp"
56c068982SEd Tanous #include "http_request.hpp"
66c068982SEd Tanous #include "http_response.hpp"
76c068982SEd Tanous #include "query.hpp"
8*8b2521a5SCarson Labrado #include "redfish_aggregator.hpp"
96c068982SEd Tanous #include "registries/privilege_registry.hpp"
106c068982SEd Tanous 
116c068982SEd Tanous #include <nlohmann/json.hpp>
126c068982SEd Tanous 
136c068982SEd Tanous #include <functional>
146c068982SEd Tanous #include <memory>
156c068982SEd Tanous 
166c068982SEd Tanous namespace redfish
176c068982SEd Tanous {
186c068982SEd Tanous 
196c068982SEd Tanous inline void handleAggregationServiceHead(
206c068982SEd Tanous     App& app, const crow::Request& req,
216c068982SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
226c068982SEd Tanous {
236c068982SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
246c068982SEd Tanous     {
256c068982SEd Tanous         return;
266c068982SEd Tanous     }
276c068982SEd Tanous     asyncResp->res.addHeader(
286c068982SEd Tanous         boost::beast::http::field::link,
296c068982SEd Tanous         "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
306c068982SEd Tanous }
316c068982SEd Tanous 
326c068982SEd Tanous inline void handleAggregationServiceGet(
336c068982SEd Tanous     App& app, const crow::Request& req,
346c068982SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
356c068982SEd Tanous {
366c068982SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
376c068982SEd Tanous     {
386c068982SEd Tanous         return;
396c068982SEd Tanous     }
406c068982SEd Tanous     asyncResp->res.addHeader(
416c068982SEd Tanous         boost::beast::http::field::link,
426c068982SEd Tanous         "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
436c068982SEd Tanous     nlohmann::json& json = asyncResp->res.jsonValue;
446c068982SEd Tanous     json["@odata.id"] = "/redfish/v1/AggregationService";
456c068982SEd Tanous     json["@odata.type"] = "#AggregationService.v1_0_1.AggregationService";
466c068982SEd Tanous     json["Id"] = "AggregationService";
476c068982SEd Tanous     json["Name"] = "Aggregation Service";
486c068982SEd Tanous     json["Description"] = "Aggregation Service";
496c068982SEd Tanous     json["ServiceEnabled"] = true;
505315c1b1SCarson Labrado     json["AggregationSources"]["@odata.id"] =
515315c1b1SCarson Labrado         "/redfish/v1/AggregationService/AggregationSources";
526c068982SEd Tanous }
536c068982SEd Tanous 
54*8b2521a5SCarson Labrado inline void requestRoutesAggregationService(App& app)
556c068982SEd Tanous {
566c068982SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
576c068982SEd Tanous         .privileges(redfish::privileges::headAggregationService)
586c068982SEd Tanous         .methods(boost::beast::http::verb::head)(
596c068982SEd Tanous             std::bind_front(handleAggregationServiceHead, std::ref(app)));
606c068982SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
616c068982SEd Tanous         .privileges(redfish::privileges::getAggregationService)
626c068982SEd Tanous         .methods(boost::beast::http::verb::get)(
636c068982SEd Tanous             std::bind_front(handleAggregationServiceGet, std::ref(app)));
646c068982SEd Tanous }
656c068982SEd Tanous 
66*8b2521a5SCarson Labrado inline void populateAggregationSourceCollection(
67*8b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
68*8b2521a5SCarson Labrado     const boost::system::error_code ec,
69*8b2521a5SCarson Labrado     const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
70*8b2521a5SCarson Labrado {
71*8b2521a5SCarson Labrado     // Something went wrong while querying dbus
72*8b2521a5SCarson Labrado     if (ec)
73*8b2521a5SCarson Labrado     {
74*8b2521a5SCarson Labrado         messages::internalError(asyncResp->res);
75*8b2521a5SCarson Labrado         return;
76*8b2521a5SCarson Labrado     }
77*8b2521a5SCarson Labrado     nlohmann::json::array_t members = nlohmann::json::array();
78*8b2521a5SCarson Labrado     for (const auto& sat : satelliteInfo)
79*8b2521a5SCarson Labrado     {
80*8b2521a5SCarson Labrado         nlohmann::json::object_t member;
81*8b2521a5SCarson Labrado         member["@odata.id"] =
82*8b2521a5SCarson Labrado             crow::utility::urlFromPieces("redfish", "v1", "AggregationService",
83*8b2521a5SCarson Labrado                                          "AggregationSources", sat.first);
84*8b2521a5SCarson Labrado         members.push_back(std::move(member));
85*8b2521a5SCarson Labrado     }
86*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
87*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["Members"] = std::move(members);
88*8b2521a5SCarson Labrado }
89*8b2521a5SCarson Labrado 
90*8b2521a5SCarson Labrado inline void handleAggregationSourceCollectionGet(
915315c1b1SCarson Labrado     App& app, const crow::Request& req,
925315c1b1SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
935315c1b1SCarson Labrado {
945315c1b1SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
955315c1b1SCarson Labrado     {
965315c1b1SCarson Labrado         return;
975315c1b1SCarson Labrado     }
985315c1b1SCarson Labrado     asyncResp->res.addHeader(
995315c1b1SCarson Labrado         boost::beast::http::field::link,
1005315c1b1SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationSourceCollection/AggregationSourceCollection.json>; rel=describedby");
1015315c1b1SCarson Labrado     nlohmann::json& json = asyncResp->res.jsonValue;
1025315c1b1SCarson Labrado     json["@odata.id"] = "/redfish/v1/AggregationService/AggregationSources";
1035315c1b1SCarson Labrado     json["@odata.type"] =
1045315c1b1SCarson Labrado         "#AggregationSourceCollection.AggregationSourceCollection";
1055315c1b1SCarson Labrado     json["Name"] = "Aggregation Source Collection";
1065315c1b1SCarson Labrado 
107*8b2521a5SCarson Labrado     // Query D-Bus for satellite configs and add them to the Members array
108*8b2521a5SCarson Labrado     RedfishAggregator::getSatelliteConfigs(
109*8b2521a5SCarson Labrado         std::bind_front(populateAggregationSourceCollection, asyncResp));
1105315c1b1SCarson Labrado }
1115315c1b1SCarson Labrado 
112*8b2521a5SCarson Labrado inline void handleAggregationSourceCollectionHead(
113*8b2521a5SCarson Labrado     App& app, const crow::Request& req,
114*8b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
115*8b2521a5SCarson Labrado {
116*8b2521a5SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
117*8b2521a5SCarson Labrado     {
118*8b2521a5SCarson Labrado         return;
119*8b2521a5SCarson Labrado     }
120*8b2521a5SCarson Labrado     asyncResp->res.addHeader(
121*8b2521a5SCarson Labrado         boost::beast::http::field::link,
122*8b2521a5SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationService/AggregationSourceCollection.json>; rel=describedby");
123*8b2521a5SCarson Labrado }
124*8b2521a5SCarson Labrado 
125*8b2521a5SCarson Labrado inline void requestRoutesAggregationSourceCollection(App& app)
1265315c1b1SCarson Labrado {
1275315c1b1SCarson Labrado     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
128*8b2521a5SCarson Labrado         .privileges(redfish::privileges::getAggregationSourceCollection)
129*8b2521a5SCarson Labrado         .methods(boost::beast::http::verb::get)(std::bind_front(
130*8b2521a5SCarson Labrado             handleAggregationSourceCollectionGet, std::ref(app)));
131*8b2521a5SCarson Labrado 
132*8b2521a5SCarson Labrado     BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
133*8b2521a5SCarson Labrado         .privileges(redfish::privileges::getAggregationSourceCollection)
134*8b2521a5SCarson Labrado         .methods(boost::beast::http::verb::head)(std::bind_front(
135*8b2521a5SCarson Labrado             handleAggregationSourceCollectionHead, std::ref(app)));
136*8b2521a5SCarson Labrado }
137*8b2521a5SCarson Labrado 
138*8b2521a5SCarson Labrado inline void populateAggregationSource(
139*8b2521a5SCarson Labrado     const std::string& aggregationSourceId,
140*8b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
141*8b2521a5SCarson Labrado     const boost::system::error_code ec,
142*8b2521a5SCarson Labrado     const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
143*8b2521a5SCarson Labrado {
144*8b2521a5SCarson Labrado     asyncResp->res.addHeader(
145*8b2521a5SCarson Labrado         boost::beast::http::field::link,
146*8b2521a5SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationSource/AggregationSource.json>; rel=describedby");
147*8b2521a5SCarson Labrado 
148*8b2521a5SCarson Labrado     // Something went wrong while querying dbus
149*8b2521a5SCarson Labrado     if (ec)
150*8b2521a5SCarson Labrado     {
151*8b2521a5SCarson Labrado         messages::internalError(asyncResp->res);
152*8b2521a5SCarson Labrado         return;
153*8b2521a5SCarson Labrado     }
154*8b2521a5SCarson Labrado 
155*8b2521a5SCarson Labrado     const auto& sat = satelliteInfo.find(aggregationSourceId);
156*8b2521a5SCarson Labrado     if (sat == satelliteInfo.end())
157*8b2521a5SCarson Labrado     {
158*8b2521a5SCarson Labrado         messages::resourceNotFound(asyncResp->res, "AggregationSource",
159*8b2521a5SCarson Labrado                                    aggregationSourceId);
160*8b2521a5SCarson Labrado         return;
161*8b2521a5SCarson Labrado     }
162*8b2521a5SCarson Labrado 
163*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["@odata.id"] =
164*8b2521a5SCarson Labrado         crow::utility::urlFromPieces("redfish", "v1", "AggregationService",
165*8b2521a5SCarson Labrado                                      "AggregationSources", aggregationSourceId);
166*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["@odata.type"] =
167*8b2521a5SCarson Labrado         "#AggregationSource.v1_3_1.AggregationSource";
168*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["Id"] = aggregationSourceId;
169*8b2521a5SCarson Labrado 
170*8b2521a5SCarson Labrado     // TODO: We may want to change this whenever we support aggregating multiple
171*8b2521a5SCarson Labrado     // satellite BMCs.  Otherwise all AggregationSource resources will have the
172*8b2521a5SCarson Labrado     // same "Name".
173*8b2521a5SCarson Labrado     // TODO: We should use the "Name" from the satellite config whenever we add
174*8b2521a5SCarson Labrado     // support for including it in the data returned in satelliteInfo.
175*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["Name"] = "Aggregation source";
176*8b2521a5SCarson Labrado     std::string hostName(sat->second.encoded_origin());
177*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["HostName"] = std::move(hostName);
178*8b2521a5SCarson Labrado 
179*8b2521a5SCarson Labrado     // The Redfish spec requires Password to be null in responses
180*8b2521a5SCarson Labrado     asyncResp->res.jsonValue["Password"] = nullptr;
181*8b2521a5SCarson Labrado }
182*8b2521a5SCarson Labrado 
183*8b2521a5SCarson Labrado inline void handleAggregationSourceGet(
184*8b2521a5SCarson Labrado     App& app, const crow::Request& req,
185*8b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
186*8b2521a5SCarson Labrado     const std::string& aggregationSourceId)
187*8b2521a5SCarson Labrado {
188*8b2521a5SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
189*8b2521a5SCarson Labrado     {
190*8b2521a5SCarson Labrado         return;
191*8b2521a5SCarson Labrado     }
192*8b2521a5SCarson Labrado 
193*8b2521a5SCarson Labrado     // Query D-Bus for satellite config corresponding to the specified
194*8b2521a5SCarson Labrado     // AggregationSource
195*8b2521a5SCarson Labrado     RedfishAggregator::getSatelliteConfigs(std::bind_front(
196*8b2521a5SCarson Labrado         populateAggregationSource, aggregationSourceId, asyncResp));
197*8b2521a5SCarson Labrado }
198*8b2521a5SCarson Labrado 
199*8b2521a5SCarson Labrado inline void handleAggregationSourceHead(
200*8b2521a5SCarson Labrado     App& app, const crow::Request& req,
201*8b2521a5SCarson Labrado     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
202*8b2521a5SCarson Labrado     const std::string& aggregationSourceId)
203*8b2521a5SCarson Labrado {
204*8b2521a5SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
205*8b2521a5SCarson Labrado     {
206*8b2521a5SCarson Labrado         return;
207*8b2521a5SCarson Labrado     }
208*8b2521a5SCarson Labrado     asyncResp->res.addHeader(
209*8b2521a5SCarson Labrado         boost::beast::http::field::link,
210*8b2521a5SCarson Labrado         "</redfish/v1/JsonSchemas/AggregationService/AggregationSource.json>; rel=describedby");
211*8b2521a5SCarson Labrado 
212*8b2521a5SCarson Labrado     // Needed to prevent unused variable error
213*8b2521a5SCarson Labrado     BMCWEB_LOG_DEBUG << "Added link header to response from "
214*8b2521a5SCarson Labrado                      << aggregationSourceId;
215*8b2521a5SCarson Labrado }
216*8b2521a5SCarson Labrado 
217*8b2521a5SCarson Labrado inline void requestRoutesAggregationSource(App& app)
218*8b2521a5SCarson Labrado {
219*8b2521a5SCarson Labrado     BMCWEB_ROUTE(app,
220*8b2521a5SCarson Labrado                  "/redfish/v1/AggregationService/AggregationSources/<str>/")
221*8b2521a5SCarson Labrado         .privileges(redfish::privileges::getAggregationSource)
2225315c1b1SCarson Labrado         .methods(boost::beast::http::verb::get)(
223*8b2521a5SCarson Labrado             std::bind_front(handleAggregationSourceGet, std::ref(app)));
2245315c1b1SCarson Labrado }
2255315c1b1SCarson Labrado 
2266c068982SEd Tanous } // namespace redfish
227