blob: e19fe7512a66dd422e4cef4ed89d7449210105e3 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ed Tanous6c068982023-02-07 15:44:38 -08003#pragma once
4
5#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "async_resp.hpp"
Ed Tanous6c068982023-02-07 15:44:38 -08007#include "error_messages.hpp"
8#include "http_request.hpp"
9#include "http_response.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080010#include "logging.hpp"
Ed Tanous6c068982023-02-07 15:44:38 -080011#include "query.hpp"
Carson Labrado8b2521a2023-02-18 02:33:14 +000012#include "redfish_aggregator.hpp"
Ed Tanous6c068982023-02-07 15:44:38 -080013#include "registries/privilege_registry.hpp"
14
Ed Tanousd7857202025-01-28 15:32:26 -080015#include <boost/beast/http/field.hpp>
16#include <boost/beast/http/verb.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070017#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080018#include <boost/url/url.hpp>
Ed Tanous6c068982023-02-07 15:44:38 -080019#include <nlohmann/json.hpp>
20
21#include <functional>
22#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080023#include <unordered_map>
24#include <utility>
Ed Tanous6c068982023-02-07 15:44:38 -080025
26namespace redfish
27{
28
29inline void handleAggregationServiceHead(
30 App& app, const crow::Request& req,
31 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
32{
33 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
34 {
35 return;
36 }
37 asyncResp->res.addHeader(
38 boost::beast::http::field::link,
39 "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
40}
41
42inline void handleAggregationServiceGet(
43 App& app, const crow::Request& req,
44 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
45{
46 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
47 {
48 return;
49 }
50 asyncResp->res.addHeader(
51 boost::beast::http::field::link,
52 "</redfish/v1/JsonSchemas/AggregationService/AggregationService.json>; rel=describedby");
53 nlohmann::json& json = asyncResp->res.jsonValue;
54 json["@odata.id"] = "/redfish/v1/AggregationService";
55 json["@odata.type"] = "#AggregationService.v1_0_1.AggregationService";
56 json["Id"] = "AggregationService";
57 json["Name"] = "Aggregation Service";
58 json["Description"] = "Aggregation Service";
59 json["ServiceEnabled"] = true;
Carson Labrado5315c1b2023-02-18 01:02:18 +000060 json["AggregationSources"]["@odata.id"] =
61 "/redfish/v1/AggregationService/AggregationSources";
Ed Tanous6c068982023-02-07 15:44:38 -080062}
63
Carson Labrado8b2521a2023-02-18 02:33:14 +000064inline void requestRoutesAggregationService(App& app)
Ed Tanous6c068982023-02-07 15:44:38 -080065{
66 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
67 .privileges(redfish::privileges::headAggregationService)
68 .methods(boost::beast::http::verb::head)(
69 std::bind_front(handleAggregationServiceHead, std::ref(app)));
70 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/")
71 .privileges(redfish::privileges::getAggregationService)
72 .methods(boost::beast::http::verb::get)(
73 std::bind_front(handleAggregationServiceGet, std::ref(app)));
74}
75
Carson Labrado8b2521a2023-02-18 02:33:14 +000076inline void populateAggregationSourceCollection(
77 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous81c4e332023-05-18 10:30:34 -070078 const boost::system::error_code& ec,
Carson Labrado8b2521a2023-02-18 02:33:14 +000079 const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
80{
81 // Something went wrong while querying dbus
82 if (ec)
83 {
84 messages::internalError(asyncResp->res);
85 return;
86 }
Ed Tanous82b286f2025-05-06 13:29:48 -070087 nlohmann::json::array_t members;
Carson Labrado8b2521a2023-02-18 02:33:14 +000088 for (const auto& sat : satelliteInfo)
89 {
90 nlohmann::json::object_t member;
Ed Tanousef4c65b2023-04-24 15:28:50 -070091 member["@odata.id"] = boost::urls::format(
92 "/redfish/v1/AggregationService/AggregationSources/{}", sat.first);
Patrick Williamsad539542023-05-12 10:10:08 -050093 members.emplace_back(std::move(member));
Carson Labrado8b2521a2023-02-18 02:33:14 +000094 }
95 asyncResp->res.jsonValue["Members@odata.count"] = members.size();
96 asyncResp->res.jsonValue["Members"] = std::move(members);
97}
98
99inline void handleAggregationSourceCollectionGet(
Carson Labrado5315c1b2023-02-18 01:02:18 +0000100 App& app, const crow::Request& req,
101 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
102{
103 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
104 {
105 return;
106 }
107 asyncResp->res.addHeader(
108 boost::beast::http::field::link,
109 "</redfish/v1/JsonSchemas/AggregationSourceCollection/AggregationSourceCollection.json>; rel=describedby");
110 nlohmann::json& json = asyncResp->res.jsonValue;
111 json["@odata.id"] = "/redfish/v1/AggregationService/AggregationSources";
112 json["@odata.type"] =
113 "#AggregationSourceCollection.AggregationSourceCollection";
114 json["Name"] = "Aggregation Source Collection";
Carson Labrado5315c1b2023-02-18 01:02:18 +0000115
Carson Labrado8b2521a2023-02-18 02:33:14 +0000116 // Query D-Bus for satellite configs and add them to the Members array
117 RedfishAggregator::getSatelliteConfigs(
118 std::bind_front(populateAggregationSourceCollection, asyncResp));
Carson Labrado5315c1b2023-02-18 01:02:18 +0000119}
120
Carson Labrado8b2521a2023-02-18 02:33:14 +0000121inline void handleAggregationSourceCollectionHead(
122 App& app, const crow::Request& req,
123 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
124{
125 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
126 {
127 return;
128 }
129 asyncResp->res.addHeader(
130 boost::beast::http::field::link,
131 "</redfish/v1/JsonSchemas/AggregationService/AggregationSourceCollection.json>; rel=describedby");
132}
133
134inline void requestRoutesAggregationSourceCollection(App& app)
Carson Labrado5315c1b2023-02-18 01:02:18 +0000135{
136 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
Carson Labrado8b2521a2023-02-18 02:33:14 +0000137 .privileges(redfish::privileges::getAggregationSourceCollection)
138 .methods(boost::beast::http::verb::get)(std::bind_front(
139 handleAggregationSourceCollectionGet, std::ref(app)));
140
141 BMCWEB_ROUTE(app, "/redfish/v1/AggregationService/AggregationSources/")
142 .privileges(redfish::privileges::getAggregationSourceCollection)
143 .methods(boost::beast::http::verb::head)(std::bind_front(
144 handleAggregationSourceCollectionHead, std::ref(app)));
145}
146
147inline void populateAggregationSource(
148 const std::string& aggregationSourceId,
149 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous81c4e332023-05-18 10:30:34 -0700150 const boost::system::error_code& ec,
Carson Labrado8b2521a2023-02-18 02:33:14 +0000151 const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
152{
153 asyncResp->res.addHeader(
154 boost::beast::http::field::link,
155 "</redfish/v1/JsonSchemas/AggregationSource/AggregationSource.json>; rel=describedby");
156
157 // Something went wrong while querying dbus
158 if (ec)
159 {
160 messages::internalError(asyncResp->res);
161 return;
162 }
163
164 const auto& sat = satelliteInfo.find(aggregationSourceId);
165 if (sat == satelliteInfo.end())
166 {
167 messages::resourceNotFound(asyncResp->res, "AggregationSource",
168 aggregationSourceId);
169 return;
170 }
171
Ed Tanousef4c65b2023-04-24 15:28:50 -0700172 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
173 "/redfish/v1/AggregationService/AggregationSources/{}",
174 aggregationSourceId);
Carson Labrado8b2521a2023-02-18 02:33:14 +0000175 asyncResp->res.jsonValue["@odata.type"] =
176 "#AggregationSource.v1_3_1.AggregationSource";
177 asyncResp->res.jsonValue["Id"] = aggregationSourceId;
178
179 // TODO: We may want to change this whenever we support aggregating multiple
180 // satellite BMCs. Otherwise all AggregationSource resources will have the
181 // same "Name".
182 // TODO: We should use the "Name" from the satellite config whenever we add
183 // support for including it in the data returned in satelliteInfo.
184 asyncResp->res.jsonValue["Name"] = "Aggregation source";
185 std::string hostName(sat->second.encoded_origin());
186 asyncResp->res.jsonValue["HostName"] = std::move(hostName);
187
188 // The Redfish spec requires Password to be null in responses
189 asyncResp->res.jsonValue["Password"] = nullptr;
190}
191
192inline void handleAggregationSourceGet(
193 App& app, const crow::Request& req,
194 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
195 const std::string& aggregationSourceId)
196{
197 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
198 {
199 return;
200 }
201
202 // Query D-Bus for satellite config corresponding to the specified
203 // AggregationSource
204 RedfishAggregator::getSatelliteConfigs(std::bind_front(
205 populateAggregationSource, aggregationSourceId, asyncResp));
206}
207
208inline void handleAggregationSourceHead(
209 App& app, const crow::Request& req,
210 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
211 const std::string& aggregationSourceId)
212{
213 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
214 {
215 return;
216 }
217 asyncResp->res.addHeader(
218 boost::beast::http::field::link,
219 "</redfish/v1/JsonSchemas/AggregationService/AggregationSource.json>; rel=describedby");
220
221 // Needed to prevent unused variable error
Ed Tanous62598e32023-07-17 17:06:25 -0700222 BMCWEB_LOG_DEBUG("Added link header to response from {}",
223 aggregationSourceId);
Carson Labrado8b2521a2023-02-18 02:33:14 +0000224}
225
226inline void requestRoutesAggregationSource(App& app)
227{
228 BMCWEB_ROUTE(app,
229 "/redfish/v1/AggregationService/AggregationSources/<str>/")
230 .privileges(redfish::privileges::getAggregationSource)
Carson Labrado5315c1b2023-02-18 01:02:18 +0000231 .methods(boost::beast::http::verb::get)(
Carson Labrado8b2521a2023-02-18 02:33:14 +0000232 std::bind_front(handleAggregationSourceGet, std::ref(app)));
Carson Labrado5315c1b2023-02-18 01:02:18 +0000233}
234
Ed Tanous6c068982023-02-07 15:44:38 -0800235} // namespace redfish