blob: 64a20092ffa0849bb6ae66e2bb7bdbca7446d103 [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
19namespace redfish
20{
21
AppaRao Puli156d6b02020-04-25 06:04:05 +053022static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
23 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053024static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +053025 "Base", "OpenBMC", "TaskEvent"};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053026static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
27 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
28
Sunitha Harishe56f2542020-07-22 02:38:59 -050029#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
30static constexpr const std::array<const char*, 2> supportedResourceTypes = {
31 "IBMConfigFile", "Task"};
32#else
33static constexpr const std::array<const char*, 1> supportedResourceTypes = {
34 "Task"};
35#endif
36
AppaRao Pulie5aaf042020-03-20 01:05:52 +053037static constexpr const uint8_t maxNoOfSubscriptions = 20;
38
AppaRao Pulie5aaf042020-03-20 01:05:52 +053039class EventService : public Node
40{
41 public:
Ed Tanous52cc1122020-07-18 13:51:21 -070042 EventService(App& app) : Node(app, "/redfish/v1/EventService/")
AppaRao Pulie5aaf042020-03-20 01:05:52 +053043 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +053044 entityPrivileges = {
45 {boost::beast::http::verb::get, {{"Login"}}},
46 {boost::beast::http::verb::head, {{"Login"}}},
47 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
48 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
49 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
50 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
51 }
52
53 private:
zhanghch058d1b46d2021-04-01 11:18:24 +080054 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
55 const crow::Request&, const std::vector<std::string>&) override
AppaRao Pulie5aaf042020-03-20 01:05:52 +053056 {
zhanghch058d1b46d2021-04-01 11:18:24 +080057
58 asyncResp->res.jsonValue = {
AppaRao Pulie5aaf042020-03-20 01:05:52 +053059 {"@odata.type", "#EventService.v1_5_0.EventService"},
60 {"Id", "EventService"},
61 {"Name", "Event Service"},
AppaRao Pulie5aaf042020-03-20 01:05:52 +053062 {"Subscriptions",
63 {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
AppaRao Puli0b4bdd92020-04-14 17:57:45 +053064 {"Actions",
65 {{"#EventService.SubmitTestEvent",
66 {{"target", "/redfish/v1/EventService/Actions/"
67 "EventService.SubmitTestEvent"}}}}},
AppaRao Pulie5aaf042020-03-20 01:05:52 +053068 {"@odata.id", "/redfish/v1/EventService"}};
69
AppaRao Puli7d1cc382020-05-16 02:42:22 +053070 const auto& [enabled, retryAttempts, retryTimeoutInterval] =
71 EventServiceManager::getInstance().getEventServiceConfig();
72
73 asyncResp->res.jsonValue["Status"]["State"] =
74 (enabled ? "Enabled" : "Disabled");
75 asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
76 asyncResp->res.jsonValue["DeliveryRetryAttempts"] = retryAttempts;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053077 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
AppaRao Puli7d1cc382020-05-16 02:42:22 +053078 retryTimeoutInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053079 asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
80 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
Sunitha Harishe56f2542020-07-22 02:38:59 -050081 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
Ayushi Smriti07941a82020-05-21 15:55:34 +053082
83 nlohmann::json supportedSSEFilters = {
84 {"EventFormatType", true}, {"MessageId", true},
85 {"MetricReportDefinition", true}, {"RegistryPrefix", true},
86 {"OriginResource", false}, {"ResourceType", false}};
87
88 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
89 supportedSSEFilters;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053090 }
91
zhanghch058d1b46d2021-04-01 11:18:24 +080092 void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
93 const crow::Request& req,
Ed Tanouscb13a392020-07-25 19:02:03 +000094 const std::vector<std::string>&) override
AppaRao Pulie5aaf042020-03-20 01:05:52 +053095 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +053096
97 std::optional<bool> serviceEnabled;
98 std::optional<uint32_t> retryAttemps;
99 std::optional<uint32_t> retryInterval;
100
zhanghch058d1b46d2021-04-01 11:18:24 +0800101 if (!json_util::readJson(req, asyncResp->res, "ServiceEnabled",
102 serviceEnabled, "DeliveryRetryAttempts",
103 retryAttemps, "DeliveryRetryIntervalSeconds",
104 retryInterval))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530105 {
106 return;
107 }
108
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530109 auto [enabled, retryCount, retryTimeoutInterval] =
110 EventServiceManager::getInstance().getEventServiceConfig();
111
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530112 if (serviceEnabled)
113 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530114 enabled = *serviceEnabled;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530115 }
116
117 if (retryAttemps)
118 {
119 // Supported range [1-3]
120 if ((*retryAttemps < 1) || (*retryAttemps > 3))
121 {
122 messages::queryParameterOutOfRange(
123 asyncResp->res, std::to_string(*retryAttemps),
124 "DeliveryRetryAttempts", "[1-3]");
125 }
126 else
127 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530128 retryCount = *retryAttemps;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530129 }
130 }
131
132 if (retryInterval)
133 {
134 // Supported range [30 - 180]
135 if ((*retryInterval < 30) || (*retryInterval > 180))
136 {
137 messages::queryParameterOutOfRange(
138 asyncResp->res, std::to_string(*retryInterval),
139 "DeliveryRetryIntervalSeconds", "[30-180]");
140 }
141 else
142 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530143 retryTimeoutInterval = *retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530144 }
145 }
146
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530147 EventServiceManager::getInstance().setEventServiceConfig(
148 std::make_tuple(enabled, retryCount, retryTimeoutInterval));
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530149 }
150};
151
AppaRao Puli0b4bdd92020-04-14 17:57:45 +0530152class SubmitTestEvent : public Node
153{
154 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700155 SubmitTestEvent(App& app) :
AppaRao Puli0b4bdd92020-04-14 17:57:45 +0530156 Node(app,
157 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
158 {
159 entityPrivileges = {
160 {boost::beast::http::verb::get, {{"Login"}}},
161 {boost::beast::http::verb::head, {{"Login"}}},
162 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
163 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
164 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
165 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
166 }
167
168 private:
zhanghch058d1b46d2021-04-01 11:18:24 +0800169 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
170 const crow::Request&, const std::vector<std::string>&) override
AppaRao Puli0b4bdd92020-04-14 17:57:45 +0530171 {
172 EventServiceManager::getInstance().sendTestEventLog();
zhanghch058d1b46d2021-04-01 11:18:24 +0800173 asyncResp->res.result(boost::beast::http::status::no_content);
AppaRao Puli0b4bdd92020-04-14 17:57:45 +0530174 }
175};
176
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530177class EventDestinationCollection : public Node
178{
179 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700180 EventDestinationCollection(App& app) :
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530181 Node(app, "/redfish/v1/EventService/Subscriptions/")
182 {
183 entityPrivileges = {
184 {boost::beast::http::verb::get, {{"Login"}}},
185 {boost::beast::http::verb::head, {{"Login"}}},
186 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
187 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
188 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
189 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
190 }
191
192 private:
zhanghch058d1b46d2021-04-01 11:18:24 +0800193 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
194 const crow::Request&, const std::vector<std::string>&) override
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530195 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530196
zhanghch058d1b46d2021-04-01 11:18:24 +0800197 asyncResp->res.jsonValue = {
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530198 {"@odata.type",
199 "#EventDestinationCollection.EventDestinationCollection"},
200 {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
201 {"Name", "Event Destination Collections"}};
202
203 nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530204
AppaRao Pulib52664e2020-04-09 21:36:51 +0530205 std::vector<std::string> subscripIds =
206 EventServiceManager::getInstance().getAllIDs();
207 memberArray = nlohmann::json::array();
208 asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
209
210 for (const std::string& id : subscripIds)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530211 {
212 memberArray.push_back(
213 {{"@odata.id",
AppaRao Pulib52664e2020-04-09 21:36:51 +0530214 "/redfish/v1/EventService/Subscriptions/" + id}});
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530215 }
216 }
217
zhanghch058d1b46d2021-04-01 11:18:24 +0800218 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
219 const crow::Request& req,
Ed Tanouscb13a392020-07-25 19:02:03 +0000220 const std::vector<std::string>&) override
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530221 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530222
AppaRao Pulib52664e2020-04-09 21:36:51 +0530223 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
224 maxNoOfSubscriptions)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530225 {
226 messages::eventSubscriptionLimitExceeded(asyncResp->res);
227 return;
228 }
229 std::string destUrl;
230 std::string protocol;
231 std::optional<std::string> context;
232 std::optional<std::string> subscriptionType;
Ed Tanous23a21a12020-07-25 04:45:05 +0000233 std::optional<std::string> eventFormatType2;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530234 std::optional<std::string> retryPolicy;
235 std::optional<std::vector<std::string>> msgIds;
236 std::optional<std::vector<std::string>> regPrefixes;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500237 std::optional<std::vector<std::string>> resTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530238 std::optional<std::vector<nlohmann::json>> headers;
AppaRao Puli144b6312020-08-03 22:23:12 +0530239 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530240
241 if (!json_util::readJson(
zhanghch058d1b46d2021-04-01 11:18:24 +0800242 req, asyncResp->res, "Destination", destUrl, "Context", context,
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530243 "Protocol", protocol, "SubscriptionType", subscriptionType,
Ed Tanous23a21a12020-07-25 04:45:05 +0000244 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530245 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
AppaRao Puli156d6b02020-04-25 06:04:05 +0530246 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
AppaRao Puli144b6312020-08-03 22:23:12 +0530247 mrdJsonArray, "ResourceTypes", resTypes))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530248 {
249 return;
250 }
251
AppaRao Pulidd28ba82020-09-08 01:53:21 +0530252 if (regPrefixes && msgIds)
253 {
254 if (regPrefixes->size() && msgIds->size())
255 {
256 messages::mutualExclusiveProperties(
257 asyncResp->res, "RegistryPrefixes", "MessageIds");
258 return;
259 }
260 }
261
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530262 // Validate the URL using regex expression
AppaRao Pulib52664e2020-04-09 21:36:51 +0530263 // Format: <protocol>://<host>:<port>/<uri>
264 // protocol: http/https
265 // host: Exclude ' ', ':', '#', '?'
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500266 // port: Empty or numeric value with ':' separator.
AppaRao Pulib52664e2020-04-09 21:36:51 +0530267 // uri: Start with '/' and Exclude '#', ' '
268 // Can include query params(ex: '/event?test=1')
269 // TODO: Need to validate hostname extensively(as per rfc)
270 const std::regex urlRegex(
271 "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
272 "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
273 std::cmatch match;
274 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530275 {
276 messages::propertyValueFormatError(asyncResp->res, destUrl,
277 "Destination");
278 return;
279 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530280
281 std::string uriProto = std::string(match[1].first, match[1].second);
282 if (uriProto == "http")
283 {
284#ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
285 messages::propertyValueFormatError(asyncResp->res, destUrl,
286 "Destination");
287 return;
288#endif
289 }
290
291 std::string host = std::string(match[2].first, match[2].second);
292 std::string port = std::string(match[3].first, match[3].second);
293 std::string path = std::string(match[4].first, match[4].second);
294 if (port.empty())
295 {
296 if (uriProto == "http")
297 {
298 port = "80";
299 }
300 else
301 {
302 port = "443";
303 }
304 }
305 if (path.empty())
306 {
307 path = "/";
308 }
309
310 std::shared_ptr<Subscription> subValue =
311 std::make_shared<Subscription>(host, port, path, uriProto);
312
313 subValue->destinationUrl = destUrl;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530314
315 if (subscriptionType)
316 {
317 if (*subscriptionType != "RedfishEvent")
318 {
319 messages::propertyValueNotInList(
320 asyncResp->res, *subscriptionType, "SubscriptionType");
321 return;
322 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530323 subValue->subscriptionType = *subscriptionType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530324 }
325 else
326 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530327 subValue->subscriptionType = "RedfishEvent"; // Default
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530328 }
329
330 if (protocol != "Redfish")
331 {
332 messages::propertyValueNotInList(asyncResp->res, protocol,
333 "Protocol");
334 return;
335 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530336 subValue->protocol = protocol;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530337
Ed Tanous23a21a12020-07-25 04:45:05 +0000338 if (eventFormatType2)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530339 {
340 if (std::find(supportedEvtFormatTypes.begin(),
341 supportedEvtFormatTypes.end(),
Ed Tanous23a21a12020-07-25 04:45:05 +0000342 *eventFormatType2) == supportedEvtFormatTypes.end())
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530343 {
344 messages::propertyValueNotInList(
Ed Tanous23a21a12020-07-25 04:45:05 +0000345 asyncResp->res, *eventFormatType2, "EventFormatType");
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530346 return;
347 }
Ed Tanous23a21a12020-07-25 04:45:05 +0000348 subValue->eventFormatType = *eventFormatType2;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530349 }
350 else
351 {
352 // If not specified, use default "Event"
Ed Tanous23a21a12020-07-25 04:45:05 +0000353 subValue->eventFormatType = "Event";
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530354 }
355
356 if (context)
357 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530358 subValue->customText = *context;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530359 }
360
361 if (headers)
362 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530363 subValue->httpHeaders = *headers;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530364 }
365
366 if (regPrefixes)
367 {
368 for (const std::string& it : *regPrefixes)
369 {
370 if (std::find(supportedRegPrefixes.begin(),
371 supportedRegPrefixes.end(),
372 it) == supportedRegPrefixes.end())
373 {
374 messages::propertyValueNotInList(asyncResp->res, it,
375 "RegistryPrefixes");
376 return;
377 }
378 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530379 subValue->registryPrefixes = *regPrefixes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530380 }
381
Sunitha Harishe56f2542020-07-22 02:38:59 -0500382 if (resTypes)
383 {
384 for (const std::string& it : *resTypes)
385 {
386 if (std::find(supportedResourceTypes.begin(),
387 supportedResourceTypes.end(),
388 it) == supportedResourceTypes.end())
389 {
390 messages::propertyValueNotInList(asyncResp->res, it,
391 "ResourceTypes");
392 return;
393 }
394 }
395 subValue->resourceTypes = *resTypes;
396 }
397
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530398 if (msgIds)
399 {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530400 std::vector<std::string> registryPrefix;
401
402 // If no registry prefixes are mentioned, consider all supported
403 // prefixes
404 if (subValue->registryPrefixes.empty())
405 {
406 registryPrefix.assign(supportedRegPrefixes.begin(),
407 supportedRegPrefixes.end());
408 }
409 else
410 {
411 registryPrefix = subValue->registryPrefixes;
412 }
413
414 for (const std::string& id : *msgIds)
415 {
416 bool validId = false;
417
418 // Check for Message ID in each of the selected Registry
419 for (const std::string& it : registryPrefix)
420 {
421 const boost::beast::span<
422 const redfish::message_registries::MessageEntry>
423 registry =
424 redfish::message_registries::getRegistryFromPrefix(
425 it);
426
427 if (std::any_of(
428 registry.cbegin(), registry.cend(),
429 [&id](
430 const redfish::message_registries::MessageEntry&
431 messageEntry) {
432 return !id.compare(messageEntry.first);
433 }))
434 {
435 validId = true;
436 break;
437 }
438 }
439
440 if (!validId)
441 {
442 messages::propertyValueNotInList(asyncResp->res, id,
443 "MessageIds");
444 return;
445 }
446 }
447
AppaRao Pulib52664e2020-04-09 21:36:51 +0530448 subValue->registryMsgIds = *msgIds;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530449 }
450
451 if (retryPolicy)
452 {
453 if (std::find(supportedRetryPolicies.begin(),
454 supportedRetryPolicies.end(),
455 *retryPolicy) == supportedRetryPolicies.end())
456 {
457 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
458 "DeliveryRetryPolicy");
459 return;
460 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530461 subValue->retryPolicy = *retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530462 }
463 else
464 {
465 // Default "TerminateAfterRetries"
AppaRao Pulib52664e2020-04-09 21:36:51 +0530466 subValue->retryPolicy = "TerminateAfterRetries";
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530467 }
468
AppaRao Puli144b6312020-08-03 22:23:12 +0530469 if (mrdJsonArray)
AppaRao Puli156d6b02020-04-25 06:04:05 +0530470 {
AppaRao Puli144b6312020-08-03 22:23:12 +0530471 for (nlohmann::json& mrdObj : *mrdJsonArray)
472 {
473 std::string mrdUri;
474 if (json_util::getValueFromJsonObject(mrdObj, "@odata.id",
475 mrdUri))
476 {
477 subValue->metricReportDefinitions.emplace_back(mrdUri);
478 }
479 else
480 {
481 messages::propertyValueFormatError(
Ed Tanous71f52d92021-02-19 08:51:17 -0800482 asyncResp->res,
483 mrdObj.dump(2, ' ', true,
484 nlohmann::json::error_handler_t::replace),
AppaRao Puli144b6312020-08-03 22:23:12 +0530485 "MetricReportDefinitions");
486 return;
487 }
488 }
AppaRao Puli156d6b02020-04-25 06:04:05 +0530489 }
490
AppaRao Pulib52664e2020-04-09 21:36:51 +0530491 std::string id =
492 EventServiceManager::getInstance().addSubscription(subValue);
493 if (id.empty())
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530494 {
495 messages::internalError(asyncResp->res);
496 return;
497 }
498
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530499 messages::created(asyncResp->res);
500 asyncResp->res.addHeader(
501 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
502 }
503};
504
505class EventDestination : public Node
506{
507 public:
Ed Tanous52cc1122020-07-18 13:51:21 -0700508 EventDestination(App& app) :
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530509 Node(app, "/redfish/v1/EventService/Subscriptions/<str>/",
510 std::string())
511 {
512 entityPrivileges = {
513 {boost::beast::http::verb::get, {{"Login"}}},
514 {boost::beast::http::verb::head, {{"Login"}}},
515 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
516 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
517 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
518 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
519 }
520
521 private:
zhanghch058d1b46d2021-04-01 11:18:24 +0800522 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
523 const crow::Request&,
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530524 const std::vector<std::string>& params) override
525 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800526
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530527 if (params.size() != 1)
528 {
529 messages::internalError(asyncResp->res);
530 return;
531 }
532
AppaRao Pulib52664e2020-04-09 21:36:51 +0530533 std::shared_ptr<Subscription> subValue =
534 EventServiceManager::getInstance().getSubscription(params[0]);
535 if (subValue == nullptr)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530536 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800537 asyncResp->res.result(boost::beast::http::status::not_found);
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530538 return;
539 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530540 const std::string& id = params[0];
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530541
zhanghch058d1b46d2021-04-01 11:18:24 +0800542 asyncResp->res.jsonValue = {
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530543 {"@odata.type", "#EventDestination.v1_7_0.EventDestination"},
544 {"Protocol", "Redfish"}};
545 asyncResp->res.jsonValue["@odata.id"] =
546 "/redfish/v1/EventService/Subscriptions/" + id;
547 asyncResp->res.jsonValue["Id"] = id;
548 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
AppaRao Pulib52664e2020-04-09 21:36:51 +0530549 asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
550 asyncResp->res.jsonValue["Context"] = subValue->customText;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530551 asyncResp->res.jsonValue["SubscriptionType"] =
AppaRao Pulib52664e2020-04-09 21:36:51 +0530552 subValue->subscriptionType;
553 asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
554 asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530555 asyncResp->res.jsonValue["RegistryPrefixes"] =
AppaRao Pulib52664e2020-04-09 21:36:51 +0530556 subValue->registryPrefixes;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500557 asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
558
AppaRao Pulib52664e2020-04-09 21:36:51 +0530559 asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
560 asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
AppaRao Puli144b6312020-08-03 22:23:12 +0530561
562 std::vector<nlohmann::json> mrdJsonArray;
563 for (const auto& mdrUri : subValue->metricReportDefinitions)
564 {
565 mrdJsonArray.push_back({{"@odata.id", mdrUri}});
566 }
567 asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530568 }
569
zhanghch058d1b46d2021-04-01 11:18:24 +0800570 void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
571 const crow::Request& req,
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530572 const std::vector<std::string>& params) override
573 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800574
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530575 if (params.size() != 1)
576 {
577 messages::internalError(asyncResp->res);
578 return;
579 }
580
AppaRao Pulib52664e2020-04-09 21:36:51 +0530581 std::shared_ptr<Subscription> subValue =
582 EventServiceManager::getInstance().getSubscription(params[0]);
583 if (subValue == nullptr)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530584 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800585 asyncResp->res.result(boost::beast::http::status::not_found);
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530586 return;
587 }
588
589 std::optional<std::string> context;
590 std::optional<std::string> retryPolicy;
591 std::optional<std::vector<nlohmann::json>> headers;
592
zhanghch058d1b46d2021-04-01 11:18:24 +0800593 if (!json_util::readJson(req, asyncResp->res, "Context", context,
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530594 "DeliveryRetryPolicy", retryPolicy,
595 "HttpHeaders", headers))
596 {
597 return;
598 }
599
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530600 if (context)
601 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530602 subValue->customText = *context;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530603 }
604
605 if (headers)
606 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530607 subValue->httpHeaders = *headers;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530608 }
609
610 if (retryPolicy)
611 {
612 if (std::find(supportedRetryPolicies.begin(),
613 supportedRetryPolicies.end(),
614 *retryPolicy) == supportedRetryPolicies.end())
615 {
616 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
617 "DeliveryRetryPolicy");
618 return;
619 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530620 subValue->retryPolicy = *retryPolicy;
Ayushi Smritife44eb02020-05-15 15:24:45 +0530621 subValue->updateRetryPolicy();
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530622 }
623
AppaRao Pulib52664e2020-04-09 21:36:51 +0530624 EventServiceManager::getInstance().updateSubscriptionData();
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530625 }
626
zhanghch058d1b46d2021-04-01 11:18:24 +0800627 void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
628 const crow::Request&,
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530629 const std::vector<std::string>& params) override
630 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530631
632 if (params.size() != 1)
633 {
634 messages::internalError(asyncResp->res);
635 return;
636 }
637
AppaRao Pulib52664e2020-04-09 21:36:51 +0530638 if (!EventServiceManager::getInstance().isSubscriptionExist(params[0]))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530639 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800640 asyncResp->res.result(boost::beast::http::status::not_found);
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530641 return;
642 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530643 EventServiceManager::getInstance().deleteSubscription(params[0]);
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530644 }
645};
646
647} // namespace redfish