summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch400
1 files changed, 226 insertions, 174 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
index 03feec633..8b08c6c5e 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
@@ -1,7 +1,7 @@
-From b6ccf463b4cfb8df4a904f06c5f4852029a96c50 Mon Sep 17 00:00:00 2001
-From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
-Date: Tue, 15 Dec 2020 12:28:17 +0100
-Subject: [PATCH 3/4] Add support for MetricDefinition scheme
+From d664a145a96a642597c74819c183410d4a04fce0 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
Added MetricDefinition node to Redfish code. Now user is able
to list all available metrics in OpenBMC that are supported
@@ -23,16 +23,16 @@ Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00
---
redfish-core/include/redfish.hpp | 3 +
.../include/utils/telemetry_utils.hpp | 2 +
- redfish-core/lib/metric_definition.hpp | 283 ++++++++++++++++++
+ redfish-core/lib/metric_definition.hpp | 335 ++++++++++++++++++
redfish-core/lib/telemetry_service.hpp | 2 +
- 4 files changed, 290 insertions(+)
+ 4 files changed, 342 insertions(+)
create mode 100644 redfish-core/lib/metric_definition.hpp
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
-index aad28ac..dfcb8cd 100644
+index 7a14969..d280a86 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"
@@ -40,7 +40,7 @@ index aad28ac..dfcb8cd 100644
#include "../lib/metric_report.hpp"
#include "../lib/metric_report_definition.hpp"
#include "../lib/network_protocol.hpp"
-@@ -215,6 +216,8 @@ class RedfishService
+@@ -219,6 +220,8 @@ class RedfishService
nodes.emplace_back(std::make_unique<HypervisorResetActionInfo>(app));
nodes.emplace_back(std::make_unique<TelemetryService>(app));
@@ -50,7 +50,7 @@ index aad28ac..dfcb8cd 100644
std::make_unique<MetricReportDefinitionCollection>(app));
nodes.emplace_back(std::make_unique<MetricReportDefinition>(app));
diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
-index 0a3af5f..54b5133 100644
+index 5872350..1b4f75d 100644
--- a/redfish-core/include/utils/telemetry_utils.hpp
+++ b/redfish-core/include/utils/telemetry_utils.hpp
@@ -10,6 +10,8 @@ namespace telemetry
@@ -64,12 +64,13 @@ index 0a3af5f..54b5133 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..f9c7779
+index 0000000..515fe86
--- /dev/null
+++ b/redfish-core/lib/metric_definition.hpp
-@@ -0,0 +1,283 @@
+@@ -0,0 +1,335 @@
+#pragma once
+
++#include "async_resp.hpp"
+#include "node.hpp"
+#include "sensors.hpp"
+#include "utils/telemetry_utils.hpp"
@@ -80,150 +81,138 @@ index 0000000..f9c7779
+namespace utils
+{
+
++class AsyncRespWithFinalizer
++{
++ public:
++ AsyncRespWithFinalizer(
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) :
++ asyncResp(asyncResp)
++ {}
++
++ AsyncRespWithFinalizer(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++ std::function<void(crow::Response&)> finalizer) :
++ asyncResp(asyncResp),
++ finalizer(std::move(finalizer))
++ {}
++
++ AsyncRespWithFinalizer(const AsyncRespWithFinalizer&) = delete;
++ AsyncRespWithFinalizer(AsyncRespWithFinalizer&&) = delete;
++
++ ~AsyncRespWithFinalizer()
++ {
++ if (finalizer)
++ {
++ try
++ {
++ finalizer(asyncResp->res);
++ }
++ catch (const std::exception& e)
++ {
++ BMCWEB_LOG_ERROR << "Executing finalizer failed: " << e.what();
++ messages::internalError(asyncResp->res);
++ }
++ }
++ }
++
++ void setFinalizer(std::function<void(crow::Response&)> newFinalizer)
++ {
++ finalizer = std::move(newFinalizer);
++ }
++
++ private:
++ std::shared_ptr<bmcweb::AsyncResp> asyncResp;
++ std::function<void(crow::Response&)> finalizer;
++
++ public:
++ crow::Response& res = asyncResp->res;
++};
++
+template <typename F>
-+inline void getChassisNames(F&& cb, const std::shared_ptr<AsyncResp>& asyncResp)
++inline void getChassisNames(F&& cb)
+{
+ const std::array<const char*, 2> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
+
+ crow::connections::systemBus->async_method_call(
-+ [asyncResp,
-+ callback = std::move(cb)](const boost::system::error_code ec,
-+ std::vector<std::string>& chassis) {
++ [callback = std::move(cb)](const boost::system::error_code ec,
++ const std::vector<std::string>& chassis) {
++ std::vector<std::string> chassisNames;
++
+ if (ec)
+ {
-+ messages::internalError(asyncResp->res);
-+ BMCWEB_LOG_DEBUG << "DBus call error: " << ec.value();
++ callback(ec, chassisNames);
+ return;
+ }
+
-+ std::vector<std::string> chassisNames;
+ chassisNames.reserve(chassis.size());
-+ for (const auto& path : chassis)
++ for (const std::string& path : chassis)
+ {
+ sdbusplus::message::object_path dbusPath = path;
+ std::string name = dbusPath.filename();
+ if (name.empty())
+ {
-+ messages::internalError(asyncResp->res);
-+ BMCWEB_LOG_ERROR << "Invalid chassis: " << dbusPath.str;
++ callback(boost::system::errc::make_error_code(
++ boost::system::errc::invalid_argument),
++ chassisNames);
+ return;
+ }
+ chassisNames.emplace_back(std::move(name));
+ }
+
-+ callback(chassisNames);
++ callback(ec, chassisNames);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ "/xyz/openbmc_project/inventory", 0, interfaces);
+}
++
+} // namespace utils
+
+namespace telemetry
+{
+
-+class MetricDefinitionCollectionReduce
++void addMembers(crow::Response& res,
++ const boost::container::flat_map<std::string, std::string>& el)
+{
-+ public:
-+ MetricDefinitionCollectionReduce(
-+ const std::shared_ptr<AsyncResp>& asyncResp) :
-+ asyncResp{asyncResp}
-+ {}
-+
-+ ~MetricDefinitionCollectionReduce()
++ for (const auto& [_, dbusSensor] : el)
+ {
-+ if (asyncResp->res.result() != boost::beast::http::status::ok)
++ sdbusplus::message::object_path path(dbusSensor);
++ sdbusplus::message::object_path parentPath = path.parent_path();
++ std::string type = parentPath.filename();
++ if (type.empty())
+ {
-+ return;
++ BMCWEB_LOG_ERROR << "Received invalid DBus Sensor Path = "
++ << dbusSensor;
++ continue;
+ }
+
-+ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
-+ members = nlohmann::json::array();
++ nlohmann::json& members = res.jsonValue["Members"];
+
-+ for (const std::string& type : dbusTypes)
-+ {
-+ members.push_back(
-+ {{"@odata.id", telemetry::metricDefinitionUri + type}});
-+ }
-+ asyncResp->res.jsonValue["Members@odata.count"] = members.size();
-+ }
++ const std::string odataId =
++ telemetry::metricDefinitionUri + std::move(type);
+
-+ void insert(const boost::container::flat_map<std::string, std::string>& el)
-+ {
-+ for (const auto& [_, dbusSensor] : el)
-+ {
-+ sdbusplus::message::object_path path(dbusSensor);
-+ sdbusplus::message::object_path parentPath = path.parent_path();
-+ std::string type = parentPath.filename();
-+ if (type.empty())
-+ {
-+ BMCWEB_LOG_ERROR << "Received invalid DBus Sensor Path = "
-+ << dbusSensor;
-+ continue;
-+ }
++ const auto it =
++ std::find_if(members.begin(), members.end(),
++ [&odataId](const nlohmann::json& item) {
++ auto kt = item.find("@odata.id");
++ if (kt == item.end())
++ {
++ return false;
++ }
++ return kt->get<std::string>() == odataId;
++ });
+
-+ dbusTypes.insert(std::move(type));
-+ }
-+ }
-+
-+ private:
-+ const std::shared_ptr<AsyncResp> asyncResp;
-+ boost::container::flat_set<std::string> dbusTypes;
-+};
-+
-+class MetricDefinitionReduce
-+{
-+ public:
-+ MetricDefinitionReduce(const std::shared_ptr<AsyncResp>& asyncResp,
-+ const std::string& id) :
-+ id(id),
-+ pattern{'/' + id + '/'}, asyncResp{asyncResp}
-+ {}
-+ ~MetricDefinitionReduce()
-+ {
-+ if (asyncResp->res.result() != boost::beast::http::status::ok)
-+ {
-+ return;
-+ }
-+ if (redfishSensors.empty())
++ if (it == members.end())
+ {
-+ messages::resourceNotFound(asyncResp->res, "MetricDefinition", id);
-+ return;
++ members.push_back({{"@odata.id", odataId}});
+ }
+
-+ asyncResp->res.jsonValue["MetricProperties"] = redfishSensors;
-+ asyncResp->res.jsonValue["Id"] = id;
-+ asyncResp->res.jsonValue["Name"] = id;
-+ asyncResp->res.jsonValue["@odata.id"] =
-+ telemetry::metricDefinitionUri + id;
-+ 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["Units"] = sensors::toReadingUnits(id);
-+ }
-+
-+ void insert(const boost::container::flat_map<std::string, std::string>& el)
-+ {
-+ for (const auto& [redfishSensor, dbusSensor] : el)
-+ {
-+ if (dbusSensor.find(pattern) != std::string::npos)
-+ {
-+ redfishSensors.push_back(redfishSensor);
-+ }
-+ }
++ res.jsonValue["Members@odata.count"] = members.size();
+ }
++}
+
-+ private:
-+ const std::string id;
-+ const std::string pattern;
-+ const std::shared_ptr<AsyncResp> asyncResp;
-+ std::vector<std::string> redfishSensors;
-+};
+} // namespace telemetry
+
+class MetricDefinitionCollection : public Node
@@ -242,52 +231,83 @@ index 0000000..f9c7779
+ }
+
+ private:
-+ void doGet(crow::Response& res, const crow::Request&,
-+ const std::vector<std::string>&) override
++ void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++ const crow::Request&, const std::vector<std::string>&) override
+ {
-+ res.jsonValue["@odata.type"] = "#MetricDefinitionCollection."
-+ "MetricDefinitionCollection";
-+ res.jsonValue["@odata.id"] =
++ asyncResp->res.jsonValue["@odata.type"] = "#MetricDefinitionCollection."
++ "MetricDefinitionCollection";
++ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricDefinitions";
-+ res.jsonValue["Name"] = "Metric Definition Collection";
-+ res.jsonValue["Members"] = nlohmann::json::array();
-+ res.jsonValue["Members@odata.count"] = 0;
++ asyncResp->res.jsonValue["Name"] = "Metric Definition Collection";
++ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
++ asyncResp->res.jsonValue["Members@odata.count"] = 0;
++
++ 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);
++ };
+
-+ auto asyncResp = std::make_shared<AsyncResp>(res);
+ utils::getChassisNames(
-+ [asyncResp](const std::vector<std::string>& chassisNames) {
-+ auto collectionReduce = std::make_shared<
-+ telemetry::MetricDefinitionCollectionReduce>(asyncResp);
++ [handleRetrieveUriToDbusMap = std::move(handleRetrieveUriToDbusMap),
++ 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;
++ }
++
+ for (const std::string& chassisName : chassisNames)
+ {
+ for (const auto& [sensorNode, _] : sensors::dbus::paths)
+ {
-+ BMCWEB_LOG_INFO << "Chassis: " << chassisName
-+ << " sensor: " << sensorNode;
-+ retrieveUriToDbusMap(
-+ chassisName, sensorNode.data(),
-+ [asyncResp, collectionReduce](
-+ 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;
-+ }
-+ collectionReduce->insert(uriToDbus);
-+ });
++ BMCWEB_LOG_DEBUG << "Chassis: " << chassisName
++ << " sensor: " << sensorNode;
++ retrieveUriToDbusMap(chassisName, sensorNode.data(),
++ handleRetrieveUriToDbusMap);
+ }
+ }
-+ },
-+ asyncResp);
++ });
+ }
+};
+
++namespace telemetry
++{
++
++void addMetricProperty(
++ utils::AsyncRespWithFinalizer& asyncResp, const std::string& id,
++ const boost::container::flat_map<std::string, std::string>& el)
++{
++ nlohmann::json& metricProperties =
++ asyncResp.res.jsonValue["MetricProperties"];
++
++ for (const auto& [redfishSensor, dbusSensor] : el)
++ {
++ std::string sensorId;
++ if (dbus::utility::getNthStringFromPath(dbusSensor, 3, sensorId))
++ {
++ if (sensorId == id)
++ {
++ metricProperties.push_back(redfishSensor);
++ }
++ }
++ }
++}
++
++} // namespace telemetry
++
+class MetricDefinition : public Node
+{
+ public:
@@ -305,65 +325,97 @@ index 0000000..f9c7779
+ }
+
+ private:
-+ void doGet(crow::Response& res, const crow::Request&,
++ void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++ const crow::Request&,
+ const std::vector<std::string>& params) override
+ {
-+ auto asyncResp = std::make_shared<AsyncResp>(res);
++ auto telemetryAsyncResp =
++ std::make_shared<utils::AsyncRespWithFinalizer>(asyncResp);
++
+ if (params.size() != 1)
+ {
-+ messages::internalError(asyncResp->res);
++ messages::internalError(telemetryAsyncResp->res);
+ return;
+ }
+
+ const std::string& id = params[0];
++ telemetryAsyncResp->setFinalizer([id](crow::Response& res) {
++ if (res.jsonValue["MetricProperties"].empty())
++ {
++ messages::resourceNotFound(res, "MetricDefinition", id);
++ }
++ });
++
++ telemetryAsyncResp->res.jsonValue["MetricProperties"] =
++ nlohmann::json::array();
++ telemetryAsyncResp->res.jsonValue["Id"] = id;
++ telemetryAsyncResp->res.jsonValue["Name"] = id;
++ telemetryAsyncResp->res.jsonValue["@odata.id"] =
++ telemetry::metricDefinitionUri + id;
++ telemetryAsyncResp->res.jsonValue["@odata.type"] =
++ "#MetricDefinition.v1_0_3.MetricDefinition";
++ telemetryAsyncResp->res.jsonValue["MetricDataType"] = "Decimal";
++ telemetryAsyncResp->res.jsonValue["MetricType"] = "Numeric";
++ telemetryAsyncResp->res.jsonValue["IsLinear"] = true;
++ telemetryAsyncResp->res.jsonValue["Units"] =
++ sensors::toReadingUnits(id);
++
++ auto handleRetrieveUriToDbusMap =
++ [telemetryAsyncResp,
++ id](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(telemetryAsyncResp->res);
++ return;
++ }
++ telemetry::addMetricProperty(*telemetryAsyncResp, id,
++ uriToDbus);
++ };
++
+ utils::getChassisNames(
-+ [asyncResp, id](const std::vector<std::string>& chassisNames) {
-+ auto definitionGather =
-+ std::make_shared<telemetry::MetricDefinitionReduce>(
-+ asyncResp, id);
++ [handleRetrieveUriToDbusMap = std::move(handleRetrieveUriToDbusMap),
++ telemetryAsyncResp,
++ id](boost::system::error_code ec,
++ const std::vector<std::string>& chassisNames) {
++ if (ec)
++ {
++ messages::internalError(telemetryAsyncResp->res);
++ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value();
++ return;
++ }
++
+ for (const std::string& chassisName : chassisNames)
+ {
+ for (const auto& [sensorNode, dbusPaths] :
+ sensors::dbus::paths)
+ {
-+ retrieveUriToDbusMap(
-+ chassisName, sensorNode.data(),
-+ [asyncResp, definitionGather](
-+ 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;
-+ }
-+ definitionGather->insert(uriToDbus);
-+ });
++ retrieveUriToDbusMap(chassisName, sensorNode.data(),
++ handleRetrieveUriToDbusMap);
+ }
+ }
-+ },
-+ asyncResp);
++ });
+ }
+};
+
+} // namespace redfish
diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
-index 61ca891..a8c8b03 100644
+index 9ec0737..de9c800 100644
--- a/redfish-core/lib/telemetry_service.hpp
+++ b/redfish-core/lib/telemetry_service.hpp
@@ -32,6 +32,8 @@ class TelemetryService : public Node
- res.jsonValue["Id"] = "TelemetryService";
- res.jsonValue["Name"] = "Telemetry Service";
+ asyncResp->res.jsonValue["Id"] = "TelemetryService";
+ asyncResp->res.jsonValue["Name"] = "Telemetry Service";
-+ res.jsonValue["MetricDefinitions"]["@odata.id"] =
++ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricDefinitions";
- res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
+ asyncResp->res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
"/redfish/v1/TelemetryService/MetricReportDefinitions";
- res.jsonValue["MetricReports"]["@odata.id"] =
+ asyncResp->res.jsonValue["MetricReports"]["@odata.id"] =
--
2.17.1