summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch919
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch258
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-DELETE-method-for-MetricReport.patch132
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch (renamed from meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-GET-method-for-TriggerCollection.patch)0
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch (renamed from meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Revert-Remove-LogService-from-TelemetryService.patch)0
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch (renamed from meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-event-service-fix-added-Context-field-to-response.patch)0
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch (renamed from meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Generalize-ReadingType-in-MetricDefinition.patch)0
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch46
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README14
9 files changed, 1230 insertions, 139 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch
new file mode 100644
index 000000000..0e4fc4903
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch
@@ -0,0 +1,919 @@
+From 9814f83f36afafffa55bd19481654c064840e73d Mon Sep 17 00:00:00 2001
+From: Arun Lal K M <arun.lal@intel.com>
+Date: Mon, 16 Aug 2021 17:49:11 +0000
+Subject: [PATCH] Add fix for broken feature 'Pending Attributes'.
+
+Fix is added for the following:
+1) GET to 'redfish/v1/Systems/system/Bios'.
+2) PATCH to 'redfish/v1/Systems/system/Bios/Settings'.
+3) GET to 'redfish/v1/Systems/system/Bios/Settings'.
+4) Fix for incremental duplicate values in BiosAttributeRegistry.
+
+Tested:
+By giving PATCH to 'redfish/v1/Systems/system/Bios/Settings'
+PATCH command raw data:
+{
+ "data":{
+ "AmpPrefetchEnable": "0x1",
+ "Ce2LmLoggingEn": "0x1",
+ "DfxEadrDebugLogs": "0x2",
+ "PsfUrEnable": "0x1",
+ "ATS": "0x0"
+ }
+}
+
+Response:
+{
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "#Message.v1_1_1.Message",
+ "Message": "Successfully Completed Request",
+ "MessageArgs": [],
+ "MessageId": "Base.1.8.1.Success",
+ "MessageSeverity": "OK",
+ "Resolution": "None"
+ }
+ ]
+}
+
+By giving GET to 'redfish/v1/Systems/system/Bios'
+Response:
+{
+ "@Redfish.Settings": {
+ "@odata.type": "#Settings.v1_3_0.Settings",
+ "SettingsObject": {
+ "@odata.id":
+ "/redfish/v1/Systems/system/Bios/Settings"
+ }
+ },
+ "@odata.id": "/redfish/v1/Systems/system/Bios",
+ "@odata.type": "#Bios.v1_1_0.Bios",
+ "Actions": {
+ "#Bios.ChangePassword": {
+ "target":
+ "/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword"
+ },
+ "#Bios.ResetBios": {
+ "target":
+ "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"
+ }
+ },
+ "AttributeRegistry": "BiosAttributeRegistry",
+ "Attributes": {
+ "AEPErrorInjEn": "0x00",
+ "ARIEnable": "0x01",
+ "ARIForward": "0x00",
+ ...
+ ...
+ ...
+ "txEqCalibration": "0x01",
+ "volMemMode": "0x00",
+ "wrVrefCenter": "0x01"
+ },
+ "Description": "BIOS Configuration Service",
+ "Id": "BIOS",
+ "Links": {
+ "ActiveSoftwareImage": {
+ "@odata.id":
+ "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
+ },
+ "SoftwareImages": [
+ {
+ "@odata.id":
+ "/redfish/v1/UpdateService/FirmwareInventory/bios_active"
+ }
+ ],
+ "SoftwareImages@odata.count": 1
+ },
+ "Name": "BIOS Configuration"
+}
+
+By giving GET to 'redfish/v1/Systems/system/Bios/Settings'
+Response:
+{
+ "@odata.id": "/redfish/v1/Systems/system/Bios/Settings",
+ "@odata.type": "#Bios.v1_1_0.Bios",
+ "AttributeRegistry": "BiosAttributeRegistry",
+ "Attributes": {
+ "ATS": "0x0",
+ "AmpPrefetchEnable": "0x1",
+ "Ce2LmLoggingEn": "0x1",
+ "DfxEadrDebugLogs": "0x2",
+ "PsfUrEnable": "0x1"
+ },
+ "Id": "BiosSettingsV1",
+ "Name": "Bios Settings Version 1"
+}
+
+By running Redfish-Service-Validator
+Result:
+Elapsed time: 0:09:36
+invalidPropertyValue: 108
+metadataNamespaces: 2185
+missingNamespaces: 1
+optionalAction: 9
+pass: 13772
+passAction: 22
+passGet: 541
+reflink: 1
+repeat: 47
+serviceNamespaces: 75
+skipOptional: 9276
+unverifiedComplexAdditional: 1
+warnDeprecated: 230
+warningPresent: 54
+Validation has succeeded.
+
+Change-Id: Ib92eb7a1b81bef5adaf432b9225a183d7a78ebef
+Signed-off-by: Arun Lal K M <arun.lal@intel.com>
+---
+ redfish-core/lib/bios.hpp | 583 ++++++++++++++++++++++++--------------
+ 1 file changed, 374 insertions(+), 209 deletions(-)
+
+diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
+index 360a749..a927772 100644
+--- a/redfish-core/lib/bios.hpp
++++ b/redfish-core/lib/bios.hpp
+@@ -12,13 +12,15 @@ map{attributeName,struct{attributeType,readonlyStatus,displayname,
+ description,menuPath,current,default,
+ array{struct{optionstring,optionvalue}}}}
+ */
+-using BiosBaseTableType = std::vector<std::pair<
++
++using BiosBaseTableType = boost::container::flat_map<
+ std::string,
+ std::tuple<
+ std::string, bool, std::string, std::string, std::string,
+ std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
+ std::vector<
+- std::tuple<std::string, std::variant<int64_t, std::string>>>>>>;
++ std::tuple<std::string, std::variant<int64_t, std::string>>>>>;
++
+ using BiosBaseTableItemType = std::pair<
+ std::string,
+ std::tuple<
+@@ -29,6 +31,13 @@ using BiosBaseTableItemType = std::pair<
+ using OptionsItemType =
+ std::tuple<std::string, std::variant<int64_t, std::string>>;
+
++using PendingAttributesType = boost::container::flat_map<
++ std::string, std::tuple<std::string, std::variant<int64_t, std::string>>>;
++
++using PendingAttributesItemType =
++ std::pair<std::string,
++ std::tuple<std::string, std::variant<int64_t, std::string>>>;
++
+ enum BiosBaseTableIndex
+ {
+ biosBaseAttrType = 0,
+@@ -45,17 +54,7 @@ enum OptionsItemIndex
+ optItemType = 0,
+ optItemValue
+ };
+-/*
+- The Pending attribute name and new value.
+- ex- { {"QuietBoot",Type.Integer, 0x1},
+- { "DdrFreqLimit",Type.String,"2933"}
+- }
+-*/
+-using PendingAttributesType = std::vector<std::pair<
+- std::string, std::tuple<std::string, std::variant<int64_t, std::string>>>>;
+-using PendingAttributesItemType =
+- std::pair<std::string,
+- std::tuple<std::string, std::variant<int64_t, std::string>>>;
++
+ enum PendingAttributesIndex
+ {
+ pendingAttrType = 0,
+@@ -64,31 +63,16 @@ enum PendingAttributesIndex
+ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus)
+ {
+ std::string ret;
+- if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
+- "AttributeType.Enumeration")
+- {
+- ret = "Enumeration";
+- }
+- else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+- "Manager.AttributeType.String")
++ if (typeDbus == "xyz.openbmc_project.BIOSConfig."
++ "Manager.AttributeType.String")
+ {
+ ret = "String";
+ }
+- else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+- "Manager.AttributeType.Password")
+- {
+- ret = "Password";
+- }
+ else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+ "Manager.AttributeType.Integer")
+ {
+ ret = "Integer";
+ }
+- else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
+- "Manager.AttributeType.Boolean")
+- {
+- ret = "Boolean";
+- }
+ else
+ {
+ ret = "UNKNOWN";
+@@ -96,29 +80,7 @@ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus)
+
+ return ret;
+ }
+-static std::string mapRedfishToAttrType(const std::string_view type)
+-{
+- std::string ret;
+- if (type == "string")
+- {
+- ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String";
+- }
+- else if (type == "int")
+- {
+- ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer";
+- }
+- else if (type == "enum")
+- {
+- ret = "xyz.openbmc_project.BIOSConfig.Manager.AttributeType."
+- "Enumeration";
+- }
+- else
+- {
+- ret = "UNKNOWN";
+- }
+
+- return ret;
+-}
+ static std::string mapBoundTypeToRedfish(const std::string_view typeDbus)
+ {
+ std::string ret;
+@@ -208,6 +170,15 @@ inline void requestRoutesBiosService(App& app)
+
+ return;
+ }
++
++ if (getObjectType.empty())
++ {
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++
+ const std::string& service =
+ getObjectType.begin()->first;
+
+@@ -231,7 +202,7 @@ inline void requestRoutesBiosService(App& app)
+ if (baseBiosTable == nullptr)
+ {
+ BMCWEB_LOG_ERROR
+- << "baseBiosTable == nullptr ";
++ << "baseBiosTable is empty";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+@@ -269,7 +240,6 @@ inline void requestRoutesBiosService(App& app)
+ {
+ BMCWEB_LOG_ERROR
+ << "Unsupported attribute type.";
+- messages::internalError(asyncResp->res);
+ }
+ }
+ },
+@@ -293,7 +263,7 @@ inline void requestRoutesBiosService(App& app)
+ inline void requestRoutesBiosChangePassword(App& app)
+ {
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/")
+- .privileges({{"ConfigureComponents"}})
++ .privileges(redfish::privileges::postBios)
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+@@ -359,180 +329,298 @@ inline void requestRoutesBiosSettings(App& app)
+ {
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings")
+ .privileges(redfish::privileges::getBios)
+- .methods(boost::beast::http::verb::get)(
+- [](const crow::Request&,
+- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+- asyncResp->res.jsonValue["@odata.id"] =
+- asyncResp->res.jsonValue["@odata.id"] =
+- "/redfish/v1/Systems/system/Bios/Settings";
+- asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
+- asyncResp->res.jsonValue["Name"] = "Bios Settings Version 1";
+- asyncResp->res.jsonValue["Id"] = "BiosSettingsV1";
+- asyncResp->res.jsonValue["AttributeRegistry"] =
+- "BiosAttributeRegistry";
+- asyncResp->res.jsonValue["Attributes"] = {};
++ .methods(
++ boost::beast::http::verb::
++ get)([](const crow::Request&,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ asyncResp->res.jsonValue["@odata.id"] =
++ "/redfish/v1/Systems/system/Bios/Settings";
++ asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
++ asyncResp->res.jsonValue["Name"] = "Bios Settings Version 1";
++ asyncResp->res.jsonValue["Id"] = "BiosSettingsV1";
++ asyncResp->res.jsonValue["AttributeRegistry"] =
++ "BiosAttributeRegistry";
++ asyncResp->res.jsonValue["Attributes"] = {};
+
+- crow::connections::systemBus->async_method_call(
+- [asyncResp](const boost::system::error_code ec,
+- const GetObjectType& getObjectType) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR
+- << "ObjectMapper::GetObject call failed: "
+- << ec;
+- messages::internalError(asyncResp->res);
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const GetObjectType& getObjectType) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "ObjectMapper::GetObject call failed: " << ec;
++ messages::internalError(asyncResp->res);
+
+- return;
+- }
+- std::string service = getObjectType.begin()->first;
++ return;
++ }
+
+- crow::connections::systemBus->async_method_call(
+- [asyncResp](
+- const boost::system::error_code ec,
+- const std::variant<PendingAttributesType>&
+- retPendingAttributes) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR
+- << "getBiosSettings DBUS error: " << ec;
+- messages::resourceNotFound(
+- asyncResp->res, "Systems/system/Bios",
+- "Settings");
+- return;
+- }
+- const PendingAttributesType* pendingAttributes =
+- std::get_if<PendingAttributesType>(
+- &retPendingAttributes);
+- nlohmann::json& attributesJson =
+- asyncResp->res.jsonValue["Attributes"];
+- if (pendingAttributes == nullptr)
+- {
+- BMCWEB_LOG_ERROR
+- << "pendingAttributes == nullptr ";
+- messages::internalError(asyncResp->res);
+- return;
+- }
+- for (const PendingAttributesItemType& item :
+- *pendingAttributes)
++ if (getObjectType.empty())
++ {
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++
++ std::string service = getObjectType.begin()->first;
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](const boost::system::error_code ec,
++ const std::variant<PendingAttributesType>&
++ retPendingAttributes) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "getBiosSettings DBUS error: " << ec;
++ messages::resourceNotFound(
++ asyncResp->res, "Systems/system/Bios",
++ "Settings");
++ return;
++ }
++
++ const PendingAttributesType* pendingAttributes =
++ std::get_if<PendingAttributesType>(
++ &retPendingAttributes);
++ nlohmann::json& attributesJson =
++ asyncResp->res.jsonValue["Attributes"];
++ if (pendingAttributes == nullptr)
++ {
++ BMCWEB_LOG_ERROR
++ << "pendingAttributes is empty";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ for (const PendingAttributesItemType&
++ pendingAttributesItem : *pendingAttributes)
++ {
++ const std::string& biosAttrType =
++ std::get<pendingAttrType>(
++ pendingAttributesItem.second);
++
++ std::string itemType =
++ mapAttrTypeToRedfish(biosAttrType);
++
++ if (itemType == "String")
+ {
+- const std::string& key = item.first;
+- const std::string& itemType =
+- std::get<pendingAttrType>(item.second);
+- std::string attrType =
+- mapAttrTypeToRedfish(itemType);
+- if (attrType == "String")
+- {
+- const std::string* currValue =
+- std::get_if<std::string>(
+- &std::get<pendingAttrValue>(
+- item.second));
+- attributesJson.emplace(
+- key, currValue != nullptr
+- ? *currValue
+- : "");
+- }
+- else if (attrType == "Integer")
++ const std::string* currValue =
++ std::get_if<std::string>(
++ &std::get<pendingAttrValue>(
++ pendingAttributesItem.second));
++
++ if (!currValue)
+ {
+- const int64_t* currValue =
+- std::get_if<int64_t>(
+- &std::get<pendingAttrValue>(
+- item.second));
+- attributesJson.emplace(
+- key, currValue != nullptr
+- ? *currValue
+- : 0);
++ BMCWEB_LOG_ERROR
++ << "No string data in pending "
++ "attributes item data";
++ messages::internalError(asyncResp->res);
++ return;
+ }
+- else
++
++ attributesJson.emplace(
++ pendingAttributesItem.first,
++ *currValue);
++ }
++ else if (itemType == "Integer")
++ {
++ const int64_t* currValue =
++ std::get_if<int64_t>(
++ &std::get<pendingAttrValue>(
++ pendingAttributesItem.second));
++
++ if (!currValue)
+ {
+ BMCWEB_LOG_ERROR
+- << "Unsupported attribute type.";
++ << "No int64_t data in pending "
++ "attributes item data";
+ messages::internalError(asyncResp->res);
++ return;
+ }
++
++ attributesJson.emplace(
++ pendingAttributesItem.first,
++ *currValue);
+ }
+- },
+- service, "/xyz/openbmc_project/bios_config/manager",
+- "org.freedesktop.DBus.Properties", "Get",
+- "xyz.openbmc_project.BIOSConfig.Manager",
+- "PendingAttributes");
+- },
+- "xyz.openbmc_project.ObjectMapper",
+- "/xyz/openbmc_project/object_mapper",
+- "xyz.openbmc_project.ObjectMapper", "GetObject",
+- "/xyz/openbmc_project/bios_config/manager",
+- std::array<const char*, 0>());
+- });
++ else
++ {
++ BMCWEB_LOG_ERROR
++ << "Unsupported attribute type.";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++ }
++ },
++ service, "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Get",
++ "xyz.openbmc_project.BIOSConfig.Manager",
++ "PendingAttributes");
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject",
++ "/xyz/openbmc_project/bios_config/manager",
++ std::array<const char*, 0>());
++ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings")
+- .privileges({{"ConfigureComponents"}})
+- .methods(boost::beast::http::verb::patch)(
+- [](const crow::Request& req,
+- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+- nlohmann::json inpJson;
+-
+- if (!redfish::json_util::readJson(req, asyncResp->res, "data",
+- inpJson))
+- {
+- return;
+- }
++ .privileges(redfish::privileges::patchBios)
++ .methods(
++ boost::beast::http::verb::
++ patch)([](const crow::Request& req,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ nlohmann::json inpJson;
++
++ if (!redfish::json_util::readJson(req, asyncResp->res, "data",
++ inpJson))
++ {
++ BMCWEB_LOG_ERROR << "No 'data' in req!";
++ return;
++ }
++
++ if (inpJson.empty())
++ {
++ messages::invalidObject(asyncResp->res, "data");
++ BMCWEB_LOG_ERROR << "No input in req!";
++ return;
++ }
+
+- for (auto& attrInfo : inpJson)
+- {
+- std::optional<std::string> attrName;
+- std::optional<std::string> attrType;
+- std::optional<std::string> attrValue;
+- if (!json_util::getValueFromJsonObject(
+- attrInfo, "AttributeName", attrName))
+- {
+- messages::propertyMissing(asyncResp->res,
+- "AttributeName");
+- return;
+- }
+- if (!json_util::getValueFromJsonObject(
+- attrInfo, "AttributeType", attrType))
+- {
+- messages::propertyMissing(asyncResp->res,
+- "AttributeType");
+- return;
+- }
+- if (!json_util::getValueFromJsonObject(
+- attrInfo, "AttributeValue", attrValue))
++ crow::connections::systemBus->async_method_call(
++ [asyncResp, inpJson](const boost::system::error_code ec,
++ const GetObjectType& getObjectType) {
++ if (ec)
+ {
+- messages::propertyMissing(asyncResp->res,
+- "AttributeValue");
++ BMCWEB_LOG_ERROR
++ << "ObjectMapper::GetObject call failed: " << ec;
++ messages::internalError(asyncResp->res);
++
+ return;
+ }
+- std::string biosAttrType = mapRedfishToAttrType(*attrType);
+
+- if (biosAttrType == "UNKNOWN")
++ if (getObjectType.empty())
+ {
+- BMCWEB_LOG_ERROR << "Invalid attribute type";
+- messages::propertyValueNotInList(
+- asyncResp->res, "AttributeType", *attrType);
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
+ return;
+ }
+
+- PendingAttributesType pendingAttributes;
+- pendingAttributes.emplace_back(std::make_pair(
+- *attrName, std::make_tuple(biosAttrType, *attrValue)));
++ std::string service = getObjectType.begin()->first;
+
+ crow::connections::systemBus->async_method_call(
+- [asyncResp](const boost::system::error_code ec) {
++ [asyncResp,
++ inpJson](const boost::system::error_code ec,
++ const std::variant<BiosBaseTableType>&
++ retBiosTable) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+- << "doPatch resp_handler got error " << ec;
++ << "getBiosAttributes DBUS error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
++
++ const BiosBaseTableType* baseBiosTable =
++ std::get_if<BiosBaseTableType>(&retBiosTable);
++
++ if (baseBiosTable == nullptr)
++ {
++ BMCWEB_LOG_ERROR << "baseBiosTable is empty.";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ PendingAttributesType pendingAttributes{};
++
++ for (nlohmann::detail::iteration_proxy_value<
++ nlohmann::detail::iter_impl<
++ const nlohmann::basic_json<>>>&
++ attributes : inpJson.items())
++ {
++ BiosBaseTableType::const_iterator knobIter =
++ baseBiosTable->find(attributes.key());
++ if (knobIter == baseBiosTable->end())
++ {
++ BMCWEB_LOG_ERROR << "Cannot find "
++ << attributes.key()
++ << " in baseBiosTable";
++ messages::propertyValueNotInList(
++ asyncResp->res, attributes.key(),
++ "data");
++ return;
++ }
++
++ const std::string& itemType =
++ std::get<biosBaseAttrType>(
++ knobIter->second);
++ std::string attrType =
++ mapAttrTypeToRedfish(itemType);
++
++ if (attrType == "String")
++ {
++ std::string val = attributes.value();
++
++ pendingAttributes.emplace(
++ attributes.key(),
++ std::make_tuple(itemType, val));
++ }
++ else if (attrType == "Integer")
++ {
++ pendingAttributes.emplace(
++ attributes.key(),
++ std::make_tuple(
++ itemType, static_cast<int64_t>(
++ attributes.value())));
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "UNKNOWN attrType == "
++ << itemType;
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++ }
++
++ if (pendingAttributes.empty())
++ {
++ BMCWEB_LOG_ERROR
++ << "pendingAttributes is empty.";
++ messages::invalidObject(asyncResp->res, "data");
++ }
++
++ crow::connections::systemBus->async_method_call(
++ [asyncResp](
++ const boost::system::error_code ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR
++ << "doPatch resp_handler got error "
++ << ec << "\n";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ messages::success(asyncResp->res);
++ },
++ "xyz.openbmc_project.BIOSConfigManager",
++ "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Set",
++ "xyz.openbmc_project.BIOSConfig.Manager",
++ "PendingAttributes",
++ std::variant<PendingAttributesType>(
++ pendingAttributes));
+ },
+- "xyz.openbmc_project.BIOSConfigManager",
+- "/xyz/openbmc_project/bios_config/manager",
+- "org.freedesktop.DBus.Properties", "Set",
++ service, "/xyz/openbmc_project/bios_config/manager",
++ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.BIOSConfig.Manager",
+- "PendingAttributes",
+- std::variant<PendingAttributesType>(pendingAttributes));
+- }
+- });
++ "BaseBIOSTable");
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject",
++ "/xyz/openbmc_project/bios_config/manager",
++ std::array<const char*, 0>());
++ });
+ }
+ /**
+ * BiosAttributeRegistry class supports handle get method for BIOS attribute
+@@ -572,6 +660,15 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+
+ return;
+ }
++
++ if (getObjectType.empty())
++ {
++ BMCWEB_LOG_ERROR << "getObjectType is empty.";
++ messages::internalError(asyncResp->res);
++
++ return;
++ }
++
+ std::string service = getObjectType.begin()->first;
+
+ crow::connections::systemBus->async_method_call(
+@@ -592,8 +689,6 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ nlohmann::json& attributeArray =
+ asyncResp->res
+ .jsonValue["RegistryEntries"]["Attributes"];
+- nlohmann::json optionsArray =
+- nlohmann::json::array();
+ if (baseBiosTable == nullptr)
+ {
+ BMCWEB_LOG_ERROR << "baseBiosTable == nullptr ";
+@@ -609,10 +704,11 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ mapAttrTypeToRedfish(itemType);
+ if (attrType == "UNKNOWN")
+ {
+- BMCWEB_LOG_ERROR << "attrType == UNKNOWN";
+- messages::internalError(asyncResp->res);
+- return;
++ BMCWEB_LOG_ERROR << "UNKNOWN attrType == "
++ << itemType;
++ continue;
+ }
++
+ nlohmann::json attributeItem;
+ attributeItem["AttributeName"] = item.first;
+ attributeItem["Type"] = attrType;
+@@ -632,10 +728,30 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ std::get_if<std::string>(
+ &std::get<biosBaseCurrValue>(
+ item.second));
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, no "
++ "std::string data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ const std::string* defValue =
+ std::get_if<std::string>(
+ &std::get<biosBaseDefaultValue>(
+ item.second));
++
++ if (!defValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get defValue, no "
++ "std::string data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ attributeItem["CurrentValue"] =
+ currValue != nullptr ? *currValue : "";
+ attributeItem["DefaultValue"] =
+@@ -647,10 +763,30 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ std::get_if<int64_t>(
+ &std::get<biosBaseCurrValue>(
+ item.second));
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, no "
++ "int64_t data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ const int64_t* defValue =
+ std::get_if<int64_t>(
+ &std::get<biosBaseDefaultValue>(
+ item.second));
++
++ if (!defValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get defValue, no "
++ "int64_t data in BIOS "
++ "attributes item data";
++ continue;
++ }
++
+ attributeItem["CurrentValue"] =
+ currValue != nullptr ? *currValue : 0;
+ attributeItem["DefaultValue"] =
+@@ -658,12 +794,13 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ }
+ else
+ {
+- BMCWEB_LOG_ERROR
+- << "Unsupported attribute type.";
+- messages::internalError(asyncResp->res);
+- return;
++ BMCWEB_LOG_ERROR << "UNKNOWN attrType == "
++ << itemType;
++ continue;
+ }
+
++ nlohmann::json optionsArray =
++ nlohmann::json::array();
+ const std::vector<OptionsItemType>&
+ optionsVector =
+ std::get<biosBaseOptions>(item.second);
+@@ -678,9 +815,9 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ if (optItemTypeRedfish == "UNKNOWN")
+ {
+ BMCWEB_LOG_ERROR
+- << "optItemTypeRedfish == UNKNOWN";
+- messages::internalError(asyncResp->res);
+- return;
++ << "UNKNOWN optItemTypeRedfish == "
++ << strOptItemType;
++ continue;
+ }
+ if (optItemTypeRedfish == "OneOf")
+ {
+@@ -688,6 +825,17 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ std::get_if<std::string>(
+ &std::get<optItemValue>(
+ optItem));
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, "
++ "no "
++ "std::string data in option "
++ "item value";
++ continue;
++ }
++
+ optItemJson[optItemTypeRedfish] =
+ currValue != nullptr ? *currValue
+ : "";
+@@ -698,6 +846,17 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ std::get_if<int64_t>(
+ &std::get<optItemValue>(
+ optItem));
++
++ if (!currValue)
++ {
++ BMCWEB_LOG_ERROR
++ << "Unable to get currValue, "
++ "no "
++ "int64_t data in option "
++ "item value";
++ continue;
++ }
++
+ optItemJson[optItemTypeRedfish] =
+ currValue != nullptr ? *currValue
+ : 0;
+@@ -706,6 +865,12 @@ inline void requestRoutesBiosAttributeRegistry(App& app)
+ optionsArray.push_back(optItemJson);
+ }
+
++ if (optionsArray.empty())
++ {
++ BMCWEB_LOG_ERROR << "optionsArray is empty";
++ continue;
++ }
++
+ attributeItem["Value"] = optionsArray;
+ attributeArray.push_back(attributeItem);
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch
new file mode 100644
index 000000000..7fcc235d2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0010-Remove-Terminated-Event-Subscriptions.patch
@@ -0,0 +1,258 @@
+From adaa5cb4c494148430b90edb248260eb2e66bca7 Mon Sep 17 00:00:00 2001
+From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+Date: Wed, 8 Sep 2021 15:42:52 +0530
+Subject: [PATCH] Delete/Remove Terminated Event Subscription(s)
+
+Added functionality to delete/remove event subscription(s) which are
+configured to Terminate after retries.
+
+Currently, when an Event is subscribed with Retry Policy as
+"TerminateAfterRetries", the state of the connection is set to
+"Terminated" after retrying, but the Subscription is not removed.
+This commit adds the functionality to detect terminated connection and
+remove the respective subscription.
+
+Tested:
+ - Created a Subscription with
+ DeliveryRetryPolicy: "TerminateAfterRetries"
+ - Received Events successfully on Event listener
+ - Once the Event listener was stopped, the Subscription was
+ removed/deleted after retries.
+
+Change-Id: If447acb2db74fb29a5d1cfe6194b77cda82bc8a1
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+---
+ http/http_client.hpp | 43 +++++++++++++++----
+ .../include/event_service_manager.hpp | 37 ++++++++++++++++
+ 2 files changed, 71 insertions(+), 9 deletions(-)
+
+diff --git a/http/http_client.hpp b/http/http_client.hpp
+index aaf1b2d..4f62c40 100644
+--- a/http/http_client.hpp
++++ b/http/http_client.hpp
+@@ -56,6 +56,8 @@ enum class ConnState
+ closeInProgress,
+ closed,
+ suspended,
++ terminate,
++ terminateInProgress,
+ terminated,
+ abortConnection,
+ retry
+@@ -263,7 +265,14 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
+ void doClose()
+ {
+- state = ConnState::closeInProgress;
++ if (state == ConnState::terminate)
++ {
++ state = ConnState::terminateInProgress;
++ }
++ else if (state != ConnState::suspended)
++ {
++ state = ConnState::closeInProgress;
++ }
+
+ // Set the timeout on the tcp stream socket for the async operation
+ conn.expires_after(std::chrono::seconds(30));
+@@ -293,8 +302,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
+ self->conn.close();
+
+- if ((self->state != ConnState::suspended) &&
+- (self->state != ConnState::terminated))
++ if (self->state == ConnState::terminateInProgress)
++ {
++ self->state = ConnState::terminated;
++ }
++ else if (self->state == ConnState::closeInProgress)
+ {
+ self->state = ConnState::closed;
+ self->handleConnState();
+@@ -316,8 +328,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
+ conn.close();
+
+- if ((state != ConnState::suspended) &&
+- (state != ConnState::terminated))
++ if (state == ConnState::terminateInProgress)
++ {
++ state = ConnState::terminated;
++ }
++ else if (state == ConnState::closeInProgress)
+ {
+ state = ConnState::closed;
+ handleConnState();
+@@ -340,8 +355,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ BMCWEB_LOG_DEBUG << "Retry policy: " << retryPolicyAction;
+ if (retryPolicyAction == "TerminateAfterRetries")
+ {
+- // TODO: delete subscription
+- state = ConnState::terminated;
++ state = ConnState::terminate;
+ }
+ if (retryPolicyAction == "SuspendRetries")
+ {
+@@ -392,6 +406,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ case ConnState::sendInProgress:
+ case ConnState::recvInProgress:
+ case ConnState::closeInProgress:
++ case ConnState::terminateInProgress:
+ {
+ BMCWEB_LOG_DEBUG << "Async operation is already in progress";
+ break;
+@@ -413,7 +428,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ break;
+ }
+ case ConnState::suspended:
+- case ConnState::terminated:
++ case ConnState::terminate:
+ {
+ doClose();
+ break;
+@@ -480,7 +495,8 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
+ void sendData(const std::string& data)
+ {
+- if ((state == ConnState::suspended) || (state == ConnState::terminated))
++ if ((state == ConnState::terminate) ||
++ (state == ConnState::terminated) || (state == ConnState::suspended))
+ {
+ return;
+ }
+@@ -489,6 +505,15 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ return;
+ }
+
++ bool isTerminated()
++ {
++ if (state == ConnState::terminated)
++ {
++ return true;
++ }
++ return false;
++ }
++
+ void addHeaders(
+ const std::vector<std::pair<std::string, std::string>>& httpHeaders)
+ {
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 8d7067b..79618f6 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -591,6 +591,14 @@ class Subscription : public persistent_data::UserSubscription
+ return std::nullopt;
+ }
+
++ bool isTerminated()
++ {
++ if (conn != nullptr)
++ return conn->isTerminated();
++
++ return false;
++ }
++
+ private:
+ std::shared_ptr<crow::SseConnection> sseConn = nullptr;
+ uint64_t eventSeqNum;
+@@ -847,6 +855,22 @@ class EventServiceManager
+ }
+ }
+
++ void deleteTerminatedSubcriptions()
++ {
++ boost::container::flat_map<std::string,
++ std::shared_ptr<Subscription>>::iterator it =
++ subscriptionsMap.begin();
++ while (it != subscriptionsMap.end())
++ {
++ std::shared_ptr<Subscription> entry = it->second;
++ if (entry->isTerminated())
++ {
++ subscriptionsMap.erase(it);
++ }
++ it++;
++ }
++ }
++
+ void updateNoOfSubscribersCount()
+ {
+ size_t eventLogSubCount = 0;
+@@ -881,6 +905,7 @@ class EventServiceManager
+
+ std::shared_ptr<Subscription> getSubscription(const std::string& id)
+ {
++ deleteTerminatedSubcriptions();
+ auto obj = subscriptionsMap.find(id);
+ if (obj == subscriptionsMap.end())
+ {
+@@ -971,6 +996,7 @@ class EventServiceManager
+
+ bool isSubscriptionExist(const std::string& id)
+ {
++ deleteTerminatedSubcriptions();
+ auto obj = subscriptionsMap.find(id);
+ if (obj == subscriptionsMap.end())
+ {
+@@ -1033,6 +1059,7 @@ class EventServiceManager
+
+ size_t getNumberOfSubscriptions()
+ {
++ deleteTerminatedSubcriptions();
+ return subscriptionsMap.size();
+ }
+
+@@ -1049,6 +1076,7 @@ class EventServiceManager
+
+ std::vector<std::string> getAllIDs()
+ {
++ deleteTerminatedSubcriptions();
+ std::vector<std::string> idList;
+ for (const auto& it : subscriptionsMap)
+ {
+@@ -1059,6 +1087,7 @@ class EventServiceManager
+
+ bool isDestinationExist(const std::string& destUrl)
+ {
++ deleteTerminatedSubcriptions();
+ for (const auto& it : subscriptionsMap)
+ {
+ std::shared_ptr<Subscription> entry = it.second;
+@@ -1073,6 +1102,7 @@ class EventServiceManager
+
+ void sendTestEventLog()
+ {
++ deleteTerminatedSubcriptions();
+ for (const auto& it : this->subscriptionsMap)
+ {
+ std::shared_ptr<Subscription> entry = it.second;
+@@ -1100,6 +1130,8 @@ class EventServiceManager
+ }
+ eventRecord.push_back(eventMessage);
+
++ deleteTerminatedSubcriptions();
++
+ for (const auto& it : this->subscriptionsMap)
+ {
+ std::shared_ptr<Subscription> entry = it.second;
+@@ -1143,6 +1175,8 @@ class EventServiceManager
+ }
+ void sendBroadcastMsg(const std::string& broadcastMsg)
+ {
++ deleteTerminatedSubcriptions();
++
+ for (const auto& it : this->subscriptionsMap)
+ {
+ std::shared_ptr<Subscription> entry = it.second;
+@@ -1291,6 +1325,8 @@ class EventServiceManager
+ return;
+ }
+
++ deleteTerminatedSubcriptions();
++
+ for (const auto& it : this->subscriptionsMap)
+ {
+ std::shared_ptr<Subscription> entry = it.second;
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-DELETE-method-for-MetricReport.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-DELETE-method-for-MetricReport.patch
deleted file mode 100644
index aabe500f5..000000000
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-DELETE-method-for-MetricReport.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-From 4cf883dba6e16c56d04dbd092d30c9a13d5a5eb4 Mon Sep 17 00:00:00 2001
-From: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
-Date: Fri, 6 Aug 2021 15:15:17 +0200
-Subject: [PATCH] Add DELETE method for MetricReport
-
-Added DELETE method for removing Reports by using MetricReports uri;
-metric_report.hpp and metric_report_definition.hpp files are sharing
-now common lambda function for DELETE operations
-
-Tested on QEMU:
-- Added Reports and requested from bmcweb to delete them via
- /redfish/v1/TelemetryService/MetricReports/<reportname> or via
- /redfish/v1/TelemetryService/MetricReportDefinitions/<reportname>
-- Added two different reports via POST, deleted first of them via
- MetricReports DELETE, checked by MetricReports GET if list of reports
- contain only second report, deleted second report via MetricReports
- DELETE and checked by MetricReports GET if list of reports is empty
-- Same as one above but using MetricReportDefinitions DELETE and GET
-
-Signed-off-by: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
-Change-Id: I151bad363dcabd57246eb10b501abd24107b937e
----
- .../include/utils/telemetry_utils.hpp | 35 +++++++++++++++++++
- redfish-core/lib/metric_report.hpp | 4 +++
- redfish-core/lib/metric_report_definition.hpp | 34 +-----------------
- 3 files changed, 40 insertions(+), 33 deletions(-)
-
-diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
-index 5872350..743585f 100644
---- a/redfish-core/include/utils/telemetry_utils.hpp
-+++ b/redfish-core/include/utils/telemetry_utils.hpp
-@@ -70,5 +70,40 @@ inline std::string getDbusReportPath(const std::string& id)
- return path;
- }
-
-+inline std::function<void(const crow::Request&,
-+ const std::shared_ptr<bmcweb::AsyncResp>&,
-+ const std::string&)>
-+ getMetricReportDeleteHandler(const std::string& type)
-+{
-+ return [type](const crow::Request&,
-+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-+ const std::string& id) {
-+ const std::string reportPath = getDbusReportPath(id);
-+
-+ crow::connections::systemBus->async_method_call(
-+ [asyncResp, type, id](const boost::system::error_code ec) {
-+ /*
-+ * boost::system::errc and std::errc are missing value
-+ * for EBADR error that is defined in Linux.
-+ */
-+ if (ec.value() == EBADR)
-+ {
-+ messages::resourceNotFound(asyncResp->res, type, id);
-+ return;
-+ }
-+
-+ if (ec)
-+ {
-+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
-+ messages::internalError(asyncResp->res);
-+ return;
-+ }
-+
-+ asyncResp->res.result(boost::beast::http::status::no_content);
-+ },
-+ service, reportPath, "xyz.openbmc_project.Object.Delete", "Delete");
-+ };
-+}
-+
- } // namespace telemetry
- } // namespace redfish
-diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
-index 63c8c19..60ce74e 100644
---- a/redfish-core/lib/metric_report.hpp
-+++ b/redfish-core/lib/metric_report.hpp
-@@ -127,5 +127,9 @@ inline void requestRoutesMetricReport(App& app)
- telemetry::service, reportPath, telemetry::reportInterface,
- "Update");
- });
-+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReports/<str>/")
-+ .privileges(redfish::privileges::deleteMetricReport)
-+ .methods(boost::beast::http::verb::delete_)(
-+ telemetry::getMetricReportDeleteHandler("MetricReports"));
- }
- } // namespace redfish
-diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
-index a0c4f1d..e0505e5 100644
---- a/redfish-core/lib/metric_report_definition.hpp
-+++ b/redfish-core/lib/metric_report_definition.hpp
-@@ -450,38 +450,6 @@ inline void requestRoutesMetricReportDefinition(App& app)
- "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
- .privileges(redfish::privileges::deleteMetricReportDefinitionCollection)
- .methods(boost::beast::http::verb::delete_)(
-- [](const crow::Request&,
-- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-- const std::string& id)
--
-- {
-- const std::string reportPath = telemetry::getDbusReportPath(id);
--
-- crow::connections::systemBus->async_method_call(
-- [asyncResp, id](const boost::system::error_code ec) {
-- /*
-- * boost::system::errc and std::errc are missing value
-- * for EBADR error that is defined in Linux.
-- */
-- if (ec.value() == EBADR)
-- {
-- messages::resourceNotFound(
-- asyncResp->res, "MetricReportDefinition", id);
-- return;
-- }
--
-- if (ec)
-- {
-- BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
-- messages::internalError(asyncResp->res);
-- return;
-- }
--
-- asyncResp->res.result(
-- boost::beast::http::status::no_content);
-- },
-- telemetry::service, reportPath,
-- "xyz.openbmc_project.Object.Delete", "Delete");
-- });
-+ telemetry::getMetricReportDeleteHandler("MetricReportDefinition"));
- }
- } // namespace redfish
---
-2.25.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-GET-method-for-TriggerCollection.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch
index 0646aba5c..0646aba5c 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-GET-method-for-TriggerCollection.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Revert-Remove-LogService-from-TelemetryService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch
index 987a43b4c..987a43b4c 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Revert-Remove-LogService-from-TelemetryService.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-event-service-fix-added-Context-field-to-response.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch
index ffab743f6..ffab743f6 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-event-service-fix-added-Context-field-to-response.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Generalize-ReadingType-in-MetricDefinition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch
index bd6e64346..bd6e64346 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Generalize-ReadingType-in-MetricDefinition.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch
new file mode 100644
index 000000000..548e3d9c6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch
@@ -0,0 +1,46 @@
+From ef83a4fb14648edc6c8370363ff88fb6f060a43b Mon Sep 17 00:00:00 2001
+From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+Date: Mon, 20 Sep 2021 21:55:57 +0530
+Subject: [PATCH] Add support for deleting terminated subscriptions
+
+Added functionality to delete/remove event subscription(s) which are
+configured to Terminate after retries.
+
+Currently, when an Event is subscribed with Retry Policy as
+"TerminateAfterRetries", the state of the connection is set to
+"Terminated" after retrying, but the Subscription is not removed.
+This commit adds the functionality to detect terminated connection and
+remove the respective subscription.
+
+This commit adds this check for metric reports.
+
+Tested:
+ - Created a Subscription with
+ DeliveryRetryPolicy: "TerminateAfterRetries"
+ - Received Events successfully on Event listener
+ - Once the Event listener was stopped, the Subscription was
+ removed/deleted after retries.
+
+Change-Id: I3cb0af5bc24411cddcdb3d1d9de25e8e9144106c
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index c9e2812..c2fefb3 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -1535,6 +1535,9 @@ class EventServiceManager
+
+ std::variant<telemetry::TimestampReadings>& readings =
+ found->second;
++
++ this->deleteTerminatedSubcriptions();
++
+ for (const auto& it :
+ EventServiceManager::getInstance().subscriptionsMap)
+ {
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
index 8dab07e2b..fd88e9e18 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
@@ -14,17 +14,17 @@ Current revisions:
- Add support for MetricDefinition property in MetricReport
https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44512/9
-- Add DELETE method for MetricReport
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/45688/5
-
- Add GET method for TriggerCollection
- file://telemetry/0006-Add-GET-method-for-TriggerCollection.patch
+ file://telemetry/0005-Add-GET-method-for-TriggerCollection.patch
- LogService field, actual implementation will be upstreamed with triggers feature
- file://telemetry/0007-Revert-Remove-LogService-from-TelemetryService.patch
+ file://telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch
- Event service fix for Context field
- file://telemetry/0008-event-service-fix-added-Context-field-to-response.patch
+ file://telemetry/0007-event-service-fix-added-Context-field-to-response.patch
- Generalize ReadingType in MetricDefinition
- file://telemetry/0009-Generalize-ReadingType-in-MetricDefinition.patch
+ file://telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch
+
+- Add support for deleting terminated subscriptions
+ file://telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch