blob: 882640912d5a48f4d37d1243d07bab9010071855 [file] [log] [blame]
AppaRao Pulie5aaf042020-03-20 01:05:52 +05301/*
2// Copyright (c) 2020 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
AppaRao Pulib52664e2020-04-09 21:36:51 +053017#include "event_service_manager.hpp"
AppaRao Pulie5aaf042020-03-20 01:05:52 +053018
John Edward Broadbent7e860f12021-04-08 15:57:16 -070019#include <app.hpp>
Ed Tanous601c71a2021-09-08 16:40:12 -070020#include <boost/beast/http/fields.hpp>
Ed Tanouseb1c47d2022-02-09 11:47:27 -080021#include <http/utility.hpp>
22#include <logging.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
25
Patrick Williams1e270c52021-12-04 06:06:56 -060026#include <span>
27
AppaRao Pulie5aaf042020-03-20 01:05:52 +053028namespace redfish
29{
30
AppaRao Puli156d6b02020-04-25 06:04:05 +053031static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
32 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053033static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +053034 "Base", "OpenBMC", "TaskEvent"};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053035static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
36 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
37
Sunitha Harishe56f2542020-07-22 02:38:59 -050038#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
39static constexpr const std::array<const char*, 2> supportedResourceTypes = {
40 "IBMConfigFile", "Task"};
41#else
42static constexpr const std::array<const char*, 1> supportedResourceTypes = {
43 "Task"};
44#endif
45
AppaRao Pulie5aaf042020-03-20 01:05:52 +053046static constexpr const uint8_t maxNoOfSubscriptions = 20;
47
John Edward Broadbent7e860f12021-04-08 15:57:16 -070048inline void requestRoutesEventService(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +053049{
John Edward Broadbent7e860f12021-04-08 15:57:16 -070050 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070051 .privileges(redfish::privileges::getEventService)
Ed Tanous002d39b2022-05-31 08:59:27 -070052 .methods(boost::beast::http::verb::get)(
53 [&app](const crow::Request& req,
54 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +000055 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -070056 {
57 return;
58 }
Ed Tanous14766872022-03-15 10:44:42 -070059
Ed Tanous002d39b2022-05-31 08:59:27 -070060 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
61 asyncResp->res.jsonValue["@odata.type"] =
62 "#EventService.v1_5_0.EventService";
63 asyncResp->res.jsonValue["Id"] = "EventService";
64 asyncResp->res.jsonValue["Name"] = "Event Service";
65 asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
66 "/redfish/v1/EventService/Subscriptions";
67 asyncResp->res
68 .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
69 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
AppaRao Pulie5aaf042020-03-20 01:05:52 +053070
Ed Tanous002d39b2022-05-31 08:59:27 -070071 const persistent_data::EventServiceConfig eventServiceConfig =
72 persistent_data::EventServiceStore::getInstance()
73 .getEventServiceConfig();
zhanghch058d1b46d2021-04-01 11:18:24 +080074
Ed Tanous002d39b2022-05-31 08:59:27 -070075 asyncResp->res.jsonValue["Status"]["State"] =
76 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
77 asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
78 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
79 eventServiceConfig.retryAttempts;
80 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
81 eventServiceConfig.retryTimeoutInterval;
82 asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
83 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
84 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053085
Ed Tanous613dabe2022-07-09 11:17:36 -070086 nlohmann::json::object_t supportedSSEFilters;
87 supportedSSEFilters["EventFormatType"] = true;
88 supportedSSEFilters["MessageId"] = true;
89 supportedSSEFilters["MetricReportDefinition"] = true;
90 supportedSSEFilters["RegistryPrefix"] = true;
91 supportedSSEFilters["OriginResource"] = false;
92 supportedSSEFilters["ResourceType"] = false;
AppaRao Puli7d1cc382020-05-16 02:42:22 +053093
Ed Tanous002d39b2022-05-31 08:59:27 -070094 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
Ed Tanous613dabe2022-07-09 11:17:36 -070095 std::move(supportedSSEFilters);
George Liu0fda0f12021-11-16 10:06:17 +080096 });
Ayushi Smriti07941a82020-05-21 15:55:34 +053097
John Edward Broadbent7e860f12021-04-08 15:57:16 -070098 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070099 .privileges(redfish::privileges::patchEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700100 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700101 [&app](const crow::Request& req,
102 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000103 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700104 {
105 return;
106 }
107 std::optional<bool> serviceEnabled;
108 std::optional<uint32_t> retryAttemps;
109 std::optional<uint32_t> retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530110
Ed Tanous002d39b2022-05-31 08:59:27 -0700111 if (!json_util::readJsonPatch(
112 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
113 "DeliveryRetryAttempts", retryAttemps,
114 "DeliveryRetryIntervalSeconds", retryInterval))
115 {
116 return;
117 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530118
Ed Tanous002d39b2022-05-31 08:59:27 -0700119 persistent_data::EventServiceConfig eventServiceConfig =
120 persistent_data::EventServiceStore::getInstance()
121 .getEventServiceConfig();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700122
Ed Tanous002d39b2022-05-31 08:59:27 -0700123 if (serviceEnabled)
124 {
125 eventServiceConfig.enabled = *serviceEnabled;
126 }
Sunitha Harishe56f2542020-07-22 02:38:59 -0500127
Ed Tanous002d39b2022-05-31 08:59:27 -0700128 if (retryAttemps)
129 {
130 // Supported range [1-3]
131 if ((*retryAttemps < 1) || (*retryAttemps > 3))
132 {
133 messages::queryParameterOutOfRange(
134 asyncResp->res, std::to_string(*retryAttemps),
135 "DeliveryRetryAttempts", "[1-3]");
136 }
137 else
138 {
139 eventServiceConfig.retryAttempts = *retryAttemps;
140 }
141 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530142
Ed Tanous002d39b2022-05-31 08:59:27 -0700143 if (retryInterval)
144 {
Gunnar Mills33a32b32022-11-17 14:29:07 -0600145 // Supported range [5 - 180]
146 if ((*retryInterval < 5) || (*retryInterval > 180))
Ed Tanous002d39b2022-05-31 08:59:27 -0700147 {
148 messages::queryParameterOutOfRange(
149 asyncResp->res, std::to_string(*retryInterval),
Gunnar Mills33a32b32022-11-17 14:29:07 -0600150 "DeliveryRetryIntervalSeconds", "[5-180]");
Ed Tanous002d39b2022-05-31 08:59:27 -0700151 }
152 else
153 {
154 eventServiceConfig.retryTimeoutInterval = *retryInterval;
155 }
156 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700157
Ed Tanous002d39b2022-05-31 08:59:27 -0700158 EventServiceManager::getInstance().setEventServiceConfig(
159 eventServiceConfig);
160 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700161}
162
163inline void requestRoutesSubmitTestEvent(App& app)
164{
165
166 BMCWEB_ROUTE(
167 app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
Ed Tanoused398212021-06-09 17:05:54 -0700168 .privileges(redfish::privileges::postEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700169 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700170 [&app](const crow::Request& req,
171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000172 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700173 {
174 return;
175 }
176 if (!EventServiceManager::getInstance().sendTestEventLog())
177 {
178 messages::serviceDisabled(asyncResp->res,
179 "/redfish/v1/EventService/");
180 return;
181 }
182 asyncResp->res.result(boost::beast::http::status::no_content);
183 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700184}
185
186inline void requestRoutesEventDestinationCollection(App& app)
187{
Gayathri Leburu1ebe3e42022-02-09 10:45:19 +0000188 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Ed Tanoused398212021-06-09 17:05:54 -0700189 .privileges(redfish::privileges::getEventDestinationCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700190 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700191 [&app](const crow::Request& req,
192 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000193 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700194 {
195 return;
196 }
197 asyncResp->res.jsonValue["@odata.type"] =
198 "#EventDestinationCollection.EventDestinationCollection";
199 asyncResp->res.jsonValue["@odata.id"] =
200 "/redfish/v1/EventService/Subscriptions";
201 asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700202
Ed Tanous002d39b2022-05-31 08:59:27 -0700203 nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700204
Ed Tanous002d39b2022-05-31 08:59:27 -0700205 std::vector<std::string> subscripIds =
206 EventServiceManager::getInstance().getAllIDs();
207 memberArray = nlohmann::json::array();
208 asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700209
Ed Tanous002d39b2022-05-31 08:59:27 -0700210 for (const std::string& id : subscripIds)
211 {
212 nlohmann::json::object_t member;
213 member["@odata.id"] =
214 "/redfish/v1/EventService/Subscriptions/" + id;
215 memberArray.push_back(std::move(member));
216 }
217 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700218 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500219 .privileges(redfish::privileges::postEventDestinationCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700220 .methods(boost::beast::http::verb::post)(
221 [&app](const crow::Request& req,
222 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000223 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700224 {
225 return;
226 }
227 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
228 maxNoOfSubscriptions)
229 {
230 messages::eventSubscriptionLimitExceeded(asyncResp->res);
231 return;
232 }
233 std::string destUrl;
234 std::string protocol;
235 std::optional<std::string> context;
236 std::optional<std::string> subscriptionType;
237 std::optional<std::string> eventFormatType2;
238 std::optional<std::string> retryPolicy;
239 std::optional<std::vector<std::string>> msgIds;
240 std::optional<std::vector<std::string>> regPrefixes;
241 std::optional<std::vector<std::string>> resTypes;
242 std::optional<std::vector<nlohmann::json>> headers;
243 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800244
Ed Tanous002d39b2022-05-31 08:59:27 -0700245 if (!json_util::readJsonPatch(
246 req, asyncResp->res, "Destination", destUrl, "Context", context,
247 "Protocol", protocol, "SubscriptionType", subscriptionType,
248 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
249 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
250 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
251 mrdJsonArray, "ResourceTypes", resTypes))
252 {
253 return;
254 }
255
256 if (regPrefixes && msgIds)
257 {
258 if (!regPrefixes->empty() && !msgIds->empty())
Ed Tanousfffb8c12022-02-07 23:53:03 -0800259 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700260 messages::propertyValueConflict(asyncResp->res, "MessageIds",
261 "RegistryPrefixes");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800262 return;
263 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700264 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800265
Ed Tanous002d39b2022-05-31 08:59:27 -0700266 std::string host;
267 std::string urlProto;
268 uint16_t port = 0;
269 std::string path;
270
271 if (!crow::utility::validateAndSplitUrl(destUrl, urlProto, host, port,
272 path))
273 {
274 BMCWEB_LOG_WARNING
275 << "Failed to validate and split destination url";
276 messages::propertyValueFormatError(asyncResp->res, destUrl,
277 "Destination");
278 return;
279 }
280
281 if (path.empty())
282 {
283 path = "/";
284 }
285 std::shared_ptr<Subscription> subValue =
286 std::make_shared<Subscription>(host, port, path, urlProto);
287
288 subValue->destinationUrl = destUrl;
289
290 if (subscriptionType)
291 {
292 if (*subscriptionType != "RedfishEvent")
Ed Tanousfffb8c12022-02-07 23:53:03 -0800293 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700294 messages::propertyValueNotInList(
295 asyncResp->res, *subscriptionType, "SubscriptionType");
296 return;
297 }
298 subValue->subscriptionType = *subscriptionType;
299 }
300 else
301 {
302 subValue->subscriptionType = "RedfishEvent"; // Default
303 }
304
305 if (protocol != "Redfish")
306 {
307 messages::propertyValueNotInList(asyncResp->res, protocol,
308 "Protocol");
309 return;
310 }
311 subValue->protocol = protocol;
312
313 if (eventFormatType2)
314 {
315 if (std::find(supportedEvtFormatTypes.begin(),
316 supportedEvtFormatTypes.end(),
317 *eventFormatType2) == supportedEvtFormatTypes.end())
318 {
319 messages::propertyValueNotInList(
320 asyncResp->res, *eventFormatType2, "EventFormatType");
321 return;
322 }
323 subValue->eventFormatType = *eventFormatType2;
324 }
325 else
326 {
327 // If not specified, use default "Event"
328 subValue->eventFormatType = "Event";
329 }
330
331 if (context)
332 {
333 subValue->customText = *context;
334 }
335
336 if (headers)
337 {
338 for (const nlohmann::json& headerChunk : *headers)
339 {
340 for (const auto& item : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700341 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700342 const std::string* value =
343 item.value().get_ptr<const std::string*>();
344 if (value == nullptr)
345 {
346 messages::propertyValueFormatError(
347 asyncResp->res, item.value().dump(2, 1),
348 "HttpHeaders/" + item.key());
349 return;
350 }
351 subValue->httpHeaders.set(item.key(), *value);
352 }
353 }
354 }
355
356 if (regPrefixes)
357 {
358 for (const std::string& it : *regPrefixes)
359 {
360 if (std::find(supportedRegPrefixes.begin(),
361 supportedRegPrefixes.end(),
362 it) == supportedRegPrefixes.end())
363 {
364 messages::propertyValueNotInList(asyncResp->res, it,
365 "RegistryPrefixes");
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530366 return;
367 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800368 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700369 subValue->registryPrefixes = *regPrefixes;
370 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530371
Ed Tanous002d39b2022-05-31 08:59:27 -0700372 if (resTypes)
373 {
374 for (const std::string& it : *resTypes)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800375 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700376 if (std::find(supportedResourceTypes.begin(),
377 supportedResourceTypes.end(),
378 it) == supportedResourceTypes.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700379 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700380 messages::propertyValueNotInList(asyncResp->res, it,
381 "ResourceTypes");
AppaRao Puli144b6312020-08-03 22:23:12 +0530382 return;
383 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700384 }
385 subValue->resourceTypes = *resTypes;
386 }
387
388 if (msgIds)
389 {
390 std::vector<std::string> registryPrefix;
391
392 // If no registry prefixes are mentioned, consider all
393 // supported prefixes
394 if (subValue->registryPrefixes.empty())
395 {
396 registryPrefix.assign(supportedRegPrefixes.begin(),
397 supportedRegPrefixes.end());
Ed Tanousfffb8c12022-02-07 23:53:03 -0800398 }
399 else
400 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700401 registryPrefix = subValue->registryPrefixes;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800402 }
AppaRao Puli156d6b02020-04-25 06:04:05 +0530403
Ed Tanous002d39b2022-05-31 08:59:27 -0700404 for (const std::string& id : *msgIds)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800405 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700406 bool validId = false;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800407
Ed Tanous002d39b2022-05-31 08:59:27 -0700408 // Check for Message ID in each of the selected Registry
409 for (const std::string& it : registryPrefix)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700410 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700411 const std::span<const redfish::registries::MessageEntry>
412 registry =
413 redfish::registries::getRegistryFromPrefix(it);
414
415 if (std::any_of(
416 registry.begin(), registry.end(),
417 [&id](const redfish::registries::MessageEntry&
418 messageEntry) {
419 return id == messageEntry.first;
420 }))
421 {
422 validId = true;
423 break;
424 }
425 }
426
427 if (!validId)
428 {
429 messages::propertyValueNotInList(asyncResp->res, id,
430 "MessageIds");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800431 return;
432 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800433 }
434
Ed Tanous002d39b2022-05-31 08:59:27 -0700435 subValue->registryMsgIds = *msgIds;
436 }
437
438 if (retryPolicy)
439 {
440 if (std::find(supportedRetryPolicies.begin(),
441 supportedRetryPolicies.end(),
442 *retryPolicy) == supportedRetryPolicies.end())
Ed Tanousfffb8c12022-02-07 23:53:03 -0800443 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700444 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
445 "DeliveryRetryPolicy");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800446 return;
447 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700448 subValue->retryPolicy = *retryPolicy;
449 }
450 else
451 {
452 // Default "TerminateAfterRetries"
453 subValue->retryPolicy = "TerminateAfterRetries";
454 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800455
Ed Tanous002d39b2022-05-31 08:59:27 -0700456 if (mrdJsonArray)
457 {
458 for (nlohmann::json& mrdObj : *mrdJsonArray)
459 {
460 std::string mrdUri;
461
462 if (!json_util::readJson(mrdObj, asyncResp->res, "@odata.id",
463 mrdUri))
464
465 {
466 return;
467 }
468 subValue->metricReportDefinitions.emplace_back(mrdUri);
469 }
470 }
471
472 std::string id =
473 EventServiceManager::getInstance().addSubscription(subValue);
474 if (id.empty())
475 {
476 messages::internalError(asyncResp->res);
477 return;
478 }
479
480 messages::created(asyncResp->res);
481 asyncResp->res.addHeader(
482 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
Ed Tanousfffb8c12022-02-07 23:53:03 -0800483 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700484}
485
486inline void requestRoutesEventDestination(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530487{
Ravi Teja9d41aec2021-07-23 01:57:01 -0500488 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700489 .privileges(redfish::privileges::getEventDestination)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700490 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700491 [&app](const crow::Request& req,
492 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
493 const std::string& param) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000494 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700495 {
496 return;
497 }
498 std::shared_ptr<Subscription> subValue =
499 EventServiceManager::getInstance().getSubscription(param);
500 if (subValue == nullptr)
501 {
502 asyncResp->res.result(boost::beast::http::status::not_found);
503 return;
504 }
505 const std::string& id = param;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530506
Ed Tanous002d39b2022-05-31 08:59:27 -0700507 asyncResp->res.jsonValue["@odata.type"] =
508 "#EventDestination.v1_7_0.EventDestination";
509 asyncResp->res.jsonValue["Protocol"] = "Redfish";
510 asyncResp->res.jsonValue["@odata.id"] =
511 "/redfish/v1/EventService/Subscriptions/" + id;
512 asyncResp->res.jsonValue["Id"] = id;
513 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
514 asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
515 asyncResp->res.jsonValue["Context"] = subValue->customText;
516 asyncResp->res.jsonValue["SubscriptionType"] =
517 subValue->subscriptionType;
518 asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
519 asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
520 asyncResp->res.jsonValue["RegistryPrefixes"] =
521 subValue->registryPrefixes;
522 asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
zhanghch058d1b46d2021-04-01 11:18:24 +0800523
Ed Tanous002d39b2022-05-31 08:59:27 -0700524 asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
525 asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530526
Ed Tanous002d39b2022-05-31 08:59:27 -0700527 nlohmann::json::array_t mrdJsonArray;
528 for (const auto& mdrUri : subValue->metricReportDefinitions)
529 {
530 nlohmann::json::object_t mdr;
531 mdr["@odata.id"] = mdrUri;
532 mrdJsonArray.emplace_back(std::move(mdr));
533 }
534 asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
535 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500536 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700537 // The below privilege is wrong, it should be ConfigureManager OR
538 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500539 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700540 //.privileges(redfish::privileges::patchEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700541 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700542 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700543 [&app](const crow::Request& req,
544 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
545 const std::string& param) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000546 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700547 {
548 return;
549 }
550 std::shared_ptr<Subscription> subValue =
551 EventServiceManager::getInstance().getSubscription(param);
552 if (subValue == nullptr)
553 {
554 asyncResp->res.result(boost::beast::http::status::not_found);
555 return;
556 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530557
Ed Tanous002d39b2022-05-31 08:59:27 -0700558 std::optional<std::string> context;
559 std::optional<std::string> retryPolicy;
560 std::optional<std::vector<nlohmann::json>> headers;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500561
Ed Tanous002d39b2022-05-31 08:59:27 -0700562 if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
563 "DeliveryRetryPolicy", retryPolicy,
564 "HttpHeaders", headers))
565 {
566 return;
567 }
AppaRao Puli144b6312020-08-03 22:23:12 +0530568
Ed Tanous002d39b2022-05-31 08:59:27 -0700569 if (context)
570 {
571 subValue->customText = *context;
572 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530573
Ed Tanous002d39b2022-05-31 08:59:27 -0700574 if (headers)
575 {
576 boost::beast::http::fields fields;
577 for (const nlohmann::json& headerChunk : *headers)
578 {
Patrick Williams62bafc02022-09-08 17:35:35 -0500579 for (const auto& it : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700580 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700581 const std::string* value =
582 it.value().get_ptr<const std::string*>();
583 if (value == nullptr)
Ed Tanous601c71a2021-09-08 16:40:12 -0700584 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700585 messages::propertyValueFormatError(
586 asyncResp->res, it.value().dump(2, ' ', true),
587 "HttpHeaders/" + it.key());
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700588 return;
589 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700590 fields.set(it.key(), *value);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700591 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700592 }
593 subValue->httpHeaders = fields;
594 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530595
Ed Tanous002d39b2022-05-31 08:59:27 -0700596 if (retryPolicy)
597 {
598 if (std::find(supportedRetryPolicies.begin(),
599 supportedRetryPolicies.end(),
600 *retryPolicy) == supportedRetryPolicies.end())
601 {
602 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
603 "DeliveryRetryPolicy");
604 return;
605 }
606 subValue->retryPolicy = *retryPolicy;
607 subValue->updateRetryPolicy();
608 }
609
610 EventServiceManager::getInstance().updateSubscriptionData();
611 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500612 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700613 // The below privilege is wrong, it should be ConfigureManager OR
614 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500615 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700616 //.privileges(redfish::privileges::deleteEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700617 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700618 .methods(boost::beast::http::verb::delete_)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700619 [&app](const crow::Request& req,
620 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
621 const std::string& param) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000622 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700623 {
624 return;
625 }
626 if (!EventServiceManager::getInstance().isSubscriptionExist(param))
627 {
628 asyncResp->res.result(boost::beast::http::status::not_found);
629 return;
630 }
631 EventServiceManager::getInstance().deleteSubscription(param);
632 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700633}
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530634
635} // namespace redfish