blob: b88cb43a19ceb590da621d55eab6ac19bc2f5b45 [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 = {
25 "Base", "OpenBMC", "Task"};
26static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
27 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
28
29static constexpr const uint8_t maxNoOfSubscriptions = 20;
30
AppaRao Pulie5aaf042020-03-20 01:05:52 +053031class EventService : public Node
32{
33 public:
34 EventService(CrowApp& app) : Node(app, "/redfish/v1/EventService/")
35 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +053036 entityPrivileges = {
37 {boost::beast::http::verb::get, {{"Login"}}},
38 {boost::beast::http::verb::head, {{"Login"}}},
39 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
40 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
41 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
42 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
43 }
44
45 private:
46 void doGet(crow::Response& res, const crow::Request& req,
47 const std::vector<std::string>& params) override
48 {
49 auto asyncResp = std::make_shared<AsyncResp>(res);
50 res.jsonValue = {
51 {"@odata.type", "#EventService.v1_5_0.EventService"},
52 {"Id", "EventService"},
53 {"Name", "Event Service"},
54 {"ServerSentEventUri",
55 "/redfish/v1/EventService/Subscriptions/SSE"},
56 {"Subscriptions",
57 {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
AppaRao Puli0b4bdd92020-04-14 17:57:45 +053058 {"Actions",
59 {{"#EventService.SubmitTestEvent",
60 {{"target", "/redfish/v1/EventService/Actions/"
61 "EventService.SubmitTestEvent"}}}}},
AppaRao Pulie5aaf042020-03-20 01:05:52 +053062 {"@odata.id", "/redfish/v1/EventService"}};
63
AppaRao Puli7d1cc382020-05-16 02:42:22 +053064 const auto& [enabled, retryAttempts, retryTimeoutInterval] =
65 EventServiceManager::getInstance().getEventServiceConfig();
66
67 asyncResp->res.jsonValue["Status"]["State"] =
68 (enabled ? "Enabled" : "Disabled");
69 asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
70 asyncResp->res.jsonValue["DeliveryRetryAttempts"] = retryAttempts;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053071 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
AppaRao Puli7d1cc382020-05-16 02:42:22 +053072 retryTimeoutInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053073 asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
74 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
75 }
76
77 void doPatch(crow::Response& res, const crow::Request& req,
78 const std::vector<std::string>& params) override
79 {
80 auto asyncResp = std::make_shared<AsyncResp>(res);
81
82 std::optional<bool> serviceEnabled;
83 std::optional<uint32_t> retryAttemps;
84 std::optional<uint32_t> retryInterval;
85
86 if (!json_util::readJson(req, res, "ServiceEnabled", serviceEnabled,
87 "DeliveryRetryAttempts", retryAttemps,
88 "DeliveryRetryIntervalSeconds", retryInterval))
89 {
90 return;
91 }
92
AppaRao Puli7d1cc382020-05-16 02:42:22 +053093 auto [enabled, retryCount, retryTimeoutInterval] =
94 EventServiceManager::getInstance().getEventServiceConfig();
95
AppaRao Pulie5aaf042020-03-20 01:05:52 +053096 if (serviceEnabled)
97 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +053098 enabled = *serviceEnabled;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053099 }
100
101 if (retryAttemps)
102 {
103 // Supported range [1-3]
104 if ((*retryAttemps < 1) || (*retryAttemps > 3))
105 {
106 messages::queryParameterOutOfRange(
107 asyncResp->res, std::to_string(*retryAttemps),
108 "DeliveryRetryAttempts", "[1-3]");
109 }
110 else
111 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530112 retryCount = *retryAttemps;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530113 }
114 }
115
116 if (retryInterval)
117 {
118 // Supported range [30 - 180]
119 if ((*retryInterval < 30) || (*retryInterval > 180))
120 {
121 messages::queryParameterOutOfRange(
122 asyncResp->res, std::to_string(*retryInterval),
123 "DeliveryRetryIntervalSeconds", "[30-180]");
124 }
125 else
126 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530127 retryTimeoutInterval = *retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530128 }
129 }
130
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530131 EventServiceManager::getInstance().setEventServiceConfig(
132 std::make_tuple(enabled, retryCount, retryTimeoutInterval));
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530133 }
134};
135
AppaRao Puli0b4bdd92020-04-14 17:57:45 +0530136class SubmitTestEvent : public Node
137{
138 public:
139 SubmitTestEvent(CrowApp& app) :
140 Node(app,
141 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
142 {
143 entityPrivileges = {
144 {boost::beast::http::verb::get, {{"Login"}}},
145 {boost::beast::http::verb::head, {{"Login"}}},
146 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
147 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
148 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
149 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
150 }
151
152 private:
153 void doPost(crow::Response& res, const crow::Request& req,
154 const std::vector<std::string>& params) override
155 {
156 EventServiceManager::getInstance().sendTestEventLog();
157 res.result(boost::beast::http::status::no_content);
158 res.end();
159 }
160};
161
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530162class EventDestinationCollection : public Node
163{
164 public:
165 EventDestinationCollection(CrowApp& app) :
166 Node(app, "/redfish/v1/EventService/Subscriptions/")
167 {
168 entityPrivileges = {
169 {boost::beast::http::verb::get, {{"Login"}}},
170 {boost::beast::http::verb::head, {{"Login"}}},
171 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
172 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
173 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
174 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
175 }
176
177 private:
178 void doGet(crow::Response& res, const crow::Request& req,
179 const std::vector<std::string>& params) override
180 {
181 auto asyncResp = std::make_shared<AsyncResp>(res);
182
183 res.jsonValue = {
184 {"@odata.type",
185 "#EventDestinationCollection.EventDestinationCollection"},
186 {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
187 {"Name", "Event Destination Collections"}};
188
189 nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530190
AppaRao Pulib52664e2020-04-09 21:36:51 +0530191 std::vector<std::string> subscripIds =
192 EventServiceManager::getInstance().getAllIDs();
193 memberArray = nlohmann::json::array();
194 asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
195
196 for (const std::string& id : subscripIds)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530197 {
198 memberArray.push_back(
199 {{"@odata.id",
AppaRao Pulib52664e2020-04-09 21:36:51 +0530200 "/redfish/v1/EventService/Subscriptions/" + id}});
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530201 }
202 }
203
204 void doPost(crow::Response& res, const crow::Request& req,
205 const std::vector<std::string>& params) override
206 {
207 auto asyncResp = std::make_shared<AsyncResp>(res);
208
AppaRao Pulib52664e2020-04-09 21:36:51 +0530209 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
210 maxNoOfSubscriptions)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530211 {
212 messages::eventSubscriptionLimitExceeded(asyncResp->res);
213 return;
214 }
215 std::string destUrl;
216 std::string protocol;
217 std::optional<std::string> context;
218 std::optional<std::string> subscriptionType;
219 std::optional<std::string> eventFormatType;
220 std::optional<std::string> retryPolicy;
221 std::optional<std::vector<std::string>> msgIds;
222 std::optional<std::vector<std::string>> regPrefixes;
223 std::optional<std::vector<nlohmann::json>> headers;
AppaRao Puli156d6b02020-04-25 06:04:05 +0530224 std::optional<std::vector<nlohmann::json>> metricReportDefinitions;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530225
226 if (!json_util::readJson(
227 req, res, "Destination", destUrl, "Context", context,
228 "Protocol", protocol, "SubscriptionType", subscriptionType,
229 "EventFormatType", eventFormatType, "HttpHeaders", headers,
230 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
AppaRao Puli156d6b02020-04-25 06:04:05 +0530231 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
232 metricReportDefinitions))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530233 {
234 return;
235 }
236
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530237 // Validate the URL using regex expression
AppaRao Pulib52664e2020-04-09 21:36:51 +0530238 // Format: <protocol>://<host>:<port>/<uri>
239 // protocol: http/https
240 // host: Exclude ' ', ':', '#', '?'
241 // port: Empty or numeric value with ':' seperator.
242 // uri: Start with '/' and Exclude '#', ' '
243 // Can include query params(ex: '/event?test=1')
244 // TODO: Need to validate hostname extensively(as per rfc)
245 const std::regex urlRegex(
246 "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
247 "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
248 std::cmatch match;
249 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530250 {
251 messages::propertyValueFormatError(asyncResp->res, destUrl,
252 "Destination");
253 return;
254 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530255
256 std::string uriProto = std::string(match[1].first, match[1].second);
257 if (uriProto == "http")
258 {
259#ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
260 messages::propertyValueFormatError(asyncResp->res, destUrl,
261 "Destination");
262 return;
263#endif
264 }
265
266 std::string host = std::string(match[2].first, match[2].second);
267 std::string port = std::string(match[3].first, match[3].second);
268 std::string path = std::string(match[4].first, match[4].second);
269 if (port.empty())
270 {
271 if (uriProto == "http")
272 {
273 port = "80";
274 }
275 else
276 {
277 port = "443";
278 }
279 }
280 if (path.empty())
281 {
282 path = "/";
283 }
284
285 std::shared_ptr<Subscription> subValue =
286 std::make_shared<Subscription>(host, port, path, uriProto);
287
288 subValue->destinationUrl = destUrl;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530289
290 if (subscriptionType)
291 {
292 if (*subscriptionType != "RedfishEvent")
293 {
294 messages::propertyValueNotInList(
295 asyncResp->res, *subscriptionType, "SubscriptionType");
296 return;
297 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530298 subValue->subscriptionType = *subscriptionType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530299 }
300 else
301 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530302 subValue->subscriptionType = "RedfishEvent"; // Default
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530303 }
304
305 if (protocol != "Redfish")
306 {
307 messages::propertyValueNotInList(asyncResp->res, protocol,
308 "Protocol");
309 return;
310 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530311 subValue->protocol = protocol;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530312
313 if (eventFormatType)
314 {
315 if (std::find(supportedEvtFormatTypes.begin(),
316 supportedEvtFormatTypes.end(),
317 *eventFormatType) == supportedEvtFormatTypes.end())
318 {
319 messages::propertyValueNotInList(
320 asyncResp->res, *eventFormatType, "EventFormatType");
321 return;
322 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530323 subValue->eventFormatType = *eventFormatType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530324 }
325 else
326 {
327 // If not specified, use default "Event"
AppaRao Pulib52664e2020-04-09 21:36:51 +0530328 subValue->eventFormatType.assign({"Event"});
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530329 }
330
331 if (context)
332 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530333 subValue->customText = *context;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530334 }
335
336 if (headers)
337 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530338 subValue->httpHeaders = *headers;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530339 }
340
341 if (regPrefixes)
342 {
343 for (const std::string& it : *regPrefixes)
344 {
345 if (std::find(supportedRegPrefixes.begin(),
346 supportedRegPrefixes.end(),
347 it) == supportedRegPrefixes.end())
348 {
349 messages::propertyValueNotInList(asyncResp->res, it,
350 "RegistryPrefixes");
351 return;
352 }
353 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530354 subValue->registryPrefixes = *regPrefixes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530355 }
356
357 if (msgIds)
358 {
359 // Do we need to loop-up MessageRegistry and validate
360 // data for authenticity??? Not mandate, i believe.
AppaRao Pulib52664e2020-04-09 21:36:51 +0530361 subValue->registryMsgIds = *msgIds;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530362 }
363
364 if (retryPolicy)
365 {
366 if (std::find(supportedRetryPolicies.begin(),
367 supportedRetryPolicies.end(),
368 *retryPolicy) == supportedRetryPolicies.end())
369 {
370 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
371 "DeliveryRetryPolicy");
372 return;
373 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530374 subValue->retryPolicy = *retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530375 }
376 else
377 {
378 // Default "TerminateAfterRetries"
AppaRao Pulib52664e2020-04-09 21:36:51 +0530379 subValue->retryPolicy = "TerminateAfterRetries";
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530380 }
381
AppaRao Puli156d6b02020-04-25 06:04:05 +0530382 if (metricReportDefinitions)
383 {
384 subValue->metricReportDefinitions = *metricReportDefinitions;
385 }
386
AppaRao Pulib52664e2020-04-09 21:36:51 +0530387 std::string id =
388 EventServiceManager::getInstance().addSubscription(subValue);
389 if (id.empty())
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530390 {
391 messages::internalError(asyncResp->res);
392 return;
393 }
394
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530395 messages::created(asyncResp->res);
396 asyncResp->res.addHeader(
397 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
398 }
399};
400
401class EventDestination : public Node
402{
403 public:
404 EventDestination(CrowApp& app) :
405 Node(app, "/redfish/v1/EventService/Subscriptions/<str>/",
406 std::string())
407 {
408 entityPrivileges = {
409 {boost::beast::http::verb::get, {{"Login"}}},
410 {boost::beast::http::verb::head, {{"Login"}}},
411 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
412 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
413 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
414 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
415 }
416
417 private:
418 void doGet(crow::Response& res, const crow::Request& req,
419 const std::vector<std::string>& params) override
420 {
421 auto asyncResp = std::make_shared<AsyncResp>(res);
422 if (params.size() != 1)
423 {
424 messages::internalError(asyncResp->res);
425 return;
426 }
427
AppaRao Pulib52664e2020-04-09 21:36:51 +0530428 std::shared_ptr<Subscription> subValue =
429 EventServiceManager::getInstance().getSubscription(params[0]);
430 if (subValue == nullptr)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530431 {
432 res.result(boost::beast::http::status::not_found);
433 res.end();
434 return;
435 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530436 const std::string& id = params[0];
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530437
438 res.jsonValue = {
439 {"@odata.type", "#EventDestination.v1_7_0.EventDestination"},
440 {"Protocol", "Redfish"}};
441 asyncResp->res.jsonValue["@odata.id"] =
442 "/redfish/v1/EventService/Subscriptions/" + id;
443 asyncResp->res.jsonValue["Id"] = id;
444 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
AppaRao Pulib52664e2020-04-09 21:36:51 +0530445 asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
446 asyncResp->res.jsonValue["Context"] = subValue->customText;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530447 asyncResp->res.jsonValue["SubscriptionType"] =
AppaRao Pulib52664e2020-04-09 21:36:51 +0530448 subValue->subscriptionType;
449 asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
450 asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530451 asyncResp->res.jsonValue["RegistryPrefixes"] =
AppaRao Pulib52664e2020-04-09 21:36:51 +0530452 subValue->registryPrefixes;
453 asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
454 asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
AppaRao Puli156d6b02020-04-25 06:04:05 +0530455 asyncResp->res.jsonValue["MetricReportDefinitions"] =
456 subValue->metricReportDefinitions;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530457 }
458
459 void doPatch(crow::Response& res, const crow::Request& req,
460 const std::vector<std::string>& params) override
461 {
462 auto asyncResp = std::make_shared<AsyncResp>(res);
463 if (params.size() != 1)
464 {
465 messages::internalError(asyncResp->res);
466 return;
467 }
468
AppaRao Pulib52664e2020-04-09 21:36:51 +0530469 std::shared_ptr<Subscription> subValue =
470 EventServiceManager::getInstance().getSubscription(params[0]);
471 if (subValue == nullptr)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530472 {
473 res.result(boost::beast::http::status::not_found);
474 res.end();
475 return;
476 }
477
478 std::optional<std::string> context;
479 std::optional<std::string> retryPolicy;
480 std::optional<std::vector<nlohmann::json>> headers;
481
482 if (!json_util::readJson(req, res, "Context", context,
483 "DeliveryRetryPolicy", retryPolicy,
484 "HttpHeaders", headers))
485 {
486 return;
487 }
488
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530489 if (context)
490 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530491 subValue->customText = *context;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530492 }
493
494 if (headers)
495 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530496 subValue->httpHeaders = *headers;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530497 }
498
499 if (retryPolicy)
500 {
501 if (std::find(supportedRetryPolicies.begin(),
502 supportedRetryPolicies.end(),
503 *retryPolicy) == supportedRetryPolicies.end())
504 {
505 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
506 "DeliveryRetryPolicy");
507 return;
508 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530509 subValue->retryPolicy = *retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530510 }
511
AppaRao Pulib52664e2020-04-09 21:36:51 +0530512 EventServiceManager::getInstance().updateSubscriptionData();
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530513 }
514
515 void doDelete(crow::Response& res, const crow::Request& req,
516 const std::vector<std::string>& params) override
517 {
518 auto asyncResp = std::make_shared<AsyncResp>(res);
519
520 if (params.size() != 1)
521 {
522 messages::internalError(asyncResp->res);
523 return;
524 }
525
AppaRao Pulib52664e2020-04-09 21:36:51 +0530526 if (!EventServiceManager::getInstance().isSubscriptionExist(params[0]))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530527 {
528 res.result(boost::beast::http::status::not_found);
529 res.end();
530 return;
531 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530532 EventServiceManager::getInstance().deleteSubscription(params[0]);
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530533 }
534};
535
536} // namespace redfish