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.patch369
1 files changed, 369 insertions, 0 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
new file mode 100644
index 000000000..03feec633
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
@@ -0,0 +1,369 @@
+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
+
+Added MetricDefinition node to Redfish code. Now user is able
+to list all available metrics in OpenBMC that are supported
+by Telemetry service. Metrics are grouped by following
+categories: temperature, power, voltage, current, fan_tach,
+fan_pwm, utilization.
+
+Tested:
+ - MetricDefinitions response is filled with existing sensors,
+ it works with and without Telemetry service
+ - Validated a presence of MetricDefinition members and it
+ attributes
+ - Succesfully 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/telemetry_utils.hpp | 2 +
+ redfish-core/lib/metric_definition.hpp | 283 ++++++++++++++++++
+ redfish-core/lib/telemetry_service.hpp | 2 +
+ 4 files changed, 290 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
+--- a/redfish-core/include/redfish.hpp
++++ b/redfish-core/include/redfish.hpp
+@@ -25,6 +25,7 @@
+ #include "../lib/managers.hpp"
+ #include "../lib/memory.hpp"
+ #include "../lib/message_registries.hpp"
++#include "../lib/metric_definition.hpp"
+ #include "../lib/metric_report.hpp"
+ #include "../lib/metric_report_definition.hpp"
+ #include "../lib/network_protocol.hpp"
+@@ -215,6 +216,8 @@ class RedfishService
+ nodes.emplace_back(std::make_unique<HypervisorResetActionInfo>(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/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
+index 0a3af5f..54b5133 100644
+--- a/redfish-core/include/utils/telemetry_utils.hpp
++++ b/redfish-core/include/utils/telemetry_utils.hpp
+@@ -10,6 +10,8 @@ namespace telemetry
+
+ constexpr const char* service = "xyz.openbmc_project.Telemetry";
+ constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report";
++constexpr const char* metricDefinitionUri =
++ "/redfish/v1/TelemetryService/MetricDefinitions/";
+ constexpr const char* metricReportDefinitionUri =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/";
+ constexpr const char* metricReportUri =
+diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp
+new file mode 100644
+index 0000000..f9c7779
+--- /dev/null
++++ b/redfish-core/lib/metric_definition.hpp
+@@ -0,0 +1,283 @@
++#pragma once
++
++#include "node.hpp"
++#include "sensors.hpp"
++#include "utils/telemetry_utils.hpp"
++
++namespace redfish
++{
++
++namespace utils
++{
++
++template <typename F>
++inline void getChassisNames(F&& cb, const std::shared_ptr<AsyncResp>& asyncResp)
++{
++ 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) {
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_DEBUG << "DBus call error: " << ec.value();
++ return;
++ }
++
++ std::vector<std::string> chassisNames;
++ chassisNames.reserve(chassis.size());
++ for (const auto& 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;
++ return;
++ }
++ chassisNames.emplace_back(std::move(name));
++ }
++
++ callback(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
++{
++ public:
++ MetricDefinitionCollectionReduce(
++ const std::shared_ptr<AsyncResp>& asyncResp) :
++ asyncResp{asyncResp}
++ {}
++
++ ~MetricDefinitionCollectionReduce()
++ {
++ if (asyncResp->res.result() != boost::beast::http::status::ok)
++ {
++ return;
++ }
++
++ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
++ members = nlohmann::json::array();
++
++ for (const std::string& type : dbusTypes)
++ {
++ members.push_back(
++ {{"@odata.id", telemetry::metricDefinitionUri + type}});
++ }
++ asyncResp->res.jsonValue["Members@odata.count"] = members.size();
++ }
++
++ 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;
++ }
++
++ 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())
++ {
++ messages::resourceNotFound(asyncResp->res, "MetricDefinition", id);
++ return;
++ }
++
++ 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);
++ }
++ }
++ }
++
++ 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
++{
++ 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(crow::Response& res, const crow::Request&,
++ const std::vector<std::string>&) override
++ {
++ res.jsonValue["@odata.type"] = "#MetricDefinitionCollection."
++ "MetricDefinitionCollection";
++ 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;
++
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ utils::getChassisNames(
++ [asyncResp](const std::vector<std::string>& chassisNames) {
++ auto collectionReduce = std::make_shared<
++ telemetry::MetricDefinitionCollectionReduce>(asyncResp);
++ 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);
++ });
++ }
++ }
++ },
++ asyncResp);
++ }
++};
++
++class MetricDefinition : public Node
++{
++ 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(crow::Response& res, const crow::Request&,
++ const std::vector<std::string>& params) override
++ {
++ auto asyncResp = std::make_shared<AsyncResp>(res);
++ if (params.size() != 1)
++ {
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ const std::string& id = params[0];
++ utils::getChassisNames(
++ [asyncResp, id](const std::vector<std::string>& chassisNames) {
++ auto definitionGather =
++ std::make_shared<telemetry::MetricDefinitionReduce>(
++ asyncResp, id);
++ 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);
++ });
++ }
++ }
++ },
++ asyncResp);
++ }
++};
++
++} // namespace redfish
+diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
+index 61ca891..a8c8b03 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";
+
++ res.jsonValue["MetricDefinitions"]["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricDefinitions";
+ res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions";
+ res.jsonValue["MetricReports"]["@odata.id"] =
+--
+2.17.1
+