summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch326
1 files changed, 326 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
new file mode 100644
index 000000000..816456cec
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
@@ -0,0 +1,326 @@
+From e207fca58bf0d05b160ea6735f4f576737d7a9cb Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Wed, 17 Mar 2021 01:16:50 +0000
+Subject: [PATCH] Add EventService SSE filter support
+
+This commit implements the Event Service SSE stream
+filters support. As per redfish specification:
+The SSE streams have these formats:
+ - Metric report SSE stream
+ - Event message SSE stream
+
+To reduce the amount of data, service supports $filter
+query parameter in SSE URI.
+Below properties support as filter criteria:
+ - EventFormatType( Event & MetricReport)
+ - MessageId
+ - RegistryPrefix
+ - MetricReportDefinition
+
+For more details, refer Redfish specification section 13.5.2
+
+Tested:
+ Created SSE stream with different filters and observed
+ desired events on SSE stream client(browser), some examples
+ - To get all Redfish events,
+ URI: /redfish/v1/EventService/Subscriptions/SSE?$filter=(EventFormatType%20eq%20Event)
+ - To get Redfish events with RegistryPrefix "OpenBMC"
+ URI: /redfish/v1/EventService/Subscriptions/SSE?$filter=(RegistryPrefix%20eq%20OpenBMC)
+ - To get only DC power of Events,
+ URI: /redfish/v1/EventService/Subscriptions/SSE?$filter=(EventFormatType%20eq%20Event)%20and%20(MessageId%20eq%20DCPowerOff)
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+Change-Id: I55c6f53bb5e57aa1f2d1601f1a16525a33b13bd2
+---
+ include/eventservice_sse.hpp | 172 +++++++++++++++++-
+ redfish-core/include/error_messages.hpp | 9 +
+ .../include/event_service_manager.hpp | 5 +
+ redfish-core/lib/event_service.hpp | 5 -
+ redfish-core/src/error_messages.cpp | 27 +++
+ 5 files changed, 209 insertions(+), 9 deletions(-)
+
+diff --git a/include/eventservice_sse.hpp b/include/eventservice_sse.hpp
+index 14daf00..5847766 100644
+--- a/include/eventservice_sse.hpp
++++ b/include/eventservice_sse.hpp
+@@ -21,18 +21,182 @@ static bool createSubscription(std::shared_ptr<crow::SseConnection>& conn,
+ res.end();
+ return false;
+ }
++#ifdef NEW_BOOST_URL
++ BMCWEB_LOG_DEBUG << "Request query param size: "
++ << req.urlView.params().size();
++
++ // EventService SSE supports only "$filter" query param.
++ if (req.urlView.params().size() > 1)
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return false;
++ }
++ std::string eventFormatType;
++ std::string queryFilters;
++ if (req.urlView.params().size())
++ {
++ boost::urls::params_view::iterator it =
++ req.urlView.params().find("$filter");
++ if (it == req.urlView.params().end())
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return false;
++ }
++ queryFilters = std::string((*it).value);
++ }
++ else
++ {
++ eventFormatType = "Event";
++ }
++#else
+ BMCWEB_LOG_DEBUG << "Request query param size: " << req.urlParams.size();
+
++ // EventService SSE supports only "$filter" query param.
++ if (req.urlParams.size() > 1)
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return false;
++ }
++ std::string eventFormatType;
++ std::string queryFilters;
++ if (req.urlParams.size())
++ {
++ boost::urls::query_params_view::iterator it =
++ req.urlParams.find("$filter");
++ if (it == req.urlParams.end())
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return false;
++ }
++ queryFilters = it->value();
++ }
++ else
++ {
++ eventFormatType = "Event";
++ }
++#endif
++
++ std::vector<std::string> msgIds;
++ std::vector<std::string> regPrefixes;
++ std::vector<std::string> mrdsArray;
++ if (!queryFilters.empty())
++ {
++ // Reading from query params.
++ bool status = readSSEQueryParams(queryFilters, eventFormatType, msgIds,
++ regPrefixes, mrdsArray);
++ if (!status)
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return false;
++ }
++
++ // RegsitryPrefix and messageIds are mutuly exclusive as per redfish
++ // specification.
++ if (!regPrefixes.empty() && !msgIds.empty())
++ {
++ messages::propertyValueConflict(res, "RegistryPrefix", "MessageId");
++ res.end();
++ return false;
++ }
++
++ if (!eventFormatType.empty())
++ {
++ if (std::find(supportedEvtFormatTypes.begin(),
++ supportedEvtFormatTypes.end(),
++ eventFormatType) == supportedEvtFormatTypes.end())
++ {
++ messages::propertyValueNotInList(res, eventFormatType,
++ "EventFormatType");
++ res.end();
++ return false;
++ }
++ }
++ else
++ {
++ // If nothing specified, using default "Event"
++ eventFormatType = "Event";
++ }
++
++ if (!regPrefixes.empty())
++ {
++ for (const std::string& it : regPrefixes)
++ {
++ if (std::find(supportedRegPrefixes.begin(),
++ supportedRegPrefixes.end(),
++ it) == supportedRegPrefixes.end())
++ {
++ messages::propertyValueNotInList(res, it, "RegistryPrefix");
++ res.end();
++ return false;
++ }
++ }
++ }
++
++ if (!msgIds.empty())
++ {
++ std::vector<std::string> registryPrefix;
++
++ // If no registry prefixes are mentioned, consider all supported
++ // prefixes to validate message ID
++ if (regPrefixes.empty())
++ {
++ registryPrefix.assign(supportedRegPrefixes.begin(),
++ supportedRegPrefixes.end());
++ }
++ else
++ {
++ registryPrefix = regPrefixes;
++ }
++
++ for (const std::string& id : msgIds)
++ {
++ bool validId = false;
++
++ // Check for Message ID in each of the selected Registry
++ for (const std::string& it : registryPrefix)
++ {
++ const std::span<const redfish::registries::MessageEntry>
++ registry =
++ redfish::registries::getRegistryFromPrefix(it);
++
++ if (std::any_of(
++ registry.begin(), registry.end(),
++ [&id](const redfish::registries::MessageEntry&
++ messageEntry) {
++ return !id.compare(messageEntry.first);
++ }))
++ {
++ validId = true;
++ break;
++ }
++ }
++
++ if (!validId)
++ {
++ messages::propertyValueNotInList(res, id, "MessageIds");
++ res.end();
++ return false;
++ }
++ }
++ }
++ }
++
+ std::shared_ptr<redfish::Subscription> subValue =
+ std::make_shared<redfish::Subscription>(std::move(conn));
+
+ // GET on this URI means, Its SSE subscriptionType.
+- subValue->subscriptionType = redfish::subscriptionTypeSSE;
+-
+- // TODO: parse $filter query params and fill config.
++ subValue->subscriptionType = subscriptionTypeSSE;
+ subValue->protocol = "Redfish";
+ subValue->retryPolicy = "TerminateAfterRetries";
+- subValue->eventFormatType = "Event";
++ subValue->eventFormatType = eventFormatType;
++ subValue->registryMsgIds = msgIds;
++ subValue->registryPrefixes = regPrefixes;
++ subValue->metricReportDefinitions = mrdsArray;
+
+ std::string id =
+ redfish::EventServiceManager::getInstance().addSubscription(subValue,
+diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
+index b3b2305..9b3ee49 100644
+--- a/redfish-core/include/error_messages.hpp
++++ b/redfish-core/include/error_messages.hpp
+@@ -980,6 +980,15 @@ nlohmann::json invalidUpload(std::string_view arg1, std::string_view arg2);
+ void invalidUpload(crow::Response& res, std::string_view arg1,
+ std::string_view arg2);
+
++/**
++ * @brief Formats InvalidQueryFilter message into JSON
++ * Message body: "The requested URL contains the invalid query filters"
++ *
++ * @returns Message InvalidQueryFilter formatted to JSON */
++nlohmann::json invalidQueryFilter();
++
++void invalidQueryFilter(crow::Response& res);
++
+ } // namespace messages
+
+ } // namespace redfish
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index c64bb59..e03dd9b 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -57,6 +57,11 @@ static constexpr const char* eventServiceFile =
+ static constexpr const uint8_t maxNoOfSubscriptions = 20;
+ static constexpr const uint8_t maxNoOfSSESubscriptions = 10;
+
++static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
++ eventFormatType, metricReportFormatType};
++static constexpr const std::array<const char*, 2> supportedRegPrefixes = {
++ "OpenBMC", "TaskEvent"};
++
+ #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
+ static std::optional<boost::asio::posix::stream_descriptor> inotifyConn;
+ static constexpr const char* redfishEventLogDir = "/var/log";
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index 2181346..e9ee78f 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -24,11 +24,6 @@
+
+ namespace redfish
+ {
+-
+-static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
+- eventFormatType, metricReportFormatType};
+-static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
+- "Base", "OpenBMC", "TaskEvent"};
+ static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
+ "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
+
+diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
+index 381b8a9..cad145a 100644
+--- a/redfish-core/src/error_messages.cpp
++++ b/redfish-core/src/error_messages.cpp
+@@ -1668,6 +1668,33 @@ nlohmann::json invalidUpload(std::string_view arg1, std::string_view arg2)
+ {"MessageSeverity", "Warning"},
+ {"Resolution", "None."}};
+ }
++
++/**
++ * @internal
++ * @brief Formats InvalidQueryFilter into JSON
++ *
++ * See header file for more information
++ * @endinternal
++ */
++nlohmann::json invalidQueryFilter()
++{
++ return nlohmann::json{
++ {"@odata.type", "#Message.v1_0_0.Message"},
++ {"MessageId", "Base.1.5.0.InvalidQueryFilter"},
++ {"Message", "The requested url contains the invalid query filter."},
++ {"MessageArgs", nlohmann::json::array()},
++ {"Severity", "Warning"},
++ {"Resolution",
++ "Ensure the correct query filter is specified in requested url "
++ "and resubmit the request."}};
++}
++
++void invalidQueryFilter(crow::Response& res)
++{
++ res.result(boost::beast::http::status::bad_request);
++ addMessageToErrorJson(res.jsonValue, invalidQueryFilter());
++}
++
+ } // namespace messages
+
+ } // namespace redfish
+--
+2.25.1
+