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 <boost/url/format.hpp>
12 #include <nlohmann/json.hpp>
13
14 #include <functional>
15 #include <memory>
16
17 namespace redfish
18 {
19
handleAggregationServiceHead(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)20 inline void handleAggregationServiceHead(
21 App& app, const crow::Request& req,
22 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
23 {
24 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
25 {
26 return;
27 }
28 asyncResp->res.addHeader(
29 boost::beast::http::field::link,
30 "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
31 }
32
handleAggregationServiceGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)33 inline void handleAggregationServiceGet(
34 App& app, const crow::Request& req,
35 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
36 {
37 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
38 {
39 return;
40 }
41 asyncResp->res.addHeader(
42 boost::beast::http::field::link,
43 "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
44 nlohmann::json& json = asyncResp->res.jsonValue;
45 json["@odata.id"] = "/redfish/v1/AggregationService";
46 json["@odata.type"] = "#AggregationService.v1_0_1.AggregationService";
47 json["Id"] = "AggregationService";
48 json["Name"] = "Aggregation Service";
49 json["Description"] = "Aggregation Service";
50 json["ServiceEnabled"] = true;
51 json["AggregationSources"]["@odata.id"] =
52 "/redfish/v1/AggregationService/AggregationSources";
53 }
54
requestRoutesAggregationService(App & app)55 inline void requestRoutesAggregationService(App& app)
56 {
57 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
58 .privileges(redfish::privileges::headAggregationService)
59 .methods(boost::beast::http::verb::head)(
60 std::bind_front(handleAggregationServiceHead, std::ref(app)));
61 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
62 .privileges(redfish::privileges::getAggregationService)
63 .methods(boost::beast::http::verb::get)(
64 std::bind_front(handleAggregationServiceGet, std::ref(app)));
65 }
66
populateAggregationSourceCollection(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::system::error_code & ec,const std::unordered_map<std::string,boost::urls::url> & satelliteInfo)67 inline void populateAggregationSourceCollection(
68 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
69 const boost::system::error_code& ec,
70 const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
71 {
72 // Something went wrong while querying dbus
73 if (ec)
74 {
75 messages::internalError(asyncResp->res);
76 return;
77 }
78 nlohmann::json::array_t members = nlohmann::json::array();
79 for (const auto& sat : satelliteInfo)
80 {
81 nlohmann::json::object_t member;
82 member["@odata.id"] = boost::urls::format(
83 "/redfish/v1/AggregationService/AggregationSources/{}", sat.first);
84 members.emplace_back(std::move(member));
85 }
86 asyncResp->res.jsonValue["Members@odata.count"] = members.size();
87 asyncResp->res.jsonValue["Members"] = std::move(members);
88 }
89
handleAggregationSourceCollectionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)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
handleAggregationSourceCollectionHead(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)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
requestRoutesAggregationSourceCollection(App & app)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
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)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"] = boost::urls::format(
164 "/redfish/v1/AggregationService/AggregationSources/{}",
165 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
handleAggregationSourceGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & aggregationSourceId)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
handleAggregationSourceHead(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & aggregationSourceId)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
requestRoutesAggregationSource(App & app)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