summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry
diff options
context:
space:
mode:
authorjmbills <jason.m.bills@intel.com>2021-08-31 21:23:16 +0300
committerGitHub <noreply@github.com>2021-08-31 21:23:16 +0300
commit04cd92067d2481643df5010cb39b2134b648cf4d (patch)
treed98626c9763ad9048ac9bfd8269e12eced18d496 /meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry
parent10ad77d5bc86709d8ff7f95e7040e39f1c153903 (diff)
parent6f106a0a4ce15fe0678d4ffefd572e6978c72597 (diff)
downloadopenbmc-04cd92067d2481643df5010cb39b2134b648cf4d.tar.xz
Merge pull request #70 from Intel-BMC/update2021-0.701-0.70
Update
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch329
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch22
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Switched-bmcweb-to-use-new-telemetry-service-API.patch301
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-support-for-MetricDefinition-property-in-MetricReport.patch268
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch168
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README13
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