diff options
author | jmbills <jason.m.bills@intel.com> | 2021-08-31 21:23:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-31 21:23:16 +0300 |
commit | 04cd92067d2481643df5010cb39b2134b648cf4d (patch) | |
tree | d98626c9763ad9048ac9bfd8269e12eced18d496 /meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry | |
parent | 10ad77d5bc86709d8ff7f95e7040e39f1c153903 (diff) | |
parent | 6f106a0a4ce15fe0678d4ffefd572e6978c72597 (diff) | |
download | openbmc-04cd92067d2481643df5010cb39b2134b648cf4d.tar.xz |
Update
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry')
7 files changed, 934 insertions, 211 deletions
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 index f03e49223..f53b7013f 100644 --- 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 @@ -1,4 +1,4 @@ -From 6acffea563905c00f4b6d00c738fe7516e03c724 Mon Sep 17 00:00:00 2001 +From e37e30943fcb1ba504658ed07d69f950ccf44585 Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> Date: Tue, 13 Apr 2021 13:00:18 +0000 Subject: [PATCH] Add support for MetricDefinition scheme @@ -12,28 +12,28 @@ 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 + - Successfully passed RedfishServiceValidator.py using witherspoon + image on QEMU Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com> Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com> Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00 --- redfish-core/include/redfish.hpp | 3 + - .../include/utils/get_chassis_names.hpp | 58 ++++ + .../include/utils/get_chassis_names.hpp | 58 +++++ .../include/utils/telemetry_utils.hpp | 2 + - redfish-core/lib/metric_definition.hpp | 264 ++++++++++++++++++ + redfish-core/lib/metric_definition.hpp | 242 ++++++++++++++++++ redfish-core/lib/sensors.hpp | 25 +- redfish-core/lib/telemetry_service.hpp | 2 + - 6 files changed, 342 insertions(+), 12 deletions(-) + 6 files changed, 320 insertions(+), 12 deletions(-) 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 4418c3d..594520d 100644 +index 1c7b695..9983b88 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp -@@ -25,6 +25,7 @@ +@@ -26,6 +26,7 @@ #include "../lib/managers.hpp" #include "../lib/memory.hpp" #include "../lib/message_registries.hpp" @@ -41,15 +41,15 @@ index 4418c3d..594520d 100644 #include "../lib/metric_report.hpp" #include "../lib/metric_report_definition.hpp" #include "../lib/network_protocol.hpp" -@@ -215,6 +216,8 @@ class RedfishService - nodes.emplace_back(std::make_unique<HypervisorResetActionInfo>(app)); +@@ -199,6 +200,8 @@ class RedfishService + requestRoutesMetricReportDefinition(app); + requestRoutesMetricReportCollection(app); + requestRoutesMetricReport(app); ++ requestRoutesMetricDefinitionCollection(app); ++ requestRoutesMetricDefinition(app); + } + }; - nodes.emplace_back(std::make_unique<TelemetryService>(app)); -+ nodes.emplace_back(std::make_unique<MetricDefinitionCollection>(app)); -+ nodes.emplace_back(std::make_unique<MetricDefinition>(app)); - nodes.emplace_back( - std::make_unique<MetricReportDefinitionCollection>(app)); - nodes.emplace_back(std::make_unique<MetricReportDefinition>(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 @@ -129,14 +129,13 @@ index 5872350..1b4f75d 100644 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..072fe20 +index 0000000..2443996 --- /dev/null +++ b/redfish-core/lib/metric_definition.hpp -@@ -0,0 +1,264 @@ +@@ -0,0 +1,242 @@ +#pragma once + +#include "async_resp.hpp" -+#include "node.hpp" +#include "sensors.hpp" +#include "utils/get_chassis_names.hpp" +#include "utils/telemetry_utils.hpp" @@ -196,72 +195,67 @@ index 0000000..072fe20 + +} // namespace telemetry + -+class MetricDefinitionCollection : public Node ++inline void requestRoutesMetricDefinitionCollection(App& app) +{ -+ public: -+ MetricDefinitionCollection(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricDefinitions/") -+ { -+ entityPrivileges = { -+ {boost::beast::http::verb::get, {{"Login"}}}, -+ {boost::beast::http::verb::head, {{"Login"}}}, -+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, -+ {boost::beast::http::verb::put, {{"ConfigureManager"}}}, -+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, -+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; -+ } -+ -+ private: -+ void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -+ const crow::Request&, const std::vector<std::string>&) override -+ { -+ 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; -+ -+ utils::getChassisNames( -+ [asyncResp](boost::system::error_code ec, -+ const std::vector<std::string>& chassisNames) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value(); -+ return; -+ } -+ -+ auto handleRetrieveUriToDbusMap = -+ [asyncResp](const boost::beast::http::status status, -+ const boost::container::flat_map< -+ std::string, std::string>& uriToDbus) { -+ if (status != boost::beast::http::status::ok) ++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/") ++ .privileges({{"Login"}}) ++ .methods(boost::beast::http::verb::get)( ++ [](const crow::Request&, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ 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; ++ ++ utils::getChassisNames( ++ [asyncResp](boost::system::error_code ec, ++ const std::vector<std::string>& chassisNames) { ++ if (ec) + { -+ BMCWEB_LOG_ERROR -+ << "Failed to retrieve URI to dbus " -+ "sensors map with err " -+ << static_cast<unsigned>(status); + messages::internalError(asyncResp->res); ++ BMCWEB_LOG_ERROR << "getChassisNames error: " ++ << ec.value(); + return; + } -+ telemetry::addMembers(asyncResp->res, uriToDbus); -+ }; + -+ for (const std::string& chassisName : chassisNames) -+ { -+ for (const auto& [sensorNode, _] : sensors::dbus::paths) -+ { -+ BMCWEB_LOG_DEBUG << "Chassis: " << chassisName -+ << " sensor: " << sensorNode; -+ retrieveUriToDbusMap(chassisName, sensorNode.data(), -+ handleRetrieveUriToDbusMap); -+ } -+ } ++ auto handleRetrieveUriToDbusMap = ++ [asyncResp]( ++ const boost::beast::http::status status, ++ const boost::container::flat_map< ++ std::string, std::string>& uriToDbus) { ++ if (status != boost::beast::http::status::ok) ++ { ++ BMCWEB_LOG_ERROR ++ << "Failed to retrieve URI to dbus " ++ "sensors map with err " ++ << static_cast<unsigned>(status); ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ telemetry::addMembers(asyncResp->res, ++ uriToDbus); ++ }; ++ ++ for (const std::string& chassisName : chassisNames) ++ { ++ for (const auto& [sensorNode, _] : ++ sensors::dbus::paths) ++ { ++ BMCWEB_LOG_DEBUG << "Chassis: " << chassisName ++ << " sensor: " << sensorNode; ++ retrieveUriToDbusMap( ++ chassisName, sensorNode.data(), ++ handleRetrieveUriToDbusMap); ++ } ++ } ++ }); + }); -+ } -+}; ++} + +namespace telemetry +{ @@ -306,99 +300,83 @@ index 0000000..072fe20 + +} // namespace telemetry + -+class MetricDefinition : public Node ++inline void requestRoutesMetricDefinition(App& app) +{ -+ public: -+ MetricDefinition(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricDefinitions/<str>/", -+ std::string()) -+ { -+ entityPrivileges = { -+ {boost::beast::http::verb::get, {{"Login"}}}, -+ {boost::beast::http::verb::head, {{"Login"}}}, -+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, -+ {boost::beast::http::verb::put, {{"ConfigureManager"}}}, -+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, -+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; -+ } -+ -+ private: -+ void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -+ const crow::Request&, -+ const std::vector<std::string>& params) override -+ { -+ if (params.size() != 1) -+ { -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ const std::string& readingType = params[0]; -+ -+ if (!telemetry::isSensorIdSupported(readingType)) -+ { -+ messages::resourceNotFound(asyncResp->res, "MetricDefinition", -+ readingType); -+ return; -+ } -+ -+ asyncResp->res.jsonValue["MetricProperties"] = nlohmann::json::array(); -+ asyncResp->res.jsonValue["Id"] = readingType; -+ asyncResp->res.jsonValue["Name"] = readingType; -+ asyncResp->res.jsonValue["@odata.id"] = -+ telemetry::metricDefinitionUri + readingType; -+ asyncResp->res.jsonValue["@odata.type"] = -+ "#MetricDefinition.v1_0_3.MetricDefinition"; -+ asyncResp->res.jsonValue["MetricDataType"] = "Decimal"; -+ asyncResp->res.jsonValue["MetricType"] = "Numeric"; -+ asyncResp->res.jsonValue["IsLinear"] = true; -+ asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; -+ asyncResp->res.jsonValue["Units"] = -+ sensors::toReadingUnits(readingType); -+ -+ utils::getChassisNames([asyncResp, -+ readingType](boost::system::error_code ec, -+ const std::vector<std::string>& -+ chassisNames) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value(); -+ return; -+ } -+ -+ auto handleRetrieveUriToDbusMap = -+ [asyncResp, readingType]( -+ const boost::beast::http::status status, -+ const boost::container::flat_map<std::string, std::string>& -+ uriToDbus) { -+ if (status != boost::beast::http::status::ok) -+ { -+ BMCWEB_LOG_ERROR << "Failed to retrieve URI to dbus " -+ "sensors map with err " -+ << static_cast<unsigned>(status); -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ telemetry::addMetricProperty(*asyncResp, readingType, -+ uriToDbus); -+ }; -+ -+ for (const std::string& chassisName : chassisNames) -+ { -+ for (const auto& [sensorNode, dbusPaths] : sensors::dbus::paths) ++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/<str>/") ++ .privileges({{"Login"}}) ++ .methods(boost::beast::http::verb::get)( ++ [](const crow::Request&, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, ++ const std::string& readingType) { ++ if (!telemetry::isSensorIdSupported(readingType)) + { -+ retrieveUriToDbusMap(chassisName, sensorNode.data(), -+ handleRetrieveUriToDbusMap); ++ messages::resourceNotFound(asyncResp->res, ++ "MetricDefinition", readingType); ++ return; + } -+ } -+ }); -+ } -+}; ++ ++ asyncResp->res.jsonValue["MetricProperties"] = ++ nlohmann::json::array(); ++ asyncResp->res.jsonValue["Id"] = readingType; ++ asyncResp->res.jsonValue["Name"] = readingType; ++ asyncResp->res.jsonValue["@odata.id"] = ++ telemetry::metricDefinitionUri + readingType; ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#MetricDefinition.v1_0_3.MetricDefinition"; ++ asyncResp->res.jsonValue["MetricDataType"] = "Decimal"; ++ asyncResp->res.jsonValue["MetricType"] = "Numeric"; ++ asyncResp->res.jsonValue["IsLinear"] = true; ++ asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; ++ asyncResp->res.jsonValue["Units"] = ++ sensors::toReadingUnits(readingType); ++ ++ utils::getChassisNames( ++ [asyncResp, readingType]( ++ boost::system::error_code ec, ++ const std::vector<std::string>& chassisNames) { ++ if (ec) ++ { ++ messages::internalError(asyncResp->res); ++ BMCWEB_LOG_ERROR << "getChassisNames error: " ++ << ec.value(); ++ return; ++ } ++ ++ auto handleRetrieveUriToDbusMap = ++ [asyncResp, readingType]( ++ const boost::beast::http::status status, ++ const boost::container::flat_map< ++ std::string, std::string>& uriToDbus) { ++ if (status != boost::beast::http::status::ok) ++ { ++ BMCWEB_LOG_ERROR ++ << "Failed to retrieve URI to dbus " ++ "sensors map with err " ++ << static_cast<unsigned>(status); ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ telemetry::addMetricProperty( ++ *asyncResp, readingType, uriToDbus); ++ }; ++ ++ for (const std::string& chassisName : chassisNames) ++ { ++ for (const auto& [sensorNode, dbusPaths] : ++ sensors::dbus::paths) ++ { ++ retrieveUriToDbusMap( ++ chassisName, sensorNode.data(), ++ handleRetrieveUriToDbusMap); ++ } ++ } ++ }); ++ }); ++} + +} // namespace redfish diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp -index e7f4cde..b16b014 100644 +index d986565..bccbb94 100644 --- a/redfish-core/lib/sensors.hpp +++ b/redfish-core/lib/sensors.hpp @@ -111,46 +111,47 @@ inline const char* toReadingType(const std::string& sensorType) @@ -474,18 +452,17 @@ index e7f4cde..b16b014 100644 else { diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -index 9ec0737..de9c800 100644 +index ad86d5c..c4962e9 100644 --- a/redfish-core/lib/telemetry_service.hpp +++ b/redfish-core/lib/telemetry_service.hpp -@@ -32,6 +32,8 @@ class TelemetryService : public Node - asyncResp->res.jsonValue["Id"] = "TelemetryService"; - asyncResp->res.jsonValue["Name"] = "Telemetry Service"; +@@ -29,6 +29,8 @@ inline void requestRoutesTelemetryService(App& app) + "/redfish/v1/TelemetryService/MetricReportDefinitions"; + asyncResp->res.jsonValue["MetricReports"]["@odata.id"] = + "/redfish/v1/TelemetryService/MetricReports"; ++ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] = ++ "/redfish/v1/TelemetryService/MetricDefinitions"; -+ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricDefinitions"; - asyncResp->res.jsonValue["MetricReportDefinitions"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricReportDefinitions"; - asyncResp->res.jsonValue["MetricReports"]["@odata.id"] = + crow::connections::systemBus->async_method_call( + [asyncResp]( -- -2.17.1 - +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 index 9b77c29df..0ca58a114 100644 --- 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 @@ -1,4 +1,4 @@ -From 206411b4c9b603e7b0edf63e03c0ef7bf10b09b2 Mon Sep 17 00:00:00 2001 +From 277d261ef3b1723c9d198baf4b84d2e01a7460b8 Mon Sep 17 00:00:00 2001 From: "Wludzik, Jozef" <jozef.wludzik@intel.com> Date: Tue, 15 Dec 2020 12:30:31 +0100 Subject: [PATCH] Sync Telmetry service with EventService @@ -22,7 +22,7 @@ Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com> 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 a1761bb..0e2ebfd 100644 +index 11190ef..ffe9435 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp @@ -14,6 +14,7 @@ @@ -30,10 +30,10 @@ index a1761bb..0e2ebfd 100644 */ #pragma once +#include "metric_report.hpp" - #include "node.hpp" #include "registries.hpp" #include "registries/base_message_registry.hpp" -@@ -523,47 +524,32 @@ class Subscription + #include "registries/openbmc_message_registry.hpp" +@@ -522,47 +523,32 @@ class Subscription } #endif @@ -92,7 +92,7 @@ index a1761bb..0e2ebfd 100644 this->sendEvent( msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); } -@@ -1359,75 +1345,6 @@ class EventServiceManager +@@ -1358,75 +1344,6 @@ class EventServiceManager } #endif @@ -168,7 +168,7 @@ index a1761bb..0e2ebfd 100644 void unregisterMetricReportSignal() { if (matchTelemetryMonitor) -@@ -1447,9 +1364,11 @@ class EventServiceManager +@@ -1446,9 +1363,11 @@ class EventServiceManager } BMCWEB_LOG_DEBUG << "Metrics report signal - Register"; @@ -183,7 +183,7 @@ index a1761bb..0e2ebfd 100644 matchTelemetryMonitor = std::make_shared<sdbusplus::bus::match::match>( *crow::connections::systemBus, matchStr, -@@ -1460,10 +1379,43 @@ class EventServiceManager +@@ -1459,10 +1378,43 @@ class EventServiceManager return; } @@ -232,10 +232,10 @@ index a1761bb..0e2ebfd 100644 } diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index ad15a05..18a6dcc 100644 +index 66f4f93..a43f6a6 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp -@@ -31,16 +31,14 @@ inline nlohmann::json toMetricValues(const Readings& readings) +@@ -32,16 +32,14 @@ inline nlohmann::json toMetricValues(const Readings& readings) return metricValues; } @@ -258,7 +258,7 @@ index ad15a05..18a6dcc 100644 telemetry::metricReportDefinitionUri + id; const TimestampReadings* timestampReadings = -@@ -48,14 +46,14 @@ inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, +@@ -49,14 +47,14 @@ inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, if (!timestampReadings) { BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; @@ -277,18 +277,18 @@ index ad15a05..18a6dcc 100644 } } // namespace telemetry -@@ -145,7 +143,11 @@ class MetricReport : public Node - return; - } +@@ -117,7 +115,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", +- 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-Revert-Remove-LogService-from-TelemetryService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch index 645351a51..987a43b4c 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch @@ -1,6 +1,6 @@ -From dc7e43c70285596195efd9d328b303091794278c Mon Sep 17 00:00:00 2001 +From 472ac5f15a19917042852b243e8b668b3ab49e32 Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> -Date: Mon, 31 May 2021 10:08:57 +0000 +Date: Tue, 22 Jun 2021 13:59:48 +0000 Subject: [PATCH] Revert "Remove LogService from TelemetryService" This reverts commit 2b3da45876aac57a36d3093379a992d699e7e396. @@ -9,18 +9,18 @@ This reverts commit 2b3da45876aac57a36d3093379a992d699e7e396. 1 file changed, 2 insertions(+) diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -index de9c800..f05bf6d 100644 +index 37221c3..f3a1efb 100644 --- a/redfish-core/lib/telemetry_service.hpp +++ b/redfish-core/lib/telemetry_service.hpp -@@ -38,6 +38,8 @@ class TelemetryService : public Node - "/redfish/v1/TelemetryService/MetricReportDefinitions"; - asyncResp->res.jsonValue["MetricReports"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricReports"; -+ asyncResp->res.jsonValue["LogService"]["@odata.id"] = -+ "/redfish/v1/Managers/bmc/LogServices/Journal"; +@@ -30,6 +30,8 @@ inline void requestRoutesTelemetryService(App& app) + "/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]( + crow::connections::systemBus->async_method_call( + [asyncResp]( -- 2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Switched-bmcweb-to-use-new-telemetry-service-API.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Switched-bmcweb-to-use-new-telemetry-service-API.patch new file mode 100644 index 000000000..4e326ff88 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Switched-bmcweb-to-use-new-telemetry-service-API.patch @@ -0,0 +1,301 @@ +From 51869fd549cd826981ad30c6cdea4c4e94a972db Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Thu, 17 Jun 2021 13:37:57 +0000 +Subject: [PATCH] Switched bmcweb to use new telemetry service API + +Added support for multiple MetricProperties. Added support for new +parameters: CollectionTimeScope, CollectionDuration. + +Tested: + - It is possible to create MetricReportDefinitions with multiple + MetricProperties. + - Stub values for new parameters are correctly passed to telemetry + service. + - All existing telemetry service functionalities remain unchanged. + +Change-Id: I2cd17069e3ea015c8f5571c29278f1d50536272a +Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +--- + redfish-core/lib/metric_report_definition.hpp | 212 ++++++++++-------- + 1 file changed, 114 insertions(+), 98 deletions(-) + +diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp +index a0c4f1d..7c26787 100644 +--- a/redfish-core/lib/metric_report_definition.hpp ++++ b/redfish-core/lib/metric_report_definition.hpp +@@ -7,6 +7,8 @@ + #include <app.hpp> + #include <boost/container/flat_map.hpp> + #include <registries/privilege_registry.hpp> ++#include <sdbusplus/asio/property.hpp> ++#include <sdbusplus/unpack_properties.hpp> + + #include <tuple> + #include <variant> +@@ -17,87 +19,90 @@ namespace redfish + namespace telemetry + { + +-using ReadingParameters = +- std::vector<std::tuple<sdbusplus::message::object_path, std::string, +- std::string, std::string>>; ++using ReadingParameters = std::vector< ++ std::tuple<std::vector<sdbusplus::message::object_path>, std::string, ++ std::string, std::string, std::string, uint64_t>>; + + inline void fillReportDefinition( + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, + const std::vector< +- std::pair<std::string, std::variant<std::string, bool, uint64_t, +- ReadingParameters>>>& ret) ++ std::pair<std::string, std::variant<std::monostate, std::string, bool, ++ uint64_t, ReadingParameters>>>& ++ properties) + { +- asyncResp->res.jsonValue["@odata.type"] = +- "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; +- asyncResp->res.jsonValue["@odata.id"] = +- telemetry::metricReportDefinitionUri + id; +- asyncResp->res.jsonValue["Id"] = id; +- asyncResp->res.jsonValue["Name"] = id; +- asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = +- telemetry::metricReportUri + id; +- asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; +- asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; +- +- const bool* emitsReadingsUpdate = nullptr; +- const bool* logToMetricReportsCollection = nullptr; +- const ReadingParameters* readingParams = nullptr; +- const std::string* reportingType = nullptr; +- const uint64_t* interval = nullptr; +- for (const auto& [key, var] : ret) ++ try + { +- 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<std::string> redfishReportActions; ++ redfishReportActions.reserve(2); ++ if (emitsReadingsUpdate) + { +- emitsReadingsUpdate = std::get_if<bool>(&var); ++ redfishReportActions.emplace_back("RedfishEvent"); + } +- else if (key == "LogToMetricReportsCollection") ++ if (logToMetricReportsCollection) + { +- logToMetricReportsCollection = std::get_if<bool>(&var); ++ redfishReportActions.emplace_back("LogToMetricReportsCollection"); + } +- else if (key == "ReadingParameters") +- { +- readingParams = std::get_if<ReadingParameters>(&var); +- } +- else if (key == "ReportingType") +- { +- reportingType = std::get_if<std::string>(&var); +- } +- else if (key == "Interval") ++ ++ nlohmann::json metrics = nlohmann::json::array(); ++ for (auto& [sensorPath, operationType, id, metadata, ++ collectionTimeScope, collectionDuration] : readingParams) + { +- interval = std::get_if<uint64_t>(&var); ++ std::vector<std::string> 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)}, ++ }); + } +- } +- if (!emitsReadingsUpdate || !logToMetricReportsCollection || +- !readingParams || !reportingType || !interval) +- { +- BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; +- messages::internalError(asyncResp->res); +- return; +- } + +- std::vector<std::string> redfishReportActions; +- redfishReportActions.reserve(2); +- if (*emitsReadingsUpdate) +- { +- redfishReportActions.emplace_back("RedfishEvent"); ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; ++ asyncResp->res.jsonValue["@odata.id"] = ++ telemetry::metricReportDefinitionUri + id; ++ asyncResp->res.jsonValue["Id"] = id; ++ asyncResp->res.jsonValue["Name"] = id; ++ asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = ++ telemetry::metricReportUri + id; ++ asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; ++ asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; ++ asyncResp->res.jsonValue["Metrics"] = metrics; ++ asyncResp->res.jsonValue["MetricReportDefinitionType"] = reportingType; ++ asyncResp->res.jsonValue["ReportActions"] = redfishReportActions; ++ 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::internalError(asyncResp->res); + } +- asyncResp->res.jsonValue["Metrics"] = metrics; +- asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType; +- asyncResp->res.jsonValue["ReportActions"] = redfishReportActions; +- asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = +- time_utils::toDurationString(std::chrono::milliseconds(*interval)); + } + + struct AddReportArgs +@@ -275,6 +280,11 @@ class AddReport + + for (const auto& [id, uris] : args.metrics) + { ++ std::vector<sdbusplus::message::object_path> dbusPaths; ++ dbusPaths.reserve(uris.size()); ++ nlohmann::json metadata; ++ metadata["MetricProperties"] = nlohmann::json::array(); ++ + for (size_t i = 0; i < uris.size(); i++) + { + const std::string& uri = uris[i]; +@@ -291,8 +301,12 @@ class AddReport + } + + const std::string& dbusPath = el->second; +- readingParams.emplace_back(dbusPath, "SINGLE", id, uri); ++ dbusPaths.emplace_back(dbusPath); ++ metadata["MetricProperties"].emplace_back(uri); + } ++ ++ readingParams.emplace_back(dbusPaths, "SINGLE", id, metadata.dump(), ++ "Point", 0u); + } + const std::shared_ptr<bmcweb::AsyncResp> aResp = asyncResp; + crow::connections::systemBus->async_method_call( +@@ -330,10 +344,10 @@ class AddReport + messages::created(aResp->res); + }, + telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", +- "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", +- "TelemetryService/" + args.name, args.reportingType, +- 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); + } + + void insert(const boost::container::flat_map<std::string, std::string>& el) +@@ -415,37 +429,39 @@ inline void requestRoutesMetricReportDefinition(App& app) + BMCWEB_ROUTE(app, + "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") + .privileges(redfish::privileges::getMetricReportDefinition) +- .methods(boost::beast::http::verb::get)( +- [](const crow::Request&, +- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, +- const std::string& id) { +- crow::connections::systemBus->async_method_call( +- [asyncResp, id]( +- const boost::system::error_code ec, +- const std::vector<std::pair< +- std::string, +- std::variant<std::string, bool, uint64_t, +- telemetry::ReadingParameters>>>& 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<std::pair< ++ std::string, ++ std::variant<std::monostate, std::string, bool, ++ uint64_t, telemetry::ReadingParameters>>>& ++ 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); ++ }); ++ }); + +- telemetry::fillReportDefinition(asyncResp, id, ret); +- }, +- telemetry::service, telemetry::getDbusReportPath(id), +- "org.freedesktop.DBus.Properties", "GetAll", +- telemetry::reportInterface); +- }); + BMCWEB_ROUTE(app, + "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") + .privileges(redfish::privileges::deleteMetricReportDefinitionCollection) +-- +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-support-for-MetricDefinition-property-in-MetricReport.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-support-for-MetricDefinition-property-in-MetricReport.patch new file mode 100644 index 000000000..d3a7c0a35 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-support-for-MetricDefinition-property-in-MetricReport.patch @@ -0,0 +1,268 @@ +From d37ba16f837380ea5fbd7fae2d0f2e229c601754 Mon Sep 17 00:00:00 2001 +From: Szymon Dompke <szymon.dompke@intel.com> +Date: Mon, 28 Jun 2021 11:10:23 +0200 +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 <szymon.dompke@intel.com> +--- + 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 bdc514b..aadfd7d 100644 +--- a/meson.build ++++ b/meson.build +@@ -354,6 +354,8 @@ srcfiles_unittest = ['include/ut/dbus_utility_test.cpp', + 'redfish-core/ut/time_utils_test.cpp', + 'http/ut/utility_test.cpp'] + ++srcfiles_unittest_dependencies = ['redfish-core/src/error_messages.cpp'] ++ + # Gather the Configuration data + + conf_data = configuration_data() +@@ -411,7 +413,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<nlohmann::json> ++ getMetadataJson(const std::string& metadataStr) ++{ ++ std::optional<nlohmann::json> 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<std::string> ++ readStringFromMetadata(const nlohmann::json& metadataJson, const char* key) ++{ ++ std::optional<std::string> res; ++ if (auto it = metadataJson.find(key); it != metadataJson.end()) ++ { ++ if (const std::string* value = it->get_ptr<const std::string*>()) ++ { ++ 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<bmcweb::AsyncResp>& 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 <app.hpp> +@@ -15,34 +16,56 @@ using Readings = + std::vector<std::tuple<std::string, std::string, double, uint64_t>>; + using TimestampReadings = std::tuple<uint64_t, Readings>; + +-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<nlohmann::json> readingMetadataJson = ++ getMetadataJson(metadataStr); ++ if (!readingMetadataJson) ++ { ++ return false; ++ } ++ ++ std::optional<std::string> sensorDbusPath = ++ readStringFromMetadata(*readingMetadataJson, "SensorDbusPath"); ++ if (!sensorDbusPath) ++ { ++ return false; ++ } ++ ++ std::optional<std::string> 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<time_t>(timestamp))}, + }); + } + +- return metricValues; ++ return true; + } + + inline bool fillReport(nlohmann::json& json, const std::string& id, + const std::variant<TimestampReadings>& 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<TimestampReadings>(&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<time_t>(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 bccbb94..3e1d003 100644 +--- a/redfish-core/lib/sensors.hpp ++++ b/redfish-core/lib/sensors.hpp +@@ -21,6 +21,8 @@ + #include <boost/container/flat_map.hpp> + #include <boost/range/algorithm/replace_copy_if.hpp> + #include <dbus_singleton.hpp> ++#include <dbus_utility.hpp> ++#include <error_messages.hpp> + #include <registries/privilege_registry.hpp> + #include <utils/json_utils.hpp> + +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch new file mode 100644 index 000000000..1cdd59d4b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch @@ -0,0 +1,168 @@ +From 872a7bdb9c272944914d7c5babc751e6bb33afec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Adrian=20Ambro=C5=BCewicz?= <adrian.ambrozewicz@intel.com> +Date: Tue, 3 Aug 2021 13:59:31 +0200 +Subject: [PATCH] Generalize ReadingType in MetricDefinition + +Recent addition of PMT required adding new type of sensor 'count', which +doesnt comply with any of Redfish-defined Sensor.ReadingType values. + +To support property of this kind MetricDefinition implementation was +altered to support sensor types not covered by Redfish types by +a 'fallback' to direct usage of sensor type. Populating 'Units' was also +modified, so it won't be shown if value does not have any units mapped. + +Testing: +- PMT counters are shown properly in MetricDefinitions/Count +- Redfish Validator passes +--- + redfish-core/lib/metric_definition.hpp | 63 ++++++++++++++++---------- + 1 file changed, 39 insertions(+), 24 deletions(-) + +diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp +index 2443996..fcab44d 100644 +--- a/redfish-core/lib/metric_definition.hpp ++++ b/redfish-core/lib/metric_definition.hpp +@@ -11,6 +11,18 @@ namespace redfish + namespace telemetry + { + ++std::string groupName(const std::string& sensorType) ++{ ++ std::string group = sensors::toReadingType(sensorType); ++ if (group.empty()) ++ { ++ // Fallback for types not covered by standard Redfish Sensor.ReadingType ++ group = sensorType; ++ group[0] = static_cast<char>(std::toupper(group[0])); ++ } ++ return group; ++} ++ + void addMembers(crow::Response& res, + const boost::container::flat_map<std::string, std::string>& el) + { +@@ -30,8 +42,7 @@ void addMembers(crow::Response& res, + nlohmann::json& members = res.jsonValue["Members"]; + + const std::string odataId = +- std::string(telemetry::metricDefinitionUri) + +- sensors::toReadingType(type); ++ std::string(telemetry::metricDefinitionUri) + groupName(type); + + const auto it = std::find_if(members.begin(), members.end(), + [&odataId](const nlohmann::json& item) { +@@ -125,15 +136,15 @@ inline void requestRoutesMetricDefinitionCollection(App& app) + namespace telemetry + { + +-bool isSensorIdSupported(std::string_view readingType) ++bool isSensorIdSupported(std::string_view group) + { + for (const std::pair<std::string_view, std::vector<const char*>>& + typeToPaths : sensors::dbus::paths) + { + for (const char* supportedPath : typeToPaths.second) + { +- if (readingType == +- sensors::toReadingType( ++ if (group == ++ groupName( + sdbusplus::message::object_path(supportedPath).filename())) + { + return true; +@@ -144,7 +155,7 @@ bool isSensorIdSupported(std::string_view readingType) + } + + void addMetricProperty( +- bmcweb::AsyncResp& asyncResp, const std::string& readingType, ++ bmcweb::AsyncResp& asyncResp, const std::string& group, + const boost::container::flat_map<std::string, std::string>& el) + { + nlohmann::json& metricProperties = +@@ -155,7 +166,7 @@ void addMetricProperty( + std::string sensorId; + if (dbus::utility::getNthStringFromPath(dbusSensor, 3, sensorId)) + { +- if (sensors::toReadingType(sensorId) == readingType) ++ if (groupName(sensorId) == group) + { + metricProperties.push_back(redfishSensor); + } +@@ -172,33 +183,37 @@ inline void requestRoutesMetricDefinition(App& app) + .methods(boost::beast::http::verb::get)( + [](const crow::Request&, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, +- const std::string& readingType) { +- if (!telemetry::isSensorIdSupported(readingType)) ++ const std::string& group) { ++ if (!telemetry::isSensorIdSupported(group)) + { + messages::resourceNotFound(asyncResp->res, +- "MetricDefinition", readingType); ++ "MetricDefinition", group); + return; + } + + asyncResp->res.jsonValue["MetricProperties"] = + nlohmann::json::array(); +- asyncResp->res.jsonValue["Id"] = readingType; +- asyncResp->res.jsonValue["Name"] = readingType; ++ asyncResp->res.jsonValue["Id"] = group; ++ asyncResp->res.jsonValue["Name"] = group; + asyncResp->res.jsonValue["@odata.id"] = +- telemetry::metricDefinitionUri + readingType; ++ telemetry::metricDefinitionUri + group; + asyncResp->res.jsonValue["@odata.type"] = + "#MetricDefinition.v1_0_3.MetricDefinition"; + asyncResp->res.jsonValue["MetricDataType"] = "Decimal"; + asyncResp->res.jsonValue["MetricType"] = "Numeric"; + asyncResp->res.jsonValue["IsLinear"] = true; + asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; +- asyncResp->res.jsonValue["Units"] = +- sensors::toReadingUnits(readingType); ++ ++ std::string readingUnits = sensors::toReadingUnits(group); ++ if (!readingUnits.empty()) ++ { ++ asyncResp->res.jsonValue["Units"] = readingUnits; ++ } + + utils::getChassisNames( +- [asyncResp, readingType]( +- boost::system::error_code ec, +- const std::vector<std::string>& chassisNames) { ++ [asyncResp, ++ group](boost::system::error_code ec, ++ const std::vector<std::string>& chassisNames) { + if (ec) + { + messages::internalError(asyncResp->res); +@@ -208,10 +223,10 @@ inline void requestRoutesMetricDefinition(App& app) + } + + auto handleRetrieveUriToDbusMap = +- [asyncResp, readingType]( +- const boost::beast::http::status status, +- const boost::container::flat_map< +- std::string, std::string>& uriToDbus) { ++ [asyncResp, ++ group](const boost::beast::http::status status, ++ const boost::container::flat_map< ++ std::string, std::string>& uriToDbus) { + if (status != boost::beast::http::status::ok) + { + BMCWEB_LOG_ERROR +@@ -221,8 +236,8 @@ inline void requestRoutesMetricDefinition(App& app) + messages::internalError(asyncResp->res); + return; + } +- telemetry::addMetricProperty( +- *asyncResp, readingType, uriToDbus); ++ telemetry::addMetricProperty(*asyncResp, group, ++ uriToDbus); + }; + + for (const std::string& chassisName : chassisNames) +-- +2.25.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 ea6ac73bd..cd15a815c 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 @@ -3,13 +3,22 @@ Until change is integrated they will be manually merged here to enable feature i Current revisions: - Add support for MetricDefinition scheme - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/80 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/89 - Sync Telmetry service with EventService - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/31 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/36 - LogService field, actual implementation will be upstreamed with triggers feature file://telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch - Event service fix for Context field file://telemetry/0004-event-service-fix-added-Context-field-to-response.patch + +- Switched bmcweb to use new telemetry service API + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44270/4 + +- Add support for MetricDefinition property in MetricReport + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44512/8 + +- Generalize ReadingType in MetricDefinition + file://telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch
\ No newline at end of file |