1e5aaf047SAppaRao Puli /* 26be832e2SEd Tanous Copyright (c) 2020 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous limitations under the License. 15e5aaf047SAppaRao Puli */ 16e5aaf047SAppaRao Puli #pragma once 173ccb3adbSEd Tanous #include "app.hpp" 18b52664e2SAppaRao Puli #include "event_service_manager.hpp" 19539d8c6bSEd Tanous #include "generated/enums/event_service.hpp" 203ccb3adbSEd Tanous #include "http/utility.hpp" 213ccb3adbSEd Tanous #include "logging.hpp" 223ccb3adbSEd Tanous #include "query.hpp" 23d109e2b6SAlexander Hansen #include "registries.hpp" 243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 25d109e2b6SAlexander Hansen #include "registries_selector.hpp" 263d30708fSChicago Duan #include "snmp_trap_event_clients.hpp" 27d109e2b6SAlexander Hansen #include "utils/json_utils.hpp" 28e5aaf047SAppaRao Puli 29601c71aeSEd Tanous #include <boost/beast/http/fields.hpp> 303d30708fSChicago Duan #include <boost/system/error_code.hpp> 31a716aa74SEd Tanous #include <boost/url/parse.hpp> 323d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp> 333d30708fSChicago Duan #include <utils/dbus_utils.hpp> 34ed398213SEd Tanous 353d30708fSChicago Duan #include <charconv> 363d30708fSChicago Duan #include <memory> 375064a25bSMyung Bae #include <optional> 383544d2a7SEd Tanous #include <ranges> 391e270c5fSPatrick Williams #include <span> 403d30708fSChicago Duan #include <string> 41a14c9113SEd Tanous #include <vector> 421e270c5fSPatrick Williams 43e5aaf047SAppaRao Puli namespace redfish 44e5aaf047SAppaRao Puli { 45e5aaf047SAppaRao Puli 46156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = { 47156d6b00SAppaRao Puli eventFormatType, metricReportFormatType}; 48fb546105SMyung Bae static constexpr const std::array<const char*, 4> supportedRegPrefixes = { 49fb546105SMyung Bae "Base", "OpenBMC", "TaskEvent", "HeartbeatEvent"}; 50e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = { 51e5aaf047SAppaRao Puli "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; 52e5aaf047SAppaRao Puli 53fb546105SMyung Bae static constexpr const std::array<const char*, 2> supportedResourceTypes = { 54fb546105SMyung Bae "Task", "Heartbeat"}; 55e56f254cSSunitha Harish 567e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app) 57e5aaf047SAppaRao Puli { 587e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 59ed398213SEd Tanous .privileges(redfish::privileges::getEventService) 60bd79bce8SPatrick Williams .methods( 61bd79bce8SPatrick Williams boost::beast::http::verb:: 62bd79bce8SPatrick Williams get)([&app]( 63bd79bce8SPatrick Williams const crow::Request& req, 64002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 653ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 6645ca1b86SEd Tanous { 6745ca1b86SEd Tanous return; 6845ca1b86SEd Tanous } 691476687dSEd Tanous 701476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService"; 711476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 721476687dSEd Tanous "#EventService.v1_5_0.EventService"; 731476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "EventService"; 741476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Event Service"; 755e44e3d8SAppaRao Puli asyncResp->res.jsonValue["ServerSentEventUri"] = 765e44e3d8SAppaRao Puli "/redfish/v1/EventService/SSE"; 775e44e3d8SAppaRao Puli 781476687dSEd Tanous asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] = 791476687dSEd Tanous "/redfish/v1/EventService/Subscriptions"; 80bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#EventService.SubmitTestEvent"] 81bd79bce8SPatrick Williams ["target"] = 821476687dSEd Tanous "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent"; 83e5aaf047SAppaRao Puli 8428afb49cSJunLin Chen const persistent_data::EventServiceConfig eventServiceConfig = 8528afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 8628afb49cSJunLin Chen .getEventServiceConfig(); 877d1cc387SAppaRao Puli 887d1cc387SAppaRao Puli asyncResp->res.jsonValue["Status"]["State"] = 8928afb49cSJunLin Chen (eventServiceConfig.enabled ? "Enabled" : "Disabled"); 90bd79bce8SPatrick Williams asyncResp->res.jsonValue["ServiceEnabled"] = 91bd79bce8SPatrick Williams eventServiceConfig.enabled; 927e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 9328afb49cSJunLin Chen eventServiceConfig.retryAttempts; 94e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 9528afb49cSJunLin Chen eventServiceConfig.retryTimeoutInterval; 96bd79bce8SPatrick Williams asyncResp->res.jsonValue["EventFormatTypes"] = 97bd79bce8SPatrick Williams supportedEvtFormatTypes; 980fda0f12SGeorge Liu asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes; 990fda0f12SGeorge Liu asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes; 10007941a88SAyushi Smriti 101613dabeaSEd Tanous nlohmann::json::object_t supportedSSEFilters; 102613dabeaSEd Tanous supportedSSEFilters["EventFormatType"] = true; 103613dabeaSEd Tanous supportedSSEFilters["MessageId"] = true; 104613dabeaSEd Tanous supportedSSEFilters["MetricReportDefinition"] = true; 105613dabeaSEd Tanous supportedSSEFilters["RegistryPrefix"] = true; 106613dabeaSEd Tanous supportedSSEFilters["OriginResource"] = false; 107613dabeaSEd Tanous supportedSSEFilters["ResourceType"] = false; 10807941a88SAyushi Smriti 10907941a88SAyushi Smriti asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] = 110613dabeaSEd Tanous std::move(supportedSSEFilters); 1117e860f15SJohn Edward Broadbent }); 112e5aaf047SAppaRao Puli 1137e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 114ed398213SEd Tanous .privileges(redfish::privileges::patchEventService) 1157e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 11645ca1b86SEd Tanous [&app](const crow::Request& req, 11745ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1183ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 119e5aaf047SAppaRao Puli { 12045ca1b86SEd Tanous return; 12145ca1b86SEd Tanous } 122e5aaf047SAppaRao Puli std::optional<bool> serviceEnabled; 123e5aaf047SAppaRao Puli std::optional<uint32_t> retryAttemps; 124e5aaf047SAppaRao Puli std::optional<uint32_t> retryInterval; 125afc474aeSMyung Bae if (!json_util::readJsonPatch( // 126afc474aeSMyung Bae req, asyncResp->res, // 127afc474aeSMyung Bae "DeliveryRetryAttempts", retryAttemps, // 128afc474aeSMyung Bae "DeliveryRetryIntervalSeconds", retryInterval, // 129afc474aeSMyung Bae "ServiceEnabled", serviceEnabled // 130afc474aeSMyung Bae )) 131e5aaf047SAppaRao Puli { 132e5aaf047SAppaRao Puli return; 133e5aaf047SAppaRao Puli } 134e5aaf047SAppaRao Puli 13528afb49cSJunLin Chen persistent_data::EventServiceConfig eventServiceConfig = 13628afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 13728afb49cSJunLin Chen .getEventServiceConfig(); 1387d1cc387SAppaRao Puli 139e5aaf047SAppaRao Puli if (serviceEnabled) 140e5aaf047SAppaRao Puli { 14128afb49cSJunLin Chen eventServiceConfig.enabled = *serviceEnabled; 142e5aaf047SAppaRao Puli } 143e5aaf047SAppaRao Puli 144e5aaf047SAppaRao Puli if (retryAttemps) 145e5aaf047SAppaRao Puli { 146e5aaf047SAppaRao Puli // Supported range [1-3] 147e5aaf047SAppaRao Puli if ((*retryAttemps < 1) || (*retryAttemps > 3)) 148e5aaf047SAppaRao Puli { 149e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 150e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryAttemps), 151e5aaf047SAppaRao Puli "DeliveryRetryAttempts", "[1-3]"); 152e5aaf047SAppaRao Puli } 153e5aaf047SAppaRao Puli else 154e5aaf047SAppaRao Puli { 15528afb49cSJunLin Chen eventServiceConfig.retryAttempts = *retryAttemps; 156e5aaf047SAppaRao Puli } 157e5aaf047SAppaRao Puli } 158e5aaf047SAppaRao Puli 159e5aaf047SAppaRao Puli if (retryInterval) 160e5aaf047SAppaRao Puli { 16133a32b34SGunnar Mills // Supported range [5 - 180] 16233a32b34SGunnar Mills if ((*retryInterval < 5) || (*retryInterval > 180)) 163e5aaf047SAppaRao Puli { 164e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 165e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryInterval), 16633a32b34SGunnar Mills "DeliveryRetryIntervalSeconds", "[5-180]"); 167e5aaf047SAppaRao Puli } 168e5aaf047SAppaRao Puli else 169e5aaf047SAppaRao Puli { 170bd79bce8SPatrick Williams eventServiceConfig.retryTimeoutInterval = 171bd79bce8SPatrick Williams *retryInterval; 172e5aaf047SAppaRao Puli } 173e5aaf047SAppaRao Puli } 174e5aaf047SAppaRao Puli 1757d1cc387SAppaRao Puli EventServiceManager::getInstance().setEventServiceConfig( 17628afb49cSJunLin Chen eventServiceConfig); 1777e860f15SJohn Edward Broadbent }); 1780b4bdd93SAppaRao Puli } 1790b4bdd93SAppaRao Puli 1807e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app) 1810b4bdd93SAppaRao Puli { 1827e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 1837e860f15SJohn Edward Broadbent app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/") 184ed398213SEd Tanous .privileges(redfish::privileges::postEventService) 1857e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 18645ca1b86SEd Tanous [&app](const crow::Request& req, 1877e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1883ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18945ca1b86SEd Tanous { 19045ca1b86SEd Tanous return; 19145ca1b86SEd Tanous } 192*81ee0e74SChandramohan Harkude 193*81ee0e74SChandramohan Harkude TestEvent testEvent; 194*81ee0e74SChandramohan Harkude // clang-format off 195*81ee0e74SChandramohan Harkude if (!json_util::readJsonAction( 196*81ee0e74SChandramohan Harkude req, asyncResp->res, 197*81ee0e74SChandramohan Harkude "EventGroupId", testEvent.eventGroupId, 198*81ee0e74SChandramohan Harkude "EventId", testEvent.eventId, 199*81ee0e74SChandramohan Harkude "EventTimestamp", testEvent.eventTimestamp, 200*81ee0e74SChandramohan Harkude "Message", testEvent.message, 201*81ee0e74SChandramohan Harkude "MessageArgs", testEvent.messageArgs, 202*81ee0e74SChandramohan Harkude "MessageId", testEvent.messageId, 203*81ee0e74SChandramohan Harkude "OriginOfCondition", testEvent.originOfCondition, 204*81ee0e74SChandramohan Harkude "Resolution", testEvent.resolution, 205*81ee0e74SChandramohan Harkude "Severity", testEvent.severity)) 206*81ee0e74SChandramohan Harkude { 207*81ee0e74SChandramohan Harkude return; 208*81ee0e74SChandramohan Harkude } 209*81ee0e74SChandramohan Harkude // clang-format on 210*81ee0e74SChandramohan Harkude 211*81ee0e74SChandramohan Harkude if (!EventServiceManager::getInstance().sendTestEventLog( 212*81ee0e74SChandramohan Harkude testEvent)) 2136ba8c82eSsunharis_in { 2146ba8c82eSsunharis_in messages::serviceDisabled(asyncResp->res, 2156ba8c82eSsunharis_in "/redfish/v1/EventService/"); 2166ba8c82eSsunharis_in return; 2176ba8c82eSsunharis_in } 2188d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 2197e860f15SJohn Edward Broadbent }); 220e5aaf047SAppaRao Puli } 221e5aaf047SAppaRao Puli 2223d30708fSChicago Duan inline void doSubscriptionCollection( 223e81de512SEd Tanous const boost::system::error_code& ec, 2243d30708fSChicago Duan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2253d30708fSChicago Duan const dbus::utility::ManagedObjectType& resp) 2263d30708fSChicago Duan { 2273d30708fSChicago Duan if (ec) 2283d30708fSChicago Duan { 2291306101eSEd Tanous if (ec.value() == EBADR || ec.value() == EHOSTUNREACH) 2303d30708fSChicago Duan { 2313d30708fSChicago Duan // This is an optional process so just return if it isn't there 2323d30708fSChicago Duan return; 2333d30708fSChicago Duan } 2343d30708fSChicago Duan 23562598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec); 2363d30708fSChicago Duan messages::internalError(asyncResp->res); 2373d30708fSChicago Duan return; 2383d30708fSChicago Duan } 2393d30708fSChicago Duan nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; 2403d30708fSChicago Duan for (const auto& objpath : resp) 2413d30708fSChicago Duan { 2423d30708fSChicago Duan sdbusplus::message::object_path path(objpath.first); 2433d30708fSChicago Duan const std::string snmpId = path.filename(); 2443d30708fSChicago Duan if (snmpId.empty()) 2453d30708fSChicago Duan { 24662598e31SEd Tanous BMCWEB_LOG_ERROR("The SNMP client ID is wrong"); 2473d30708fSChicago Duan messages::internalError(asyncResp->res); 2483d30708fSChicago Duan return; 2493d30708fSChicago Duan } 2503d30708fSChicago Duan 2513d30708fSChicago Duan getSnmpSubscriptionList(asyncResp, snmpId, memberArray); 2523d30708fSChicago Duan } 2533d30708fSChicago Duan } 2543d30708fSChicago Duan 2557e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app) 256e5aaf047SAppaRao Puli { 2571ebe3e41SGayathri Leburu BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 258ed398213SEd Tanous .privileges(redfish::privileges::getEventDestinationCollection) 2597e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 26045ca1b86SEd Tanous [&app](const crow::Request& req, 2617e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2623ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 26345ca1b86SEd Tanous { 26445ca1b86SEd Tanous return; 26545ca1b86SEd Tanous } 2661476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2671476687dSEd Tanous "#EventDestinationCollection.EventDestinationCollection"; 2681476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2691476687dSEd Tanous "/redfish/v1/EventService/Subscriptions"; 270bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 271bd79bce8SPatrick Williams "Event Destination Collections"; 272e5aaf047SAppaRao Puli 273bd79bce8SPatrick Williams nlohmann::json& memberArray = 274bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 275e5aaf047SAppaRao Puli 276b52664e2SAppaRao Puli std::vector<std::string> subscripIds = 277b52664e2SAppaRao Puli EventServiceManager::getInstance().getAllIDs(); 278b52664e2SAppaRao Puli memberArray = nlohmann::json::array(); 279bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 280bd79bce8SPatrick Williams subscripIds.size(); 281b52664e2SAppaRao Puli 282b52664e2SAppaRao Puli for (const std::string& id : subscripIds) 283e5aaf047SAppaRao Puli { 2841476687dSEd Tanous nlohmann::json::object_t member; 2853d30708fSChicago Duan member["@odata.id"] = boost::urls::format( 2863d30708fSChicago Duan "/redfish/v1/EventService/Subscriptions/{}" + id); 287b2ba3072SPatrick Williams memberArray.emplace_back(std::move(member)); 288e5aaf047SAppaRao Puli } 2893d30708fSChicago Duan crow::connections::systemBus->async_method_call( 290e81de512SEd Tanous [asyncResp](const boost::system::error_code& ec, 2913d30708fSChicago Duan const dbus::utility::ManagedObjectType& resp) { 2923d30708fSChicago Duan doSubscriptionCollection(ec, asyncResp, resp); 2933d30708fSChicago Duan }, 2943d30708fSChicago Duan "xyz.openbmc_project.Network.SNMP", 2953d30708fSChicago Duan "/xyz/openbmc_project/network/snmp/manager", 2963d30708fSChicago Duan "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 2977e860f15SJohn Edward Broadbent }); 2983d30708fSChicago Duan 2997e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 3007eeafa76SAbhishek Patel .privileges(redfish::privileges::postEventDestinationCollection) 301bd79bce8SPatrick Williams .methods( 302bd79bce8SPatrick Williams boost::beast::http::verb:: 303bd79bce8SPatrick Williams post)([&app]( 304bd79bce8SPatrick Williams const crow::Request& req, 3057e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 3063ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 30745ca1b86SEd Tanous { 30845ca1b86SEd Tanous return; 30945ca1b86SEd Tanous } 310fffb8c1fSEd Tanous if (EventServiceManager::getInstance().getNumberOfSubscriptions() >= 311fffb8c1fSEd Tanous maxNoOfSubscriptions) 312e5aaf047SAppaRao Puli { 313e5aaf047SAppaRao Puli messages::eventSubscriptionLimitExceeded(asyncResp->res); 314e5aaf047SAppaRao Puli return; 315e5aaf047SAppaRao Puli } 316e5aaf047SAppaRao Puli std::string destUrl; 317e5aaf047SAppaRao Puli std::string protocol; 31819bb362bSEd Tanous std::optional<bool> verifyCertificate; 319e5aaf047SAppaRao Puli std::optional<std::string> context; 320e5aaf047SAppaRao Puli std::optional<std::string> subscriptionType; 32123a21a1cSEd Tanous std::optional<std::string> eventFormatType2; 322e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 3235064a25bSMyung Bae std::optional<bool> sendHeartbeat; 3245064a25bSMyung Bae std::optional<uint64_t> hbIntervalMinutes; 325e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> msgIds; 326e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> regPrefixes; 327a14c9113SEd Tanous std::optional<std::vector<std::string>> originResources; 328e56f254cSSunitha Harish std::optional<std::vector<std::string>> resTypes; 32978d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> headers; 33078d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray; 331e5aaf047SAppaRao Puli 332afc474aeSMyung Bae if (!json_util::readJsonPatch( // 333afc474aeSMyung Bae req, asyncResp->res, // 334afc474aeSMyung Bae "Context", context, // 335afc474aeSMyung Bae "DeliveryRetryPolicy", retryPolicy, // 336afc474aeSMyung Bae "Destination", destUrl, // 337afc474aeSMyung Bae "EventFormatType", eventFormatType2, // 3385064a25bSMyung Bae "HeartbeatIntervalMinutes", hbIntervalMinutes, // 339afc474aeSMyung Bae "HttpHeaders", headers, // 340afc474aeSMyung Bae "MessageIds", msgIds, // 341afc474aeSMyung Bae "MetricReportDefinitions", mrdJsonArray, // 342afc474aeSMyung Bae "OriginResources", originResources, // 343afc474aeSMyung Bae "Protocol", protocol, // 344afc474aeSMyung Bae "RegistryPrefixes", regPrefixes, // 345afc474aeSMyung Bae "ResourceTypes", resTypes, // 3465064a25bSMyung Bae "SendHeartbeat", sendHeartbeat, // 347afc474aeSMyung Bae "SubscriptionType", subscriptionType, // 348afc474aeSMyung Bae "VerifyCertificate", verifyCertificate // 3494b712a29SEd Tanous )) 350e5aaf047SAppaRao Puli { 351e5aaf047SAppaRao Puli return; 352e5aaf047SAppaRao Puli } 3534b712a29SEd Tanous // clang-format on 354e5aaf047SAppaRao Puli 355600af5f1SAppaRao Puli // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers 356600af5f1SAppaRao Puli static constexpr const uint16_t maxDestinationSize = 2000; 357600af5f1SAppaRao Puli if (destUrl.size() > maxDestinationSize) 358600af5f1SAppaRao Puli { 359600af5f1SAppaRao Puli messages::stringValueTooLong(asyncResp->res, "Destination", 360600af5f1SAppaRao Puli maxDestinationSize); 361600af5f1SAppaRao Puli return; 362600af5f1SAppaRao Puli } 363600af5f1SAppaRao Puli 364dd28ba82SAppaRao Puli if (regPrefixes && msgIds) 365dd28ba82SAppaRao Puli { 36626f6976fSEd Tanous if (!regPrefixes->empty() && !msgIds->empty()) 367dd28ba82SAppaRao Puli { 368bd79bce8SPatrick Williams messages::propertyValueConflict( 369bd79bce8SPatrick Williams asyncResp->res, "MessageIds", "RegistryPrefixes"); 370dd28ba82SAppaRao Puli return; 371dd28ba82SAppaRao Puli } 372dd28ba82SAppaRao Puli } 373dd28ba82SAppaRao Puli 3746fd29553SEd Tanous boost::system::result<boost::urls::url> url = 375a716aa74SEd Tanous boost::urls::parse_absolute_uri(destUrl); 376a716aa74SEd Tanous if (!url) 377e5aaf047SAppaRao Puli { 378bd79bce8SPatrick Williams BMCWEB_LOG_WARNING( 379bd79bce8SPatrick Williams "Failed to validate and split destination url"); 380e5aaf047SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 381e5aaf047SAppaRao Puli "Destination"); 382e5aaf047SAppaRao Puli return; 383e5aaf047SAppaRao Puli } 384a716aa74SEd Tanous url->normalize(); 385b07942e3SGeorge Liu 386b07942e3SGeorge Liu // port_number returns zero if it is not a valid representable port 387b07942e3SGeorge Liu if (url->has_port() && url->port_number() == 0) 388b07942e3SGeorge Liu { 389b07942e3SGeorge Liu BMCWEB_LOG_WARNING("{} is an invalid port in destination url", 390b07942e3SGeorge Liu url->port()); 391b07942e3SGeorge Liu messages::propertyValueFormatError(asyncResp->res, destUrl, 392b07942e3SGeorge Liu "Destination"); 393b07942e3SGeorge Liu return; 394b07942e3SGeorge Liu } 395b07942e3SGeorge Liu 396a716aa74SEd Tanous crow::utility::setProtocolDefaults(*url, protocol); 397a716aa74SEd Tanous crow::utility::setPortDefaults(*url); 398a716aa74SEd Tanous 399a716aa74SEd Tanous if (url->path().empty()) 400a716aa74SEd Tanous { 401a716aa74SEd Tanous url->set_path("/"); 402a716aa74SEd Tanous } 403a716aa74SEd Tanous 404a716aa74SEd Tanous if (url->has_userinfo()) 405a716aa74SEd Tanous { 406a716aa74SEd Tanous messages::propertyValueFormatError(asyncResp->res, destUrl, 407a716aa74SEd Tanous "Destination"); 408a716aa74SEd Tanous return; 409a716aa74SEd Tanous } 410b52664e2SAppaRao Puli 4113d30708fSChicago Duan if (protocol == "SNMPv2c") 4123d30708fSChicago Duan { 4133d30708fSChicago Duan if (context) 4143d30708fSChicago Duan { 4153d30708fSChicago Duan messages::propertyValueConflict(asyncResp->res, "Context", 4163d30708fSChicago Duan "Protocol"); 4173d30708fSChicago Duan return; 4183d30708fSChicago Duan } 4193d30708fSChicago Duan if (eventFormatType2) 4203d30708fSChicago Duan { 421bd79bce8SPatrick Williams messages::propertyValueConflict( 422bd79bce8SPatrick Williams asyncResp->res, "EventFormatType", "Protocol"); 4233d30708fSChicago Duan return; 4243d30708fSChicago Duan } 4253d30708fSChicago Duan if (retryPolicy) 4263d30708fSChicago Duan { 427bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 428bd79bce8SPatrick Williams "RetryPolicy", "Protocol"); 4293d30708fSChicago Duan return; 4303d30708fSChicago Duan } 4315064a25bSMyung Bae if (sendHeartbeat) 4325064a25bSMyung Bae { 4335064a25bSMyung Bae messages::propertyValueConflict( 4345064a25bSMyung Bae asyncResp->res, "SendHeartbeat", "Protocol"); 4355064a25bSMyung Bae return; 4365064a25bSMyung Bae } 4375064a25bSMyung Bae if (hbIntervalMinutes) 4385064a25bSMyung Bae { 4395064a25bSMyung Bae messages::propertyValueConflict( 4405064a25bSMyung Bae asyncResp->res, "HeartbeatIntervalMinutes", "Protocol"); 4415064a25bSMyung Bae return; 4425064a25bSMyung Bae } 4433d30708fSChicago Duan if (msgIds) 4443d30708fSChicago Duan { 445bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 446bd79bce8SPatrick Williams "MessageIds", "Protocol"); 4473d30708fSChicago Duan return; 4483d30708fSChicago Duan } 4493d30708fSChicago Duan if (regPrefixes) 4503d30708fSChicago Duan { 451bd79bce8SPatrick Williams messages::propertyValueConflict( 452bd79bce8SPatrick Williams asyncResp->res, "RegistryPrefixes", "Protocol"); 4533d30708fSChicago Duan return; 4543d30708fSChicago Duan } 4553d30708fSChicago Duan if (resTypes) 4563d30708fSChicago Duan { 457bd79bce8SPatrick Williams messages::propertyValueConflict( 458bd79bce8SPatrick Williams asyncResp->res, "ResourceTypes", "Protocol"); 4593d30708fSChicago Duan return; 4603d30708fSChicago Duan } 4613d30708fSChicago Duan if (headers) 4623d30708fSChicago Duan { 463bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 464bd79bce8SPatrick Williams "HttpHeaders", "Protocol"); 4653d30708fSChicago Duan return; 4663d30708fSChicago Duan } 4673d30708fSChicago Duan if (mrdJsonArray) 4683d30708fSChicago Duan { 4693d30708fSChicago Duan messages::propertyValueConflict( 4703d30708fSChicago Duan asyncResp->res, "MetricReportDefinitions", "Protocol"); 4713d30708fSChicago Duan return; 4723d30708fSChicago Duan } 473a716aa74SEd Tanous if (url->scheme() != "snmp") 474a716aa74SEd Tanous { 475bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 476bd79bce8SPatrick Williams "Destination", "Protocol"); 4773d30708fSChicago Duan return; 4783d30708fSChicago Duan } 4793d30708fSChicago Duan 480a716aa74SEd Tanous addSnmpTrapClient(asyncResp, url->host_address(), 481a716aa74SEd Tanous url->port_number()); 482a716aa74SEd Tanous return; 483b52664e2SAppaRao Puli } 4843d30708fSChicago Duan 485a716aa74SEd Tanous std::shared_ptr<Subscription> subValue = 48621a94d5cSMyung Bae std::make_shared<Subscription>( 4875fe4ef35SMyung Bae std::make_shared<persistent_data::UserSubscription>(), *url, 4885fe4ef35SMyung Bae app.ioContext()); 489e5aaf047SAppaRao Puli 490e5aaf047SAppaRao Puli if (subscriptionType) 491e5aaf047SAppaRao Puli { 492e5aaf047SAppaRao Puli if (*subscriptionType != "RedfishEvent") 493e5aaf047SAppaRao Puli { 494fffb8c1fSEd Tanous messages::propertyValueNotInList( 495fffb8c1fSEd Tanous asyncResp->res, *subscriptionType, "SubscriptionType"); 496e5aaf047SAppaRao Puli return; 497e5aaf047SAppaRao Puli } 4985fe4ef35SMyung Bae subValue->userSub->subscriptionType = *subscriptionType; 499e5aaf047SAppaRao Puli } 500e5aaf047SAppaRao Puli else 501e5aaf047SAppaRao Puli { 5024b712a29SEd Tanous // Default 5035fe4ef35SMyung Bae subValue->userSub->subscriptionType = "RedfishEvent"; 504e5aaf047SAppaRao Puli } 505e5aaf047SAppaRao Puli 506e5aaf047SAppaRao Puli if (protocol != "Redfish") 507e5aaf047SAppaRao Puli { 508e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, protocol, 509e5aaf047SAppaRao Puli "Protocol"); 510e5aaf047SAppaRao Puli return; 511e5aaf047SAppaRao Puli } 5125fe4ef35SMyung Bae subValue->userSub->protocol = protocol; 513e5aaf047SAppaRao Puli 51419bb362bSEd Tanous if (verifyCertificate) 51519bb362bSEd Tanous { 5165fe4ef35SMyung Bae subValue->userSub->verifyCertificate = *verifyCertificate; 51719bb362bSEd Tanous } 51819bb362bSEd Tanous 51923a21a1cSEd Tanous if (eventFormatType2) 520e5aaf047SAppaRao Puli { 521bd79bce8SPatrick Williams if (std::ranges::find(supportedEvtFormatTypes, 522bd79bce8SPatrick Williams *eventFormatType2) == 5233544d2a7SEd Tanous supportedEvtFormatTypes.end()) 524e5aaf047SAppaRao Puli { 525fffb8c1fSEd Tanous messages::propertyValueNotInList( 526fffb8c1fSEd Tanous asyncResp->res, *eventFormatType2, "EventFormatType"); 527e5aaf047SAppaRao Puli return; 528e5aaf047SAppaRao Puli } 5295fe4ef35SMyung Bae subValue->userSub->eventFormatType = *eventFormatType2; 530e5aaf047SAppaRao Puli } 531e5aaf047SAppaRao Puli else 532e5aaf047SAppaRao Puli { 533e5aaf047SAppaRao Puli // If not specified, use default "Event" 5345fe4ef35SMyung Bae subValue->userSub->eventFormatType = "Event"; 535e5aaf047SAppaRao Puli } 536e5aaf047SAppaRao Puli 537e5aaf047SAppaRao Puli if (context) 538e5aaf047SAppaRao Puli { 5398ece0e45SEd Tanous // This value is selected arbitrarily. 540600af5f1SAppaRao Puli constexpr const size_t maxContextSize = 256; 541600af5f1SAppaRao Puli if (context->size() > maxContextSize) 542600af5f1SAppaRao Puli { 543600af5f1SAppaRao Puli messages::stringValueTooLong(asyncResp->res, "Context", 544600af5f1SAppaRao Puli maxContextSize); 545600af5f1SAppaRao Puli return; 546600af5f1SAppaRao Puli } 5475fe4ef35SMyung Bae subValue->userSub->customText = *context; 548e5aaf047SAppaRao Puli } 549e5aaf047SAppaRao Puli 550e5aaf047SAppaRao Puli if (headers) 551e5aaf047SAppaRao Puli { 552600af5f1SAppaRao Puli size_t cumulativeLen = 0; 553600af5f1SAppaRao Puli 55478d4ec4fSEd Tanous for (const nlohmann::json::object_t& headerChunk : *headers) 555601c71aeSEd Tanous { 55678d4ec4fSEd Tanous for (const auto& item : headerChunk) 55778d4ec4fSEd Tanous { 55878d4ec4fSEd Tanous const std::string* value = 55978d4ec4fSEd Tanous item.second.get_ptr<const std::string*>(); 56078d4ec4fSEd Tanous if (value == nullptr) 56178d4ec4fSEd Tanous { 56278d4ec4fSEd Tanous messages::propertyValueFormatError( 56378d4ec4fSEd Tanous asyncResp->res, item.second, 56478d4ec4fSEd Tanous "HttpHeaders/" + item.first); 56578d4ec4fSEd Tanous return; 56678d4ec4fSEd Tanous } 56778d4ec4fSEd Tanous // Adding a new json value is the size of the key, + 56878d4ec4fSEd Tanous // the size of the value + 2 * 2 quotes for each, + 56978d4ec4fSEd Tanous // the colon and space between. example: 57078d4ec4fSEd Tanous // "key": "value" 57178d4ec4fSEd Tanous cumulativeLen += item.first.size() + value->size() + 6; 572600af5f1SAppaRao Puli // This value is selected to mirror http_connection.hpp 573600af5f1SAppaRao Puli constexpr const uint16_t maxHeaderSizeED = 8096; 574600af5f1SAppaRao Puli if (cumulativeLen > maxHeaderSizeED) 575600af5f1SAppaRao Puli { 57678d4ec4fSEd Tanous messages::arraySizeTooLong( 57778d4ec4fSEd Tanous asyncResp->res, "HttpHeaders", maxHeaderSizeED); 578600af5f1SAppaRao Puli return; 579600af5f1SAppaRao Puli } 5805fe4ef35SMyung Bae subValue->userSub->httpHeaders.set(item.first, *value); 581601c71aeSEd Tanous } 582601c71aeSEd Tanous } 583e5aaf047SAppaRao Puli } 584e5aaf047SAppaRao Puli 585e5aaf047SAppaRao Puli if (regPrefixes) 586e5aaf047SAppaRao Puli { 587e5aaf047SAppaRao Puli for (const std::string& it : *regPrefixes) 588e5aaf047SAppaRao Puli { 5893544d2a7SEd Tanous if (std::ranges::find(supportedRegPrefixes, it) == 5903544d2a7SEd Tanous supportedRegPrefixes.end()) 591e5aaf047SAppaRao Puli { 592fffb8c1fSEd Tanous messages::propertyValueNotInList(asyncResp->res, it, 593fffb8c1fSEd Tanous "RegistryPrefixes"); 594e5aaf047SAppaRao Puli return; 595e5aaf047SAppaRao Puli } 596e5aaf047SAppaRao Puli } 5975fe4ef35SMyung Bae subValue->userSub->registryPrefixes = *regPrefixes; 598e5aaf047SAppaRao Puli } 599e5aaf047SAppaRao Puli 600a14c9113SEd Tanous if (originResources) 601a14c9113SEd Tanous { 6025fe4ef35SMyung Bae subValue->userSub->originResources = *originResources; 603a14c9113SEd Tanous } 604a14c9113SEd Tanous 605e56f254cSSunitha Harish if (resTypes) 606e56f254cSSunitha Harish { 607e56f254cSSunitha Harish for (const std::string& it : *resTypes) 608e56f254cSSunitha Harish { 6093544d2a7SEd Tanous if (std::ranges::find(supportedResourceTypes, it) == 6103544d2a7SEd Tanous supportedResourceTypes.end()) 611e56f254cSSunitha Harish { 612e56f254cSSunitha Harish messages::propertyValueNotInList(asyncResp->res, it, 613e56f254cSSunitha Harish "ResourceTypes"); 614e56f254cSSunitha Harish return; 615e56f254cSSunitha Harish } 616e56f254cSSunitha Harish } 6175fe4ef35SMyung Bae subValue->userSub->resourceTypes = *resTypes; 618e56f254cSSunitha Harish } 619e56f254cSSunitha Harish 620e5aaf047SAppaRao Puli if (msgIds) 621e5aaf047SAppaRao Puli { 622b304bd79SP Dheeraj Srujan Kumar std::vector<std::string> registryPrefix; 623b304bd79SP Dheeraj Srujan Kumar 6247e860f15SJohn Edward Broadbent // If no registry prefixes are mentioned, consider all 6257e860f15SJohn Edward Broadbent // supported prefixes 6265fe4ef35SMyung Bae if (subValue->userSub->registryPrefixes.empty()) 627b304bd79SP Dheeraj Srujan Kumar { 628b304bd79SP Dheeraj Srujan Kumar registryPrefix.assign(supportedRegPrefixes.begin(), 629b304bd79SP Dheeraj Srujan Kumar supportedRegPrefixes.end()); 630b304bd79SP Dheeraj Srujan Kumar } 631b304bd79SP Dheeraj Srujan Kumar else 632b304bd79SP Dheeraj Srujan Kumar { 6335fe4ef35SMyung Bae registryPrefix = subValue->userSub->registryPrefixes; 634b304bd79SP Dheeraj Srujan Kumar } 635b304bd79SP Dheeraj Srujan Kumar 636b304bd79SP Dheeraj Srujan Kumar for (const std::string& id : *msgIds) 637b304bd79SP Dheeraj Srujan Kumar { 638b304bd79SP Dheeraj Srujan Kumar bool validId = false; 639b304bd79SP Dheeraj Srujan Kumar 640b304bd79SP Dheeraj Srujan Kumar // Check for Message ID in each of the selected Registry 641b304bd79SP Dheeraj Srujan Kumar for (const std::string& it : registryPrefix) 642b304bd79SP Dheeraj Srujan Kumar { 643fffb8c1fSEd Tanous const std::span<const redfish::registries::MessageEntry> 644fffb8c1fSEd Tanous registry = 645fffb8c1fSEd Tanous redfish::registries::getRegistryFromPrefix(it); 646b304bd79SP Dheeraj Srujan Kumar 6473544d2a7SEd Tanous if (std::ranges::any_of( 6483544d2a7SEd Tanous registry, 649fffb8c1fSEd Tanous [&id](const redfish::registries::MessageEntry& 650fffb8c1fSEd Tanous messageEntry) { 65155f79e6fSEd Tanous return id == messageEntry.first; 652b304bd79SP Dheeraj Srujan Kumar })) 653b304bd79SP Dheeraj Srujan Kumar { 654b304bd79SP Dheeraj Srujan Kumar validId = true; 655b304bd79SP Dheeraj Srujan Kumar break; 656b304bd79SP Dheeraj Srujan Kumar } 657b304bd79SP Dheeraj Srujan Kumar } 658b304bd79SP Dheeraj Srujan Kumar 659b304bd79SP Dheeraj Srujan Kumar if (!validId) 660b304bd79SP Dheeraj Srujan Kumar { 661b304bd79SP Dheeraj Srujan Kumar messages::propertyValueNotInList(asyncResp->res, id, 662b304bd79SP Dheeraj Srujan Kumar "MessageIds"); 663b304bd79SP Dheeraj Srujan Kumar return; 664b304bd79SP Dheeraj Srujan Kumar } 665b304bd79SP Dheeraj Srujan Kumar } 666b304bd79SP Dheeraj Srujan Kumar 6675fe4ef35SMyung Bae subValue->userSub->registryMsgIds = *msgIds; 668e5aaf047SAppaRao Puli } 669e5aaf047SAppaRao Puli 670e5aaf047SAppaRao Puli if (retryPolicy) 671e5aaf047SAppaRao Puli { 6723544d2a7SEd Tanous if (std::ranges::find(supportedRetryPolicies, *retryPolicy) == 6733544d2a7SEd Tanous supportedRetryPolicies.end()) 674e5aaf047SAppaRao Puli { 675bd79bce8SPatrick Williams messages::propertyValueNotInList( 676bd79bce8SPatrick Williams asyncResp->res, *retryPolicy, "DeliveryRetryPolicy"); 677e5aaf047SAppaRao Puli return; 678e5aaf047SAppaRao Puli } 6795fe4ef35SMyung Bae subValue->userSub->retryPolicy = *retryPolicy; 680e5aaf047SAppaRao Puli } 681e5aaf047SAppaRao Puli else 682e5aaf047SAppaRao Puli { 683e5aaf047SAppaRao Puli // Default "TerminateAfterRetries" 6845fe4ef35SMyung Bae subValue->userSub->retryPolicy = "TerminateAfterRetries"; 685e5aaf047SAppaRao Puli } 6865064a25bSMyung Bae if (sendHeartbeat) 6875064a25bSMyung Bae { 6885064a25bSMyung Bae subValue->userSub->sendHeartbeat = *sendHeartbeat; 6895064a25bSMyung Bae } 6905064a25bSMyung Bae if (hbIntervalMinutes) 6915064a25bSMyung Bae { 6925064a25bSMyung Bae if (*hbIntervalMinutes < 1 || *hbIntervalMinutes > 65535) 6935064a25bSMyung Bae { 6945064a25bSMyung Bae messages::propertyValueOutOfRange( 6955064a25bSMyung Bae asyncResp->res, *hbIntervalMinutes, 6965064a25bSMyung Bae "HeartbeatIntervalMinutes"); 6975064a25bSMyung Bae return; 6985064a25bSMyung Bae } 6995064a25bSMyung Bae subValue->userSub->hbIntervalMinutes = *hbIntervalMinutes; 7005064a25bSMyung Bae } 701e5aaf047SAppaRao Puli 702144b6318SAppaRao Puli if (mrdJsonArray) 703156d6b00SAppaRao Puli { 70478d4ec4fSEd Tanous for (nlohmann::json::object_t& mrdObj : *mrdJsonArray) 705144b6318SAppaRao Puli { 706144b6318SAppaRao Puli std::string mrdUri; 707ea2e6eecSWilly Tu 70878d4ec4fSEd Tanous if (!json_util::readJsonObject(mrdObj, asyncResp->res, 70978d4ec4fSEd Tanous "@odata.id", mrdUri)) 710ea2e6eecSWilly Tu 711144b6318SAppaRao Puli { 712144b6318SAppaRao Puli return; 713144b6318SAppaRao Puli } 7145fe4ef35SMyung Bae subValue->userSub->metricReportDefinitions.emplace_back( 7154b712a29SEd Tanous mrdUri); 716144b6318SAppaRao Puli } 717156d6b00SAppaRao Puli } 718156d6b00SAppaRao Puli 719b52664e2SAppaRao Puli std::string id = 720bd79bce8SPatrick Williams EventServiceManager::getInstance().addPushSubscription( 721bd79bce8SPatrick Williams subValue); 722b52664e2SAppaRao Puli if (id.empty()) 723e5aaf047SAppaRao Puli { 724e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 725e5aaf047SAppaRao Puli return; 726e5aaf047SAppaRao Puli } 727e5aaf047SAppaRao Puli 728e5aaf047SAppaRao Puli messages::created(asyncResp->res); 729e5aaf047SAppaRao Puli asyncResp->res.addHeader( 730e5aaf047SAppaRao Puli "Location", "/redfish/v1/EventService/Subscriptions/" + id); 731fb546105SMyung Bae 732fb546105SMyung Bae // schedule a heartbeat 733fb546105SMyung Bae if (subValue->userSub->sendHeartbeat) 734fb546105SMyung Bae { 735fb546105SMyung Bae subValue->scheduleNextHeartbeatEvent(); 736fb546105SMyung Bae } 7377e860f15SJohn Edward Broadbent }); 738e5aaf047SAppaRao Puli } 739e5aaf047SAppaRao Puli 7407e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app) 741e5aaf047SAppaRao Puli { 7429d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 743ed398213SEd Tanous .privileges(redfish::privileges::getEventDestination) 7447e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 74545ca1b86SEd Tanous [&app](const crow::Request& req, 7467e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7477e860f15SJohn Edward Broadbent const std::string& param) { 7483ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 74945ca1b86SEd Tanous { 75045ca1b86SEd Tanous return; 75145ca1b86SEd Tanous } 7523d30708fSChicago Duan 7533d30708fSChicago Duan if (param.starts_with("snmp")) 7543d30708fSChicago Duan { 7553d30708fSChicago Duan getSnmpTrapClient(asyncResp, param); 7563d30708fSChicago Duan return; 7573d30708fSChicago Duan } 7583d30708fSChicago Duan 759b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 7607e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 761b52664e2SAppaRao Puli if (subValue == nullptr) 762e5aaf047SAppaRao Puli { 763bd79bce8SPatrick Williams asyncResp->res.result( 764bd79bce8SPatrick Williams boost::beast::http::status::not_found); 765e5aaf047SAppaRao Puli return; 766e5aaf047SAppaRao Puli } 7677e860f15SJohn Edward Broadbent const std::string& id = param; 768e5aaf047SAppaRao Puli 7694b712a29SEd Tanous const persistent_data::UserSubscription& userSub = 7705fe4ef35SMyung Bae *subValue->userSub; 771e56f254cSSunitha Harish 7724b712a29SEd Tanous nlohmann::json& jVal = asyncResp->res.jsonValue; 7734b712a29SEd Tanous jVal["@odata.type"] = 7744b712a29SEd Tanous "#EventDestination.v1_14_1.EventDestination"; 7754b712a29SEd Tanous jVal["Protocol"] = 7764b712a29SEd Tanous event_destination::EventDestinationProtocol::Redfish; 7774b712a29SEd Tanous jVal["@odata.id"] = boost::urls::format( 7784b712a29SEd Tanous "/redfish/v1/EventService/Subscriptions/{}", id); 7794b712a29SEd Tanous jVal["Id"] = id; 7804b712a29SEd Tanous jVal["Name"] = "Event Destination " + id; 7814b712a29SEd Tanous jVal["Destination"] = userSub.destinationUrl; 7824b712a29SEd Tanous jVal["Context"] = userSub.customText; 7834b712a29SEd Tanous jVal["SubscriptionType"] = userSub.subscriptionType; 7844b712a29SEd Tanous jVal["HttpHeaders"] = nlohmann::json::array(); 7854b712a29SEd Tanous jVal["EventFormatType"] = userSub.eventFormatType; 7864b712a29SEd Tanous jVal["RegistryPrefixes"] = userSub.registryPrefixes; 7874b712a29SEd Tanous jVal["ResourceTypes"] = userSub.resourceTypes; 7884b712a29SEd Tanous 7894b712a29SEd Tanous jVal["MessageIds"] = userSub.registryMsgIds; 7904b712a29SEd Tanous jVal["DeliveryRetryPolicy"] = userSub.retryPolicy; 7915064a25bSMyung Bae jVal["SendHeartbeat"] = userSub.sendHeartbeat; 7925064a25bSMyung Bae jVal["HeartbeatIntervalMinutes"] = userSub.hbIntervalMinutes; 7934b712a29SEd Tanous jVal["VerifyCertificate"] = userSub.verifyCertificate; 794144b6318SAppaRao Puli 7951476687dSEd Tanous nlohmann::json::array_t mrdJsonArray; 7964b712a29SEd Tanous for (const auto& mdrUri : userSub.metricReportDefinitions) 797144b6318SAppaRao Puli { 7981476687dSEd Tanous nlohmann::json::object_t mdr; 7991476687dSEd Tanous mdr["@odata.id"] = mdrUri; 8001476687dSEd Tanous mrdJsonArray.emplace_back(std::move(mdr)); 801144b6318SAppaRao Puli } 8024b712a29SEd Tanous jVal["MetricReportDefinitions"] = mrdJsonArray; 8037e860f15SJohn Edward Broadbent }); 8049d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 805ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 806ed398213SEd Tanous // ConfigureSelf 8077eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 808ed398213SEd Tanous //.privileges(redfish::privileges::patchEventDestination) 809432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 8107e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 81145ca1b86SEd Tanous [&app](const crow::Request& req, 8127e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8137e860f15SJohn Edward Broadbent const std::string& param) { 8143ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 81545ca1b86SEd Tanous { 81645ca1b86SEd Tanous return; 81745ca1b86SEd Tanous } 818b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 8197e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 820b52664e2SAppaRao Puli if (subValue == nullptr) 821e5aaf047SAppaRao Puli { 822bd79bce8SPatrick Williams asyncResp->res.result( 823bd79bce8SPatrick Williams boost::beast::http::status::not_found); 824e5aaf047SAppaRao Puli return; 825e5aaf047SAppaRao Puli } 826e5aaf047SAppaRao Puli 827e5aaf047SAppaRao Puli std::optional<std::string> context; 828e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 8295064a25bSMyung Bae std::optional<bool> sendHeartbeat; 8305064a25bSMyung Bae std::optional<uint64_t> hbIntervalMinutes; 83119bb362bSEd Tanous std::optional<bool> verifyCertificate; 83278d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> headers; 833e5aaf047SAppaRao Puli 834afc474aeSMyung Bae if (!json_util::readJsonPatch( // 835afc474aeSMyung Bae req, asyncResp->res, // 836afc474aeSMyung Bae "Context", context, // 837afc474aeSMyung Bae "DeliveryRetryPolicy", retryPolicy, // 8385064a25bSMyung Bae "HeartbeatIntervalMinutes", hbIntervalMinutes, // 839afc474aeSMyung Bae "HttpHeaders", headers, // 8405064a25bSMyung Bae "SendHeartbeat", sendHeartbeat, // 841afc474aeSMyung Bae "VerifyCertificate", verifyCertificate // 842afc474aeSMyung Bae )) 843e5aaf047SAppaRao Puli { 844e5aaf047SAppaRao Puli return; 845e5aaf047SAppaRao Puli } 846e5aaf047SAppaRao Puli 847e5aaf047SAppaRao Puli if (context) 848e5aaf047SAppaRao Puli { 8495fe4ef35SMyung Bae subValue->userSub->customText = *context; 850e5aaf047SAppaRao Puli } 851e5aaf047SAppaRao Puli 852e5aaf047SAppaRao Puli if (headers) 853e5aaf047SAppaRao Puli { 854601c71aeSEd Tanous boost::beast::http::fields fields; 85578d4ec4fSEd Tanous for (const nlohmann::json::object_t& headerChunk : *headers) 856601c71aeSEd Tanous { 85778d4ec4fSEd Tanous for (const auto& it : headerChunk) 858601c71aeSEd Tanous { 859601c71aeSEd Tanous const std::string* value = 86078d4ec4fSEd Tanous it.second.get_ptr<const std::string*>(); 861601c71aeSEd Tanous if (value == nullptr) 862601c71aeSEd Tanous { 863601c71aeSEd Tanous messages::propertyValueFormatError( 86478d4ec4fSEd Tanous asyncResp->res, it.second, 86578d4ec4fSEd Tanous "HttpHeaders/" + it.first); 866601c71aeSEd Tanous return; 867601c71aeSEd Tanous } 86878d4ec4fSEd Tanous fields.set(it.first, *value); 869601c71aeSEd Tanous } 870601c71aeSEd Tanous } 8715fe4ef35SMyung Bae subValue->userSub->httpHeaders = std::move(fields); 872e5aaf047SAppaRao Puli } 873e5aaf047SAppaRao Puli 874e5aaf047SAppaRao Puli if (retryPolicy) 875e5aaf047SAppaRao Puli { 876bd79bce8SPatrick Williams if (std::ranges::find(supportedRetryPolicies, 877bd79bce8SPatrick Williams *retryPolicy) == 8783544d2a7SEd Tanous supportedRetryPolicies.end()) 879e5aaf047SAppaRao Puli { 880bd79bce8SPatrick Williams messages::propertyValueNotInList(asyncResp->res, 881bd79bce8SPatrick Williams *retryPolicy, 882e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 883e5aaf047SAppaRao Puli return; 884e5aaf047SAppaRao Puli } 8855fe4ef35SMyung Bae subValue->userSub->retryPolicy = *retryPolicy; 886e5aaf047SAppaRao Puli } 887e5aaf047SAppaRao Puli 8885064a25bSMyung Bae if (sendHeartbeat) 8895064a25bSMyung Bae { 8905064a25bSMyung Bae subValue->userSub->sendHeartbeat = *sendHeartbeat; 8915064a25bSMyung Bae } 8925064a25bSMyung Bae if (hbIntervalMinutes) 8935064a25bSMyung Bae { 8945064a25bSMyung Bae if (*hbIntervalMinutes < 1 || *hbIntervalMinutes > 65535) 8955064a25bSMyung Bae { 8965064a25bSMyung Bae messages::propertyValueOutOfRange( 8975064a25bSMyung Bae asyncResp->res, *hbIntervalMinutes, 8985064a25bSMyung Bae "HeartbeatIntervalMinutes"); 8995064a25bSMyung Bae return; 9005064a25bSMyung Bae } 9015064a25bSMyung Bae subValue->userSub->hbIntervalMinutes = *hbIntervalMinutes; 9025064a25bSMyung Bae } 9035064a25bSMyung Bae 904fb546105SMyung Bae if (hbIntervalMinutes || sendHeartbeat) 905fb546105SMyung Bae { 906fb546105SMyung Bae // if Heartbeat interval or send heart were changed, cancel 907fb546105SMyung Bae // the heartbeat timer if running and start a new heartbeat 908fb546105SMyung Bae // if needed 909fb546105SMyung Bae subValue->heartbeatParametersChanged(); 910fb546105SMyung Bae } 911fb546105SMyung Bae 91219bb362bSEd Tanous if (verifyCertificate) 91319bb362bSEd Tanous { 9145fe4ef35SMyung Bae subValue->userSub->verifyCertificate = *verifyCertificate; 91519bb362bSEd Tanous } 91619bb362bSEd Tanous 917b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 9187e860f15SJohn Edward Broadbent }); 9199d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 920ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 921ed398213SEd Tanous // ConfigureSelf 9227eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 923ed398213SEd Tanous //.privileges(redfish::privileges::deleteEventDestination) 924432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 9257e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 92645ca1b86SEd Tanous [&app](const crow::Request& req, 9277e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9287e860f15SJohn Edward Broadbent const std::string& param) { 9293ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 93045ca1b86SEd Tanous { 93145ca1b86SEd Tanous return; 93245ca1b86SEd Tanous } 9334b712a29SEd Tanous EventServiceManager& event = EventServiceManager::getInstance(); 9343d30708fSChicago Duan if (param.starts_with("snmp")) 9353d30708fSChicago Duan { 9363d30708fSChicago Duan deleteSnmpTrapClient(asyncResp, param); 9374b712a29SEd Tanous event.deleteSubscription(param); 9383d30708fSChicago Duan return; 9393d30708fSChicago Duan } 9403d30708fSChicago Duan 9414b712a29SEd Tanous if (!event.deleteSubscription(param)) 942e5aaf047SAppaRao Puli { 9434b712a29SEd Tanous messages::resourceNotFound(asyncResp->res, 9444b712a29SEd Tanous "EventDestination", param); 945e5aaf047SAppaRao Puli return; 946e5aaf047SAppaRao Puli } 9474b712a29SEd Tanous messages::success(asyncResp->res); 9487e860f15SJohn Edward Broadbent }); 949e5aaf047SAppaRao Puli } 950e5aaf047SAppaRao Puli 951e5aaf047SAppaRao Puli } // namespace redfish 952