From 18f97faa411078b95d042d207f5fff32bc8ece1d Mon Sep 17 00:00:00 2001 From: P Dheeraj Srujan Kumar Date: Thu, 31 Mar 2022 02:50:48 +0530 Subject: Update to internal 1-0.91 Signed-off-by: P Dheeraj Srujan Kumar --- ...001-Firmware-update-configuration-changes.patch | 288 ++----- ...5-Add-Model-CoreCount-to-ProcessorSummary.patch | 288 ------- .../0025-Add-Model-to-ProcessorSummary.patch | 108 +++ ...elete-the-copy-constructor-on-the-Request.patch | 30 + ...27-Convert-VariantType-to-DbusVariantType.patch | 50 ++ ...fix-for-broken-feature-Pending-Attributes.patch | 89 ++- ...osAttributeRegistry-node-under-Registries.patch | 76 ++ ...d-unmerged-changes-for-http-retry-support.patch | 172 ++-- .../0002-EventService-https-client-support.patch | 243 +++--- .../0004-Add-Server-Sent-Events-support.patch | 14 +- ...tyle-subscription-support-to-eventservice.patch | 70 +- .../0006-Add-EventService-SSE-filter-support.patch | 24 +- ...rvice-Log-events-for-subscription-actions.patch | 21 +- ...ks-on-Event-Subscription-input-parameters.patch | 33 +- ...cture-Redifsh-EventLog-Transmit-code-flow.patch | 18 +- ...010-Remove-Terminated-Event-Subscriptions.patch | 71 +- ...h-while-deleting-terminated-subscriptions.patch | 12 +- ...ort-for-deleting-terminated-subscriptions.patch | 45 ++ ...rvice-fix-added-Context-field-to-response.patch | 33 + .../interfaces/bmcweb/eventservice/README | 10 +- ...dd-asyncResp-support-during-handleUpgrade.patch | 2 +- ...port-for-privilege-check-in-handleUpgrade.patch | 2 +- .../0004-Add-Privileges-to-Websockets.patch | 6 +- ...1-Add-support-for-MetricDefinition-scheme.patch | 619 -------------- ...dd-support-for-POST-on-TriggersCollection.patch | 889 +++++++++++++++++++++ ...1-Sync-Telmetry-service-with-EventService.patch | 284 +++++++ ...t-Remove-LogService-from-TelemetryService.patch | 26 + ...2-Sync-Telmetry-service-with-EventService.patch | 295 ------- ...d-bmcweb-to-use-new-telemetry-service-API.patch | 513 ++++++++---- ...MetricDefinition-property-in-MetricReport.patch | 268 ------- ...0005-Add-GET-method-for-TriggerCollection.patch | 313 -------- ...t-Remove-LogService-from-TelemetryService.patch | 26 - ...rvice-fix-added-Context-field-to-response.patch | 29 - ...ort-for-deleting-terminated-subscriptions.patch | 46 -- .../interfaces/bmcweb/telemetry/README | 28 +- ...1-Revert-Disable-nbd-proxy-from-the-build.patch | 30 +- ...status-code-from-InsertMedia-REST-methods.patch | 24 +- .../recipes-phosphor/interfaces/bmcweb_%.bbappend | 47 +- 38 files changed, 2437 insertions(+), 2705 deletions(-) delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-CoreCount-to-ProcessorSummary.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-to-ProcessorSummary.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0026-Revert-Delete-the-copy-constructor-on-the-Request.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0027-Convert-VariantType-to-DbusVariantType.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0012-Add-support-for-deleting-terminated-subscriptions.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0013-event-service-fix-added-Context-field-to-response.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-POST-on-TriggersCollection.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync-Telmetry-service-with-EventService.patch create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Revert-Remove-LogService-from-TelemetryService.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces') diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch index 6621d2512..4fb12ed04 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch @@ -1,6 +1,6 @@ -From 7c005c318a12c53ed887b3081bd4b34ea0213053 Mon Sep 17 00:00:00 2001 +From 74309a2b2f9a41b741816cb427d9008f67c6f160 Mon Sep 17 00:00:00 2001 From: Vikram Bodireddy -Date: Mon, 28 Jun 2021 21:56:18 +0530 +Date: Fri, 3 Dec 2021 05:25:02 +0530 Subject: [PATCH] Firmware update configuration changes This commit will provide user to PATCH the below firmware update @@ -39,20 +39,18 @@ Tested: - Successfully ran redfish validater with no new errors. -Change-Id: I25ef6d64af3f1dcea3acba93d7fd2b505130142e Signed-off-by: Vikram Bodireddy -Signed-off-by: AppaRao Puli --- - redfish-core/lib/update_service.hpp | 462 ++++++++++++++---- + redfish-core/lib/update_service.hpp | 337 ++++++++++++++++-- static/redfish/v1/$metadata/index.xml | 3 + - .../JsonSchemas/OemUpdateService/index.json | 69 +++ - .../redfish/v1/schema/OemUpdateService_v1.xml | 40 ++ - 4 files changed, 484 insertions(+), 90 deletions(-) + .../JsonSchemas/OemUpdateService/index.json | 69 ++++ + .../redfish/v1/schema/OemUpdateService_v1.xml | 40 +++ + 4 files changed, 421 insertions(+), 28 deletions(-) create mode 100644 static/redfish/v1/JsonSchemas/OemUpdateService/index.json create mode 100644 static/redfish/v1/schema/OemUpdateService_v1.xml diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp -index e420130..b3270f0 100644 +index fde878e..be0abc9 100644 --- a/redfish-core/lib/update_service.hpp +++ b/redfish-core/lib/update_service.hpp @@ -26,7 +26,9 @@ @@ -84,7 +82,7 @@ index e420130..b3270f0 100644 inline static void cleanUp() { -@@ -42,28 +55,120 @@ inline static void cleanUp() +@@ -42,27 +55,120 @@ inline static void cleanUp() fwUpdateErrorMatcher = nullptr; } inline static void activateImage(const std::string& objPath, @@ -97,13 +95,13 @@ index e420130..b3270f0 100644 + if (imgUriTargets.size() == 0) + { + crow::connections::systemBus->async_method_call( -+ [](const boost::system::error_code error_code) { -+ if (error_code) ++ [](const boost::system::error_code errorCode) { ++ if (errorCode) + { + BMCWEB_LOG_DEBUG + << "RequestedActivation failed: error_code = " -+ << error_code; -+ BMCWEB_LOG_DEBUG << "error msg = " << error_code.message(); ++ << errorCode; ++ BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); + } + }, + service, objPath, "org.freedesktop.DBus.Properties", "Set", @@ -123,14 +121,14 @@ index e420130..b3270f0 100644 + const boost::system::error_code ec, + const crow::openbmc_mapper::GetSubTreeType& subtree) { + if (ec || !subtree.size()) -+ { + { +- BMCWEB_LOG_DEBUG << "error_code = " << errorCode; +- BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); + return; + } + + for (const auto& [invObjPath, invDict] : subtree) - { -- BMCWEB_LOG_DEBUG << "error_code = " << errorCode; -- BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); ++ { + std::size_t idPos = invObjPath.rfind("/"); + if ((idPos == std::string::npos) || + ((idPos + 1) >= invObjPath.size())) @@ -198,9 +196,8 @@ index e420130..b3270f0 100644 }, - service, objPath, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Software.Activation", "RequestedActivation", -- std::variant( -- "xyz.openbmc_project.Software.Activation.RequestedActivations." -- "Active")); +- dbus::utility::DbusVariantType( +- "xyz.openbmc_project.Software.Activation.RequestedActivations.Active")); + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", @@ -215,7 +212,7 @@ index e420130..b3270f0 100644 sdbusplus::message::message& m, task::Payload&& payload) { -@@ -76,23 +181,25 @@ static void +@@ -75,23 +181,26 @@ static void m.read(objPath, interfacesProperties); @@ -234,11 +231,9 @@ index e420130..b3270f0 100644 + [objPath, asyncResp, imgTargets{imgUriTargets}, + payload(std::move(payload))]( const boost::system::error_code errorCode, -- const std::vector< -- std::pair>>& -- objInfo) mutable { -+ const std::vector>>& objInfo) { + const std::vector< + std::pair>>& + objInfo) mutable { if (errorCode) { - BMCWEB_LOG_DEBUG << "error_code = " << errorCode; @@ -248,7 +243,7 @@ index e420130..b3270f0 100644 BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); if (asyncResp) -@@ -119,7 +226,7 @@ static void +@@ -118,7 +227,7 @@ static void // is added fwAvailableTimer = nullptr; @@ -257,7 +252,7 @@ index e420130..b3270f0 100644 if (asyncResp) { std::shared_ptr task = -@@ -251,8 +358,7 @@ static void +@@ -249,8 +358,7 @@ static void "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", "xyz.openbmc_project.ObjectMapper", "GetObject", objPath.str, @@ -267,7 +262,7 @@ index e420130..b3270f0 100644 } } } -@@ -262,7 +368,7 @@ static void +@@ -260,7 +368,7 @@ static void static void monitorForSoftwareAvailable( const std::shared_ptr& asyncResp, const crow::Request& req, const std::string& url, @@ -276,11 +271,9 @@ index e420130..b3270f0 100644 { // Only allow one FW update at a time if (fwUpdateInProgress != false) -@@ -301,11 +407,12 @@ static void monitorForSoftwareAvailable( - redfish::messages::internalError(asyncResp->res); +@@ -300,10 +408,10 @@ static void monitorForSoftwareAvailable( } }); -+ task::Payload payload(req); - auto callback = [asyncResp, + auto callback = [asyncResp, imgTargets{imgUriTargets}, @@ -291,7 +284,7 @@ index e420130..b3270f0 100644 }; fwUpdateInProgress = true; -@@ -470,12 +577,15 @@ inline void requestRoutesUpdateServiceActionsSimpleUpdate(App& app) +@@ -470,12 +578,15 @@ inline void requestRoutesUpdateServiceActionsSimpleUpdate(App& app) std::string fwFile = imageURI.substr(separator + 1); BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile; @@ -308,7 +301,7 @@ index e420130..b3270f0 100644 // TFTP can take up to 10 minutes depending on image size and // connection speed. Return to caller as soon as the TFTP operation -@@ -524,6 +634,9 @@ inline void requestRoutesUpdateService(App& app) +@@ -524,6 +635,9 @@ inline void requestRoutesUpdateService(App& app) asyncResp->res.jsonValue["Name"] = "Update Service"; asyncResp->res.jsonValue["HttpPushUri"] = "/redfish/v1/UpdateService"; @@ -318,20 +311,10 @@ index e420130..b3270f0 100644 // UpdateService cannot be disabled asyncResp->res.jsonValue["ServiceEnabled"] = true; asyncResp->res.jsonValue["FirmwareInventory"] = { -@@ -538,7 +651,8 @@ inline void requestRoutesUpdateService(App& app) - asyncResp->res - .jsonValue["Actions"]["#UpdateService.SimpleUpdate"]; - updateSvcSimpleUpdate["target"] = -- "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate"; -+ "/redfish/v1/UpdateService/Actions/" -+ "UpdateService.SimpleUpdate"; - updateSvcSimpleUpdate["TransferProtocol@Redfish.AllowableValues"] = - {"TFTP"}; - #endif -@@ -580,89 +694,258 @@ inline void requestRoutesUpdateService(App& app) - "/xyz/openbmc_project/software/apply_time", - "org.freedesktop.DBus.Properties", "Get", - "xyz.openbmc_project.Software.ApplyTime", "RequestedApplyTime"); +@@ -575,6 +689,34 @@ inline void requestRoutesUpdateService(App& app) + "OnReset"; + } + }); + + // Get the ApplyOptions value + crow::connections::systemBus->async_method_call( @@ -361,33 +344,26 @@ index e420130..b3270f0 100644 + "org.freedesktop.DBus.Properties", "Get", + "xyz.openbmc_project.Software.ApplyOptions", "ClearConfig"); }); -+ BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/") .privileges(redfish::privileges::patchUpdateService) -- .methods(boost::beast::http::verb::patch)( -- [](const crow::Request& req, -- const std::shared_ptr& asyncResp) { -- BMCWEB_LOG_DEBUG << "doPatch..."; -+ .methods( -+ boost::beast::http::verb:: -+ patch)([](const crow::Request& req, -+ const std::shared_ptr& asyncResp) { -+ BMCWEB_LOG_DEBUG << "doPatch..."; -+ -+ std::optional pushUriOptions; +@@ -585,12 +727,60 @@ inline void requestRoutesUpdateService(App& app) + BMCWEB_LOG_DEBUG << "doPatch..."; + + std::optional pushUriOptions; + std::optional> imgTargets; + std::optional imgTargetBusy; + std::optional oemProps; -+ if (!json_util::readJson(req, asyncResp->res, "HttpPushUriOptions", + if (!json_util::readJson(req, asyncResp->res, "HttpPushUriOptions", +- pushUriOptions)) + pushUriOptions, "HttpPushUriTargets", + imgTargets, "HttpPushUriTargetsBusy", + imgTargetBusy, "Oem", oemProps)) -+ { + { + BMCWEB_LOG_DEBUG + << "UpdateService doPatch: Invalid request body"; -+ return; -+ } -+ + return; + } + + if (oemProps) + { + std::optional applyOptions; @@ -406,10 +382,7 @@ index e420130..b3270f0 100644 + { + return; + } - -- std::optional pushUriOptions; -- if (!json_util::readJson(req, asyncResp->res, -- "HttpPushUriOptions", pushUriOptions)) ++ + if (clearConfig) + { + // Set the requested image apply time value @@ -432,82 +405,13 @@ index e420130..b3270f0 100644 + } + } + } -+ if (pushUriOptions) -+ { -+ std::optional pushUriApplyTime; -+ if (!json_util::readJson(*pushUriOptions, asyncResp->res, -+ "HttpPushUriApplyTime", -+ pushUriApplyTime)) - { - return; - } - -- if (pushUriOptions) -+ if (pushUriApplyTime) - { -- std::optional pushUriApplyTime; -- if (!json_util::readJson(*pushUriOptions, asyncResp->res, -- "HttpPushUriApplyTime", -- pushUriApplyTime)) -+ std::optional applyTime; -+ if (!json_util::readJson(*pushUriApplyTime, asyncResp->res, -+ "ApplyTime", applyTime)) - { - return; + if (pushUriOptions) + { + std::optional pushUriApplyTime; +@@ -653,6 +843,98 @@ inline void requestRoutesUpdateService(App& app) } - -- if (pushUriApplyTime) -+ if (applyTime) - { -- std::optional applyTime; -- if (!json_util::readJson(*pushUriApplyTime, -- asyncResp->res, "ApplyTime", -- applyTime)) -+ std::string applyTimeNewVal; -+ if (applyTime == "Immediate") - { -+ applyTimeNewVal = -+ "xyz.openbmc_project.Software.ApplyTime." -+ "RequestedApplyTimes.Immediate"; -+ } -+ else if (applyTime == "OnReset") -+ { -+ applyTimeNewVal = -+ "xyz.openbmc_project.Software.ApplyTime." -+ "RequestedApplyTimes.OnReset"; -+ } -+ else -+ { -+ BMCWEB_LOG_INFO -+ << "ApplyTime value is not in the list of " -+ "acceptable values"; -+ messages::propertyValueNotInList( -+ asyncResp->res, *applyTime, "ApplyTime"); - return; - } - -- if (applyTime) -+ // Set the requested image apply time value -+ crow::connections::systemBus->async_method_call( -+ [asyncResp](const boost::system::error_code ec) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR -+ << "D-Bus responses error: " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ messages::success(asyncResp->res); -+ }, -+ "xyz.openbmc_project.Settings", -+ "/xyz/openbmc_project/software/apply_time", -+ "org.freedesktop.DBus.Properties", "Set", -+ "xyz.openbmc_project.Software.ApplyTime", -+ "RequestedApplyTime", -+ std::variant{applyTimeNewVal}); -+ } -+ } -+ } + } + } + if (imgTargetBusy) + { + if ((httpPushUriTargetBusy) && (*imgTargetBusy)) @@ -539,29 +443,7 @@ index e420130..b3270f0 100644 + // single image in future. For now, consider first + // target alone. + if ((*imgTargets).size() != 1) - { -- std::string applyTimeNewVal; -- if (applyTime == "Immediate") -- { -- applyTimeNewVal = -- "xyz.openbmc_project.Software.ApplyTime." -- "RequestedApplyTimes.Immediate"; -- } -- else if (applyTime == "OnReset") -- { -- applyTimeNewVal = -- "xyz.openbmc_project.Software.ApplyTime." -- "RequestedApplyTimes.OnReset"; -- } -- else -- { -- BMCWEB_LOG_INFO -- << "ApplyTime value is not in the list of " -- "acceptable values"; -- messages::propertyValueNotInList( -- asyncResp->res, *applyTime, "ApplyTime"); -- return; -- } ++ { + messages::invalidObject(asyncResp->res, + "HttpPushUriTargets"); + return; @@ -575,35 +457,19 @@ index e420130..b3270f0 100644 + { + return; + } - -- // Set the requested image apply time value -- crow::connections::systemBus->async_method_call( -- [asyncResp]( -- const boost::system::error_code ec) { -- if (ec) ++ + bool swInvObjFound = false; + for (const std::string& path : swInvPaths) + { + std::size_t idPos = path.rfind("/"); + if ((idPos == std::string::npos) || + ((idPos + 1) >= path.size())) - { -- BMCWEB_LOG_ERROR -- << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); ++ { ++ messages::internalError(asyncResp->res); + BMCWEB_LOG_DEBUG + << "Can't parse firmware ID!!"; - return; - } -- messages::success(asyncResp->res); -- }, -- "xyz.openbmc_project.Settings", -- "/xyz/openbmc_project/software/apply_time", -- "org.freedesktop.DBus.Properties", "Set", -- "xyz.openbmc_project.Software.ApplyTime", -- "RequestedApplyTime", -- std::variant{applyTimeNewVal}); -- } ++ return; ++ } + std::string swId = path.substr(idPos + 1); + + if (swId == uriTargets[0]) @@ -631,20 +497,17 @@ index e420130..b3270f0 100644 + { + httpPushUriTargetBusy = *imgTargetBusy; + httpPushUriTargets = *imgTargets; - } - } -- }); ++ } ++ } + else + { + httpPushUriTargetBusy = *imgTargetBusy; + } + } -+ }); -+ + }); BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/") .privileges(redfish::privileges::postUpdateService) - .methods(boost::beast::http::verb::post)( -@@ -672,7 +955,8 @@ inline void requestRoutesUpdateService(App& app) +@@ -663,7 +945,8 @@ inline void requestRoutesUpdateService(App& app) // Setup callback for when new software detected monitorForSoftwareAvailable(asyncResp, req, @@ -654,26 +517,17 @@ index e420130..b3270f0 100644 std::string filepath("/tmp/images/" + boost::uuids::to_string( -@@ -685,7 +969,7 @@ inline void requestRoutesUpdateService(App& app) - out.close(); - BMCWEB_LOG_DEBUG << "file upload complete!!"; - }); --} -+} // namespace redfish - - inline void requestRoutesSoftwareInventoryCollection(App& app) - { -@@ -748,8 +1032,7 @@ inline void requestRoutesSoftwareInventoryCollection(App& app) - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/software", static_cast(0), -- std::array{ -- "xyz.openbmc_project.Software.Version"}); -+ std::array{versionIntf}); - }); +@@ -739,8 +1022,7 @@ inline void requestRoutesSoftwareInventoryCollection(App& app) + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/software", static_cast(0), +- std::array{ +- "xyz.openbmc_project.Software.Version"}); ++ std::array{versionIntf}); + }); } /* Fill related item links (i.e. bmc, bios) in for inventory */ -@@ -913,7 +1196,7 @@ inline void requestRoutesSoftwareInventory(App& app) +@@ -908,7 +1190,7 @@ inline void requestRoutesSoftwareInventory(App& app) }, obj.second[0].first, obj.first, "org.freedesktop.DBus.Properties", "GetAll", @@ -682,7 +536,7 @@ index e420130..b3270f0 100644 } if (!found) { -@@ -937,8 +1220,7 @@ inline void requestRoutesSoftwareInventory(App& app) +@@ -932,8 +1214,7 @@ inline void requestRoutesSoftwareInventory(App& app) "/xyz/openbmc_project/object_mapper", "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", static_cast(0), @@ -693,10 +547,10 @@ index e420130..b3270f0 100644 } diff --git a/static/redfish/v1/$metadata/index.xml b/static/redfish/v1/$metadata/index.xml -index 66b6faf..f0919c9 100644 +index 445af04..de7dc77 100644 --- a/static/redfish/v1/$metadata/index.xml +++ b/static/redfish/v1/$metadata/index.xml -@@ -2444,6 +2444,9 @@ +@@ -2502,6 +2502,9 @@ diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-CoreCount-to-ProcessorSummary.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-CoreCount-to-ProcessorSummary.patch deleted file mode 100644 index edf4d219e..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-CoreCount-to-ProcessorSummary.patch +++ /dev/null @@ -1,288 +0,0 @@ -From f4f15a52610d1a199ddac948c8f849df05d86151 Mon Sep 17 00:00:00 2001 -From: Ali Ahmed -Date: Fri, 3 Sep 2021 02:33:43 -0500 -Subject: [PATCH] Add Model & CoreCount to ProcessorSummary - -In Redfish ComputerSystem schema, the ProcessorSummary parameter -lists summary information of the Processors on the system. This commit -adds the 'Model' and 'CoreCount' properties to ProcessorSummary. - -If the CPU Models are different, then the 'Model' field takes the first -entry in alphabetical order. - -Testing: -1. Redfish Validator Testing successfully passed. -2. Curl testing: - -curl -k -H "X-Auth-Token: $tok" https://$bmc/redfish/v1/Systems/system - -... - "ProcessorSummary": { - "CoreCount": 24, - "Count": 2, - "Model": "test_name", - "Status": { - "Health": "OK", - "HealthRollup": "OK", - "State": "Disabled" - } - }, -... - -Change-Id: I39cbf6ed35c35ce3a3551c9689237d5023775326 -Signed-off-by: Ali Ahmed -Signed-off-by: AppaRao Puli ---- - redfish-core/lib/systems.hpp | 229 ++++++++++++++++++++++------------- - 1 file changed, 147 insertions(+), 82 deletions(-) - -diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp -index 680a0ee..3b5f9e4 100644 ---- a/redfish-core/lib/systems.hpp -+++ b/redfish-core/lib/systems.hpp -@@ -139,6 +139,152 @@ inline void - } - } - -+inline void getProcessorProperties( -+ const std::shared_ptr& aResp, const std::string& service, -+ const std::string& path, -+ const std::vector>>& -+ properties) -+{ -+ -+ BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties."; -+ -+ auto getCpuPresenceState = -+ [aResp](const boost::system::error_code ec3, -+ const std::variant& cpuPresenceCheck) { -+ if (ec3) -+ { -+ BMCWEB_LOG_ERROR << "DBUS response error " << ec3; -+ return; -+ } -+ modifyCpuPresenceState(aResp, cpuPresenceCheck); -+ }; -+ -+ auto getCpuFunctionalState = -+ [aResp](const boost::system::error_code ec3, -+ const std::variant& cpuFunctionalCheck) { -+ if (ec3) -+ { -+ BMCWEB_LOG_ERROR << "DBUS response error " << ec3; -+ return; -+ } -+ modifyCpuFunctionalState(aResp, cpuFunctionalCheck); -+ }; -+ -+ // Get the Presence of CPU -+ crow::connections::systemBus->async_method_call( -+ std::move(getCpuPresenceState), service, path, -+ "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.Inventory.Item", "Present"); -+ -+ // Get the Functional State -+ crow::connections::systemBus->async_method_call( -+ std::move(getCpuFunctionalState), service, path, -+ "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional"); -+ -+ for (const auto& property : properties) -+ { -+ if (property.first == "Family") -+ { -+ // Get the CPU Model -+ const std::string* modelStr = -+ std::get_if(&property.second); -+ if (!modelStr) -+ { -+ BMCWEB_LOG_DEBUG << "Failed to get CPU Family"; -+ // Skip it and continue with other properties -+ continue; -+ } -+ if ((*modelStr).size() < 1) -+ { -+ BMCWEB_LOG_DEBUG << "Empty CPU Family info, skipping..."; -+ continue; -+ } -+ nlohmann::json& prevModel = -+ aResp->res.jsonValue["ProcessorSummary"]["Model"]; -+ std::string* prevModelPtr = prevModel.get_ptr(); -+ -+ // If CPU Models are different, use the first entry in -+ // alphabetical order -+ -+ // If Model has never been set -+ // before, set it to *modelStr -+ if (prevModelPtr == nullptr) -+ { -+ prevModel = *modelStr; -+ } -+ // If Model has been set before, only change if new Model is -+ // higher in alphabetical order -+ else -+ { -+ if (*modelStr < *prevModelPtr) -+ { -+ prevModel = *modelStr; -+ } -+ } -+ } -+ else if (property.first == "CoreCount") -+ { -+ // Get CPU CoreCount and add it to the total -+ const uint16_t* coreCountVal = -+ std::get_if(&property.second); -+ -+ if (!coreCountVal) -+ { -+ BMCWEB_LOG_DEBUG << "Failed to get CPU Core count"; -+ // Skip it and continue with other properties -+ continue; -+ } -+ -+ nlohmann::json& coreCount = -+ aResp->res.jsonValue["ProcessorSummary"]["CoreCount"]; -+ uint64_t* coreCountPtr = coreCount.get_ptr(); -+ -+ if (coreCountPtr == nullptr) -+ { -+ coreCount = *coreCountVal; -+ } -+ else -+ { -+ *coreCountPtr += *coreCountVal; -+ } -+ } -+ } -+} -+ -+/* -+ * @brief Get ProcessorSummary fields -+ * -+ * @param[in] aResp Shared pointer for completing asynchronous calls -+ * @param[in] service dbus service for Cpu Information -+ * @param[in] path dbus path for Cpu -+ * -+ * @return None. -+ */ -+inline void getProcessorSummary(const std::shared_ptr& aResp, -+ const std::string& service, -+ const std::string& path) -+{ -+ -+ crow::connections::systemBus->async_method_call( -+ [aResp, service, -+ path](const boost::system::error_code ec2, -+ const std::vector>>& properties) { -+ if (ec2) -+ { -+ BMCWEB_LOG_ERROR << "DBUS response error " << ec2; -+ messages::internalError(aResp->res); -+ return; -+ } -+ getProcessorProperties(aResp, service, path, properties); -+ }, -+ service, path, "org.freedesktop.DBus.Properties", "GetAll", -+ "xyz.openbmc_project.Inventory.Item.Cpu"); -+} -+ - /* - * @brief Retrieves computer system properties over dbus - * -@@ -309,88 +455,7 @@ inline void - BMCWEB_LOG_DEBUG - << "Found Cpu, now get its properties."; - -- crow::connections::systemBus->async_method_call( -- [aResp, service{connection.first}, -- path](const boost::system::error_code ec2, -- const std::vector< -- std::pair>& -- properties) { -- if (ec2) -- { -- BMCWEB_LOG_ERROR -- << "DBUS response error " << ec2; -- messages::internalError(aResp->res); -- return; -- } -- BMCWEB_LOG_DEBUG << "Got " -- << properties.size() -- << " Cpu properties."; -- -- auto getCpuPresenceState = -- [aResp]( -- const boost::system::error_code ec3, -- const std::variant& -- cpuPresenceCheck) { -- if (ec3) -- { -- BMCWEB_LOG_ERROR -- << "DBUS response error " -- << ec3; -- return; -- } -- modifyCpuPresenceState( -- aResp, cpuPresenceCheck); -- }; -- -- auto getCpuFunctionalState = -- [aResp]( -- const boost::system::error_code ec3, -- const std::variant& -- cpuFunctionalCheck) { -- if (ec3) -- { -- BMCWEB_LOG_ERROR -- << "DBUS response error " -- << ec3; -- return; -- } -- modifyCpuFunctionalState( -- aResp, cpuFunctionalCheck); -- }; -- -- // Get the Presence of CPU -- crow::connections::systemBus -- ->async_method_call( -- std::move(getCpuPresenceState), -- service, path, -- "org.freedesktop.DBus." -- "Properties", -- "Get", -- "xyz.openbmc_project.Inventory." -- "Item", -- "Present"); -- -- // Get the Functional State -- crow::connections::systemBus -- ->async_method_call( -- std::move(getCpuFunctionalState), -- service, path, -- "org.freedesktop.DBus." -- "Properties", -- "Get", -- "xyz.openbmc_project.State." -- "Decorator." -- "OperationalStatus", -- "Functional"); -- -- // Get the MODEL from -- // xyz.openbmc_project.Inventory.Decorator.Asset -- // support it later as Model is Empty -- // currently. -- }, -- connection.first, path, -- "org.freedesktop.DBus.Properties", "GetAll", -- "xyz.openbmc_project.Inventory.Item.Cpu"); -+ getProcessorSummary(aResp, connection.first, path); - - cpuHealth->inventory.emplace_back(path); - } --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-to-ProcessorSummary.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-to-ProcessorSummary.patch new file mode 100644 index 000000000..92654bee1 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Add-Model-to-ProcessorSummary.patch @@ -0,0 +1,108 @@ +From 1b34b289eacc2ebb9c343680a3696dda4abe4a37 Mon Sep 17 00:00:00 2001 +From: Ali Ahmed +Date: Fri, 3 Sep 2021 02:33:43 -0500 +Subject: [PATCH] Add Model to ProcessorSummary + +In Redfish ComputerSystem schema, the ProcessorSummary parameter +lists summary information of the Processors on the system. This commit +adds the 'Model' property to ProcessorSummary. + +If the CPU Models are different, then the 'Model' field takes the first +entry in alphabetical order. + +Testing: +1. Redfish Validator Testing successfully passed. +2. Curl testing: + +curl -k -H "X-Auth-Token: $tok" https://$bmc/redfish/v1/Systems/system + +... + "ProcessorSummary": { + "CoreCount": 24, + "Count": 2, + "Model": "test_name", + "Status": { + "Health": "OK", + "HealthRollup": "OK", + "State": "Disabled" + } + }, +... + +Change-Id: I39cbf6ed35c35ce3a3551c9689237d5023775326 +Signed-off-by: Ali Ahmed +Signed-off-by: AppaRao Puli +--- + redfish-core/lib/systems.hpp | 47 +++++++++++++++++++++++++++++++----- + 1 file changed, 41 insertions(+), 6 deletions(-) + +diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp +index 2f88a777..8406bd4d 100644 +--- a/redfish-core/lib/systems.hpp ++++ b/redfish-core/lib/systems.hpp +@@ -185,21 +185,56 @@ inline void getProcessorProperties( + + for (const auto& property : properties) + { ++ if (property.first == "Family") ++ { ++ // Get the CPU Model ++ const std::string* modelStr = ++ std::get_if(&property.second); ++ if (!modelStr) ++ { ++ BMCWEB_LOG_DEBUG << "Failed to get CPU Family"; ++ // Skip it and continue with other properties ++ continue; ++ } ++ if ((*modelStr).size() < 1) ++ { ++ BMCWEB_LOG_DEBUG << "Empty CPU Family info, skipping..."; ++ continue; ++ } ++ nlohmann::json& prevModel = ++ aResp->res.jsonValue["ProcessorSummary"]["Model"]; ++ std::string* prevModelPtr = prevModel.get_ptr(); + +- // TODO: Get Model ++ // If CPU Models are different, use the first entry in ++ // alphabetical order + +- // Get CoreCount +- if (property.first == "CoreCount") ++ // If Model has never been set ++ // before, set it to *modelStr ++ if (prevModelPtr == nullptr) ++ { ++ prevModel = *modelStr; ++ } ++ // If Model has been set before, only change if new Model is ++ // higher in alphabetical order ++ else ++ { ++ if (*modelStr < *prevModelPtr) ++ { ++ prevModel = *modelStr; ++ } ++ } ++ } ++ else if (property.first == "CoreCount") + { +- + // Get CPU CoreCount and add it to the total + const uint16_t* coreCountVal = + std::get_if(&property.second); + + if (!coreCountVal) + { +- messages::internalError(aResp->res); +- return; ++ BMCWEB_LOG_DEBUG << "Failed to get CPU Core count"; ++ // Skip it and continue with other properties ++ continue; + } + + nlohmann::json& coreCount = +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0026-Revert-Delete-the-copy-constructor-on-the-Request.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0026-Revert-Delete-the-copy-constructor-on-the-Request.patch new file mode 100644 index 000000000..9f21b8475 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0026-Revert-Delete-the-copy-constructor-on-the-Request.patch @@ -0,0 +1,30 @@ +From d9488db9785b599d2c1e3a9d9fe1d2b5fa953865 Mon Sep 17 00:00:00 2001 +From: P Dheeraj Srujan Kumar +Date: Tue, 4 Jan 2022 06:49:58 +0530 +Subject: [PATCH] Revert "Delete the copy constructor on the Request object" + +This commit is reverted to resolve build issues due arising due +to removal of the copy constructor. + +This reverts commit 597d2b142362bafa90f24fc8c30750afab91f78f. +--- + http/http_request.hpp | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/http/http_request.hpp b/http/http_request.hpp +index 4567314..be84f18 100644 +--- a/http/http_request.hpp ++++ b/http/http_request.hpp +@@ -45,9 +45,6 @@ struct Request + } + } + +- Request(const Request&) = delete; +- Request& operator=(const Request&) = delete; +- + boost::beast::http::verb method() const + { + return req.method(); +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0027-Convert-VariantType-to-DbusVariantType.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0027-Convert-VariantType-to-DbusVariantType.patch new file mode 100644 index 000000000..f9bb69826 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0027-Convert-VariantType-to-DbusVariantType.patch @@ -0,0 +1,50 @@ +From 8e78ffc54b2a5444e96cdcc1440928b04e21c2a5 Mon Sep 17 00:00:00 2001 +From: AppaRao Puli +Date: Thu, 6 Jan 2022 01:37:08 +0000 +Subject: [PATCH] Convert VariantType to DbusVariantType + +All bmcweb code is now converted to use +DbusVariantType to reduce the image size. + +Its missed in one place where the code is under compiler +flag BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE. This commit +convert missed types to DbusVariantType. + +Tested: +After conversion, image builds fine with compiler +flag enabled. Also tested the PFR provisioned +dbus calls and it works fine. + +Signed-off-by: AppaRao Puli +--- + redfish-core/lib/systems.hpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp +index 5fbd568..e9ae7ca 100644 +--- a/redfish-core/lib/systems.hpp ++++ b/redfish-core/lib/systems.hpp +@@ -1840,7 +1840,8 @@ inline void getProvisioningStatus(std::shared_ptr aResp) + BMCWEB_LOG_DEBUG << "Get OEM information."; + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec, +- const std::vector>& ++ const std::vector< ++ std::pair>& + propertiesList) { + nlohmann::json& oemPFR = + aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"]; +@@ -1858,8 +1859,8 @@ inline void getProvisioningStatus(std::shared_ptr aResp) + + const bool* provState = nullptr; + const bool* lockState = nullptr; +- for (const std::pair& property : +- propertiesList) ++ for (const std::pair& ++ property : propertiesList) + { + if (property.first == "UfmProvisioned") + { +-- +2.17.1 + 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 index 2e72a639d..85b5b3494 100644 --- 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 @@ -1,6 +1,6 @@ -From f75beb0472a42d5af512661470aadf12ac460470 Mon Sep 17 00:00:00 2001 +From 8225b2dc07279c65cdfe2ddc13964d84fd2ed8bb Mon Sep 17 00:00:00 2001 From: Arun Lal K M -Date: Fri, 8 Oct 2021 21:30:33 +0000 +Date: Tue, 4 Jan 2022 01:56:57 +0000 Subject: [PATCH] Add fix for broken feature 'Pending Attributes'. Fix is added for the following: @@ -10,6 +10,7 @@ Fix is added for the following: 4) Fix for incremental duplicate values in BiosAttributeRegistry. 5) POST to '/redfish/v1/Systems/system/Bios/Actions /Bios.ChangePassword/'. +6) Add support for Enumeration. Tested: By giving PATCH to 'redfish/v1/Systems/system/Bios/Settings' @@ -133,11 +134,11 @@ Validation has succeeded. Signed-off-by: Arun Lal K M Signed-off-by: Snehalatha Venkatesh --- - redfish-core/lib/bios.hpp | 586 ++++++++++++++++++++++++-------------- - 1 file changed, 376 insertions(+), 210 deletions(-) + redfish-core/lib/bios.hpp | 592 ++++++++++++++++++++++++-------------- + 1 file changed, 383 insertions(+), 209 deletions(-) diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp -index 0bb0b9e..de79be2 100644 +index 0bb0b9e..69340eb 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp @@ -12,13 +12,15 @@ map{attributeName,struct{attributeType,readonlyStatus,displayname, @@ -191,7 +192,7 @@ index 0bb0b9e..de79be2 100644 enum PendingAttributesIndex { pendingAttrType = 0, -@@ -64,31 +63,16 @@ enum PendingAttributesIndex +@@ -64,30 +63,20 @@ enum PendingAttributesIndex static std::string mapAttrTypeToRedfish(const std::string_view typeDbus) { std::string ret; @@ -217,15 +218,16 @@ index 0bb0b9e..de79be2 100644 { ret = "Integer"; } -- else if (typeDbus == "xyz.openbmc_project.BIOSConfig." + else if (typeDbus == "xyz.openbmc_project.BIOSConfig." - "Manager.AttributeType.Boolean") -- { ++ "Manager.AttributeType.Enumeration") + { - ret = "Boolean"; -- } ++ ret = "Enumeration"; + } else { - ret = "UNKNOWN"; -@@ -96,29 +80,7 @@ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus) +@@ -96,29 +85,7 @@ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus) return ret; } @@ -255,7 +257,7 @@ index 0bb0b9e..de79be2 100644 static std::string mapBoundTypeToRedfish(const std::string_view typeDbus) { std::string ret; -@@ -201,6 +163,15 @@ inline void +@@ -201,6 +168,15 @@ inline void return; } @@ -271,7 +273,7 @@ index 0bb0b9e..de79be2 100644 const std::string& service = getObjectType.begin()->first; crow::connections::systemBus->async_method_call( -@@ -220,7 +191,7 @@ inline void +@@ -220,7 +196,7 @@ inline void asyncResp->res.jsonValue["Attributes"]; if (baseBiosTable == nullptr) { @@ -280,7 +282,16 @@ index 0bb0b9e..de79be2 100644 messages::internalError(asyncResp->res); return; } -@@ -248,7 +219,6 @@ inline void +@@ -230,7 +206,7 @@ inline void + const std::string& itemType = + std::get(item.second); + std::string attrType = mapAttrTypeToRedfish(itemType); +- if (attrType == "String") ++ if (attrType == "String" || attrType == "Enumeration") + { + const std::string* currValue = + std::get_if( +@@ -248,7 +224,6 @@ inline void else { BMCWEB_LOG_ERROR << "Unsupported attribute type."; @@ -288,7 +299,7 @@ index 0bb0b9e..de79be2 100644 } } }, -@@ -275,8 +245,9 @@ inline void requestRoutesBiosService(App& app) +@@ -275,8 +250,9 @@ inline void requestRoutesBiosService(App& app) */ inline void requestRoutesBiosChangePassword(App& app) { @@ -300,7 +311,7 @@ index 0bb0b9e..de79be2 100644 .methods(boost::beast::http::verb::post)( [](const crow::Request& req, const std::shared_ptr& asyncResp) { -@@ -342,180 +313,298 @@ inline void requestRoutesBiosSettings(App& app) +@@ -342,180 +318,300 @@ inline void requestRoutesBiosSettings(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings") .privileges(redfish::privileges::getBios) @@ -429,7 +440,8 @@ index 0bb0b9e..de79be2 100644 + std::string itemType = + mapAttrTypeToRedfish(biosAttrType); + -+ if (itemType == "String") ++ if (itemType == "String" || ++ itemType == "Enumeration") { - const std::string& key = item.first; - const std::string& itemType = @@ -625,9 +637,9 @@ index 0bb0b9e..de79be2 100644 BMCWEB_LOG_ERROR - << "doPatch resp_handler got error " << ec; + << "getBiosAttributes DBUS error: " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } + messages::internalError(asyncResp->res); + return; + } + + const BiosBaseTableType* baseBiosTable = + std::get_if(&retBiosTable); @@ -635,9 +647,9 @@ index 0bb0b9e..de79be2 100644 + if (baseBiosTable == nullptr) + { + BMCWEB_LOG_ERROR << "baseBiosTable is empty."; - messages::internalError(asyncResp->res); - return; - } ++ messages::internalError(asyncResp->res); ++ return; ++ } + + PendingAttributesType pendingAttributes{}; + @@ -665,7 +677,8 @@ index 0bb0b9e..de79be2 100644 + std::string attrType = + mapAttrTypeToRedfish(itemType); + -+ if (attrType == "String") ++ if (attrType == "String" || ++ attrType == "Enumeration") + { + std::string val = attributes.value(); + @@ -741,7 +754,7 @@ index 0bb0b9e..de79be2 100644 } /** * BiosAttributeRegistry class supports handle get method for BIOS attribute -@@ -555,6 +644,15 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -555,6 +651,15 @@ inline void requestRoutesBiosAttributeRegistry(App& app) return; } @@ -757,7 +770,7 @@ index 0bb0b9e..de79be2 100644 std::string service = getObjectType.begin()->first; crow::connections::systemBus->async_method_call( -@@ -575,8 +673,6 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -575,8 +680,6 @@ inline void requestRoutesBiosAttributeRegistry(App& app) nlohmann::json& attributeArray = asyncResp->res .jsonValue["RegistryEntries"]["Attributes"]; @@ -766,7 +779,7 @@ index 0bb0b9e..de79be2 100644 if (baseBiosTable == nullptr) { BMCWEB_LOG_ERROR << "baseBiosTable == nullptr "; -@@ -592,10 +688,11 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -592,10 +695,11 @@ inline void requestRoutesBiosAttributeRegistry(App& app) mapAttrTypeToRedfish(itemType); if (attrType == "UNKNOWN") { @@ -781,7 +794,15 @@ index 0bb0b9e..de79be2 100644 nlohmann::json attributeItem; attributeItem["AttributeName"] = item.first; attributeItem["Type"] = attrType; -@@ -615,10 +712,30 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -609,16 +713,37 @@ inline void requestRoutesBiosAttributeRegistry(App& app) + attributeItem["MenuPath"] = + std::get(item.second); + +- if (attrType == "String") ++ if (attrType == "String" || ++ attrType == "Enumeration") + { + const std::string* currValue = std::get_if( &std::get( item.second)); @@ -812,7 +833,7 @@ index 0bb0b9e..de79be2 100644 attributeItem["CurrentValue"] = currValue != nullptr ? *currValue : ""; attributeItem["DefaultValue"] = -@@ -630,10 +747,30 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -630,10 +755,30 @@ inline void requestRoutesBiosAttributeRegistry(App& app) std::get_if( &std::get( item.second)); @@ -843,7 +864,7 @@ index 0bb0b9e..de79be2 100644 attributeItem["CurrentValue"] = currValue != nullptr ? *currValue : 0; attributeItem["DefaultValue"] = -@@ -641,12 +778,13 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -641,12 +786,13 @@ inline void requestRoutesBiosAttributeRegistry(App& app) } else { @@ -861,7 +882,7 @@ index 0bb0b9e..de79be2 100644 const std::vector& optionsVector = std::get(item.second); -@@ -661,9 +799,9 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -661,9 +807,9 @@ inline void requestRoutesBiosAttributeRegistry(App& app) if (optItemTypeRedfish == "UNKNOWN") { BMCWEB_LOG_ERROR @@ -874,7 +895,7 @@ index 0bb0b9e..de79be2 100644 } if (optItemTypeRedfish == "OneOf") { -@@ -671,6 +809,17 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -671,6 +817,17 @@ inline void requestRoutesBiosAttributeRegistry(App& app) std::get_if( &std::get( optItem)); @@ -892,7 +913,7 @@ index 0bb0b9e..de79be2 100644 optItemJson[optItemTypeRedfish] = currValue != nullptr ? *currValue : ""; -@@ -681,6 +830,17 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -681,6 +838,17 @@ inline void requestRoutesBiosAttributeRegistry(App& app) std::get_if( &std::get( optItem)); @@ -910,7 +931,7 @@ index 0bb0b9e..de79be2 100644 optItemJson[optItemTypeRedfish] = currValue != nullptr ? *currValue : 0; -@@ -689,6 +849,12 @@ inline void requestRoutesBiosAttributeRegistry(App& app) +@@ -689,6 +857,12 @@ inline void requestRoutesBiosAttributeRegistry(App& app) optionsArray.push_back(optItemJson); } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch new file mode 100644 index 000000000..5e05e8f3a --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch @@ -0,0 +1,76 @@ +From cf2e892bdd85b8fe1ccaf1296e02d8589aef05c1 Mon Sep 17 00:00:00 2001 +From: Snehalatha Venkatesh +Date: Tue, 28 Dec 2021 11:05:50 +0000 +Subject: [PATCH] Add BiosAttributeRegistry node under Registries. + +/redfish/v1/Registries/ is missing node BiosAttributeRegistry +under it. Added code to fix the same. + +Tested: +1.Ran Redfish Validator and passed. +2.GET - /redfish/v1/Registries/ + +Response: +{ +"@odata.id": "/redfish/v1/Registries", +"@odata.type": "#MessageRegistryFileCollection.MessageRegistryFileCollection", +"Description": "Collection of MessageRegistryFiles", +"Members": [ +{ +"@odata.id": "/redfish/v1/Registries/Base" +}, +{ +"@odata.id": "/redfish/v1/Registries/TaskEvent" +}, +{ +"@odata.id": "/redfish/v1/Registries/ResourceEvent" +}, +{ +"@odata.id": "/redfish/v1/Registries/BiosAttributeRegistry" +}, +{ +"@odata.id": "/redfish/v1/Registries/OpenBMC" +} +], +"Members@odata.count": 5, +"Name": "MessageRegistryFile Collection" +} + +Signed-off-by: Snehalatha Venkatesh +--- + redfish-core/lib/message_registries.hpp | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/redfish-core/lib/message_registries.hpp b/redfish-core/lib/message_registries.hpp +index 510b19a..0467f1e 100644 +--- a/redfish-core/lib/message_registries.hpp ++++ b/redfish-core/lib/message_registries.hpp +@@ -40,11 +40,12 @@ inline void handleMessageRegistryFileCollectionGet( + {"@odata.id", "/redfish/v1/Registries"}, + {"Name", "MessageRegistryFile Collection"}, + {"Description", "Collection of MessageRegistryFiles"}, +- {"Members@odata.count", 4}, ++ {"Members@odata.count", 5}, + {"Members", + {{{"@odata.id", "/redfish/v1/Registries/Base"}}, + {{"@odata.id", "/redfish/v1/Registries/TaskEvent"}}, + {{"@odata.id", "/redfish/v1/Registries/ResourceEvent"}}, ++ {{"@odata.id", "/redfish/v1/Registries/BiosAttributeRegistry"}}, + {{"@odata.id", "/redfish/v1/Registries/OpenBMC"}}}}}; + } + +@@ -87,6 +88,11 @@ inline void handleMessageRoutesMessageRegistryFileGet( + header = &message_registries::resource_event::header; + url = message_registries::resource_event::url; + } ++ else if (registry == "BiosAttributeRegistry") ++ { ++ header = &message_registries::bios::header; ++ dmtf.clear(); ++ } + else + { + messages::resourceNotFound( +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch index 52135e255..7229f9aa7 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-Add-unmerged-changes-for-http-retry-support.patch @@ -1,6 +1,6 @@ -From 6ff897d2b5513f15445f18aae16d8439ed94f377 Mon Sep 17 00:00:00 2001 +From 43b629c180e1b4350a9e9bd917d81a49acb57731 Mon Sep 17 00:00:00 2001 From: P Dheeraj Srujan Kumar -Date: Mon, 11 Oct 2021 18:41:27 +0530 +Date: Mon, 6 Dec 2021 19:49:01 +0000 Subject: [PATCH] Add unmerged changes for http retry support The http retry support added upstream as a single patch was slpit into @@ -9,45 +9,19 @@ This commit pulls in the differentail changes required to complete the entire http retry support. and also allow for other subsequent patches to be appplied easily. -Change-Id: Id8ccd991b7ffc505196b1a92b23e1cd51e00bc89 +Change-Id: I43e68eeffb8d69c289dd306c1c7cafc87ad766a0 Signed-off-by: P Dheeraj Srujan Kumar --- - http/http_client.hpp | 44 +++++++++++-------- - .../include/event_service_manager.hpp | 2 +- - 2 files changed, 27 insertions(+), 19 deletions(-) + http/http_client.hpp | 32 ++++++++++++++++--- + .../include/event_service_manager.hpp | 26 +++++++++------ + redfish-core/lib/event_service.hpp | 1 + + 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/http/http_client.hpp b/http/http_client.hpp -index ab20eb0..aad1cce 100644 +index 0c9e387..0701d9e 100644 --- a/http/http_client.hpp +++ b/http/http_client.hpp -@@ -68,7 +68,6 @@ class HttpClient : public std::enable_shared_from_this - std::optional< - boost::beast::http::response_parser> - parser; -- std::vector> headers; - boost::circular_buffer_space_optimized requestDataQueue{}; - - ConnState state; -@@ -137,18 +136,6 @@ class HttpClient : public std::enable_shared_from_this - - BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port; - -- req.version(static_cast(11)); // HTTP 1.1 -- req.target(uri); -- req.method(boost::beast::http::verb::post); -- -- // Set headers -- for (const auto& [key, value] : headers) -- { -- req.set(key, value); -- } -- req.set(boost::beast::http::field::host, host); -- req.keep_alive(true); -- - req.body() = data; - req.prepare_payload(); - -@@ -204,6 +191,17 @@ class HttpClient : public std::enable_shared_from_this +@@ -189,6 +189,17 @@ class HttpClient : public std::enable_shared_from_this BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->parser->get(); @@ -65,57 +39,125 @@ index ab20eb0..aad1cce 100644 unsigned int respCode = self->parser->get().result_int(); BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: " << respCode; -@@ -398,11 +396,17 @@ class HttpClient : public std::enable_shared_from_this +@@ -381,15 +392,17 @@ class HttpClient : public std::enable_shared_from_this + public: + explicit HttpClient(boost::asio::io_context& ioc, const std::string& id, const std::string& destIP, const std::string& destPort, - const std::string& destUri) : +- const std::string& destUri, +- const boost::beast::http::fields& httpHeader) : ++ const std::string& destUri) : conn(ioc), -- timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri), -- retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0), -+ timer(ioc), req(boost::beast::http::verb::post, destUri, 11), -+ state(ConnState::initialized), subId(id), host(destIP), port(destPort), -+ uri(destUri), retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0), - retryPolicyAction("TerminateAfterRetries"), runningTimer(false) +- timer(ioc), +- req(boost::beast::http::verb::post, destUri, 11, "", httpHeader), +- subId(id), host(destIP), port(destPort) ++ timer(ioc), req(boost::beast::http::verb::post, destUri, 11), subId(id), ++ host(destIP), port(destPort) { -- state = ConnState::initialized; + // Set the request header -+ req.set(boost::beast::http::field::host, host); + req.set(boost::beast::http::field::host, host); + req.set(boost::beast::http::field::content_type, "application/json"); -+ req.keep_alive(true); + req.keep_alive(true); + + requestDataQueue.set_capacity(maxRequestQueueSize); } void sendData(const std::string& data) -@@ -425,10 +429,14 @@ class HttpClient : public std::enable_shared_from_this +@@ -412,6 +425,15 @@ class HttpClient : public std::enable_shared_from_this return; } -- void setHeaders( -+ void addHeaders( - const std::vector>& httpHeaders) - { -- headers = httpHeaders; ++ void setHeaders(const boost::beast::http::fields& httpHeaders) ++ { + // Set custom headers -+ for (const auto& [key, value] : httpHeaders) ++ for (const auto& header : httpHeaders) + { -+ req.set(key, value); ++ req.set(header.name(), header.value()); + } - } - ++ } ++ void setRetryConfig(const uint32_t retryAttempts, + const uint32_t retryTimeoutInterval) + { diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 8042803..0a63b8c 100644 +index e0f290c..7a2f096 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -412,7 +412,7 @@ class Subscription : public persistent_data::UserSubscription - reqHeaders.emplace_back(std::pair(key, val)); - } - } -- conn->setHeaders(reqHeaders); -+ conn->addHeaders(reqHeaders); - conn->sendData(msg); - this->eventSeqNum++; +@@ -384,7 +384,10 @@ class Subscription : public persistent_data::UserSubscription + eventSeqNum(1), + host(inHost), port(inPort), path(inPath), uriProto(inUriProto) + { +- // Subscription constructor ++ // create the HttpClient connection ++ conn = std::make_shared( ++ crow::connections::systemBus->get_io_context(), id, host, port, ++ path); + } + + Subscription(const std::shared_ptr& adaptor) : +@@ -397,17 +400,12 @@ class Subscription : public persistent_data::UserSubscription + + void sendEvent(const std::string& msg) + { +- if (conn == nullptr) ++ if (conn != nullptr) + { +- // create the HttpClient connection +- conn = std::make_shared( +- crow::connections::systemBus->get_io_context(), id, host, port, +- path, httpHeaders); ++ conn->sendData(msg); ++ eventSeqNum++; } + +- conn->sendData(msg); +- eventSeqNum++; +- + if (sseConn != nullptr) + { + sseConn->sendData(eventSeqNum, msg); +@@ -551,6 +549,14 @@ class Subscription : public persistent_data::UserSubscription + } + } + ++ void updatehttpHeaders() ++ { ++ if (conn != nullptr) ++ { ++ conn->setHeaders(httpHeaders); ++ } ++ } ++ + uint64_t getEventSeqNum() + { + return eventSeqNum; +@@ -664,6 +670,7 @@ class EventServiceManager + // Update retry configuration. + subValue->updateRetryConfig(retryAttempts, retryTimeoutInterval); + subValue->updateRetryPolicy(); ++ subValue->updatehttpHeaders(); + } + return; + } +@@ -919,6 +926,7 @@ class EventServiceManager + // Update retry configuration. + subValue->updateRetryConfig(retryAttempts, retryTimeoutInterval); + subValue->updateRetryPolicy(); ++ subValue->updatehttpHeaders(); + + return id; + } +diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp +index d273aea..7739ad0 100644 +--- a/redfish-core/lib/event_service.hpp ++++ b/redfish-core/lib/event_service.hpp +@@ -611,6 +611,7 @@ inline void requestRoutesEventDestination(App& app) + } + } + subValue->httpHeaders = fields; ++ subValue->updatehttpHeaders(); + } + + if (retryPolicy) -- 2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch index aeeafc421..2125fcc52 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch @@ -1,6 +1,6 @@ -From 3f2ad28e6e124249cde3df50c9e18c283fbcbf3e Mon Sep 17 00:00:00 2001 +From b5e0024f33afc95751afe14e66c38bf9802645f6 Mon Sep 17 00:00:00 2001 From: AppaRao Puli -Date: Mon, 22 Feb 2021 17:07:47 +0000 +Date: Mon, 6 Dec 2021 21:39:05 +0000 Subject: [PATCH] EventService: https client support Add https client support for push style eventing. Using this BMC can @@ -13,15 +13,16 @@ Tested: listener. - Validator passed. -Change-Id: I44c3918b39baa2eb5fddda9d635f99aa280a422a +Change-Id: I480085344ba7bed6ec0d94876eda1d252e51cb45 Signed-off-by: AppaRao Puli +Signed-off-by: P Dheeraj Srujan Kumar --- http/http_client.hpp | 307 ++++++++++++------ .../include/event_service_manager.hpp | 2 +- - 2 files changed, 202 insertions(+), 107 deletions(-) + 2 files changed, 204 insertions(+), 105 deletions(-) diff --git a/http/http_client.hpp b/http/http_client.hpp -index aad1cce..5e7ff47 100644 +index d3d3491..58b5402 100644 --- a/http/http_client.hpp +++ b/http/http_client.hpp @@ -20,6 +20,7 @@ @@ -30,9 +31,9 @@ index aad1cce..5e7ff47 100644 #include +#include #include + #include #include - -@@ -43,6 +44,8 @@ enum class ConnState +@@ -44,6 +45,8 @@ enum class ConnState resolveFailed, connectInProgress, connectFailed, @@ -41,7 +42,7 @@ index aad1cce..5e7ff47 100644 connected, sendInProgress, sendFailed, -@@ -61,7 +64,9 @@ class HttpClient : public std::enable_shared_from_this +@@ -62,7 +65,9 @@ class HttpClient : public std::enable_shared_from_this { private: crow::async_resolve::Resolver resolver; @@ -51,7 +52,7 @@ index aad1cce..5e7ff47 100644 boost::asio::steady_timer timer; boost::beast::flat_static_buffer buffer; boost::beast::http::request req; -@@ -108,23 +113,52 @@ class HttpClient : public std::enable_shared_from_this +@@ -110,23 +115,52 @@ class HttpClient : public std::enable_shared_from_this const std::vector& endpointList) { state = ConnState::connectInProgress; @@ -112,15 +113,7 @@ index aad1cce..5e7ff47 100644 self->state = ConnState::connected; self->handleConnState(); }); -@@ -132,132 +166,187 @@ class HttpClient : public std::enable_shared_from_this - - void sendMessage(const std::string& data) - { -- state = ConnState::sendInProgress; -- - BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port; -+ state = ConnState::sendInProgress; - +@@ -139,124 +173,182 @@ class HttpClient : public std::enable_shared_from_this req.body() = data; req.prepare_payload(); @@ -173,23 +166,52 @@ index aad1cce..5e7ff47 100644 + boost::beast::http::async_write(conn, req, std::move(respHandler)); + } } -- + void recvMessage() { state = ConnState::recvInProgress; +- parser.emplace(std::piecewise_construct, std::make_tuple()); +- parser->body_limit(httpReadBodyLimit); + auto respHandler = [self(shared_from_this())]( + const boost::beast::error_code ec, + const std::size_t& bytesTransferred) { + if (ec && ec != boost::asio::ssl::error::stream_truncated) + { + BMCWEB_LOG_ERROR << "recvMessage() failed: " << ec.message(); -+ + +- // Receive the HTTP response +- boost::beast::http::async_read( +- conn, buffer, *parser, +- [self(shared_from_this())](const boost::beast::error_code& ec, +- const std::size_t& bytesTransferred) { +- if (ec) +- { +- BMCWEB_LOG_ERROR << "recvMessage() failed: " +- << ec.message(); +- self->state = ConnState::recvFailed; +- self->handleConnState(); +- return; +- } +- BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: " +- << bytesTransferred; +- BMCWEB_LOG_DEBUG << "recvMessage() data: " +- << self->parser->get(); + self->state = ConnState::recvFailed; + self->handleConnState(); + return; + } -+ + +- // Check if the response and header are received +- if (!self->parser->is_done()) +- { +- // The parser failed to receive the response +- BMCWEB_LOG_ERROR +- << "recvMessage() parser failed to receive response"; +- self->state = ConnState::recvFailed; +- self->handleConnState(); +- return; +- } + BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: " + << bytesTransferred; + boost::ignore_unused(bytesTransferred); @@ -204,11 +226,26 @@ index aad1cce..5e7ff47 100644 + self->handleConnState(); + return; + } -+ + +- unsigned int respCode = self->parser->get().result_int(); +- BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: " +- << respCode; + unsigned int respCode = self->parser->get().result_int(); + BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: " + << respCode; -+ + +- // 2XX response is considered to be successful +- if ((respCode < 200) || (respCode >= 300)) +- { +- // The listener failed to receive the Sent-Event +- BMCWEB_LOG_ERROR +- << "recvMessage() Listener Failed to " +- "receive Sent-Event. Header Response Code: " +- << respCode; +- self->state = ConnState::recvFailed; +- self->handleConnState(); +- return; +- } + // 2XX response is considered to be successful + if ((respCode < 200) || (respCode >= 300)) + { @@ -219,7 +256,14 @@ index aad1cce..5e7ff47 100644 + self->handleConnState(); + return; + } -+ + +- // Send is successful, Lets remove data from queue +- // check for next request data in queue. +- if (!self->requestDataQueue.empty()) +- { +- self->requestDataQueue.pop_front(); +- } +- self->state = ConnState::idle; + // Send is successful, Lets remove data from queue + // check for next request data in queue. + if (!self->requestDataQueue.empty()) @@ -236,17 +280,30 @@ index aad1cce..5e7ff47 100644 + // Abort the connection since server is not keep-alive enabled + self->state = ConnState::abortConnection; + } -+ + +- // Keep the connection alive if server supports it +- // Else close the connection +- BMCWEB_LOG_DEBUG << "recvMessage() keepalive : " +- << self->parser->keep_alive(); +- if (!self->parser->keep_alive()) +- { +- // Abort the connection since server is not keep-alive +- // enabled +- self->state = ConnState::abortConnection; +- } + // Returns ownership of the parsed message + self->parser->release(); -+ + +- self->handleConnState(); +- }); +- } + self->handleConnState(); + }; - parser.emplace(std::piecewise_construct, std::make_tuple()); - parser->body_limit(httpReadBodyLimit); ++ parser.emplace(std::piecewise_construct, std::make_tuple()); ++ parser->body_limit(httpReadBodyLimit); - // Check only for the response header - parser->skip(true); ++ // Check only for the response header ++ parser->skip(true); + conn.expires_after(std::chrono::seconds(30)); + if (sslConn) + { @@ -259,28 +316,25 @@ index aad1cce..5e7ff47 100644 + std::move(respHandler)); + } + } -+ void doClose() -+ { -+ state = ConnState::closeInProgress; + void doClose() + { + state = ConnState::closeInProgress; +- boost::beast::error_code ec; +- conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); +- conn.close(); -- // Receive the HTTP response -- boost::beast::http::async_read( -- conn, buffer, *parser, -- [self(shared_from_this())](const boost::beast::error_code& ec, -- const std::size_t& bytesTransferred) { +- // not_connected happens sometimes so don't bother reporting it. +- if (ec && ec != boost::beast::errc::not_connected) + // Set the timeout on the tcp stream socket for the async operation + conn.expires_after(std::chrono::seconds(30)); + if (sslConn) -+ { + { +- BMCWEB_LOG_ERROR << "shutdown failed: " << ec.message(); +- return; + sslConn->async_shutdown([self = shared_from_this()]( + const boost::system::error_code ec) { - if (ec) - { -- BMCWEB_LOG_ERROR << "recvMessage() failed: " -- << ec.message(); -- self->state = ConnState::recvFailed; -- self->handleConnState(); -- return; ++ if (ec) ++ { + // Many https server closes connection abruptly + // i.e witnout close_notify. More details are at + // https://github.com/boostorg/beast/issues/824 @@ -294,79 +348,20 @@ index aad1cce..5e7ff47 100644 + BMCWEB_LOG_ERROR << "doClose() failed: " + << ec.message(); + } - } -- BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: " -- << bytesTransferred; -- BMCWEB_LOG_DEBUG << "recvMessage() data: " -- << self->parser->get(); -- -- // Check if the response and header are received -- if (!self->parser->is_done()) ++ } + else - { -- // The parser failed to receive the response -- BMCWEB_LOG_ERROR -- << "recvMessage() parser failed to receive response"; -- self->state = ConnState::recvFailed; -- self->handleConnState(); -- return; ++ { + BMCWEB_LOG_DEBUG << "Connection closed gracefully..."; - } ++ } + self->conn.close(); - -- unsigned int respCode = self->parser->get().result_int(); -- BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: " -- << respCode; -- -- // 2XX response is considered to be successful -- if ((respCode < 200) || (respCode >= 300)) ++ + if ((self->state != ConnState::suspended) && + (self->state != ConnState::terminated)) - { -- // The listener failed to receive the Sent-Event -- BMCWEB_LOG_ERROR << "recvMessage() Listener Failed to " -- "receive Sent-Event"; -- self->state = ConnState::recvFailed; ++ { + self->state = ConnState::closed; - self->handleConnState(); -- return; - } -- -- // Send is successful, Lets remove data from queue -- // check for next request data in queue. -- if (!self->requestDataQueue.empty()) -- { -- self->requestDataQueue.pop_front(); -- } -- self->state = ConnState::idle; -- -- // Keep the connection alive if server supports it -- // Else close the connection -- BMCWEB_LOG_DEBUG << "recvMessage() keepalive : " -- << self->parser->keep_alive(); -- if (!self->parser->keep_alive()) -- { -- // Abort the connection since server is not keep-alive -- // enabled -- self->state = ConnState::abortConnection; -- } -- -- self->handleConnState(); - }); -- } -- -- void doClose() -- { -- state = ConnState::closeInProgress; -- boost::beast::error_code ec; -- conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); -- conn.close(); -- -- // not_connected happens sometimes so don't bother reporting it. -- if (ec && ec != boost::beast::errc::not_connected) -- { -- BMCWEB_LOG_ERROR << "shutdown failed: " << ec.message(); -- return; ++ self->handleConnState(); ++ } ++ }); } - BMCWEB_LOG_DEBUG << "Connection closed gracefully"; - if ((state != ConnState::suspended) && (state != ConnState::terminated)) @@ -396,7 +391,7 @@ index aad1cce..5e7ff47 100644 } } -@@ -330,6 +419,7 @@ class HttpClient : public std::enable_shared_from_this +@@ -329,6 +421,7 @@ class HttpClient : public std::enable_shared_from_this { case ConnState::resolveInProgress: case ConnState::connectInProgress: @@ -404,7 +399,7 @@ index aad1cce..5e7ff47 100644 case ConnState::sendInProgress: case ConnState::recvInProgress: case ConnState::closeInProgress: -@@ -356,6 +446,7 @@ class HttpClient : public std::enable_shared_from_this +@@ -355,6 +448,7 @@ class HttpClient : public std::enable_shared_from_this } case ConnState::resolveFailed: case ConnState::connectFailed: @@ -412,7 +407,7 @@ index aad1cce..5e7ff47 100644 case ConnState::sendFailed: case ConnState::recvFailed: case ConnState::retry: -@@ -394,7 +485,8 @@ class HttpClient : public std::enable_shared_from_this +@@ -391,7 +485,8 @@ class HttpClient : public std::enable_shared_from_this public: explicit HttpClient(boost::asio::io_context& ioc, const std::string& id, const std::string& destIP, const std::string& destPort, @@ -420,9 +415,9 @@ index aad1cce..5e7ff47 100644 + const std::string& destUri, + const std::string& uriProto) : conn(ioc), - timer(ioc), req(boost::beast::http::verb::post, destUri, 11), - state(ConnState::initialized), subId(id), host(destIP), port(destPort), -@@ -407,8 +499,11 @@ class HttpClient : public std::enable_shared_from_this + timer(ioc), req(boost::beast::http::verb::post, destUri, 11), subId(id), + host(destIP), port(destPort) +@@ -402,6 +497,10 @@ class HttpClient : public std::enable_shared_from_this req.keep_alive(true); requestDataQueue.set_capacity(maxRequestQueueSize); @@ -431,16 +426,14 @@ index aad1cce..5e7ff47 100644 + sslConn.emplace(conn, ctx); + } } -- + void sendData(const std::string& data) - { - if ((state == ConnState::suspended) || (state == ConnState::terminated)) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 08d0b98..f1ce0c0 100644 +index 317f900..f581b96 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -385,7 +385,7 @@ class Subscription : public persistent_data::UserSubscription - { +@@ -383,7 +383,7 @@ class Subscription : public persistent_data::UserSubscription + // create the HttpClient connection conn = std::make_shared( crow::connections::systemBus->get_io_context(), id, host, port, - path); diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch index ea521a7e4..dfa67935c 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch @@ -1,4 +1,4 @@ -From d7a2660f200c38e74bfcbfe55b8da1b8bed08833 Mon Sep 17 00:00:00 2001 +From ea7d0091545450721d8b9b901e2593401b50d24c Mon Sep 17 00:00:00 2001 From: AppaRao Puli Date: Fri, 12 Mar 2021 18:53:25 +0000 Subject: [PATCH] Add Server-Sent-Events support @@ -31,10 +31,10 @@ Signed-off-by: P Dheeraj Srujan Kumar create mode 100644 http/server_sent_event.hpp diff --git a/http/http_connection.hpp b/http/http_connection.hpp -index 8e53afa..a1bbfce 100644 +index 0f20761..9cf603d 100644 --- a/http/http_connection.hpp +++ b/http/http_connection.hpp -@@ -378,11 +378,13 @@ class Connection : +@@ -362,11 +362,13 @@ class Connection : [self] { self->completeRequest(); }); }); @@ -83,10 +83,10 @@ index a983d4a..07b0265 100644 // In case of a JSON object, set the Content-Type header void jsonMode() diff --git a/http/routing.hpp b/http/routing.hpp -index 5d9c8e3..bfff107 100644 +index fe9c7e9..c748580 100644 --- a/http/routing.hpp +++ b/http/routing.hpp -@@ -6,6 +6,7 @@ +@@ -7,6 +7,7 @@ #include "http_response.hpp" #include "logging.hpp" #include "privileges.hpp" @@ -94,7 +94,7 @@ index 5d9c8e3..bfff107 100644 #include "sessions.hpp" #include "utility.hpp" #include "websocket.hpp" -@@ -398,6 +399,68 @@ class WebSocketRule : public BaseRule +@@ -397,6 +398,68 @@ class WebSocketRule : public BaseRule std::function errorHandler; }; @@ -163,7 +163,7 @@ index 5d9c8e3..bfff107 100644 template struct RuleParameterTraits { -@@ -410,6 +473,14 @@ struct RuleParameterTraits +@@ -409,6 +472,14 @@ struct RuleParameterTraits return *p; } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch index ee69081ef..525070d93 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch @@ -1,4 +1,4 @@ -From 799e47842e179f7c752712004f0e96d3219eee11 Mon Sep 17 00:00:00 2001 +From 278ea5570d8a162774c3d84b0706e27539e714cc Mon Sep 17 00:00:00 2001 From: AppaRao Puli Date: Tue, 16 Mar 2021 15:37:24 +0000 Subject: [PATCH] Add SSE style subscription support to eventservice @@ -25,18 +25,18 @@ Signed-off-by: P Dheeraj Srujan Kumar http/http_connection.hpp | 2 +- include/eventservice_sse.hpp | 75 +++++ .../include/event_service_manager.hpp | 109 +++++-- - redfish-core/include/server_sent_events.hpp | 290 ------------------ + redfish-core/include/server_sent_events.hpp | 289 ------------------ redfish-core/lib/event_service.hpp | 8 +- src/webserver_main.cpp | 2 + - 6 files changed, 164 insertions(+), 322 deletions(-) + 6 files changed, 164 insertions(+), 321 deletions(-) create mode 100644 include/eventservice_sse.hpp delete mode 100644 redfish-core/include/server_sent_events.hpp diff --git a/http/http_connection.hpp b/http/http_connection.hpp -index a1bbfce..2d08501 100644 +index 9cf603d..cf629ea 100644 --- a/http/http_connection.hpp +++ b/http/http_connection.hpp -@@ -382,7 +382,7 @@ class Connection : +@@ -366,7 +366,7 @@ class Connection : boost::iequals( thisReq.getHeaderValue(boost::beast::http::field::upgrade), "websocket")) || @@ -127,17 +127,18 @@ index 0000000..14daf00 +} // namespace eventservice_sse +} // namespace redfish diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 3f398d7..dd833ce 100644 +index f581b96..57a2ab8 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -22,15 +22,17 @@ +@@ -23,6 +23,7 @@ #include #include +#include #include + #include #include - #include +@@ -30,9 +31,10 @@ #include #include #include @@ -149,7 +150,7 @@ index 3f398d7..dd833ce 100644 #include #include #include -@@ -46,9 +48,27 @@ using ReadingsObjType = +@@ -48,9 +50,27 @@ using ReadingsObjType = static constexpr const char* eventFormatType = "Event"; static constexpr const char* metricReportFormatType = "MetricReport"; @@ -176,10 +177,10 @@ index 3f398d7..dd833ce 100644 + namespace message_registries { - inline boost::beast::span -@@ -68,24 +88,6 @@ inline boost::beast::span + inline std::span +@@ -70,24 +90,6 @@ inline std::span } - return boost::beast::span(openbmc::registry); + return {openbmc::registry}; } -} // namespace message_registries - @@ -201,8 +202,8 @@ index 3f398d7..dd833ce 100644 -{ static const Message* getMsgFromRegistry(const std::string& messageKey, - const boost::beast::span& registry) -@@ -388,11 +390,9 @@ class Subscription : public persistent_data::UserSubscription + const std::span& registry) +@@ -386,11 +388,9 @@ class Subscription : public persistent_data::UserSubscription path, uriProto); } @@ -217,7 +218,7 @@ index 3f398d7..dd833ce 100644 ~Subscription() = default; -@@ -417,7 +417,7 @@ class Subscription : public persistent_data::UserSubscription +@@ -404,7 +404,7 @@ class Subscription : public persistent_data::UserSubscription if (sseConn != nullptr) { @@ -226,7 +227,7 @@ index 3f398d7..dd833ce 100644 } } -@@ -508,6 +508,7 @@ class Subscription : public persistent_data::UserSubscription +@@ -495,6 +495,7 @@ class Subscription : public persistent_data::UserSubscription this->sendEvent( msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); @@ -234,7 +235,7 @@ index 3f398d7..dd833ce 100644 } #endif -@@ -578,14 +579,39 @@ class Subscription : public persistent_data::UserSubscription +@@ -557,14 +558,39 @@ class Subscription : public persistent_data::UserSubscription return eventSeqNum; } @@ -275,16 +276,16 @@ index 3f398d7..dd833ce 100644 }; class EventServiceManager -@@ -942,6 +968,8 @@ class EventServiceManager - subValue->updateRetryConfig(retryAttempts, retryTimeoutInterval); +@@ -922,6 +948,8 @@ class EventServiceManager subValue->updateRetryPolicy(); + subValue->updatehttpHeaders(); + // Set Subscription ID for back trace + subValue->setSubscriptionId(id); return id; } -@@ -970,11 +998,40 @@ class EventServiceManager +@@ -950,11 +978,40 @@ class EventServiceManager } } @@ -327,10 +328,10 @@ index 3f398d7..dd833ce 100644 std::vector idList; diff --git a/redfish-core/include/server_sent_events.hpp b/redfish-core/include/server_sent_events.hpp deleted file mode 100644 -index 7613d7b..0000000 +index dd3cd36..0000000 --- a/redfish-core/include/server_sent_events.hpp +++ /dev/null -@@ -1,290 +0,0 @@ +@@ -1,289 +0,0 @@ - -/* -// Copyright (c) 2020 Intel Corporation @@ -350,7 +351,6 @@ index 7613d7b..0000000 -#pragma once - -#include --#include -#include -#include -#include @@ -622,10 +622,10 @@ index 7613d7b..0000000 - -} // namespace crow diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp -index 8609862..249e594 100644 +index 91a041e..9ad2bbd 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -37,8 +37,6 @@ static constexpr const std::array supportedResourceTypes = { +@@ -40,8 +40,6 @@ static constexpr const std::array supportedResourceTypes = { "Task"}; #endif @@ -634,16 +634,16 @@ index 8609862..249e594 100644 inline void requestRoutesEventService(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/EventService/") -@@ -50,6 +48,8 @@ inline void requestRoutesEventService(App& app) - {"@odata.type", "#EventService.v1_5_0.EventService"}, - {"Id", "EventService"}, - {"Name", "Event Service"}, -+ {"ServerSentEventUri", -+ "/redfish/v1/EventService/Subscriptions/SSE"}, - {"Subscriptions", - {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}}, - {"Actions", -@@ -90,9 +90,7 @@ inline void requestRoutesEventService(App& app) +@@ -54,6 +52,8 @@ inline void requestRoutesEventService(App& app) + {"@odata.type", "#EventService.v1_5_0.EventService"}, + {"Id", "EventService"}, + {"Name", "Event Service"}, ++ {"ServerSentEventUri", ++ "/redfish/v1/EventService/Subscriptions/SSE"}, + {"Subscriptions", + {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}}, + {"Actions", +@@ -92,9 +92,7 @@ inline void requestRoutesEventService(App& app) .privileges(redfish::privileges::patchEventService) .methods(boost::beast::http::verb::patch)( [](const crow::Request& req, 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 index 3914cc81a..05018a47d 100644 --- 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 @@ -1,4 +1,4 @@ -From 769f0e20d0a7e786d7091ffb7ee57d35204dfa28 Mon Sep 17 00:00:00 2001 +From 64a9d1826b7b4a66750f7ecaaff7bcf7e0d23932 Mon Sep 17 00:00:00 2001 From: AppaRao Puli Date: Wed, 17 Mar 2021 01:16:50 +0000 Subject: [PATCH] Add EventService SSE filter support @@ -59,7 +59,7 @@ index 14daf00..fed7fec 100644 + std::string queryFilters; + if (req.urlParams.size()) + { -+ boost::urls::url_view::params_type::iterator it = ++ boost::urls::query_params_view::iterator it = + req.urlParams.find("$filter"); + if (it == req.urlParams.end()) + { @@ -155,14 +155,14 @@ index 14daf00..fed7fec 100644 + // Check for Message ID in each of the selected Registry + for (const std::string& it : registryPrefix) + { -+ const boost::beast::span< ++ const std::span< + const redfish::message_registries::MessageEntry> + registry = + redfish::message_registries::getRegistryFromPrefix( + it); + + if (std::any_of( -+ registry.cbegin(), registry.cend(), ++ registry.begin(), registry.end(), + [&id]( + const redfish::message_registries::MessageEntry& + messageEntry) { @@ -203,10 +203,10 @@ index 14daf00..fed7fec 100644 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 3d11cc4..90084e3 100644 +index 7f53fa4..9c688b4 100644 --- a/redfish-core/include/error_messages.hpp +++ b/redfish-core/include/error_messages.hpp -@@ -971,6 +971,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1, +@@ -985,6 +985,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1, void mutualExclusiveProperties(crow::Response& res, const std::string& arg1, const std::string& arg2); @@ -223,10 +223,10 @@ index 3d11cc4..90084e3 100644 } // namespace redfish diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index dd833ce..861f4cb 100644 +index 57a2ab8..aae9f02 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -55,6 +55,11 @@ static constexpr const char* eventServiceFile = +@@ -57,6 +57,11 @@ static constexpr const char* eventServiceFile = static constexpr const uint8_t maxNoOfSubscriptions = 20; static constexpr const uint8_t maxNoOfSSESubscriptions = 10; @@ -239,10 +239,10 @@ index dd833ce..861f4cb 100644 static std::optional 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 249e594..6f01707 100644 +index 9ad2bbd..99c3bfd 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -21,11 +21,6 @@ +@@ -24,11 +24,6 @@ namespace redfish { @@ -255,10 +255,10 @@ index 249e594..6f01707 100644 "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp -index 9c28e8f..2394398 100644 +index 2087a67..ecb3721 100644 --- a/redfish-core/src/error_messages.cpp +++ b/redfish-core/src/error_messages.cpp -@@ -2173,6 +2173,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1, +@@ -2203,6 +2203,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1, addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2)); } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch index 3be65ee2a..7cad022f3 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch @@ -1,4 +1,4 @@ -From b8eb53886106e44e3668857b13f8642d2ad3cfbf Mon Sep 17 00:00:00 2001 +From b5020756ae3fbff6283c293c74b779d656429f3a Mon Sep 17 00:00:00 2001 From: AppaRao Puli Date: Fri, 27 Aug 2021 16:02:01 +0000 Subject: [PATCH] EventService: Log events for subscription actions @@ -21,13 +21,14 @@ Tested: Change-Id: I3745fa6357bd215379781a9818d9acc02a853d79 Signed-off-by: AppaRao Puli Signed-off-by: Ayushi Smriti +Signed-off-by: P Dheeraj Srujan Kumar --- .../include/event_service_manager.hpp | 35 ++++++++++++++++--- redfish-core/lib/event_service.hpp | 2 +- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index c3e7f61..e9bdbfa 100644 +index aae9f02..69db652 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp @@ -21,6 +21,7 @@ @@ -38,7 +39,7 @@ index c3e7f61..e9bdbfa 100644 #include #include -@@ -788,7 +789,7 @@ class EventServiceManager +@@ -780,7 +781,7 @@ class EventServiceManager } } @@ -47,7 +48,7 @@ index c3e7f61..e9bdbfa 100644 { persistent_data::EventServiceStore::getInstance() .eventServiceConfig.enabled = serviceEnabled; -@@ -835,7 +836,7 @@ class EventServiceManager +@@ -827,7 +828,7 @@ class EventServiceManager if (updateConfig) { @@ -56,7 +57,7 @@ index c3e7f61..e9bdbfa 100644 } if (updateRetryCfg) -@@ -947,7 +948,7 @@ class EventServiceManager +@@ -939,7 +940,7 @@ class EventServiceManager if (updateFile) { @@ -65,7 +66,7 @@ index c3e7f61..e9bdbfa 100644 } #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES -@@ -962,6 +963,13 @@ class EventServiceManager +@@ -955,6 +956,13 @@ class EventServiceManager // Set Subscription ID for back trace subValue->setSubscriptionId(id); @@ -79,7 +80,7 @@ index c3e7f61..e9bdbfa 100644 return id; } -@@ -986,7 +994,14 @@ class EventServiceManager +@@ -979,7 +987,14 @@ class EventServiceManager persistent_data::EventServiceStore::getInstance() .subscriptionsConfigMap.erase(obj2); updateNoOfSubscribersCount(); @@ -95,7 +96,7 @@ index c3e7f61..e9bdbfa 100644 } } -@@ -1008,6 +1023,18 @@ class EventServiceManager +@@ -1001,6 +1016,18 @@ class EventServiceManager } } @@ -115,10 +116,10 @@ index c3e7f61..e9bdbfa 100644 { return subscriptionsMap.size(); diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp -index 9def549..6a8421f 100644 +index 99c3bfd..15e45dc 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -617,7 +617,7 @@ inline void requestRoutesEventDestination(App& app) +@@ -624,7 +624,7 @@ inline void requestRoutesEventDestination(App& app) subValue->updateRetryPolicy(); } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch index 84ceb4ba8..a46708ee5 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch @@ -1,4 +1,4 @@ -From 05fdea2bb8e486b058d137a067ce1f5c885d2a96 Mon Sep 17 00:00:00 2001 +From ee758f1f97890f51707e72b3c6b08c8c46c41595 Mon Sep 17 00:00:00 2001 From: Nitin Wankhade Date: Mon, 28 Jun 2021 19:59:57 +0000 Subject: [PATCH] Add checks on Event Subscription input parameters @@ -16,17 +16,18 @@ Tested Change-Id: Iec2cd766c0e137b72706fc2da468d4fefd8fbaae Signed-off-by: Nitin Wankhade +Signed-off-by: P Dheeraj Srujan Kumar --- - redfish-core/lib/event_service.hpp | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) + redfish-core/lib/event_service.hpp | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp -index 52b01e5..f8a1671 100644 +index 15e45dc..27dec86 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -19,6 +19,10 @@ - #include - #include +@@ -22,6 +22,10 @@ + + #include +#define MAX_CONTEXT_SIZE 256 +#define MAX_DESTINATION_SIZE 1024 @@ -35,7 +36,7 @@ index 52b01e5..f8a1671 100644 namespace redfish { static constexpr const std::array supportedRetryPolicies = { -@@ -220,6 +224,12 @@ inline void requestRoutesEventDestinationCollection(App& app) +@@ -223,6 +227,12 @@ inline void requestRoutesEventDestinationCollection(App& app) return; } @@ -48,7 +49,7 @@ index 52b01e5..f8a1671 100644 if (regPrefixes && msgIds) { if (regPrefixes->size() && msgIds->size()) -@@ -330,11 +340,31 @@ inline void requestRoutesEventDestinationCollection(App& app) +@@ -333,13 +343,29 @@ inline void requestRoutesEventDestinationCollection(App& app) if (context) { @@ -64,22 +65,20 @@ index 52b01e5..f8a1671 100644 { + size_t cumulativeLen = 0; + -+ for (nlohmann::json& itr : *headers) -+ { -+ std::string hdr{itr.dump( + for (const nlohmann::json& headerChunk : *headers) + { ++ std::string hdr{headerChunk.dump( + -1, ' ', true, nlohmann::json::error_handler_t::replace)}; + cumulativeLen += hdr.length(); -+ + if (cumulativeLen > MAX_HEADER_SIZE) + { + messages::propertySizeExceeded(asyncResp->res, + "HttpHeaders"); + return; + } -+ } - subValue->httpHeaders = *headers; - } - + for (const auto& item : headerChunk.items()) + { + const std::string* value = -- 2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch index d1fe475f5..918560f4d 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch @@ -1,5 +1,5 @@ -From 542505dff60e3921b00b51acae882e207d46f1a6 Mon Sep 17 00:00:00 2001 -From: Krzysztof Grobelny +From d047619b7003882846b108f519b00cdd41265361 Mon Sep 17 00:00:00 2001 +From: P Dheeraj Srujan Kumar Date: Wed, 14 Jul 2021 14:13:11 +0000 Subject: [PATCH] Restructure Redfish EventLog Transmit code flow @@ -35,7 +35,7 @@ Signed-off-by: P Dheeraj Srujan Kumar 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index e9bdbfa..5c4de70 100644 +index 3208fb3..86c90fb 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp @@ -134,15 +134,10 @@ static const Message* formatMessage(const std::string_view& messageID) @@ -55,7 +55,7 @@ index e9bdbfa..5c4de70 100644 // Get the entry timestamp std::time_t curTs = 0; -@@ -621,6 +616,7 @@ class EventServiceManager +@@ -628,6 +623,7 @@ class EventServiceManager } std::string lastEventTStr; @@ -63,7 +63,7 @@ index e9bdbfa..5c4de70 100644 size_t noOfEventLogSubscribers{0}; size_t noOfMetricReportSubscribers{0}; std::shared_ptr matchTelemetryMonitor; -@@ -1163,7 +1159,22 @@ class EventServiceManager +@@ -1172,7 +1168,22 @@ class EventServiceManager #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES void cacheLastEventTimestamp() { @@ -87,7 +87,7 @@ index e9bdbfa..5c4de70 100644 std::ifstream logStream(redfishEventLogFile); if (!logStream.good()) { -@@ -1171,27 +1182,44 @@ class EventServiceManager +@@ -1180,27 +1191,44 @@ class EventServiceManager return; } std::string logEntry; @@ -143,7 +143,7 @@ index e9bdbfa..5c4de70 100644 std::ifstream logStream(redfishEventLogFile); if (!logStream.good()) { -@@ -1201,27 +1229,21 @@ class EventServiceManager +@@ -1210,27 +1238,21 @@ class EventServiceManager std::vector eventRecords; @@ -178,7 +178,7 @@ index e9bdbfa..5c4de70 100644 std::string timestamp; std::string messageID; -@@ -1233,6 +1255,16 @@ class EventServiceManager +@@ -1242,6 +1264,16 @@ class EventServiceManager continue; } @@ -195,7 +195,7 @@ index e9bdbfa..5c4de70 100644 std::string registryName; std::string messageKey; event_log::getRegistryAndMessageKey(messageID, registryName, -@@ -1242,11 +1274,23 @@ class EventServiceManager +@@ -1251,11 +1283,23 @@ class EventServiceManager continue; } 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 index 9af5a066b..f37bc241b 100644 --- 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 @@ -1,5 +1,5 @@ -From f665ba085bb2310f008b7534f827fb401ad973c2 Mon Sep 17 00:00:00 2001 -From: Krzysztof Grobelny +From 5d13aa636aba6c68ab5a74e589cac35f4e925129 Mon Sep 17 00:00:00 2001 +From: P Dheeraj Srujan Kumar Date: Tue, 12 Oct 2021 08:19:51 +0000 Subject: [PATCH] Delete/Remove Terminated Event Subscription(s) @@ -22,15 +22,15 @@ Tested: Change-Id: If447acb2db74fb29a5d1cfe6194b77cda82bc8a1 Signed-off-by: P Dheeraj Srujan Kumar --- - http/http_client.hpp | 43 +++++++++++++++---- - .../include/event_service_manager.hpp | 36 ++++++++++++++++ - 2 files changed, 70 insertions(+), 9 deletions(-) + http/http_client.hpp | 48 +++++++++++++++---- + .../include/event_service_manager.hpp | 36 ++++++++++++++ + 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/http/http_client.hpp b/http/http_client.hpp -index 5e7ff47..54ae2c3 100644 +index 58b5402..745eeb6 100644 --- a/http/http_client.hpp +++ b/http/http_client.hpp -@@ -55,6 +55,8 @@ enum class ConnState +@@ -56,6 +56,8 @@ enum class ConnState closeInProgress, closed, suspended, @@ -39,7 +39,7 @@ index 5e7ff47..54ae2c3 100644 terminated, abortConnection, retry -@@ -288,7 +290,14 @@ class HttpClient : public std::enable_shared_from_this +@@ -290,7 +292,14 @@ class HttpClient : public std::enable_shared_from_this } void doClose() { @@ -55,7 +55,7 @@ index 5e7ff47..54ae2c3 100644 // Set the timeout on the tcp stream socket for the async operation conn.expires_after(std::chrono::seconds(30)); -@@ -318,8 +327,11 @@ class HttpClient : public std::enable_shared_from_this +@@ -320,8 +329,11 @@ class HttpClient : public std::enable_shared_from_this } self->conn.close(); @@ -69,7 +69,7 @@ index 5e7ff47..54ae2c3 100644 { self->state = ConnState::closed; self->handleConnState(); -@@ -341,8 +353,11 @@ class HttpClient : public std::enable_shared_from_this +@@ -343,8 +355,11 @@ class HttpClient : public std::enable_shared_from_this } conn.close(); @@ -83,7 +83,7 @@ index 5e7ff47..54ae2c3 100644 { state = ConnState::closed; handleConnState(); -@@ -365,8 +380,7 @@ class HttpClient : public std::enable_shared_from_this +@@ -367,8 +382,7 @@ class HttpClient : public std::enable_shared_from_this BMCWEB_LOG_DEBUG << "Retry policy: " << retryPolicyAction; if (retryPolicyAction == "TerminateAfterRetries") { @@ -93,7 +93,7 @@ index 5e7ff47..54ae2c3 100644 } if (retryPolicyAction == "SuspendRetries") { -@@ -423,6 +437,7 @@ class HttpClient : public std::enable_shared_from_this +@@ -425,6 +439,7 @@ class HttpClient : public std::enable_shared_from_this case ConnState::sendInProgress: case ConnState::recvInProgress: case ConnState::closeInProgress: @@ -101,7 +101,7 @@ index 5e7ff47..54ae2c3 100644 { BMCWEB_LOG_DEBUG << "Async operation is already in progress"; break; -@@ -439,7 +454,7 @@ class HttpClient : public std::enable_shared_from_this +@@ -441,11 +456,16 @@ class HttpClient : public std::enable_shared_from_this break; } case ConnState::suspended: @@ -110,8 +110,17 @@ index 5e7ff47..54ae2c3 100644 { doClose(); break; -@@ -506,7 +521,8 @@ class HttpClient : public std::enable_shared_from_this - } + } ++ case ConnState::terminated: ++ { ++ BMCWEB_LOG_DEBUG << "Connection Terminated"; ++ break; ++ } + case ConnState::resolveFailed: + case ConnState::connectFailed: + case ConnState::handshakeFailed: +@@ -505,7 +525,8 @@ class HttpClient : public std::enable_shared_from_this + void sendData(const std::string& data) { - if ((state == ConnState::suspended) || (state == ConnState::terminated)) @@ -120,7 +129,7 @@ index 5e7ff47..54ae2c3 100644 { return; } -@@ -524,6 +540,15 @@ class HttpClient : public std::enable_shared_from_this +@@ -523,6 +544,15 @@ class HttpClient : public std::enable_shared_from_this return; } @@ -133,14 +142,14 @@ index 5e7ff47..54ae2c3 100644 + return false; + } + - void addHeaders( - const std::vector>& httpHeaders) + void setHeaders(const boost::beast::http::fields& httpHeaders) { + // Set custom headers diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 6f60a31..363adb0 100644 +index 69db652..5d71c63 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 +@@ -588,6 +588,14 @@ class Subscription : public persistent_data::UserSubscription return std::nullopt; } @@ -155,7 +164,7 @@ index 6f60a31..363adb0 100644 private: std::shared_ptr sseConn = nullptr; uint64_t eventSeqNum; -@@ -847,6 +855,22 @@ class EventServiceManager +@@ -843,6 +851,22 @@ class EventServiceManager } } @@ -178,7 +187,7 @@ index 6f60a31..363adb0 100644 void updateNoOfSubscribersCount() { size_t eventLogSubCount = 0; -@@ -881,6 +905,7 @@ class EventServiceManager +@@ -877,6 +901,7 @@ class EventServiceManager std::shared_ptr getSubscription(const std::string& id) { @@ -186,7 +195,7 @@ index 6f60a31..363adb0 100644 auto obj = subscriptionsMap.find(id); if (obj == subscriptionsMap.end()) { -@@ -971,6 +996,7 @@ class EventServiceManager +@@ -968,6 +993,7 @@ class EventServiceManager bool isSubscriptionExist(const std::string& id) { @@ -194,7 +203,7 @@ index 6f60a31..363adb0 100644 auto obj = subscriptionsMap.find(id); if (obj == subscriptionsMap.end()) { -@@ -1033,6 +1059,7 @@ class EventServiceManager +@@ -1030,6 +1056,7 @@ class EventServiceManager size_t getNumberOfSubscriptions() { @@ -202,7 +211,7 @@ index 6f60a31..363adb0 100644 return subscriptionsMap.size(); } -@@ -1049,6 +1076,7 @@ class EventServiceManager +@@ -1046,6 +1073,7 @@ class EventServiceManager std::vector getAllIDs() { @@ -210,7 +219,7 @@ index 6f60a31..363adb0 100644 std::vector idList; for (const auto& it : subscriptionsMap) { -@@ -1059,6 +1087,7 @@ class EventServiceManager +@@ -1056,6 +1084,7 @@ class EventServiceManager bool isDestinationExist(const std::string& destUrl) { @@ -218,7 +227,7 @@ index 6f60a31..363adb0 100644 for (const auto& it : subscriptionsMap) { std::shared_ptr entry = it.second; -@@ -1073,6 +1102,7 @@ class EventServiceManager +@@ -1070,6 +1099,7 @@ class EventServiceManager void sendTestEventLog() { @@ -226,7 +235,7 @@ index 6f60a31..363adb0 100644 for (const auto& it : this->subscriptionsMap) { std::shared_ptr entry = it.second; -@@ -1100,6 +1130,8 @@ class EventServiceManager +@@ -1097,6 +1127,8 @@ class EventServiceManager } eventRecord.push_back(eventMessage); @@ -235,7 +244,7 @@ index 6f60a31..363adb0 100644 for (const auto& it : this->subscriptionsMap) { std::shared_ptr entry = it.second; -@@ -1143,6 +1175,8 @@ class EventServiceManager +@@ -1140,6 +1172,8 @@ class EventServiceManager } void sendBroadcastMsg(const std::string& broadcastMsg) { @@ -244,7 +253,7 @@ index 6f60a31..363adb0 100644 for (const auto& it : this->subscriptionsMap) { std::shared_ptr entry = it.second; -@@ -1291,6 +1325,8 @@ class EventServiceManager +@@ -1254,6 +1288,8 @@ class EventServiceManager return; } @@ -254,5 +263,5 @@ index 6f60a31..363adb0 100644 { std::shared_ptr entry = it.second; -- -2.25.1 +2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch index 585f7bf09..87f0a4fd9 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch @@ -1,4 +1,4 @@ -From 5b87bb61b58e92a8c5af37a7959347747409a65c Mon Sep 17 00:00:00 2001 +From ff562320d23e1c1e075689a636505f22eb4890d4 Mon Sep 17 00:00:00 2001 From: P Dheeraj Srujan Kumar Date: Thu, 14 Oct 2021 02:56:11 +0530 Subject: [PATCH] Fix bmcweb crash while deleting terminated subscriptions @@ -33,10 +33,10 @@ Signed-off-by: P Dheeraj Srujan Kumar 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/http/http_client.hpp b/http/http_client.hpp -index 54ae2c3..162cb09 100644 +index 745eeb6..5575765 100644 --- a/http/http_client.hpp +++ b/http/http_client.hpp -@@ -367,6 +367,12 @@ class HttpClient : public std::enable_shared_from_this +@@ -369,6 +369,12 @@ class HttpClient : public std::enable_shared_from_this void waitAndRetry() { @@ -49,7 +49,7 @@ index 54ae2c3..162cb09 100644 if (retryCount >= maxRetryAttempts) { BMCWEB_LOG_ERROR << "Maximum number of retries reached."; -@@ -393,11 +399,6 @@ class HttpClient : public std::enable_shared_from_this +@@ -395,11 +401,6 @@ class HttpClient : public std::enable_shared_from_this return; } @@ -62,10 +62,10 @@ index 54ae2c3..162cb09 100644 retryCount++; diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 363adb0..7af7a4d 100644 +index 5d71c63..f97909c 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -857,18 +857,63 @@ class EventServiceManager +@@ -853,18 +853,63 @@ class EventServiceManager void deleteTerminatedSubcriptions() { diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0012-Add-support-for-deleting-terminated-subscriptions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0012-Add-support-for-deleting-terminated-subscriptions.patch new file mode 100644 index 000000000..dd4827f27 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0012-Add-support-for-deleting-terminated-subscriptions.patch @@ -0,0 +1,45 @@ +From e44cced4e8a50a6edf0ace0e00b5be4b61533190 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny +Date: Tue, 7 Dec 2021 09:48:07 +0100 +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 +--- + redfish-core/include/event_service_manager.hpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index f97909c..881d2db 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -1514,6 +1514,8 @@ class EventServiceManager + return; + } + ++ this->deleteTerminatedSubcriptions(); ++ + for (const auto& it : + EventServiceManager::getInstance().subscriptionsMap) + { +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0013-event-service-fix-added-Context-field-to-response.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0013-event-service-fix-added-Context-field-to-response.patch new file mode 100644 index 000000000..019ccbe64 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0013-event-service-fix-added-Context-field-to-response.patch @@ -0,0 +1,33 @@ +From ce9b52791e76d73050f053f8fc607c6e1eb5d8c4 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny +Date: Thu, 16 Dec 2021 10:46:55 +0100 +Subject: [PATCH] event service fix, added Context field to response + +Tested: + - Context field is present + - No regression detected + +Signed-off-by: Krzysztof Grobelny +--- + redfish-core/include/event_service_manager.hpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index 881d2db..1ba9f21 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -530,6 +530,11 @@ class Subscription : public persistent_data::UserSubscription + return; + } + ++ if (!customText.empty()) ++ { ++ msg["Context"] = customText; ++ } ++ + this->sendEvent( + msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); + } +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README index c09967456..22dae410d 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README @@ -22,7 +22,7 @@ Upstream revision information: file://eventservice/0007-EventService-Log-events-for-subscription-actions.patch - Add checks on Event-Subscription input parameters (Downstream patch) - file://eventservice//0008-Add-checks-on-Event-Subscription-input-parameters.patch + file://eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch - Restructure Redifsh EventLog Transmit code flow https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44449/3 @@ -31,4 +31,10 @@ Upstream revision information: file://eventservice/0010-Remove-Terminated-Event-Subscriptions.patch - Fix bmcweb crash while deleting terminated subscriptions (Downstream patch) - file://eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch + file://eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch + + - Add support for deleting terminated subscriptions + file://eventservice/0012-Add-support-for-deleting-terminated-subscriptions.patch + + - event service fix added Context field to response + file://eventservice/0013-event-service-fix-added-Context-field-to-response.patch diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0001-Add-asyncResp-support-during-handleUpgrade.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0001-Add-asyncResp-support-during-handleUpgrade.patch index b3aa11774..c25a79521 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0001-Add-asyncResp-support-during-handleUpgrade.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0001-Add-asyncResp-support-during-handleUpgrade.patch @@ -176,7 +176,7 @@ index 25e4ce8..858f146 100644 + crow::Response resp; + rules[ruleIndex]->handleUpgrade(req, resp, std::move(adaptor)); } - catch (std::exception& e) + catch (const std::exception& e) { BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what(); - res.result(boost::beast::http::status::internal_server_error); diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch index 1ba584616..180ee46d0 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch @@ -60,7 +60,7 @@ index acc99dc..e2a8fbb 100644 - crow::Response resp; - rules[ruleIndex]->handleUpgrade(req, resp, std::move(adaptor)); - } -- catch (std::exception& e) +- catch (const std::exception& e) - { - BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what(); - asyncResp->res.result( diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0004-Add-Privileges-to-Websockets.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0004-Add-Privileges-to-Websockets.patch index 64e235ce3..19c671754 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0004-Add-Privileges-to-Websockets.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/http_routing/0004-Add-Privileges-to-Websockets.patch @@ -117,9 +117,9 @@ index 02f958a..ebbe68f 100644 --- a/include/vm_websocket.hpp +++ b/include/vm_websocket.hpp @@ -3,6 +3,7 @@ - #include - #include - #include + #include + #include + #include +#include #include diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch deleted file mode 100644 index f5226fe6e..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch +++ /dev/null @@ -1,619 +0,0 @@ -From 32e557279450226ed9c06312649d90b802f3d4c5 Mon Sep 17 00:00:00 2001 -From: Krzysztof Grobelny -Date: Tue, 13 Apr 2021 13:00:18 +0000 -Subject: [PATCH] Add support for MetricDefinition scheme - -Added MetricDefinition node to Redfish code. Now user is able to list -all available metrics in OpenBMC that are supported by Telemetry -service. Metrics are grouped by reading type. - -MetricDefinitions contains all physical sensors supported by redfish, -algorithm iterates through all chassis and collects results for each -node available in that chassis (Power, Thermal, Sensors). - -When BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM will be enabled by -default (meson option redfish-new-powersubsystem-thermalsubsystem) it -will be possible to optimize this algorithm to only get sensors from -Sensors node. Currently Sensors node doesn't contain all available -sensors. - -Tested: - - MetricDefinitions response is filled with existing sensors, it works - with and without Telemetry service - - Validated a presence of MetricDefinition members and its attributes - - Successfully passed RedfishServiceValidator.py using witherspoon - image on QEMU - - Tested using following GET,POST requests - -GET /redfish/v1/TelemetryService/MetricDefinitions -{ - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions", - "@odata.type": "#MetricDefinitionCollection.MetricDefinitionCollection", - "Members": [ - { - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Fan_Pwm" - }, - { - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Fan_Tach" - }, - { - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/HostCpuUtilization" - }, - { - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/HostMemoryBandwidthUtilization" - }, - { - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/HostPciBandwidthUtilization" - }, - { - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Inlet_BRD_Temp" - }, - { - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Left_Rear_Board_Temp" - } - ], - "Members@odata.count": 7, - "Name": "Metric Definition Collection" -} - -GET /redfish/v1/TelemetryService/MetricDefinitions/Fan_Tach -{ - "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Fan_Tach", - "@odata.type": "#MetricDefinition.v1_0_3.MetricDefinition", - "Id": "Fan_Tach", - "IsLinear": true, - "MaxReadingRange": 25000.0, - "MetricDataType": "Decimal", - "MetricProperties": [ - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/0/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/2/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/3/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/4/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/5/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/6/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/7/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/8/Reading", - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/9/Reading" - ], - "MetricType": "Gauge", - "MinReadingRange": 0.0, - "Name": "Fan_Tach", - "Units": "RPM" -} - -POST redfish/v1/TelemetryService/MetricReportDefinitions, body: -{ - "Id": "TestReport", - "Metrics": [ - { - "MetricId": "TestMetric", - "MetricProperties": [ - "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/3/Reading", - ] - } - ], - "MetricReportDefinitionType": "OnRequest", - "ReportActions": [ - "RedfishEvent", - "LogToMetricReportsCollection" - ] -} -{ - "@Message.ExtendedInfo": [ - { - "@odata.type": "#Message.v1_1_1.Message", - "Message": "The resource has been created successfully", - "MessageArgs": [], - "MessageId": "Base.1.8.1.Created", - "MessageSeverity": "OK", - "Resolution": "None" - } - ] -} - -Signed-off-by: Wludzik, Jozef -Signed-off-by: Krzysztof Grobelny -Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00 ---- - redfish-core/include/redfish.hpp | 3 + - .../include/utils/get_chassis_names.hpp | 58 +++ - .../include/utils/telemetry_utils.hpp | 2 + - redfish-core/lib/metric_definition.hpp | 368 ++++++++++++++++++ - redfish-core/lib/telemetry_service.hpp | 3 +- - 5 files changed, 433 insertions(+), 1 deletion(-) - create mode 100644 redfish-core/include/utils/get_chassis_names.hpp - create mode 100644 redfish-core/lib/metric_definition.hpp - -diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index 0a97150..67c5af2 100644 ---- a/redfish-core/include/redfish.hpp -+++ b/redfish-core/include/redfish.hpp -@@ -26,6 +26,7 @@ - #include "../lib/managers.hpp" - #include "../lib/memory.hpp" - #include "../lib/message_registries.hpp" -+#include "../lib/metric_definition.hpp" - #include "../lib/metric_report.hpp" - #include "../lib/metric_report_definition.hpp" - #include "../lib/network_protocol.hpp" -@@ -200,6 +201,8 @@ class RedfishService - requestRoutesMetricReportDefinition(app); - requestRoutesMetricReportCollection(app); - requestRoutesMetricReport(app); -+ requestRoutesMetricDefinitionCollection(app); -+ requestRoutesMetricDefinition(app); - } - }; - -diff --git a/redfish-core/include/utils/get_chassis_names.hpp b/redfish-core/include/utils/get_chassis_names.hpp -new file mode 100644 -index 0000000..0276b6f ---- /dev/null -+++ b/redfish-core/include/utils/get_chassis_names.hpp -@@ -0,0 +1,58 @@ -+#pragma once -+ -+#include -+ -+#include -+#include -+#include -+ -+namespace redfish -+{ -+ -+namespace utils -+{ -+ -+template -+inline void getChassisNames(F&& cb) -+{ -+ const std::array interfaces = { -+ "xyz.openbmc_project.Inventory.Item.Board", -+ "xyz.openbmc_project.Inventory.Item.Chassis"}; -+ -+ crow::connections::systemBus->async_method_call( -+ [callback = std::move(cb)](const boost::system::error_code ec, -+ const std::vector& chassis) { -+ std::vector chassisNames; -+ -+ if (ec) -+ { -+ callback(ec, chassisNames); -+ return; -+ } -+ -+ chassisNames.reserve(chassis.size()); -+ for (const std::string& path : chassis) -+ { -+ sdbusplus::message::object_path dbusPath = path; -+ std::string name = dbusPath.filename(); -+ if (name.empty()) -+ { -+ callback(boost::system::errc::make_error_code( -+ boost::system::errc::invalid_argument), -+ chassisNames); -+ return; -+ } -+ chassisNames.emplace_back(std::move(name)); -+ } -+ -+ callback(ec, chassisNames); -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", -+ "/xyz/openbmc_project/inventory", 0, interfaces); -+} -+ -+} // namespace utils -+ -+} // namespace redfish -diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp -index 5872350..1b4f75d 100644 ---- a/redfish-core/include/utils/telemetry_utils.hpp -+++ b/redfish-core/include/utils/telemetry_utils.hpp -@@ -10,6 +10,8 @@ namespace telemetry - - constexpr const char* service = "xyz.openbmc_project.Telemetry"; - constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report"; -+constexpr const char* metricDefinitionUri = -+ "/redfish/v1/TelemetryService/MetricDefinitions/"; - constexpr const char* metricReportDefinitionUri = - "/redfish/v1/TelemetryService/MetricReportDefinitions/"; - constexpr const char* metricReportUri = -diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp -new file mode 100644 -index 0000000..347c297 ---- /dev/null -+++ b/redfish-core/lib/metric_definition.hpp -@@ -0,0 +1,368 @@ -+#pragma once -+ -+#include "async_resp.hpp" -+#include "sensors.hpp" -+#include "utils/get_chassis_names.hpp" -+#include "utils/telemetry_utils.hpp" -+ -+#include -+ -+namespace redfish -+{ -+ -+namespace telemetry -+{ -+ -+struct ValueVisitor -+{ -+ ValueVisitor(boost::system::error_code& ec) : ec(ec) -+ {} -+ -+ template -+ double operator()(T value) const -+ { -+ return static_cast(value); -+ } -+ -+ double operator()(std::monostate) const -+ { -+ ec = boost::system::errc::make_error_code( -+ boost::system::errc::invalid_argument); -+ return double{}; -+ } -+ -+ boost::system::error_code& ec; -+}; -+ -+inline void getReadingRange( -+ const std::string& service, const std::string& path, -+ const std::string& property, -+ std::function callback) -+{ -+ crow::connections::systemBus->async_method_call( -+ [callback = std::move(callback)]( -+ boost::system::error_code ec, -+ const std::variant& -+ valueVariant) { -+ if (ec) -+ { -+ callback(ec, double{}); -+ return; -+ } -+ -+ const double value = std::visit(ValueVisitor(ec), valueVariant); -+ -+ callback(ec, value); -+ }, -+ service, path, "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.Sensor.Value", property); -+} -+ -+inline void -+ fillMinMaxReadingRange(const std::shared_ptr& asyncResp, -+ const std::string& serviceName, -+ const std::string& sensorPath) -+{ -+ asyncResp->res.jsonValue["MetricType"] = "Numeric"; -+ -+ telemetry::getReadingRange( -+ serviceName, sensorPath, "MinValue", -+ [asyncResp](boost::system::error_code ec, double readingRange) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ if (std::isfinite(readingRange)) -+ { -+ asyncResp->res.jsonValue["MetricType"] = "Gauge"; -+ -+ asyncResp->res.jsonValue["MinReadingRange"] = readingRange; -+ } -+ }); -+ -+ telemetry::getReadingRange( -+ serviceName, sensorPath, "MaxValue", -+ [asyncResp](boost::system::error_code ec, double readingRange) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ if (std::isfinite(readingRange)) -+ { -+ asyncResp->res.jsonValue["MetricType"] = "Gauge"; -+ -+ asyncResp->res.jsonValue["MaxReadingRange"] = readingRange; -+ } -+ }); -+} -+ -+inline void getSensorService( -+ const std::string& sensorPath, -+ std::function callback) -+{ -+ using ResultType = std::pair< -+ std::string, -+ std::vector>>>; -+ -+ crow::connections::systemBus->async_method_call( -+ [sensorPath, callback = std::move(callback)]( -+ boost::system::error_code ec, -+ const std::vector& result) { -+ if (ec) -+ { -+ callback(ec, std::string{}); -+ return; -+ } -+ -+ for (const auto& [path, serviceToInterfaces] : result) -+ { -+ if (path == sensorPath) -+ { -+ for (const auto& [service, interfaces] : -+ serviceToInterfaces) -+ { -+ callback(boost::system::errc::make_error_code( -+ boost::system::errc::success), -+ service); -+ return; -+ } -+ } -+ } -+ -+ callback(boost::system::errc::make_error_code( -+ boost::system::errc::no_such_file_or_directory), -+ std::string{}); -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetSubTree", -+ "/xyz/openbmc_project/sensors", 2, -+ std::array{"xyz.openbmc_project.Sensor.Value"}); -+} -+ -+constexpr auto metricDefinitionMapping = std::array{ -+ std::pair{"fan_pwm", "Fan_Pwm"}, std::pair{"fan_tach", "Fan_Tach"}}; -+ -+std::string mapSensorToMetricDefinition(const std::string& sensorPath) -+{ -+ sdbusplus::message::object_path sensorObjectPath{sensorPath}; -+ -+ const auto it = std::find_if( -+ metricDefinitionMapping.begin(), metricDefinitionMapping.end(), -+ [&sensorObjectPath](const auto& item) { -+ return item.first == sensorObjectPath.parent_path().filename(); -+ }); -+ -+ const char* metricDefinitionPath = -+ "/redfish/v1/TelemetryService/MetricDefinitions/"; -+ -+ if (it != metricDefinitionMapping.end()) -+ { -+ return std::string{metricDefinitionPath} + it->second; -+ } -+ -+ return metricDefinitionPath + sensorObjectPath.filename(); -+} -+ -+template -+inline void mapRedfishUriToDbusPath(Callback&& callback) -+{ -+ utils::getChassisNames([callback = std::move(callback)]( -+ boost::system::error_code ec, -+ const std::vector& chassisNames) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value(); -+ callback(ec, {}); -+ return; -+ } -+ -+ auto counter = std::make_shared, size_t>>(); -+ -+ auto handleRetrieveUriToDbusMap = -+ [counter, callback = std::move(callback)]( -+ const boost::beast::http::status status, -+ const boost::container::flat_map& -+ uriToDbus) { -+ if (status != boost::beast::http::status::ok) -+ { -+ BMCWEB_LOG_ERROR << "Failed to retrieve URI to dbus " -+ "sensors map with err " -+ << static_cast(status); -+ counter->second = 0u; -+ callback(boost::system::errc::make_error_code( -+ boost::system::errc::io_error), -+ {}); -+ return; -+ } -+ -+ for (const auto& [key, value] : uriToDbus) -+ { -+ counter->first[key] = value; -+ } -+ -+ if (--counter->second == 0u) -+ { -+ callback(boost::system::errc::make_error_code( -+ boost::system::errc::success), -+ counter->first); -+ } -+ }; -+ -+ for (const std::string& chassisName : chassisNames) -+ { -+ for (const auto& [sensorNode, dbusPaths] : sensors::dbus::paths) -+ { -+ ++counter->second; -+ retrieveUriToDbusMap(chassisName, sensorNode.data(), -+ handleRetrieveUriToDbusMap); -+ } -+ } -+ }); -+} -+ -+} // namespace telemetry -+ -+inline void requestRoutesMetricDefinitionCollection(App& app) -+{ -+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/") -+ .privileges(privileges::getTelemetryService) -+ .methods(boost::beast::http::verb::get)( -+ [](const crow::Request&, -+ const std::shared_ptr& asyncResp) { -+ telemetry::mapRedfishUriToDbusPath( -+ [asyncResp](boost::system::error_code ec, -+ const boost::container::flat_map< -+ std::string, std::string>& uriToDbus) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_ERROR -+ << "mapRedfishUriToDbusPath error: " -+ << ec.value(); -+ return; -+ } -+ -+ std::set members; -+ -+ for (const auto& [uri, dbusPath] : uriToDbus) -+ { -+ members.insert( -+ telemetry::mapSensorToMetricDefinition( -+ dbusPath)); -+ } -+ -+ for (const std::string& odataId : members) -+ { -+ asyncResp->res.jsonValue["Members"].push_back( -+ {{"@odata.id", odataId}}); -+ } -+ -+ asyncResp->res.jsonValue["Members@odata.count"] = -+ asyncResp->res.jsonValue["Members"].size(); -+ }); -+ -+ asyncResp->res.jsonValue["@odata.type"] = -+ "#MetricDefinitionCollection." -+ "MetricDefinitionCollection"; -+ asyncResp->res.jsonValue["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricDefinitions"; -+ asyncResp->res.jsonValue["Name"] = -+ "Metric Definition Collection"; -+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); -+ asyncResp->res.jsonValue["Members@odata.count"] = 0; -+ }); -+} -+ -+inline void requestRoutesMetricDefinition(App& app) -+{ -+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions//") -+ .privileges(privileges::getTelemetryService) -+ .methods( -+ boost::beast::http::verb::get)([](const crow::Request&, -+ const std::shared_ptr< -+ bmcweb::AsyncResp>& asyncResp, -+ const std::string& name) { -+ telemetry::mapRedfishUriToDbusPath( -+ [asyncResp, name]( -+ boost::system::error_code ec, -+ const boost::container::flat_map& -+ uriToDbus) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_ERROR << "mapRedfishUriToDbusPath error: " -+ << ec.value(); -+ return; -+ } -+ -+ std::string odataId = telemetry::metricDefinitionUri + name; -+ boost::container::flat_map -+ matchingUris; -+ -+ for (const auto& [uri, dbusPath] : uriToDbus) -+ { -+ if (telemetry::mapSensorToMetricDefinition(dbusPath) == -+ odataId) -+ { -+ matchingUris.emplace(uri, dbusPath); -+ } -+ } -+ -+ if (matchingUris.empty()) -+ { -+ messages::resourceNotFound(asyncResp->res, -+ "MetricDefinition", name); -+ return; -+ } -+ -+ std::string sensorPath = matchingUris.begin()->second; -+ -+ telemetry::getSensorService( -+ sensorPath, -+ [asyncResp, name, odataId = std::move(odataId), -+ sensorPath, matchingUris = std::move(matchingUris)]( -+ boost::system::error_code ec, -+ const std::string& serviceName) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_ERROR << "getServiceSensorFailed: " -+ << ec.value(); -+ return; -+ } -+ -+ asyncResp->res.jsonValue["Id"] = name; -+ asyncResp->res.jsonValue["Name"] = name; -+ asyncResp->res.jsonValue["@odata.id"] = odataId; -+ asyncResp->res.jsonValue["@odata.type"] = -+ "#MetricDefinition.v1_0_3.MetricDefinition"; -+ asyncResp->res.jsonValue["MetricDataType"] = -+ "Decimal"; -+ asyncResp->res.jsonValue["IsLinear"] = true; -+ asyncResp->res.jsonValue["Units"] = -+ sensors::toReadingUnits( -+ sdbusplus::message::object_path{sensorPath} -+ .parent_path() -+ .filename()); -+ -+ for (const auto& [uri, dbusPath] : matchingUris) -+ { -+ asyncResp->res.jsonValue["MetricProperties"] -+ .push_back(uri); -+ } -+ -+ telemetry::fillMinMaxReadingRange( -+ asyncResp, serviceName, sensorPath); -+ }); -+ }); -+ }); -+} -+ -+} // namespace redfish -diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -index 8ecc591..027b51b 100644 ---- a/redfish-core/lib/telemetry_service.hpp -+++ b/redfish-core/lib/telemetry_service.hpp -@@ -18,11 +18,12 @@ inline void handleTelemetryServiceGet( - asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TelemetryService"; - asyncResp->res.jsonValue["Id"] = "TelemetryService"; - asyncResp->res.jsonValue["Name"] = "Telemetry Service"; -- - asyncResp->res.jsonValue["MetricReportDefinitions"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricReportDefinitions"; - asyncResp->res.jsonValue["MetricReports"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricReports"; -+ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricDefinitions"; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, --- -2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-POST-on-TriggersCollection.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-POST-on-TriggersCollection.patch new file mode 100644 index 000000000..b0cf44cb2 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-POST-on-TriggersCollection.patch @@ -0,0 +1,889 @@ +From 008cc1b35ccb1508d3c71ff5c6cfc6c772f1744c Mon Sep 17 00:00:00 2001 +From: Szymon Dompke +Date: Wed, 17 Nov 2021 18:18:16 +0100 +Subject: [PATCH] Add support for POST on TriggersCollection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Added POST method on /redfish/v1/TelemetryService/Triggers uri, which +creates new trigger in telemetry service, by using dbus call AddTrigger. + +By DMTF, most of the properties are not required, and as such are +treated as optional. Some values can be deduced from others (like +'MetricType', depending on 'DiscreteTriggers' or 'NumericThresholds'). +All properties provided in POST body by user will be verified against +each other, and errors will be raised. Few examples of such situations: +- 'MetricType' is set to 'Discrete' but 'NumericThresholds' was passed. +- 'MetricType' is set to 'Numeric' but "DiscreteTriggers' or + 'DiscreteTriggerCondition' were passed +- 'DiscreteTriggerCondition' is set to 'Specified' but + 'DiscreteTriggers' is an empty array or was not passed. +- 'DiscreteTriggerCondition' is set to 'Changed' but 'DiscreteTriggers' + is passed and is not an empty array. + +Example 1 – Trigger with discrete values: +{ + "Id": "TestTrigger", + "MetricType": "Discrete", + "TriggerActions": [ + "RedfishEvent" + ], + "DiscreteTriggerCondition": "Specified", + "DiscreteTriggers": [ + { + "Value": "55.88", + "DwellTime": "PT0.001S", + "Severity": "Warning" + }, + { + "Name": "My discrete trigger", + "Value": "55.88", + "DwellTime": "PT0.001S", + "Severity": "OK" + }, + { + "Value": "55.88", + "DwellTime": "PT0.001S", + "Severity": "Critical" + } + ], + "MetricProperties": [ + "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/0/Reading" + ], + "Links": { + "MetricReportDefinitions": [] + } +} + +Example 2 – trigger with numeric threshold: +{ + "Id": "TestTrigger2", + "Name": "My Numeric Trigger", + "MetricType": "Numeric", + "TriggerActions": [ + "RedfishEvent", + "RedfishMetricReport" + ], + "NumericThresholds": { + "UpperCritical": { + "Reading": 50, + "Activation": "Increasing", + "DwellTime": "PT0.001S" + }, + "UpperWarning": { + "Reading": 48.1, + "Activation": "Increasing", + "DwellTime": "PT0.004S" + } + }, + "MetricProperties": [ + "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/0/Reading", + "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/17/Reading" + ], + "Links": { + "MetricReportDefinitions": [ + "/redfish/v1/TelemetryService/MetricReportDefinitions/PowerMetrics", + "/redfish/v1/TelemetryService/MetricReportDefinitions/PowerMetricStats", + "/redfish/v1/TelemetryService/MetricReportDefinitions/PlatformPowerUsage" + ] + } +} + +Tested: +- Triggers were successfully created with above example message bodies. + This can be checked by calling: + 'busctl tree xyz.openbmc_project.Telemetry'. +- Expected errors were returned for messages with incorrect or mutually + exclusive properties and incorrect values. +- Redfish service validator is passing. + +Signed-off-by: Szymon Dompke +Change-Id: Ief8c76de8aa660ae0d2dbe4610c26a28186a290a +--- + redfish-core/include/utils/finalizer.hpp | 35 ++ + .../include/utils/telemetry_utils.hpp | 82 +++ + redfish-core/lib/metric_report_definition.hpp | 31 +- + redfish-core/lib/trigger.hpp | 526 +++++++++++++++++- + 4 files changed, 642 insertions(+), 32 deletions(-) + create mode 100644 redfish-core/include/utils/finalizer.hpp + +diff --git a/redfish-core/include/utils/finalizer.hpp b/redfish-core/include/utils/finalizer.hpp +new file mode 100644 +index 0000000..cb98507 +--- /dev/null ++++ b/redfish-core/include/utils/finalizer.hpp +@@ -0,0 +1,35 @@ ++#pragma once ++ ++#include ++ ++namespace redfish ++{ ++ ++namespace utils ++{ ++ ++class Finalizer ++{ ++ public: ++ Finalizer() = delete; ++ Finalizer(std::function finalizer) : finalizer(std::move(finalizer)) ++ {} ++ ++ Finalizer(const Finalizer&) = delete; ++ Finalizer(Finalizer&&) = delete; ++ ++ ~Finalizer() ++ { ++ if (finalizer) ++ { ++ finalizer(); ++ } ++ } ++ ++ private: ++ std::function finalizer; ++}; ++ ++} // namespace utils ++ ++} // namespace redfish +\ No newline at end of file +diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp +index 8aeff0d..c68e40c 100644 +--- a/redfish-core/include/utils/telemetry_utils.hpp ++++ b/redfish-core/include/utils/telemetry_utils.hpp +@@ -13,6 +13,9 @@ constexpr const char* metricReportDefinitionUri = + "/redfish/v1/TelemetryService/MetricReportDefinitions"; + constexpr const char* metricReportUri = + "/redfish/v1/TelemetryService/MetricReports"; ++constexpr const char* triggerInterface = ++ "xyz.openbmc_project.Telemetry.Trigger"; ++constexpr const char* triggerUri = "/redfish/v1/TelemetryService/Triggers"; + + inline std::string getDbusReportPath(const std::string& id) + { +@@ -28,5 +31,84 @@ inline std::string getDbusTriggerPath(const std::string& id) + return {triggersPath / id}; + } + ++inline std::optional ++ getReportNameFromReportDefinitionUri(const std::string& uri) ++{ ++ constexpr const char* uriPattern = ++ "/redfish/v1/TelemetryService/MetricReportDefinitions/"; ++ constexpr size_t idx = std::string_view(uriPattern).length(); ++ if (boost::starts_with(uri, uriPattern)) ++ { ++ return uri.substr(idx); ++ } ++ return std::nullopt; ++} ++ ++inline std::optional ++ getTriggerIdFromDbusPath(const std::string& dbusPath) ++{ ++ constexpr const char* triggerTree = ++ "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService/"; ++ constexpr size_t idx = std::string_view(triggerTree).length(); ++ if (boost::starts_with(dbusPath, triggerTree)) ++ { ++ return dbusPath.substr(idx); ++ } ++ return std::nullopt; ++} ++ ++inline bool getChassisSensorNode( ++ const std::shared_ptr& asyncResp, ++ const std::vector& uris, ++ boost::container::flat_set>& matched) ++{ ++ size_t uriIdx = 0; ++ for (const std::string& uri : uris) ++ { ++ std::string chassis; ++ std::string node; ++ ++ if (!boost::starts_with(uri, "/redfish/v1/Chassis/") || ++ !dbus::utility::getNthStringFromPath(uri, 3, chassis) || ++ !dbus::utility::getNthStringFromPath(uri, 4, node)) ++ { ++ BMCWEB_LOG_ERROR << "Failed to get chassis and sensor Node " ++ "from " ++ << uri; ++ messages::propertyValueIncorrect(asyncResp->res, uri, ++ "MetricProperties/" + ++ std::to_string(uriIdx)); ++ return false; ++ } ++ ++ if (boost::ends_with(node, "#")) ++ { ++ node.pop_back(); ++ } ++ ++ matched.emplace(std::move(chassis), std::move(node)); ++ uriIdx++; ++ } ++ return true; ++} ++ ++inline std::optional ++ redfishActionToDbusAction(const std::string& redfishAction) ++{ ++ if (redfishAction == "RedfishMetricReport") ++ { ++ return "UpdateReport"; ++ } ++ if (redfishAction == "RedfishEvent") ++ { ++ return "RedfishEvent"; ++ } ++ if (redfishAction == "LogToLogService") ++ { ++ return "LogToLogService"; ++ } ++ return std::nullopt; ++} ++ + } // namespace telemetry + } // namespace redfish +diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp +index cb38633..4007544 100644 +--- a/redfish-core/lib/metric_report_definition.hpp ++++ b/redfish-core/lib/metric_report_definition.hpp +@@ -217,7 +217,7 @@ inline bool getUserParameters(crow::Response& res, const crow::Request& req, + return true; + } + +-inline bool getChassisSensorNode( ++inline bool getChassisSensorNodeFromMetrics( + const std::shared_ptr& asyncResp, + const std::vector>>& + metrics, +@@ -225,30 +225,9 @@ inline bool getChassisSensorNode( + { + for (const auto& [id, uris] : metrics) + { +- for (size_t i = 0; i < uris.size(); i++) ++ if (!getChassisSensorNode(asyncResp, uris, matched)) + { +- const std::string& uri = uris[i]; +- std::string chassis; +- std::string node; +- +- if (!boost::starts_with(uri, "/redfish/v1/Chassis/") || +- !dbus::utility::getNthStringFromPath(uri, 3, chassis) || +- !dbus::utility::getNthStringFromPath(uri, 4, node)) +- { +- BMCWEB_LOG_ERROR +- << "Failed to get chassis and sensor Node from " << uri; +- messages::propertyValueIncorrect(asyncResp->res, uri, +- "MetricProperties/" + +- std::to_string(i)); +- return false; +- } +- +- if (boost::ends_with(node, "#")) +- { +- node.pop_back(); +- } +- +- matched.emplace(std::move(chassis), std::move(node)); ++ return false; + } + } + return true; +@@ -382,8 +361,8 @@ inline void requestRoutesMetricReportDefinitionCollection(App& app) + + boost::container::flat_set> + chassisSensors; +- if (!telemetry::getChassisSensorNode(asyncResp, args.metrics, +- chassisSensors)) ++ if (!telemetry::getChassisSensorNodeFromMetrics( ++ asyncResp, args.metrics, chassisSensors)) + { + return; + } +diff --git a/redfish-core/lib/trigger.hpp b/redfish-core/lib/trigger.hpp +index 210468c..01c150e 100644 +--- a/redfish-core/lib/trigger.hpp ++++ b/redfish-core/lib/trigger.hpp +@@ -1,7 +1,9 @@ + #pragma once + +-#include "utils/collection.hpp" ++#include "sensors.hpp" ++#include "utils/finalizer.hpp" + #include "utils/telemetry_utils.hpp" ++#include "utils/time_utils.hpp" + + #include + #include +@@ -14,9 +16,10 @@ namespace redfish + { + namespace telemetry + { +-constexpr const char* triggerInterface = +- "xyz.openbmc_project.Telemetry.Trigger"; +-constexpr const char* triggerUri = "/redfish/v1/TelemetryService/Triggers"; ++ ++static constexpr std::array ++ supportedNumericThresholdNames = {"UpperCritical", "LowerCritical", ++ "UpperWarning", "LowerWarning"}; + + using NumericThresholdParams = + std::tuple; +@@ -24,6 +27,10 @@ using NumericThresholdParams = + using DiscreteThresholdParams = + std::tuple; + ++using TriggerThresholdParams = ++ std::variant, ++ std::vector>; ++ + using TriggerThresholdParamsExt = + std::variant, + std::vector>; +@@ -35,6 +42,455 @@ using TriggerGetParamsVariant = + std::variant>; + ++namespace add_trigger ++{ ++ ++enum class MetricType ++{ ++ Discrete, ++ Numeric ++}; ++ ++enum class DiscreteCondition ++{ ++ Specified, ++ Changed ++}; ++ ++struct Context ++{ ++ struct ++ { ++ std::string id; ++ std::string name; ++ std::vector actions; ++ std::vector> ++ sensors; ++ std::vector reportNames; ++ TriggerThresholdParams thresholds; ++ } dbusArgs; ++ ++ struct ++ { ++ std::optional discreteCondition; ++ std::optional metricType; ++ std::optional> metricProperties; ++ } parsedInfo; ++ ++ boost::container::flat_map uriToDbusMerged{}; ++}; ++ ++inline std::optional getMetricType(const std::string& metricType) ++{ ++ if (metricType == "Discrete") ++ { ++ return MetricType::Discrete; ++ } ++ if (metricType == "Numeric") ++ { ++ return MetricType::Numeric; ++ } ++ return std::nullopt; ++} ++ ++inline std::optional ++ getDiscreteCondition(const std::string& discreteTriggerCondition) ++{ ++ if (discreteTriggerCondition == "Specified") ++ { ++ return DiscreteCondition::Specified; ++ } ++ if (discreteTriggerCondition == "Changed") ++ { ++ return DiscreteCondition::Changed; ++ } ++ return std::nullopt; ++} ++ ++inline bool parseNumericThresholds(crow::Response& res, ++ nlohmann::json& numericThresholds, ++ Context& ctx) ++{ ++ if (!numericThresholds.is_object()) ++ { ++ messages::propertyValueTypeError(res, numericThresholds.dump(), ++ "NumericThresholds"); ++ return false; ++ } ++ ++ std::vector parsedParams; ++ parsedParams.reserve(numericThresholds.size()); ++ ++ for (auto& [thresholdName, thresholdData] : numericThresholds.items()) ++ { ++ if (std::find(supportedNumericThresholdNames.begin(), ++ supportedNumericThresholdNames.end(), ++ thresholdName) == supportedNumericThresholdNames.end()) ++ { ++ messages::propertyUnknown(res, thresholdName); ++ return false; ++ } ++ ++ double reading = .0; ++ std::string activation; ++ std::string dwellTimeStr; ++ ++ if (!json_util::readJson(thresholdData, res, "Reading", reading, ++ "Activation", activation, "DwellTime", ++ dwellTimeStr)) ++ { ++ return false; ++ } ++ ++ std::optional dwellTime = ++ time_utils::fromDurationString(dwellTimeStr); ++ if (!dwellTime) ++ { ++ messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr); ++ return false; ++ } ++ ++ parsedParams.emplace_back(thresholdName, ++ static_cast(dwellTime->count()), ++ activation, reading); ++ } ++ ++ ctx.dbusArgs.thresholds = std::move(parsedParams); ++ return true; ++} ++ ++inline bool parseDiscreteTriggers( ++ crow::Response& res, ++ std::optional>& discreteTriggers, Context& ctx) ++{ ++ std::vector parsedParams; ++ if (!discreteTriggers) ++ { ++ ctx.dbusArgs.thresholds = std::move(parsedParams); ++ return true; ++ } ++ ++ parsedParams.reserve(discreteTriggers->size()); ++ for (nlohmann::json& thresholdInfo : *discreteTriggers) ++ { ++ std::optional name; ++ std::string value; ++ std::string dwellTimeStr; ++ std::string severity; ++ ++ if (!json_util::readJson(thresholdInfo, res, "Name", name, "Value", ++ value, "DwellTime", dwellTimeStr, "Severity", ++ severity)) ++ { ++ return false; ++ } ++ ++ std::optional dwellTime = ++ time_utils::fromDurationString(dwellTimeStr); ++ if (!dwellTime) ++ { ++ messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr); ++ return false; ++ } ++ ++ if (!name) ++ { ++ name = ""; ++ } ++ ++ parsedParams.emplace_back( ++ *name, severity, static_cast(dwellTime->count()), value); ++ } ++ ++ ctx.dbusArgs.thresholds = std::move(parsedParams); ++ return true; ++} ++ ++inline bool parseTriggerThresholds( ++ crow::Response& res, ++ std::optional>& discreteTriggers, ++ std::optional& numericThresholds, Context& ctx) ++{ ++ if (discreteTriggers && numericThresholds) ++ { ++ messages::mutualExclusiveProperties(res, "DiscreteTriggers", ++ "NumericThresholds"); ++ return false; ++ } ++ ++ if (ctx.parsedInfo.discreteCondition) ++ { ++ if (numericThresholds) ++ { ++ messages::mutualExclusiveProperties(res, "DiscreteTriggerCondition", ++ "NumericThresholds"); ++ return false; ++ } ++ } ++ ++ if (ctx.parsedInfo.metricType) ++ { ++ if (*ctx.parsedInfo.metricType == MetricType::Discrete && ++ numericThresholds) ++ { ++ messages::propertyValueConflict(res, "NumericThresholds", ++ "MetricType"); ++ return false; ++ } ++ if (*ctx.parsedInfo.metricType == MetricType::Numeric && ++ discreteTriggers) ++ { ++ messages::propertyValueConflict(res, "DiscreteTriggers", ++ "MetricType"); ++ return false; ++ } ++ if (*ctx.parsedInfo.metricType == MetricType::Numeric && ++ ctx.parsedInfo.discreteCondition) ++ { ++ messages::propertyValueConflict(res, "DiscreteTriggers", ++ "DiscreteTriggerCondition"); ++ return false; ++ } ++ } ++ ++ if (discreteTriggers || ctx.parsedInfo.discreteCondition || ++ (ctx.parsedInfo.metricType && ++ *ctx.parsedInfo.metricType == MetricType::Discrete)) ++ { ++ if (ctx.parsedInfo.discreteCondition) ++ { ++ if (*ctx.parsedInfo.discreteCondition == ++ DiscreteCondition::Specified && ++ !discreteTriggers) ++ { ++ messages::createFailedMissingReqProperties(res, ++ "DiscreteTriggers"); ++ return false; ++ } ++ if (discreteTriggers && ((*ctx.parsedInfo.discreteCondition == ++ DiscreteCondition::Specified && ++ discreteTriggers->empty()) || ++ (*ctx.parsedInfo.discreteCondition == ++ DiscreteCondition::Changed && ++ !discreteTriggers->empty()))) ++ { ++ messages::propertyValueConflict(res, "DiscreteTriggers", ++ "DiscreteTriggerCondition"); ++ return false; ++ } ++ } ++ if (!parseDiscreteTriggers(res, discreteTriggers, ctx)) ++ { ++ return false; ++ } ++ } ++ else if (numericThresholds) ++ { ++ if (!parseNumericThresholds(res, *numericThresholds, ctx)) ++ { ++ return false; ++ } ++ } ++ else ++ { ++ messages::createFailedMissingReqProperties( ++ res, "'DiscreteTriggers', 'NumericThresholds', " ++ "'DiscreteTriggerCondition' or 'MetricType'"); ++ return false; ++ } ++ return true; ++} ++ ++inline bool parseLinks(crow::Response& res, nlohmann::json& links, Context& ctx) ++{ ++ if (links.empty()) ++ { ++ return true; ++ } ++ ++ std::optional> metricReportDefinitions; ++ if (!json_util::readJson(links, res, "MetricReportDefinitions", ++ metricReportDefinitions)) ++ { ++ return false; ++ } ++ ++ if (metricReportDefinitions) ++ { ++ ctx.dbusArgs.reportNames.reserve(metricReportDefinitions->size()); ++ for (std::string& reportDefinionUri : *metricReportDefinitions) ++ { ++ std::optional reportName = ++ getReportNameFromReportDefinitionUri(reportDefinionUri); ++ if (!reportName) ++ { ++ messages::propertyValueIncorrect(res, "MetricReportDefinitions", ++ reportDefinionUri); ++ return false; ++ } ++ ctx.dbusArgs.reportNames.push_back(*reportName); ++ } ++ } ++ return true; ++} ++ ++inline bool parseMetricProperties(crow::Response& res, Context& ctx) ++{ ++ if (!ctx.parsedInfo.metricProperties) ++ { ++ return true; ++ } ++ ++ ctx.dbusArgs.sensors.reserve(ctx.parsedInfo.metricProperties->size()); ++ ++ size_t uriIdx = 0; ++ for (const std::string& uri : *ctx.parsedInfo.metricProperties) ++ { ++ auto el = ctx.uriToDbusMerged.find(uri); ++ if (el == ctx.uriToDbusMerged.end()) ++ { ++ BMCWEB_LOG_ERROR << "Failed to find DBus sensor " ++ "corsresponding to URI " ++ << uri; ++ messages::propertyValueNotInList( ++ res, uri, "MetricProperties/" + std::to_string(uriIdx)); ++ return false; ++ } ++ ++ const std::string& dbusPath = el->second; ++ ctx.dbusArgs.sensors.emplace_back(dbusPath, uri); ++ uriIdx++; ++ } ++ return true; ++} ++ ++inline bool parsePostTriggerParams(crow::Response& res, ++ const crow::Request& req, Context& ctx) ++{ ++ std::optional id; ++ std::optional name; ++ std::optional metricType; ++ std::optional> triggerActions; ++ std::optional discreteTriggerCondition; ++ std::optional> discreteTriggers; ++ std::optional numericThresholds; ++ std::optional links; ++ if (!json_util::readJson( ++ req, res, "Id", id, "Name", name, "MetricType", metricType, ++ "TriggerActions", triggerActions, "DiscreteTriggerCondition", ++ discreteTriggerCondition, "DiscreteTriggers", discreteTriggers, ++ "NumericThresholds", numericThresholds, "MetricProperties", ++ ctx.parsedInfo.metricProperties, "Links", links)) ++ { ++ return false; ++ } ++ ++ ctx.dbusArgs.id = id.value_or(""); ++ ctx.dbusArgs.name = name.value_or(""); ++ ++ if (metricType) ++ { ++ if (!(ctx.parsedInfo.metricType = getMetricType(*metricType))) ++ { ++ messages::propertyValueIncorrect(res, "MetricType", *metricType); ++ return false; ++ } ++ } ++ ++ if (discreteTriggerCondition) ++ { ++ if (!(ctx.parsedInfo.discreteCondition = ++ getDiscreteCondition(*discreteTriggerCondition))) ++ { ++ messages::propertyValueIncorrect(res, "DiscreteTriggerCondition", ++ *discreteTriggerCondition); ++ return false; ++ } ++ } ++ ++ if (triggerActions) ++ { ++ ctx.dbusArgs.actions.reserve(triggerActions->size()); ++ for (const std::string& action : *triggerActions) ++ { ++ if (const std::optional& dbusAction = ++ redfishActionToDbusAction(action)) ++ { ++ ctx.dbusArgs.actions.emplace_back(*dbusAction); ++ } ++ else ++ { ++ messages::propertyValueNotInList(res, action, "TriggerActions"); ++ return false; ++ } ++ } ++ } ++ ++ if (!parseTriggerThresholds(res, discreteTriggers, numericThresholds, ctx)) ++ { ++ return false; ++ } ++ ++ if (links) ++ { ++ if (!parseLinks(res, *links, ctx)) ++ { ++ return false; ++ } ++ } ++ return true; ++} ++ ++inline void createTrigger(const std::shared_ptr& asyncResp, ++ Context& ctx) ++{ ++ crow::connections::systemBus->async_method_call( ++ [aResp = asyncResp, id = ctx.dbusArgs.id]( ++ const boost::system::error_code ec, const std::string& dbusPath) { ++ if (ec == boost::system::errc::file_exists) ++ { ++ messages::resourceAlreadyExists(aResp->res, "Trigger", "Id", ++ id); ++ return; ++ } ++ if (ec == boost::system::errc::too_many_files_open) ++ { ++ messages::createLimitReachedForResource(aResp->res); ++ return; ++ } ++ if (ec) ++ { ++ messages::internalError(aResp->res); ++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; ++ return; ++ } ++ ++ const std::optional& triggerId = ++ getTriggerIdFromDbusPath(dbusPath); ++ if (!triggerId) ++ { ++ messages::internalError(aResp->res); ++ BMCWEB_LOG_ERROR << "Unknown data returned by " ++ "AddTrigger DBus method"; ++ return; ++ } ++ ++ messages::created(aResp->res); ++ aResp->res.addHeader("Location", ++ triggerUri + std::string("/") + *triggerId); ++ }, ++ service, "/xyz/openbmc_project/Telemetry/Triggers", ++ "xyz.openbmc_project.Telemetry.TriggerManager", "AddTrigger", ++ "TelemetryService/" + ctx.dbusArgs.id, ctx.dbusArgs.name, ++ ctx.dbusArgs.actions, ctx.dbusArgs.sensors, ctx.dbusArgs.reportNames, ++ ctx.dbusArgs.thresholds); ++} ++ ++} // namespace add_trigger ++ ++namespace get_trigger ++{ ++ + inline std::optional + getRedfishFromDbusAction(const std::string& dbusAction) + { +@@ -270,6 +726,8 @@ inline bool fillTrigger( + return true; + } + ++} // namespace get_trigger ++ + } // namespace telemetry + + inline void requestRoutesTriggerCollection(App& app) +@@ -290,6 +748,62 @@ inline void requestRoutesTriggerCollection(App& app) + asyncResp, telemetry::triggerUri, interfaces, + "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService"); + }); ++ ++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/") ++ .privileges(redfish::privileges::postTriggersCollection) ++ .methods(boost::beast::http::verb::post)( ++ [](const crow::Request& req, ++ const std::shared_ptr& asyncResp) { ++ const auto ctx = ++ std::make_shared(); ++ if (!telemetry::add_trigger::parsePostTriggerParams( ++ asyncResp->res, req, *ctx)) ++ { ++ return; ++ } ++ ++ if (!ctx->parsedInfo.metricProperties || ++ ctx->parsedInfo.metricProperties->empty()) ++ { ++ telemetry::add_trigger::createTrigger(asyncResp, *ctx); ++ return; ++ } ++ ++ boost::container::flat_set> ++ chassisSensors; ++ if (!telemetry::getChassisSensorNode( ++ asyncResp, *ctx->parsedInfo.metricProperties, ++ chassisSensors)) ++ { ++ return; ++ } ++ ++ const auto finalizer = ++ std::make_shared([asyncResp, ctx] { ++ if (!telemetry::add_trigger::parseMetricProperties( ++ asyncResp->res, *ctx)) ++ { ++ return; ++ } ++ telemetry::add_trigger::createTrigger(asyncResp, *ctx); ++ }); ++ ++ for (const auto& [chassis, sensorType] : chassisSensors) ++ { ++ retrieveUriToDbusMap( ++ chassis, sensorType, ++ [asyncResp, ctx, ++ finalizer](const boost::beast::http::status status, ++ const boost::container::flat_map< ++ std::string, std::string>& uriToDbus) { ++ if (status == boost::beast::http::status::ok) ++ { ++ ctx->uriToDbusMerged.insert(uriToDbus.begin(), ++ uriToDbus.end()); ++ } ++ }); ++ } ++ }); + } + + inline void requestRoutesTrigger(App& app) +@@ -320,8 +834,8 @@ inline void requestRoutesTrigger(App& app) + return; + } + +- if (!telemetry::fillTrigger(asyncResp->res.jsonValue, +- id, ret)) ++ if (!telemetry::get_trigger::fillTrigger( ++ asyncResp->res.jsonValue, id, ret)) + { + messages::internalError(asyncResp->res); + } +-- +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync-Telmetry-service-with-EventService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync-Telmetry-service-with-EventService.patch new file mode 100644 index 000000000..f86f48528 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync-Telmetry-service-with-EventService.patch @@ -0,0 +1,284 @@ +From 383848b9088056371743a28eb1f9a3ed415dc46b Mon Sep 17 00:00:00 2001 +From: "Wludzik, Jozef" +Date: Tue, 15 Dec 2020 12:30:31 +0100 +Subject: [PATCH] Sync Telmetry service with EventService + +Synced the latest changes in Telemetry service with Event Service +code. Now assembling MetricReport is covered in single place in +code. Updated method of fetching Readings from Telemetry by +Event Service. Using ReportUpdate signal is no longer +supported. Now Event Service monitors for PropertiesChanged signal +from /xyz/openbmc_project/Telemetry/Reports path. + +Tested: + - Verified that EventListener received MetricReport response from + Event Service in insecure http push style eventing mode + +Change-Id: I2fc1841a6c9259a8bff30b34bddc0d4aabd41912 +Signed-off-by: Wludzik, Jozef +Signed-off-by: Lukasz Kazmierczak +--- + .../include/event_service_manager.hpp | 135 ++++++------------ + redfish-core/lib/metric_report.hpp | 29 ++-- + 2 files changed, 59 insertions(+), 105 deletions(-) + +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index 010c991..38ab879 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -14,6 +14,7 @@ + // limitations under the License. + */ + #pragma once ++#include "metric_report.hpp" + #include "registries.hpp" + #include "registries/base_message_registry.hpp" + #include "registries/openbmc_message_registry.hpp" +@@ -503,47 +504,32 @@ class Subscription : public persistent_data::UserSubscription + } + #endif + +- void filterAndSendReports(const std::string& id2, +- const std::string& readingsTs, +- const ReadingsObjType& readings) ++ void filterAndSendReports( ++ const std::string& id, ++ const std::variant& var) + { +- std::string metricReportDef = +- "/redfish/v1/TelemetryService/MetricReportDefinitions/" + id2; ++ std::string mrdUri = telemetry::metricReportDefinitionUri + id; + + // Empty list means no filter. Send everything. + if (metricReportDefinitions.size()) + { + if (std::find(metricReportDefinitions.begin(), + metricReportDefinitions.end(), +- metricReportDef) == metricReportDefinitions.end()) ++ mrdUri) == metricReportDefinitions.end()) + { + return; + } + } + +- nlohmann::json metricValuesArray = nlohmann::json::array(); +- for (const auto& it : readings) ++ nlohmann::json msg; ++ if (!telemetry::fillReport(msg, id, var)) + { +- metricValuesArray.push_back({}); +- nlohmann::json& entry = metricValuesArray.back(); +- +- auto& [id, property, value, timestamp] = it; +- +- entry = {{"MetricId", id}, +- {"MetricProperty", property}, +- {"MetricValue", std::to_string(value)}, +- {"Timestamp", crow::utility::getDateTime(timestamp)}}; ++ BMCWEB_LOG_ERROR << "Failed to fill the MetricReport for DBus " ++ "Report with id " ++ << id; ++ return; + } + +- nlohmann::json msg = { +- {"@odata.id", "/redfish/v1/TelemetryService/MetricReports/" + id}, +- {"@odata.type", "#MetricReport.v1_3_0.MetricReport"}, +- {"Id", id2}, +- {"Name", id2}, +- {"Timestamp", readingsTs}, +- {"MetricReportDefinition", {{"@odata.id", metricReportDef}}}, +- {"MetricValues", metricValuesArray}}; +- + this->sendEvent( + msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); + } +@@ -1309,73 +1295,43 @@ class EventServiceManager + } + + #endif +- +- void getMetricReading(const std::string& service, +- const std::string& objPath, const std::string& intf) ++ void getReadingsForReport(sdbusplus::message::message& msg) + { +- std::size_t found = objPath.find_last_of('/'); +- if (found == std::string::npos) ++ sdbusplus::message::object_path path(msg.get_path()); ++ std::string id = path.filename(); ++ if (id.empty()) + { +- BMCWEB_LOG_DEBUG << "Invalid objPath received"; ++ BMCWEB_LOG_ERROR << "Failed to get Id from path"; + return; + } + +- std::string idStr = objPath.substr(found + 1); +- if (idStr.empty()) ++ std::string interface; ++ std::vector< ++ std::pair>> ++ props; ++ std::vector invalidProps; ++ msg.read(interface, props, invalidProps); ++ ++ auto found = ++ std::find_if(props.begin(), props.end(), ++ [](const auto& x) { return x.first == "Readings"; }); ++ if (found == props.end()) + { +- BMCWEB_LOG_DEBUG << "Invalid ID in objPath"; ++ BMCWEB_LOG_INFO << "Failed to get Readings from Report properties"; + return; + } + +- crow::connections::systemBus->async_method_call( +- [idStr{std::move(idStr)}]( +- const boost::system::error_code ec, +- boost::container::flat_map< +- std::string, std::variant>& +- resp) { +- if (ec) +- { +- BMCWEB_LOG_DEBUG +- << "D-Bus call failed to GetAll metric readings."; +- return; +- } +- +- const int32_t* timestampPtr = +- std::get_if(&resp["Timestamp"]); +- if (!timestampPtr) +- { +- BMCWEB_LOG_DEBUG << "Failed to Get timestamp."; +- return; +- } +- +- ReadingsObjType* readingsPtr = +- std::get_if(&resp["Readings"]); +- if (!readingsPtr) +- { +- BMCWEB_LOG_DEBUG << "Failed to Get Readings property."; +- return; +- } +- +- if (!readingsPtr->size()) +- { +- BMCWEB_LOG_DEBUG << "No metrics report to be transferred"; +- return; +- } +- +- for (const auto& it : +- EventServiceManager::getInstance().subscriptionsMap) +- { +- std::shared_ptr entry = it.second; +- if (entry->eventFormatType == metricReportFormatType) +- { +- entry->filterAndSendReports( +- idStr, crow::utility::getDateTime(*timestampPtr), +- *readingsPtr); +- } +- } +- }, +- service, objPath, "org.freedesktop.DBus.Properties", "GetAll", +- intf); ++ const std::variant& readings = ++ found->second; ++ for (const auto& it : ++ EventServiceManager::getInstance().subscriptionsMap) ++ { ++ Subscription& entry = *it.second.get(); ++ if (entry.eventFormatType == metricReportFormatType) ++ { ++ entry.filterAndSendReports(id, readings); ++ } ++ } + } + + void unregisterMetricReportSignal() +@@ -1397,9 +1353,9 @@ class EventServiceManager + } + + BMCWEB_LOG_DEBUG << "Metrics report signal - Register"; +- std::string matchStr( +- "type='signal',member='ReportUpdate', " +- "interface='xyz.openbmc_project.MonitoringService.Report'"); ++ std::string matchStr = "type='signal',member='PropertiesChanged'," ++ "interface='org.freedesktop.DBus.Properties'," ++ "arg0=xyz.openbmc_project.Telemetry.Report"; + + matchTelemetryMonitor = std::make_shared( + *crow::connections::systemBus, matchStr, +@@ -1410,10 +1366,7 @@ class EventServiceManager + return; + } + +- std::string service = msg.get_sender(); +- std::string objPath = msg.get_path(); +- std::string intf = msg.get_interface(); +- getMetricReading(service, objPath, intf); ++ getReadingsForReport(msg); + }); + } + +diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp +index 159968a..c959495 100644 +--- a/redfish-core/lib/metric_report.hpp ++++ b/redfish-core/lib/metric_report.hpp +@@ -34,17 +34,14 @@ inline nlohmann::json toMetricValues(const Readings& readings) + return metricValues; + } + +-inline void fillReport(const std::shared_ptr& asyncResp, +- const std::string& id, ++inline bool fillReport(nlohmann::json& json, const std::string& id, + const std::variant& var) + { +- asyncResp->res.jsonValue["@odata.type"] = +- "#MetricReport.v1_3_0.MetricReport"; +- asyncResp->res.jsonValue["@odata.id"] = +- telemetry::metricReportUri + std::string("/") + id; +- asyncResp->res.jsonValue["Id"] = id; +- asyncResp->res.jsonValue["Name"] = id; +- asyncResp->res.jsonValue["MetricReportDefinition"]["@odata.id"] = ++ json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; ++ json["@odata.id"] = telemetry::metricReportUri + std::string("/") + id; ++ json["Id"] = id; ++ json["Name"] = id; ++ json["MetricReportDefinition"]["@odata.id"] = + telemetry::metricReportDefinitionUri + std::string("/") + id; + + const TimestampReadings* timestampReadings = +@@ -52,14 +49,14 @@ inline void fillReport(const std::shared_ptr& asyncResp, + if (!timestampReadings) + { + BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; +- messages::internalError(asyncResp->res); +- return; ++ return false; + } + + const auto& [timestamp, readings] = *timestampReadings; +- asyncResp->res.jsonValue["Timestamp"] = ++ json["Timestamp"] = + crow::utility::getDateTime(static_cast(timestamp)); +- asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings); ++ json["MetricValues"] = toMetricValues(readings); ++ return true; + } + } // namespace telemetry + +@@ -122,7 +119,11 @@ inline void requestRoutesMetricReport(App& app) + return; + } + +- telemetry::fillReport(asyncResp, id, ret); ++ if (!telemetry::fillReport( ++ asyncResp->res.jsonValue, id, ret)) ++ { ++ messages::internalError(asyncResp->res); ++ } + }, + telemetry::service, reportPath, + "org.freedesktop.DBus.Properties", "Get", +-- +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Revert-Remove-LogService-from-TelemetryService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Revert-Remove-LogService-from-TelemetryService.patch new file mode 100644 index 000000000..6b57dc912 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Revert-Remove-LogService-from-TelemetryService.patch @@ -0,0 +1,26 @@ +From 71b55e9773c387d6510650e7cf64f050a853ac77 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny +Date: Tue, 30 Nov 2021 16:29:12 +0100 +Subject: [PATCH] Revert "Remove LogService from TelemetryService" + +This reverts commit 2b3da45876aac57a36d3093379a992d699e7e396. +--- + redfish-core/lib/telemetry_service.hpp | 2 + + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp +index b79a5cd..e3e4a25 100644 +--- a/redfish-core/lib/telemetry_service.hpp ++++ b/redfish-core/lib/telemetry_service.hpp +@@ -25,6 +25,8 @@ inline void handleTelemetryServiceGet( + "/redfish/v1/TelemetryService/MetricReports"; + asyncResp->res.jsonValue["Triggers"]["@odata.id"] = + "/redfish/v1/TelemetryService/Triggers"; ++ asyncResp->res.jsonValue["LogService"]["@odata.id"] = ++ "/redfish/v1/Managers/bmc/LogServices/Journal"; + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch deleted file mode 100644 index 3088a7f9d..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch +++ /dev/null @@ -1,295 +0,0 @@ -From 541353a4e4b06de42b6a9a400629f5a5fba04e86 Mon Sep 17 00:00:00 2001 -From: "Wludzik, Jozef" -Date: Tue, 15 Dec 2020 12:30:31 +0100 -Subject: [PATCH] Sync Telmetry service with EventService - -Synced the latest changes in Telemetry service with Event Service -code. Now assembling MetricReport is covered in single place in -code. Updated method of fetching Readings from Telemetry by -Event Service. Using ReportUpdate signal is no longer -supported. Now Event Service monitors for PropertiesChanged signal -from /xyz/openbmc_project/Telemetry/Reports path. - -Tested: - - Verified that EventListener received MetricReport response from - Event Service in insecure http push style eventing mode - -Change-Id: I2fc1841a6c9259a8bff30b34bddc0d4aabd41912 -Signed-off-by: Wludzik, Jozef -Signed-off-by: Lukasz Kazmierczak ---- - .../include/event_service_manager.hpp | 156 ++++++------------ - redfish-core/lib/metric_report.hpp | 28 ++-- - 2 files changed, 69 insertions(+), 115 deletions(-) - -diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 3f398d7..cf9f658 100644 ---- a/redfish-core/include/event_service_manager.hpp -+++ b/redfish-core/include/event_service_manager.hpp -@@ -14,6 +14,7 @@ - // limitations under the License. - */ - #pragma once -+#include "metric_report.hpp" - #include "registries.hpp" - #include "registries/base_message_registry.hpp" - #include "registries/openbmc_message_registry.hpp" -@@ -511,47 +512,32 @@ class Subscription : public persistent_data::UserSubscription - } - #endif - -- void filterAndSendReports(const std::string& id2, -- const std::string& readingsTs, -- const ReadingsObjType& readings) -+ void filterAndSendReports( -+ const std::string& id, -+ const std::variant& var) - { -- std::string metricReportDef = -- "/redfish/v1/TelemetryService/MetricReportDefinitions/" + id2; -+ std::string mrdUri = telemetry::metricReportDefinitionUri + id; - - // Empty list means no filter. Send everything. - if (metricReportDefinitions.size()) - { - if (std::find(metricReportDefinitions.begin(), - metricReportDefinitions.end(), -- metricReportDef) == metricReportDefinitions.end()) -+ mrdUri) == metricReportDefinitions.end()) - { - return; - } - } - -- nlohmann::json metricValuesArray = nlohmann::json::array(); -- for (const auto& it : readings) -+ nlohmann::json msg; -+ if (!telemetry::fillReport(msg, id, var)) - { -- metricValuesArray.push_back({}); -- nlohmann::json& entry = metricValuesArray.back(); -- -- auto& [id, property, value, timestamp] = it; -- -- entry = {{"MetricId", id}, -- {"MetricProperty", property}, -- {"MetricValue", std::to_string(value)}, -- {"Timestamp", crow::utility::getDateTime(timestamp)}}; -+ BMCWEB_LOG_ERROR << "Failed to fill the MetricReport for DBus " -+ "Report with id " -+ << id; -+ return; - } - -- nlohmann::json msg = { -- {"@odata.id", "/redfish/v1/TelemetryService/MetricReports/" + id}, -- {"@odata.type", "#MetricReport.v1_3_0.MetricReport"}, -- {"Id", id2}, -- {"Name", id2}, -- {"Timestamp", readingsTs}, -- {"MetricReportDefinition", {{"@odata.id", metricReportDef}}}, -- {"MetricValues", metricValuesArray}}; -- - this->sendEvent( - msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); - } -@@ -1317,75 +1303,6 @@ class EventServiceManager - } - - #endif -- -- void getMetricReading(const std::string& service, -- const std::string& objPath, const std::string& intf) -- { -- std::size_t found = objPath.find_last_of('/'); -- if (found == std::string::npos) -- { -- BMCWEB_LOG_DEBUG << "Invalid objPath received"; -- return; -- } -- -- std::string idStr = objPath.substr(found + 1); -- if (idStr.empty()) -- { -- BMCWEB_LOG_DEBUG << "Invalid ID in objPath"; -- return; -- } -- -- crow::connections::systemBus->async_method_call( -- [idStr{std::move(idStr)}]( -- const boost::system::error_code ec, -- boost::container::flat_map< -- std::string, std::variant>& -- resp) { -- if (ec) -- { -- BMCWEB_LOG_DEBUG -- << "D-Bus call failed to GetAll metric readings."; -- return; -- } -- -- const int32_t* timestampPtr = -- std::get_if(&resp["Timestamp"]); -- if (!timestampPtr) -- { -- BMCWEB_LOG_DEBUG << "Failed to Get timestamp."; -- return; -- } -- -- ReadingsObjType* readingsPtr = -- std::get_if(&resp["Readings"]); -- if (!readingsPtr) -- { -- BMCWEB_LOG_DEBUG << "Failed to Get Readings property."; -- return; -- } -- -- if (!readingsPtr->size()) -- { -- BMCWEB_LOG_DEBUG << "No metrics report to be transferred"; -- return; -- } -- -- for (const auto& it : -- EventServiceManager::getInstance().subscriptionsMap) -- { -- std::shared_ptr entry = it.second; -- if (entry->eventFormatType == metricReportFormatType) -- { -- entry->filterAndSendReports( -- idStr, crow::utility::getDateTime(*timestampPtr), -- *readingsPtr); -- } -- } -- }, -- service, objPath, "org.freedesktop.DBus.Properties", "GetAll", -- intf); -- } -- - void unregisterMetricReportSignal() - { - if (matchTelemetryMonitor) -@@ -1405,9 +1322,11 @@ class EventServiceManager - } - - BMCWEB_LOG_DEBUG << "Metrics report signal - Register"; -- std::string matchStr( -- "type='signal',member='ReportUpdate', " -- "interface='xyz.openbmc_project.MonitoringService.Report'"); -+ std::string matchStr = "type='signal',member='PropertiesChanged'," -+ "interface='org.freedesktop.DBus.Properties'," -+ "path_namespace=/xyz/openbmc_project/Telemetry/" -+ "Reports/TelemetryService," -+ "arg0=xyz.openbmc_project.Telemetry.Report"; - - matchTelemetryMonitor = std::make_shared( - *crow::connections::systemBus, matchStr, -@@ -1418,10 +1337,43 @@ class EventServiceManager - return; - } - -- std::string service = msg.get_sender(); -- std::string objPath = msg.get_path(); -- std::string intf = msg.get_interface(); -- getMetricReading(service, objPath, intf); -+ sdbusplus::message::object_path path(msg.get_path()); -+ std::string id = path.filename(); -+ if (id.empty()) -+ { -+ BMCWEB_LOG_ERROR << "Failed to get Id from path"; -+ return; -+ } -+ -+ std::string intf; -+ std::vector>> -+ props; -+ std::vector invalidProps; -+ msg.read(intf, props, invalidProps); -+ -+ auto found = -+ std::find_if(props.begin(), props.end(), [](const auto& x) { -+ return x.first == "Readings"; -+ }); -+ if (found == props.end()) -+ { -+ BMCWEB_LOG_INFO -+ << "Failed to get Readings from Report properties"; -+ return; -+ } -+ -+ const std::variant& readings = -+ found->second; -+ for (const auto& it : -+ EventServiceManager::getInstance().subscriptionsMap) -+ { -+ Subscription& entry = *it.second.get(); -+ if (entry.eventFormatType == metricReportFormatType) -+ { -+ entry.filterAndSendReports(id, readings); -+ } -+ } - }); - } - -diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index 63c8c19..7fe281d 100644 ---- a/redfish-core/lib/metric_report.hpp -+++ b/redfish-core/lib/metric_report.hpp -@@ -33,16 +33,14 @@ inline nlohmann::json toMetricValues(const Readings& readings) - return metricValues; - } - --inline void fillReport(const std::shared_ptr& asyncResp, -- const std::string& id, -+inline bool fillReport(nlohmann::json& json, const std::string& id, - const std::variant& var) - { -- asyncResp->res.jsonValue["@odata.type"] = -- "#MetricReport.v1_3_0.MetricReport"; -- asyncResp->res.jsonValue["@odata.id"] = telemetry::metricReportUri + id; -- asyncResp->res.jsonValue["Id"] = id; -- asyncResp->res.jsonValue["Name"] = id; -- asyncResp->res.jsonValue["MetricReportDefinition"]["@odata.id"] = -+ json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; -+ json["@odata.id"] = telemetry::metricReportUri + id; -+ json["Id"] = id; -+ json["Name"] = id; -+ json["MetricReportDefinition"]["@odata.id"] = - telemetry::metricReportDefinitionUri + id; - - const TimestampReadings* timestampReadings = -@@ -50,14 +48,14 @@ inline void fillReport(const std::shared_ptr& asyncResp, - if (!timestampReadings) - { - BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; -- messages::internalError(asyncResp->res); -- return; -+ return false; - } - - const auto& [timestamp, readings] = *timestampReadings; -- asyncResp->res.jsonValue["Timestamp"] = -+ json["Timestamp"] = - crow::utility::getDateTime(static_cast(timestamp)); -- asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings); -+ json["MetricValues"] = toMetricValues(readings); -+ return true; - } - } // namespace telemetry - -@@ -118,7 +116,11 @@ inline void requestRoutesMetricReport(App& app) - return; - } - -- telemetry::fillReport(asyncResp, id, ret); -+ if (!telemetry::fillReport( -+ asyncResp->res.jsonValue, id, ret)) -+ { -+ messages::internalError(asyncResp->res); -+ } - }, - telemetry::service, reportPath, - "org.freedesktop.DBus.Properties", "Get", --- -2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch index 5dd2f51bc..a71511a96 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch @@ -1,6 +1,6 @@ -From 8ba1bcc3503cafb33b1a06356d4f8f92ae23e39a Mon Sep 17 00:00:00 2001 +From 41ee20f46f2c6d2e9e5418128993cd176d03a927 Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny -Date: Thu, 17 Jun 2021 13:37:57 +0000 +Date: Wed, 5 Jan 2022 14:54:18 +0100 Subject: [PATCH] Switched bmcweb to use new telemetry service API Added support for multiple MetricProperties. Added support for new @@ -15,51 +15,66 @@ Tested: Change-Id: I2cd17069e3ea015c8f5571c29278f1d50536272a Signed-off-by: Krzysztof Grobelny +Signed-off-by: Lukasz Kazmierczak --- - redfish-core/lib/metric_report_definition.hpp | 212 ++++++++++-------- - 1 file changed, 114 insertions(+), 98 deletions(-) + include/dbus_utility.hpp | 5 +- + redfish-core/lib/metric_report_definition.hpp | 310 +++++++++++------- + 2 files changed, 189 insertions(+), 126 deletions(-) +diff --git a/include/dbus_utility.hpp b/include/dbus_utility.hpp +index a971325..35109c4 100644 +--- a/include/dbus_utility.hpp ++++ b/include/dbus_utility.hpp +@@ -51,8 +51,9 @@ using DbusVariantType = sdbusplus::utility::dedup_variant_t< + std::vector>, + std::vector>>, + std::vector>, +- std::vector> ++ std::vector>, ++ std::string, std::string, std::string, uint64_t>> + >; + + // clang-format on diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp -index a0c4f1d..7c26787 100644 +index 2584afc..9512381 100644 --- a/redfish-core/lib/metric_report_definition.hpp +++ b/redfish-core/lib/metric_report_definition.hpp -@@ -7,6 +7,8 @@ - #include +@@ -8,6 +8,8 @@ #include + #include #include +#include +#include #include #include -@@ -17,87 +19,90 @@ namespace redfish +@@ -18,119 +20,156 @@ namespace redfish namespace telemetry { -using ReadingParameters = - std::vector>; -+using ReadingParameters = std::vector< -+ std::tuple, std::string, -+ std::string, std::string, std::string, uint64_t>>; ++using ReadingParameters = std::vector>, ++ std::string, std::string, std::string, uint64_t>>; - inline void fillReportDefinition( - const std::shared_ptr& asyncResp, const std::string& id, - const std::vector< -- std::pair>>& ret) -+ std::pair>>& -+ properties) +-inline void fillReportDefinition( +- const std::shared_ptr& asyncResp, const std::string& id, +- const std::vector>& +- ret) ++std::string toReadfishReportAction(std::string_view action) { - asyncResp->res.jsonValue["@odata.type"] = - "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; - asyncResp->res.jsonValue["@odata.id"] = -- telemetry::metricReportDefinitionUri + id; +- telemetry::metricReportDefinitionUri + std::string("/") + id; - asyncResp->res.jsonValue["Id"] = id; - asyncResp->res.jsonValue["Name"] = id; - asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = -- telemetry::metricReportUri + id; +- telemetry::metricReportUri + std::string("/") + id; - asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; - asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; - @@ -69,34 +84,16 @@ index a0c4f1d..7c26787 100644 - const std::string* reportingType = nullptr; - const uint64_t* interval = nullptr; - for (const auto& [key, var] : ret) -+ try ++ if (action == "EmitsReadingsUpdate") { - if (key == "EmitsReadingsUpdate") -+ bool emitsReadingsUpdate = false; -+ bool logToMetricReportsCollection = false; -+ ReadingParameters readingParams; -+ std::string reportingType; -+ uint64_t interval = 0u; -+ -+ sdbusplus::unpackProperties( -+ properties, "EmitsReadingsUpdate", emitsReadingsUpdate, -+ "LogToMetricReportsCollection", logToMetricReportsCollection, -+ "ReadingParametersFutureVersion", readingParams, "ReportingType", -+ reportingType, "Interval", interval); -+ -+ std::vector redfishReportActions; -+ redfishReportActions.reserve(2); -+ if (emitsReadingsUpdate) - { +- { - emitsReadingsUpdate = std::get_if(&var); -+ redfishReportActions.emplace_back("RedfishEvent"); - } +- } - else if (key == "LogToMetricReportsCollection") -+ if (logToMetricReportsCollection) - { +- { - logToMetricReportsCollection = std::get_if(&var); -+ redfishReportActions.emplace_back("LogToMetricReportsCollection"); - } +- } - else if (key == "ReadingParameters") - { - readingParams = std::get_if(&var); @@ -106,76 +103,126 @@ index a0c4f1d..7c26787 100644 - reportingType = std::get_if(&var); - } - else if (key == "Interval") -+ -+ nlohmann::json metrics = nlohmann::json::array(); -+ for (auto& [sensorPath, operationType, id, metadata, -+ collectionTimeScope, collectionDuration] : readingParams) - { +- { - interval = std::get_if(&var); -+ std::vector metricProperties; -+ -+ nlohmann::json parsedMetadata = nlohmann::json::parse(metadata); -+ if (!json_util::readJson(parsedMetadata, asyncResp->res, -+ "MetricProperties", metricProperties)) -+ { -+ BMCWEB_LOG_ERROR << "Failed to read metadata"; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ metrics.push_back({ -+ {"MetricId", id}, -+ {"MetricProperties", std::move(metricProperties)}, -+ }); - } -- } +- } ++ return "RedfishEvent"; + } - if (!emitsReadingsUpdate || !logToMetricReportsCollection || - !readingParams || !reportingType || !interval) -- { ++ if (action == "LogToMetricReportsCollection") + { - BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; - messages::internalError(asyncResp->res); - return; -- } ++ return "LogToMetricReportsCollection"; + } ++ return ""; ++} - std::vector redfishReportActions; - redfishReportActions.reserve(2); - if (*emitsReadingsUpdate) -- { ++std::string toDbusReportAction(std::string_view action) ++{ ++ if (action == "RedfishEvent") + { - redfishReportActions.emplace_back("RedfishEvent"); ++ return "EmitsReadingsUpdate"; + } +- if (*logToMetricReportsCollection) ++ if (action == "LogToMetricReportsCollection") + { +- redfishReportActions.emplace_back("LogToMetricReportsCollection"); ++ return "LogToMetricReportsCollection"; + } ++ return ""; ++} + +- nlohmann::json metrics = nlohmann::json::array(); +- for (auto& [sensorPath, operationType, id, metadata] : *readingParams) ++inline void fillReportDefinition( ++ const std::shared_ptr& asyncResp, const std::string& id, ++ const std::vector>& ++ properties) ++{ ++ try + { +- metrics.push_back({ +- {"MetricId", id}, +- {"MetricProperties", {metadata}}, +- }); ++ std::vector reportActions; ++ ReadingParameters readingParams; ++ std::string reportingType; ++ std::string reportUpdates; ++ std::string name; ++ uint64_t appendLimit = 0u; ++ uint64_t interval = 0u; ++ ++ sdbusplus::unpackProperties( ++ properties, "ReportActions", reportActions, "ReportUpdates", ++ reportUpdates, "AppendLimit", appendLimit, ++ "ReadingParametersFutureVersion", readingParams, "ReportingType", ++ reportingType, "Interval", interval, "Name", name); ++ ++ for (std::string& action : reportActions) ++ { ++ action = toReadfishReportAction(action); ++ ++ if (action.empty()) ++ { ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ } ++ ++ nlohmann::json metrics = nlohmann::json::array(); ++ for (auto& [sensorData, collectionFunction, id, collectionTimeScope, ++ collectionDuration] : readingParams) ++ { ++ std::vector metricProperties; ++ ++ for (auto& [sensorPath, sensorMetadata] : sensorData) ++ { ++ metricProperties.emplace_back(std::move(sensorMetadata)); ++ } ++ ++ metrics.push_back( ++ {{"MetricId", std::move(id)}, ++ {"MetricProperties", std::move(metricProperties)}, ++ {"CollectionFunction", std::move(collectionFunction)}, ++ {"CollectionDuration", ++ time_utils::toDurationString( ++ std::chrono::milliseconds(collectionDuration))}, ++ {"CollectionTimeScope", std::move(collectionTimeScope)}}); ++ } ++ + asyncResp->res.jsonValue["@odata.type"] = + "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; + asyncResp->res.jsonValue["@odata.id"] = -+ telemetry::metricReportDefinitionUri + id; ++ telemetry::metricReportDefinitionUri + std::string("/") + id; + asyncResp->res.jsonValue["Id"] = id; -+ asyncResp->res.jsonValue["Name"] = id; ++ asyncResp->res.jsonValue["Name"] = name; + asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = -+ telemetry::metricReportUri + id; ++ telemetry::metricReportUri + std::string("/") + id; + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; -+ asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; ++ asyncResp->res.jsonValue["ReportUpdates"] = reportUpdates; ++ asyncResp->res.jsonValue["AppendLimit"] = appendLimit; + asyncResp->res.jsonValue["Metrics"] = metrics; + asyncResp->res.jsonValue["MetricReportDefinitionType"] = reportingType; -+ asyncResp->res.jsonValue["ReportActions"] = redfishReportActions; ++ asyncResp->res.jsonValue["ReportActions"] = reportActions; + asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = + time_utils::toDurationString(std::chrono::milliseconds(interval)); - } -- if (*logToMetricReportsCollection) ++ } + catch (const sdbusplus::exception::UnpackPropertyError& error) - { -- redfishReportActions.emplace_back("LogToMetricReportsCollection"); ++ { + BMCWEB_LOG_ERROR << error.what() << ", property: " + << error.propertyName + ", reason: " << error.reason; -+ messages::internalError(asyncResp->res); - } -- -- nlohmann::json metrics = nlohmann::json::array(); -- for (auto& [sensorPath, operationType, id, metadata] : *readingParams) -+ catch (const nlohmann::json::parse_error& e) - { -- metrics.push_back({ -- {"MetricId", id}, -- {"MetricProperties", {metadata}}, -- }); -+ BMCWEB_LOG_ERROR << "Failed to parse metadata: " << e.what(); ++ messages::queryParameterValueFormatError( ++ asyncResp->res, ++ std::string(error.propertyName) + " " + std::string(error.reason), ++ error.what()); + messages::internalError(asyncResp->res); } - asyncResp->res.jsonValue["Metrics"] = metrics; @@ -186,33 +233,196 @@ index a0c4f1d..7c26787 100644 } struct AddReportArgs -@@ -275,6 +280,11 @@ class AddReport + { +- std::string name; ++ struct MetricArgs ++ { ++ std::string id; ++ std::vector uris; ++ std::optional collectionFunction; ++ std::optional collectionTimeScope; ++ std::optional collectionDuration; ++ }; ++ ++ std::optional id; ++ std::optional name; + std::string reportingType; +- bool emitsReadingsUpdate = false; +- bool logToMetricReportsCollection = false; ++ std::optional reportUpdates; ++ std::optional appendLimit; ++ std::vector reportActions; + uint64_t interval = 0; +- std::vector>> metrics; ++ std::vector metrics; + }; - for (const auto& [id, uris] : args.metrics) + inline bool toDbusReportActions(crow::Response& res, +- std::vector& actions, ++ const std::vector& actions, + AddReportArgs& args) + { + size_t index = 0; +- for (auto& action : actions) ++ for (const auto& action : actions) + { +- if (action == "RedfishEvent") +- { +- args.emitsReadingsUpdate = true; +- } +- else if (action == "LogToMetricReportsCollection") +- { +- args.logToMetricReportsCollection = true; +- } +- else ++ std::string dbusReportAction = toDbusReportAction(action); ++ ++ if (dbusReportAction.empty()) { -+ std::vector dbusPaths; -+ dbusPaths.reserve(uris.size()); -+ nlohmann::json metadata; -+ metadata["MetricProperties"] = nlohmann::json::array(); + messages::propertyValueNotInList( + res, action, "ReportActions/" + std::to_string(index)); + return false; + } + - for (size_t i = 0; i < uris.size(); i++) ++ args.reportActions.emplace_back(std::move(dbusReportAction)); + index++; + } + return true; +@@ -142,23 +181,12 @@ inline bool getUserParameters(crow::Response& res, const crow::Request& req, + std::vector metrics; + std::vector reportActions; + std::optional schedule; +- if (!json_util::readJson(req, res, "Id", args.name, "Metrics", metrics, +- "MetricReportDefinitionType", args.reportingType, +- "ReportActions", reportActions, "Schedule", +- schedule)) +- { +- return false; +- } +- +- constexpr const char* allowedCharactersInName = +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; +- if (args.name.empty() || args.name.find_first_not_of( +- allowedCharactersInName) != std::string::npos) ++ if (!json_util::readJson( ++ req, res, "Id", args.id, "Name", args.name, "Metrics", metrics, ++ "MetricReportDefinitionType", args.reportingType, "ReportUpdates", ++ args.reportUpdates, "AppendLimit", args.appendLimit, ++ "ReportActions", reportActions, "Schedule", schedule)) + { +- BMCWEB_LOG_ERROR << "Failed to match " << args.name +- << " with allowed character " +- << allowedCharactersInName; +- messages::propertyValueIncorrect(res, "Id", args.name); + return false; + } + +@@ -203,15 +231,35 @@ inline bool getUserParameters(crow::Response& res, const crow::Request& req, + args.metrics.reserve(metrics.size()); + for (auto& m : metrics) + { +- std::string id; +- std::vector uris; +- if (!json_util::readJson(m, res, "MetricId", id, "MetricProperties", +- uris)) ++ std::optional collectionDurationStr; ++ AddReportArgs::MetricArgs metricArgs; ++ if (!json_util::readJson( ++ m, res, "MetricId", metricArgs.id, "MetricProperties", ++ metricArgs.uris, "CollectionFunction", ++ metricArgs.collectionFunction, "CollectionTimeScope", ++ metricArgs.collectionTimeScope, "CollectionDuration", ++ collectionDurationStr)) + { + return false; + } + +- args.metrics.emplace_back(std::move(id), std::move(uris)); ++ if (collectionDurationStr) ++ { ++ std::optional duration = ++ time_utils::fromDurationString(*collectionDurationStr); ++ ++ if (!duration || duration->count() < 0) ++ { ++ messages::propertyValueIncorrect(res, "CollectionDuration", ++ *collectionDurationStr); ++ return false; ++ } ++ ++ metricArgs.collectionDuration = ++ static_cast(duration->count()); ++ } ++ ++ args.metrics.emplace_back(std::move(metricArgs)); + } + + return true; +@@ -219,13 +267,12 @@ inline bool getUserParameters(crow::Response& res, const crow::Request& req, + + inline bool getChassisSensorNodeFromMetrics( + const std::shared_ptr& asyncResp, +- const std::vector>>& +- metrics, ++ const std::vector& metrics, + boost::container::flat_set>& matched) + { +- for (const auto& [id, uris] : metrics) ++ for (const auto& metric : metrics) + { +- if (!getChassisSensorNode(asyncResp, uris, matched)) ++ if (!getChassisSensorNode(asyncResp, metric.uris, matched)) + { + return false; + } +@@ -251,11 +298,16 @@ class AddReport + telemetry::ReadingParameters readingParams; + readingParams.reserve(args.metrics.size()); + +- for (const auto& [id, uris] : args.metrics) ++ for (auto& metric : args.metrics) + { +- for (size_t i = 0; i < uris.size(); i++) ++ std::vector< ++ std::tuple> ++ sensorParams; ++ sensorParams.reserve(metric.uris.size()); ++ ++ for (size_t i = 0; i < metric.uris.size(); i++) { - const std::string& uri = uris[i]; -@@ -291,8 +301,12 @@ class AddReport +- const std::string& uri = uris[i]; ++ const std::string& uri = metric.uris[i]; + auto el = uriToDbus.find(uri); + if (el == uriToDbus.end()) + { +@@ -269,17 +321,23 @@ class AddReport } const std::string& dbusPath = el->second; - readingParams.emplace_back(dbusPath, "SINGLE", id, uri); -+ dbusPaths.emplace_back(dbusPath); -+ metadata["MetricProperties"].emplace_back(uri); ++ sensorParams.emplace_back(dbusPath, uri); } + -+ readingParams.emplace_back(dbusPaths, "SINGLE", id, metadata.dump(), -+ "Point", 0u); ++ readingParams.emplace_back( ++ std::move(sensorParams), metric.collectionFunction.value_or(""), ++ std::move(metric.id), metric.collectionTimeScope.value_or(""), ++ metric.collectionDuration.value_or(0u)); } const std::shared_ptr aResp = asyncResp; crow::connections::systemBus->async_method_call( -@@ -330,10 +344,10 @@ class AddReport +- [aResp, name = args.name, uriToDbus = std::move(uriToDbus)]( ++ [aResp, id = args.id.value_or(""), ++ uriToDbus = std::move(uriToDbus)]( + const boost::system::error_code ec, const std::string&) { + if (ec == boost::system::errc::file_exists) + { + messages::resourceAlreadyExists( +- aResp->res, "MetricReportDefinition", "Id", name); ++ aResp->res, "MetricReportDefinition", "Id", id); + return; + } + if (ec == boost::system::errc::too_many_files_open) +@@ -308,10 +366,12 @@ class AddReport messages::created(aResp->res); }, telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", @@ -221,81 +431,50 @@ index a0c4f1d..7c26787 100644 - args.emitsReadingsUpdate, args.logToMetricReportsCollection, - args.interval, readingParams); + "xyz.openbmc_project.Telemetry.ReportManager", -+ "AddReportFutureVersion", "TelemetryService/" + args.name, -+ args.reportingType, args.emitsReadingsUpdate, -+ args.logToMetricReportsCollection, args.interval, readingParams); ++ "AddReportFutureVersion", ++ "TelemetryService/" + args.id.value_or(""), args.name.value_or(""), ++ args.reportingType, args.reportUpdates.value_or("Overwrite"), ++ args.appendLimit.value_or(0), args.reportActions, args.interval, ++ readingParams); } void insert(const boost::container::flat_map& el) -@@ -415,37 +429,39 @@ inline void requestRoutesMetricReportDefinition(App& app) - BMCWEB_ROUTE(app, - "/redfish/v1/TelemetryService/MetricReportDefinitions//") - .privileges(redfish::privileges::getMetricReportDefinition) -- .methods(boost::beast::http::verb::get)( -- [](const crow::Request&, -- const std::shared_ptr& asyncResp, -- const std::string& id) { +@@ -399,12 +459,15 @@ inline void requestRoutesMetricReportDefinition(App& app) + [](const crow::Request&, + const std::shared_ptr& asyncResp, + const std::string& id) { - crow::connections::systemBus->async_method_call( -- [asyncResp, id]( -- const boost::system::error_code ec, -- const std::vector>>& ret) { -- if (ec.value() == EBADR || -- ec == boost::system::errc::host_unreachable) -- { -- messages::resourceNotFound( -- asyncResp->res, "MetricReportDefinition", id); -- return; -- } -- if (ec) -- { -- BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; -- messages::internalError(asyncResp->res); -- return; -- } -+ .methods( -+ boost::beast::http::verb::get)([](const crow::Request&, -+ const std::shared_ptr< -+ bmcweb::AsyncResp>& asyncResp, -+ const std::string& id) { -+ sdbusplus::asio::getAllProperties( -+ *crow::connections::systemBus, telemetry::service, -+ telemetry::getDbusReportPath(id), telemetry::reportInterface, -+ [asyncResp, -+ id](boost::system::error_code ec, -+ const std::vector>>& -+ properties) { -+ if (ec.value() == EBADR || -+ ec == boost::system::errc::host_unreachable) -+ { -+ messages::resourceNotFound( -+ asyncResp->res, "MetricReportDefinition", id); -+ return; -+ } -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ telemetry::fillReportDefinition(asyncResp, id, properties); -+ }); -+ }); ++ sdbusplus::asio::getAllProperties( ++ *crow::connections::systemBus, telemetry::service, ++ telemetry::getDbusReportPath(id), ++ telemetry::reportInterface, + [asyncResp, +- id](const boost::system::error_code ec, ++ id](boost::system::error_code ec, + const std::vector>& +- ret) { ++ properties) { + if (ec.value() == EBADR || + ec == boost::system::errc::host_unreachable) + { +@@ -419,12 +482,11 @@ inline void requestRoutesMetricReportDefinition(App& app) + return; + } - telemetry::fillReportDefinition(asyncResp, id, ret); - }, - telemetry::service, telemetry::getDbusReportPath(id), - "org.freedesktop.DBus.Properties", "GetAll", - telemetry::reportInterface); -- }); ++ telemetry::fillReportDefinition(asyncResp, id, ++ properties); ++ }); + }); ++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions//") .privileges(redfish::privileges::deleteMetricReportDefinitionCollection) -- 2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch deleted file mode 100644 index bf5a09d9d..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch +++ /dev/null @@ -1,268 +0,0 @@ -From dab3c96f9e39a89d7c359e22655650c7c16952ec Mon Sep 17 00:00:00 2001 -From: Krzysztof Grobelny -Date: Tue, 12 Oct 2021 08:06:13 +0000 -Subject: [PATCH] Add support for MetricDefinition property in MetricReport - -Added MetricDefinition as part of MetricValues array returned by -MetricReport. It contains single @odata.id with URI to proper -MetricDefinition resource - depending on MetricProperty. - -Testing done: -- GET request on redfish/v1/TelemetryService/MetricReports - got response with MetricDefinition and proper id inside - MetricValues array. - -Testing steps: -1. POST on redfish/v1/TelemetryService/MetricReportDefinitions - with body: -{ - "Id": "PeriodicReport_1", - "MetricReportDefinitionType": "Periodic", - "ReportActions": [ - "LogToMetricReportsCollection", - "RedfishEvent" - ], - "Metrics": [ - { - "MetricId": "sensor_1", - "MetricProperties": [ - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading" - ] - } - ], - "Schedule": { - "RecurrenceInterval": "PT10S" - } -} - -2. GET on redfish/v1/TelemetryService/MetricReports/PeriodicReport_1 - should return: -{ - "@odata.id": - "/redfish/v1/TelemetryService/MetricReports/PeriodicReport_1", - "@odata.type": "#MetricReport.v1_3_0.MetricReport", - "Id": "PeriodicReport_1", - "MetricReportDefinition": { - "@odata.id": - "/redfish/v1/TelemetryService/MetricReportDefinitions/PeriodicReport_1" - }, - "MetricValues": [ - { - "MetricDefinition": { - "@odata.id": - "/redfish/v1/TelemetryService/MetricDefinitions/Rotational" - }, - "MetricId": "sensor_1", - "MetricProperty": - "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading", - "MetricValue": "nan", - "Timestamp": "1970-01-01T00:03:21+00:00" - } - ], - "Name": "PeriodicReport_1", - "Timestamp": "1970-01-01T00:03:21+00:00" -} - -Change-Id: I7181c612f9b443015d551259bae25303aa436822 -Signed-off-by: Szymon Dompke ---- - meson.build | 4 +- - .../include/utils/telemetry_utils.hpp | 40 ++++++++++++ - redfish-core/lib/metric_report.hpp | 64 +++++++++++++++---- - redfish-core/lib/sensors.hpp | 2 + - 4 files changed, 95 insertions(+), 15 deletions(-) - -diff --git a/meson.build b/meson.build -index 6b6a8ab..218ea49 100644 ---- a/meson.build -+++ b/meson.build -@@ -377,6 +377,8 @@ srcfiles_unittest = [ - 'http/ut/utility_test.cpp' - ] - -+srcfiles_unittest_dependencies = ['redfish-core/src/error_messages.cpp', 'src/boost_url.cpp'] -+ - # Gather the Configuration data - - conf_data = configuration_data() -@@ -434,7 +436,7 @@ executable('bmcweb',srcfiles_bmcweb, - if(get_option('tests').enabled()) - foreach src_test : srcfiles_unittest - testname = src_test.split('/')[-1].split('.')[0] -- test(testname,executable(testname,src_test, -+ test(testname,executable(testname,[src_test] + srcfiles_unittest_dependencies, - include_directories : incdir, - install_dir: bindir, - dependencies: [ -diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp -index 1b4f75d..c0c5ba3 100644 ---- a/redfish-core/include/utils/telemetry_utils.hpp -+++ b/redfish-core/include/utils/telemetry_utils.hpp -@@ -17,6 +17,46 @@ constexpr const char* metricReportDefinitionUri = - constexpr const char* metricReportUri = - "/redfish/v1/TelemetryService/MetricReports/"; - -+inline std::optional -+ getMetadataJson(const std::string& metadataStr) -+{ -+ std::optional res = -+ nlohmann::json::parse(metadataStr, nullptr, false); -+ if (res->is_discarded()) -+ { -+ BMCWEB_LOG_ERROR << "Malformed reading metatadata JSON provided by " -+ "telemetry service."; -+ return std::nullopt; -+ } -+ return res; -+} -+ -+inline std::optional -+ readStringFromMetadata(const nlohmann::json& metadataJson, const char* key) -+{ -+ std::optional res; -+ if (auto it = metadataJson.find(key); it != metadataJson.end()) -+ { -+ if (const std::string* value = it->get_ptr()) -+ { -+ res = *value; -+ } -+ else -+ { -+ BMCWEB_LOG_ERROR << "Incorrect reading metatadata JSON provided by " -+ "telemetry service. Missing key '" -+ << key << "'."; -+ } -+ } -+ else -+ { -+ BMCWEB_LOG_ERROR << "Incorrect reading metatadata JSON provided by " -+ "telemetry service. Key '" -+ << key << "' has a wrong type."; -+ } -+ return res; -+} -+ - inline void - getReportCollection(const std::shared_ptr& asyncResp, - const std::string& uri) -diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index 7fe281d..13bf792 100644 ---- a/redfish-core/lib/metric_report.hpp -+++ b/redfish-core/lib/metric_report.hpp -@@ -1,5 +1,6 @@ - #pragma once - -+#include "sensors.hpp" - #include "utils/telemetry_utils.hpp" - - #include -@@ -15,34 +16,56 @@ using Readings = - std::vector>; - using TimestampReadings = std::tuple; - --inline nlohmann::json toMetricValues(const Readings& readings) -+inline bool fillMetricValues(nlohmann::json& metricValues, -+ const Readings& readings) - { -- nlohmann::json metricValues = nlohmann::json::array_t(); -- -- for (auto& [id, metadata, sensorValue, timestamp] : readings) -+ for (auto& [id, metadataStr, sensorValue, timestamp] : readings) - { -+ std::optional readingMetadataJson = -+ getMetadataJson(metadataStr); -+ if (!readingMetadataJson) -+ { -+ return false; -+ } -+ -+ std::optional sensorDbusPath = -+ readStringFromMetadata(*readingMetadataJson, "SensorDbusPath"); -+ if (!sensorDbusPath) -+ { -+ return false; -+ } -+ -+ std::optional sensorRedfishUri = -+ readStringFromMetadata(*readingMetadataJson, "SensorRedfishUri"); -+ if (!sensorRedfishUri) -+ { -+ return false; -+ } -+ -+ std::string metricDefinition = -+ std::string(metricDefinitionUri) + -+ sensors::toReadingType( -+ sdbusplus::message::object_path(*sensorDbusPath) -+ .parent_path() -+ .filename()); -+ - metricValues.push_back({ -+ {"MetricDefinition", -+ nlohmann::json{{"@odata.id", metricDefinition}}}, - {"MetricId", id}, -- {"MetricProperty", metadata}, -+ {"MetricProperty", *sensorRedfishUri}, - {"MetricValue", std::to_string(sensorValue)}, - {"Timestamp", - crow::utility::getDateTime(static_cast(timestamp))}, - }); - } - -- return metricValues; -+ return true; - } - - inline bool fillReport(nlohmann::json& json, const std::string& id, - const std::variant& var) - { -- json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; -- json["@odata.id"] = telemetry::metricReportUri + id; -- json["Id"] = id; -- json["Name"] = id; -- json["MetricReportDefinition"]["@odata.id"] = -- telemetry::metricReportDefinitionUri + id; -- - const TimestampReadings* timestampReadings = - std::get_if(&var); - if (!timestampReadings) -@@ -52,9 +75,22 @@ inline bool fillReport(nlohmann::json& json, const std::string& id, - } - - const auto& [timestamp, readings] = *timestampReadings; -+ nlohmann::json metricValues = nlohmann::json::array(); -+ if (!fillMetricValues(metricValues, readings)) -+ { -+ return false; -+ } -+ -+ json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; -+ json["@odata.id"] = telemetry::metricReportUri + id; -+ json["Id"] = id; -+ json["Name"] = id; -+ json["MetricReportDefinition"]["@odata.id"] = -+ telemetry::metricReportDefinitionUri + id; - json["Timestamp"] = - crow::utility::getDateTime(static_cast(timestamp)); -- json["MetricValues"] = toMetricValues(readings); -+ json["MetricValues"] = metricValues; -+ - return true; - } - } // namespace telemetry -diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp -index 7405e5a..9850b24 100644 ---- a/redfish-core/lib/sensors.hpp -+++ b/redfish-core/lib/sensors.hpp -@@ -21,6 +21,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - --- -2.25.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch deleted file mode 100644 index 0646aba5c..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch +++ /dev/null @@ -1,313 +0,0 @@ -From a1e89d356ba5ed594a1494efe8257946e1062396 Mon Sep 17 00:00:00 2001 -From: Lukasz Kazmierczak -Date: Tue, 31 Aug 2021 14:35:31 +0200 -Subject: [PATCH] Add GET method for TriggerCollection - -Added GET method for retrieving list of Triggers from Telemetry service - -Tested: -- Added single Trigger and requested result from bmcweb via - /redfish/v1/TelemetryService/Triggers -- Added multiple Triggers numeric and discrete, and requested results - from bmcweb via /redfish/v1/TelemetryService/Triggers -- Verified uri /redfish/v1/TelemetryService/Triggers by using - Redfish-Service-Validator (all passed) - -Signed-off-by: Lukasz Kazmierczak -Change-Id: Ide00eb44901ea1b97b80fc5c5ddfd97e393d4a04 ---- - redfish-core/include/redfish.hpp | 2 + - .../include/utils/telemetry_utils.hpp | 40 ++++++++--- - redfish-core/lib/metric_report.hpp | 6 +- - redfish-core/lib/metric_report_definition.hpp | 6 +- - redfish-core/lib/trigger.hpp | 31 ++++++++ - scripts/update_schemas.py | 1 + - static/redfish/v1/$metadata/index.xml | 3 + - .../v1/schema/TriggersCollection_v1.xml | 70 +++++++++++++++++++ - 8 files changed, 144 insertions(+), 15 deletions(-) - create mode 100644 redfish-core/lib/trigger.hpp - create mode 100644 static/redfish/v1/schema/TriggersCollection_v1.xml - -diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index 9fb0ffe..99b3fe6 100644 ---- a/redfish-core/include/redfish.hpp -+++ b/redfish-core/include/redfish.hpp -@@ -42,6 +42,7 @@ - #include "../lib/task.hpp" - #include "../lib/telemetry_service.hpp" - #include "../lib/thermal.hpp" -+#include "../lib/trigger.hpp" - #include "../lib/update_service.hpp" - #include "../lib/virtual_media.hpp" - -@@ -197,6 +198,7 @@ class RedfishService - - hypervisor::requestRoutesHypervisorSystems(app); - -+ requestRoutesTriggerCollection(app); - requestRoutesTelemetryService(app); - requestRoutesMetricReportDefinitionCollection(app); - requestRoutesMetricReportDefinition(app); -diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp -index c0c5ba3..df1aa68 100644 ---- a/redfish-core/include/utils/telemetry_utils.hpp -+++ b/redfish-core/include/utils/telemetry_utils.hpp -@@ -9,6 +9,8 @@ namespace telemetry - { - - constexpr const char* service = "xyz.openbmc_project.Telemetry"; -+constexpr const char* reportSubtree = -+ "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"; - constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report"; - constexpr const char* metricDefinitionUri = - "/redfish/v1/TelemetryService/MetricDefinitions/"; -@@ -16,6 +18,11 @@ constexpr const char* metricReportDefinitionUri = - "/redfish/v1/TelemetryService/MetricReportDefinitions/"; - constexpr const char* metricReportUri = - "/redfish/v1/TelemetryService/MetricReports/"; -+constexpr const char* triggerSubtree = -+ "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService"; -+constexpr const char* triggerInterface = -+ "xyz.openbmc_project.Telemetry.Trigger"; -+constexpr const char* triggerUri = "/redfish/v1/TelemetryService/Triggers/"; - - inline std::optional - getMetadataJson(const std::string& metadataStr) -@@ -57,15 +64,27 @@ inline std::optional - return res; - } - --inline void -- getReportCollection(const std::shared_ptr& asyncResp, -- const std::string& uri) -+struct CollectionParams - { -- const std::array interfaces = {reportInterface}; -+ const char* subtree; -+ int depth; -+ std::array interfaces; - -+ CollectionParams() = delete; -+ CollectionParams(const char* st, int dp, -+ const std::array& ifaces) : -+ subtree{st}, -+ depth{dp}, interfaces{ifaces} -+ {} -+}; -+ -+inline void getCollection(const std::shared_ptr& asyncResp, -+ const std::string& uri, -+ const CollectionParams& params) -+{ - crow::connections::systemBus->async_method_call( - [asyncResp, uri](const boost::system::error_code ec, -- const std::vector& reports) { -+ const std::vector& items) { - if (ec == boost::system::errc::io_error) - { - asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); -@@ -82,13 +101,13 @@ inline void - nlohmann::json& members = asyncResp->res.jsonValue["Members"]; - members = nlohmann::json::array(); - -- for (const std::string& report : reports) -+ for (const std::string& item : items) - { -- sdbusplus::message::object_path path(report); -+ sdbusplus::message::object_path path(item); - std::string name = path.filename(); - if (name.empty()) - { -- BMCWEB_LOG_ERROR << "Received invalid path: " << report; -+ BMCWEB_LOG_ERROR << "Received invalid path: " << item; - messages::internalError(asyncResp->res); - return; - } -@@ -99,9 +118,8 @@ inline void - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", -- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", -- "/xyz/openbmc_project/Telemetry/Reports/TelemetryService", 1, -- interfaces); -+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", params.subtree, -+ params.depth, params.interfaces); - } - - inline std::string getDbusReportPath(const std::string& id) -diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index 13bf792..ea4cd62 100644 ---- a/redfish-core/lib/metric_report.hpp -+++ b/redfish-core/lib/metric_report.hpp -@@ -108,8 +108,10 @@ inline void requestRoutesMetricReportCollection(App& app) - "/redfish/v1/TelemetryService/MetricReports"; - asyncResp->res.jsonValue["Name"] = "Metric Report Collection"; - -- telemetry::getReportCollection(asyncResp, -- telemetry::metricReportUri); -+ telemetry::getCollection( -+ asyncResp, telemetry::metricReportUri, -+ telemetry::CollectionParams(telemetry::reportSubtree, 1, -+ {telemetry::reportInterface})); - }); - } - -diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp -index 7c26787..c97a1df 100644 ---- a/redfish-core/lib/metric_report_definition.hpp -+++ b/redfish-core/lib/metric_report_definition.hpp -@@ -377,8 +377,10 @@ inline void requestRoutesMetricReportDefinitionCollection(App& app) - asyncResp->res.jsonValue["Name"] = - "Metric Definition Collection"; - -- telemetry::getReportCollection( -- asyncResp, telemetry::metricReportDefinitionUri); -+ telemetry::getCollection( -+ asyncResp, telemetry::metricReportDefinitionUri, -+ telemetry::CollectionParams(telemetry::reportSubtree, 1, -+ {telemetry::reportInterface})); - }); - - BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") -diff --git a/redfish-core/lib/trigger.hpp b/redfish-core/lib/trigger.hpp -new file mode 100644 -index 0000000..681b3b4 ---- /dev/null -+++ b/redfish-core/lib/trigger.hpp -@@ -0,0 +1,31 @@ -+#pragma once -+ -+#include "utils/telemetry_utils.hpp" -+ -+#include -+#include -+ -+namespace redfish -+{ -+ -+inline void requestRoutesTriggerCollection(App& app) -+{ -+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/") -+ .privileges(redfish::privileges::getTriggersCollection) -+ .methods(boost::beast::http::verb::get)( -+ [](const crow::Request&, -+ const std::shared_ptr& asyncResp) { -+ asyncResp->res.jsonValue["@odata.type"] = -+ "#TriggersCollection.TriggersCollection"; -+ asyncResp->res.jsonValue["@odata.id"] = -+ "/redfish/v1/TelemetryService/Triggers"; -+ asyncResp->res.jsonValue["Name"] = "Triggers Collection"; -+ -+ telemetry::getCollection( -+ asyncResp, telemetry::triggerUri, -+ telemetry::CollectionParams(telemetry::triggerSubtree, 1, -+ {telemetry::triggerInterface})); -+ }); -+} -+ -+} // namespace redfish -diff --git a/scripts/update_schemas.py b/scripts/update_schemas.py -index dd39278..d66a59a 100755 ---- a/scripts/update_schemas.py -+++ b/scripts/update_schemas.py -@@ -93,6 +93,7 @@ include_list = [ - 'TaskService', - 'TelemetryService', - 'Thermal', -+ 'TriggersCollection', - 'UpdateService', - 'VLanNetworkInterfaceCollection', - 'VLanNetworkInterface', -diff --git a/static/redfish/v1/$metadata/index.xml b/static/redfish/v1/$metadata/index.xml -index 876ebfb..75e3dd4 100644 ---- a/static/redfish/v1/$metadata/index.xml -+++ b/static/redfish/v1/$metadata/index.xml -@@ -2215,6 +2215,9 @@ - - - -+ -+ -+ - - - -diff --git a/static/redfish/v1/schema/TriggersCollection_v1.xml b/static/redfish/v1/schema/TriggersCollection_v1.xml -new file mode 100644 -index 0000000..399bebd ---- /dev/null -+++ b/static/redfish/v1/schema/TriggersCollection_v1.xml -@@ -0,0 +1,70 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ /redfish/v1/TelemetryService/Triggers -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ --- -2.25.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch deleted file mode 100644 index a80ac61c7..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch +++ /dev/null @@ -1,26 +0,0 @@ -From da575aaf0bdcb15be261d58314cf7bbbcd92dd74 Mon Sep 17 00:00:00 2001 -From: Krzysztof Grobelny -Date: Tue, 12 Oct 2021 08:08:06 +0000 -Subject: [PATCH] Revert "Remove LogService from TelemetryService" - -This reverts commit 2b3da45876aac57a36d3093379a992d699e7e396. ---- - redfish-core/lib/telemetry_service.hpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -index 027b51b..49471fe 100644 ---- a/redfish-core/lib/telemetry_service.hpp -+++ b/redfish-core/lib/telemetry_service.hpp -@@ -24,6 +24,8 @@ inline void handleTelemetryServiceGet( - "/redfish/v1/TelemetryService/MetricReports"; - asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricDefinitions"; -+ asyncResp->res.jsonValue["LogService"]["@odata.id"] = -+ "/redfish/v1/Managers/bmc/LogServices/Journal"; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, --- -2.25.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-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 deleted file mode 100644 index ffab743f6..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0ca8c383db8c9afbce63380955a20ada0acc20b7 Mon Sep 17 00:00:00 2001 -From: Krzysztof Grobelny -Date: Wed, 2 Jun 2021 12:44:43 +0000 -Subject: [PATCH] event service fix, added Context field to response - -Tested: - - Context field is present - - No regression detected - -Signed-off-by: Krzysztof Grobelny ---- - redfish-core/include/event_service_manager.hpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 2b957ea..289886b 100644 ---- a/redfish-core/include/event_service_manager.hpp -+++ b/redfish-core/include/event_service_manager.hpp -@@ -556,6 +556,7 @@ class Subscription - << id; - return; - } -+ msg["Context"] = customText; - - this->sendEvent( - msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); --- -2.25.1 - 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 deleted file mode 100644 index 548e3d9c6..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch +++ /dev/null @@ -1,46 +0,0 @@ -From ef83a4fb14648edc6c8370363ff88fb6f060a43b Mon Sep 17 00:00:00 2001 -From: P Dheeraj Srujan Kumar -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 ---- - 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& 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 90916ecec..541fa6aba 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 @@ -2,29 +2,11 @@ These patches are mirror of upstream TelemetryService implementation. Until change is integrated they will be manually merged here to enable feature in Intel builds. Current revisions: -- Add support for MetricDefinition scheme - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/102 - -- Sync Telmetry service with EventService - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/53 - -- Switched bmcweb to use new telemetry service API - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44270/19 - -- Add support for MetricDefinition property in MetricReport - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44512/24 - -- Add GET method for TriggerCollection - file://telemetry/0005-Add-GET-method-for-TriggerCollection.patch +- Add support for POST on TriggersCollection + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44935/19 - LogService field, actual implementation will be upstreamed with triggers feature - file://telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch - -- Event service fix for Context field - file://telemetry/0007-event-service-fix-added-Context-field-to-response.patch + file://telemetry/0002-Revert-Remove-LogService-from-TelemetryService.patch -- Generalize ReadingType in MetricDefinition - file://telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch - -- Add support for deleting terminated subscriptions - file://telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch +- Switched bmcweb to use new telemetry service API + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44270/28 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch index de316c4fa..9225d20f1 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch @@ -1,6 +1,6 @@ -From b6863f9a0c1c36705eba0c3181541f67cd1a202a Mon Sep 17 00:00:00 2001 +From e614dec3e007d3ceaa697fd7bb264dbc1ef496e5 Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny -Date: Wed, 14 Jul 2021 09:04:42 +0000 +Date: Wed, 1 Dec 2021 12:25:07 +0100 Subject: [PATCH] Revert "Disable nbd proxy from the build" NBD Proxy has been disabled upstream. Reenable as we use it for Virtual @@ -15,24 +15,24 @@ Change-Id: I19a88b30c1074dd376f2df8f5668245b638b881f 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/meson.build b/meson.build -index 650a5ec..5738b10 100644 +index c9066d4..51c7f9d 100644 --- a/meson.build +++ b/meson.build -@@ -83,7 +83,8 @@ feature_map = { - 'rest' : '-DBMCWEB_ENABLE_DBUS_REST', - 'static-hosting' : '-DBMCWEB_ENABLE_STATIC_HOSTING', - 'insecure-tftp-update' : '-DBMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE', -- #'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY', -+ 'validate-unsecure-feature' : '-DBMCWEB_ENABLE_VALIDATION_UNSECURE_FEATURE', -+ 'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY', - 'vm-websocket' : '-DBMCWEB_ENABLE_VM_WEBSOCKET', +@@ -86,7 +86,8 @@ feature_map = { + 'static-hosting' : '-DBMCWEB_ENABLE_STATIC_HOSTING', + 'vm-websocket' : '-DBMCWEB_ENABLE_VM_WEBSOCKET', + 'xtoken-auth' : '-DBMCWEB_ENABLE_XTOKEN_AUTHENTICATION', +- #'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY', ++ 'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY', ++ 'validate-unsecure-feature' : '-DBMCWEB_ENABLE_VALIDATION_UNSECURE_FEATURE', } + # Get the options status and build a project summary to show which flags are diff --git a/meson_options.txt b/meson_options.txt -index ff5b887..645f224 100644 +index 4661658..435f382 100644 --- a/meson_options.txt +++ b/meson_options.txt -@@ -3,14 +3,7 @@ option('yocto-deps', type: 'feature', value: 'disabled', description : 'Use YOCT +@@ -2,14 +2,7 @@ option('yocto-deps', type: 'feature', value: 'disabled', description : 'Use YOCT option('kvm', type : 'feature',value : 'enabled', description : 'Enable the KVM host video WebSocket. Path is \'/kvm/0\'. Video is from the BMC\'s \'/dev/video\' device.') option ('tests', type : 'feature', value : 'enabled', description : 'Enable Unit tests for bmcweb') option('vm-websocket', type : 'feature', value : 'enabled', description : '''Enable the Virtual Media WebSocket. Path is \'/vm/0/0\'to open the websocket. See https://github.com/openbmc/jsnbd/blob/master/README.''') @@ -45,10 +45,10 @@ index ff5b887..645f224 100644 -# opportunity to upstream their backend implementation -#option('vm-nbdproxy', type: 'feature', value : 'disabled', description : 'Enable the Virtual Media WebSocket.') +option('vm-nbdproxy', type: 'feature', value : 'disabled', description : 'Enable the Virtual Media WebSocket.') - option('rest', type : 'feature', value : 'enabled', description : '''Enable Phosphor REST (D-Bus) APIs. Paths directly map Phosphor D-Bus object paths, for example, \'/xyz/openbmc_project/logging/entry/enumerate\'. See https://github.com/openbmc/docs/blob/master/rest-api.md.''') + option('rest', type : 'feature', value : 'disabled', description : '''Enable Phosphor REST (D-Bus) APIs. Paths directly map Phosphor D-Bus object paths, for example, \'/xyz/openbmc_project/logging/entry/enumerate\'. See https://github.com/openbmc/docs/blob/master/rest-api.md.''') option('redfish', type : 'feature',value : 'enabled', description: 'Enable Redfish APIs. Paths are under \'/redfish/v1/\'. See https://github.com/openbmc/bmcweb/blob/master/DEVELOPING.md#redfish.') option('host-serial-socket', type : 'feature', value : 'enabled', description : 'Enable host serial console WebSocket. Path is \'/console0\'. See https://github.com/openbmc/docs/blob/master/console.md.') -@@ -39,6 +32,7 @@ option ('https_port', type : 'integer', min : 1, max : 65535, value : 443, descr +@@ -38,6 +31,7 @@ option ('https_port', type : 'integer', min : 1, max : 65535, value : 443, descr # the implications of doing so.In general, enabling these options will cause security # problems of varying degrees diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch index 439b05b3c..6443124c2 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch @@ -1,7 +1,7 @@ -From 437a2a854303ed4e05344684b1990806464268cd Mon Sep 17 00:00:00 2001 +From 47d907688368b98320d785aa8d285c9cf031d067 Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny -Date: Thu, 1 Jul 2021 10:08:27 +0000 -Subject: [PATCH] Invalid status code from InsertMedia REST methods GET, PUT, +Date: Wed, 1 Dec 2021 12:27:22 +0100 +Subject: [PATCH] Invalid status code from InsertMedia REST methods GET, PUT, DELETE, PATCH in proxy mode Add handlers for GET, PUT, DELETE, PATCH method and function that @@ -16,7 +16,7 @@ Signed-off-by: P Dheeraj Srujan Kumar 1 file changed, 137 insertions(+) diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp -index 3b9f7ef..7d77b9f 100644 +index 601b973..7d9dade 100644 --- a/redfish-core/lib/virtual_media.hpp +++ b/redfish-core/lib/virtual_media.hpp @@ -30,6 +30,117 @@ @@ -29,7 +29,7 @@ index 3b9f7ef..7d77b9f 100644 + * and sets suitable response code for unsupported REST method. + * + */ -+void CheckProxyMode(const std::shared_ptr& aResp, ++void checkProxyMode(const std::shared_ptr& aResp, + const crow::Request& req, const std::string& name, + const std::string& resName) +{ @@ -137,7 +137,7 @@ index 3b9f7ef..7d77b9f 100644 /** * @brief Function extracts transfer protocol name from URI. */ -@@ -844,6 +955,32 @@ inline void doVmAction(const std::shared_ptr& asyncResp, +@@ -850,6 +961,32 @@ inline void doVmAction(const std::shared_ptr& asyncResp, inline void requestNBDVirtualMediaRoutes(App& app) { @@ -148,7 +148,7 @@ index 3b9f7ef..7d77b9f 100644 + [](const crow::Request& req, + const std::shared_ptr& asyncResp, + const std::string& name, const std::string& resName) { -+ CheckProxyMode(asyncResp, req, name, resName); ++ checkProxyMode(asyncResp, req, name, resName); + }); + + for (auto method : @@ -163,13 +163,13 @@ index 3b9f7ef..7d77b9f 100644 + [](const crow::Request& req, + const std::shared_ptr& asyncResp, + const std::string& name, const std::string& resName) { -+ CheckProxyMode(asyncResp, req, name, resName); ++ checkProxyMode(asyncResp, req, name, resName); + }); + } + - BMCWEB_ROUTE(app, "/redfish/v1/Managers//VirtualMedia//Actions/" - "VirtualMedia.InsertMedia") - .privileges(redfish::privileges::postVirtualMedia) + BMCWEB_ROUTE( + app, + "/redfish/v1/Managers//VirtualMedia//Actions/VirtualMedia.InsertMedia") -- -2.17.1 +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend index a716e612d..7183dfffa 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend @@ -1,16 +1,10 @@ SRC_URI = "git://github.com/openbmc/bmcweb.git" -SRCREV = "b7ff344535c42af074c60bfb272ef66a2ba157b4" +SRCREV = "85ffe86a60f50ce9ad5728caf384a0dd0c8cc6a5" DEPENDS += "boost-url" FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" -# add a user called bmcweb for the server to assume -# bmcweb is part of group shadow for non-root pam authentication -USERADD_PARAM:${PN} = "-r -s /usr/sbin/nologin -d /home/bmcweb -m -G shadow bmcweb" - -GROUPADD_PARAM:${PN} = "web; redfish " - SRC_URI += "file://0001-Firmware-update-configuration-changes.patch \ file://0002-Use-chip-id-based-UUID-for-Service-Root.patch \ file://0010-managers-add-attributes-for-Manager.CommandShell.patch \ @@ -26,7 +20,9 @@ SRC_URI += "file://0001-Firmware-update-configuration-changes.patch \ file://0020-Redfish-Deny-set-AccountLockDuration-to-zero.patch \ file://0023-Add-get-IPMI-session-id-s-to-Redfish.patch \ file://0024-Add-count-sensor-type.patch \ - file://0025-Add-Model-CoreCount-to-ProcessorSummary.patch \ + file://0025-Add-Model-to-ProcessorSummary.patch \ + file://0026-Revert-Delete-the-copy-constructor-on-the-Request.patch \ + file://0027-Convert-VariantType-to-DbusVariantType.patch \ " # OOB Bios Config: @@ -36,10 +32,12 @@ SRC_URI += "file://biosconfig/0001-Define-Redfish-interface-Registries-Bios.patc file://biosconfig/0004-Add-support-to-ChangePassword-action.patch \ file://biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch \ file://biosconfig/0006-Add-fix-for-broken-feature-Pending-Attributes.patch \ + file://biosconfig/0007-Add-BiosAttributeRegistry-node-under-Registries.patch \ " # Virtual Media: Backend code is not upstreamed so downstream only patches. -SRC_URI += "file://vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch \ +SRC_URI += " \ + file://vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch \ file://vm/0002-bmcweb-handle-device-or-resource-busy-exception.patch \ file://vm/0003-Add-ConnectedVia-property-to-virtual-media-item-temp.patch \ file://vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch \ @@ -56,35 +54,26 @@ SRC_URI += "file://eventservice/0001-Add-unmerged-changes-for-http-retry-support file://eventservice/0006-Add-EventService-SSE-filter-support.patch \ file://eventservice/0007-EventService-Log-events-for-subscription-actions.patch \ file://eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch \ - file://eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch \ file://eventservice/0010-Remove-Terminated-Event-Subscriptions.patch \ file://eventservice/0011-Fix-bmcweb-crash-while-deleting-terminated-subscriptions.patch \ + file://eventservice/0012-Add-support-for-deleting-terminated-subscriptions.patch \ + file://eventservice/0013-event-service-fix-added-Context-field-to-response.patch \ " + # Temporary downstream mirror of upstream patches, see telemetry\README for details -SRC_URI += " file://telemetry/0001-Add-support-for-MetricDefinition-scheme.patch \ - file://telemetry/0002-Sync-Telmetry-service-with-EventService.patch \ +SRC_URI += " file://telemetry/0001-Add-support-for-POST-on-TriggersCollection.patch \ + file://telemetry/0002-Revert-Remove-LogService-from-TelemetryService.patch \ file://telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch \ - file://telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch \ - file://telemetry/0005-Add-GET-method-for-TriggerCollection.patch \ - file://telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch \ - file://telemetry/0007-event-service-fix-added-Context-field-to-response.patch \ - file://telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch \ " # Temporary downstream patch for routing and privilege changes -SRC_URI += " file://http_routing/0001-Add-asyncResp-support-during-handleUpgrade.patch \ - file://http_routing/0002-Move-privileges-to-separate-entity.patch \ - file://http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch \ - file://http_routing/0004-Add-Privileges-to-Websockets.patch \ - file://http_routing/0005-Add-Privileges-to-SseSockets.patch \ -" - -# Temporary fix: Move it to service file -do_install:append() { - install -d ${D}/var/lib/bmcweb - install -d ${D}/etc/ssl/certs/authority -} +SRC_URI += "file://http_routing/0001-Add-asyncResp-support-during-handleUpgrade.patch \ + file://http_routing/0002-Move-privileges-to-separate-entity.patch \ + file://http_routing/0003-Add-Support-for-privilege-check-in-handleUpgrade.patch \ + file://http_routing/0004-Add-Privileges-to-Websockets.patch \ + file://http_routing/0005-Add-Privileges-to-SseSockets.patch \ + " # Enable PFR support EXTRA_OEMESON += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '-Dredfish-provisioning-feature=enabled', '', d)}" -- cgit v1.2.3