summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch619
1 files changed, 0 insertions, 619 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
deleted file mode 100644
index f5226fe6e..000000000
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch
+++ /dev/null
@@ -1,619 +0,0 @@
-From 32e557279450226ed9c06312649d90b802f3d4c5 Mon Sep 17 00:00:00 2001
-From: Krzysztof Grobelny <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 by Telemetry
-service. Metrics are grouped by reading type.
-
-MetricDefinitions contains all physical sensors supported by redfish,
-algorithm iterates through all chassis and collects results for each
-node available in that chassis (Power, Thermal, Sensors).
-
-When BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM will be enabled by
-default (meson option redfish-new-powersubsystem-thermalsubsystem) it
-will be possible to optimize this algorithm to only get sensors from
-Sensors node. Currently Sensors node doesn't contain all available
-sensors.
-
-Tested:
- - MetricDefinitions response is filled with existing sensors, it works
- with and without Telemetry service
- - Validated a presence of MetricDefinition members and its attributes
- - Successfully passed RedfishServiceValidator.py using witherspoon
- image on QEMU
- - Tested using following GET,POST requests
-
-GET /redfish/v1/TelemetryService/MetricDefinitions
-{
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions",
- "@odata.type": "#MetricDefinitionCollection.MetricDefinitionCollection",
- "Members": [
- {
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Fan_Pwm"
- },
- {
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Fan_Tach"
- },
- {
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/HostCpuUtilization"
- },
- {
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/HostMemoryBandwidthUtilization"
- },
- {
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/HostPciBandwidthUtilization"
- },
- {
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Inlet_BRD_Temp"
- },
- {
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Left_Rear_Board_Temp"
- }
- ],
- "Members@odata.count": 7,
- "Name": "Metric Definition Collection"
-}
-
-GET /redfish/v1/TelemetryService/MetricDefinitions/Fan_Tach
-{
- "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Fan_Tach",
- "@odata.type": "#MetricDefinition.v1_0_3.MetricDefinition",
- "Id": "Fan_Tach",
- "IsLinear": true,
- "MaxReadingRange": 25000.0,
- "MetricDataType": "Decimal",
- "MetricProperties": [
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/0/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/2/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/3/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/4/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/5/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/6/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/7/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/8/Reading",
- "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/9/Reading"
- ],
- "MetricType": "Gauge",
- "MinReadingRange": 0.0,
- "Name": "Fan_Tach",
- "Units": "RPM"
-}
-
-POST redfish/v1/TelemetryService/MetricReportDefinitions, body:
-{
- "Id": "TestReport",
- "Metrics": [
- {
- "MetricId": "TestMetric",
- "MetricProperties": [
- "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/3/Reading",
- ]
- }
- ],
- "MetricReportDefinitionType": "OnRequest",
- "ReportActions": [
- "RedfishEvent",
- "LogToMetricReportsCollection"
- ]
-}
-{
- "@Message.ExtendedInfo": [
- {
- "@odata.type": "#Message.v1_1_1.Message",
- "Message": "The resource has been created successfully",
- "MessageArgs": [],
- "MessageId": "Base.1.8.1.Created",
- "MessageSeverity": "OK",
- "Resolution": "None"
- }
- ]
-}
-
-Signed-off-by: Wludzik, Jozef <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/telemetry_utils.hpp | 2 +
- redfish-core/lib/metric_definition.hpp | 368 ++++++++++++++++++
- redfish-core/lib/telemetry_service.hpp | 3 +-
- 5 files changed, 433 insertions(+), 1 deletion(-)
- create mode 100644 redfish-core/include/utils/get_chassis_names.hpp
- create mode 100644 redfish-core/lib/metric_definition.hpp
-
-diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
-index 0a97150..67c5af2 100644
---- a/redfish-core/include/redfish.hpp
-+++ b/redfish-core/include/redfish.hpp
-@@ -26,6 +26,7 @@
- #include "../lib/managers.hpp"
- #include "../lib/memory.hpp"
- #include "../lib/message_registries.hpp"
-+#include "../lib/metric_definition.hpp"
- #include "../lib/metric_report.hpp"
- #include "../lib/metric_report_definition.hpp"
- #include "../lib/network_protocol.hpp"
-@@ -200,6 +201,8 @@ class RedfishService
- requestRoutesMetricReportDefinition(app);
- requestRoutesMetricReportCollection(app);
- requestRoutesMetricReport(app);
-+ requestRoutesMetricDefinitionCollection(app);
-+ requestRoutesMetricDefinition(app);
- }
- };
-
-diff --git a/redfish-core/include/utils/get_chassis_names.hpp b/redfish-core/include/utils/get_chassis_names.hpp
-new file mode 100644
-index 0000000..0276b6f
---- /dev/null
-+++ b/redfish-core/include/utils/get_chassis_names.hpp
-@@ -0,0 +1,58 @@
-+#pragma once
-+
-+#include <include/dbus_singleton.hpp>
-+
-+#include <array>
-+#include <string>
-+#include <vector>
-+
-+namespace redfish
-+{
-+
-+namespace utils
-+{
-+
-+template <typename F>
-+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(
-+ [callback = std::move(cb)](const boost::system::error_code ec,
-+ const std::vector<std::string>& chassis) {
-+ std::vector<std::string> chassisNames;
-+
-+ if (ec)
-+ {
-+ callback(ec, chassisNames);
-+ return;
-+ }
-+
-+ chassisNames.reserve(chassis.size());
-+ for (const std::string& path : chassis)
-+ {
-+ sdbusplus::message::object_path dbusPath = path;
-+ std::string name = dbusPath.filename();
-+ if (name.empty())
-+ {
-+ callback(boost::system::errc::make_error_code(
-+ boost::system::errc::invalid_argument),
-+ chassisNames);
-+ return;
-+ }
-+ chassisNames.emplace_back(std::move(name));
-+ }
-+
-+ callback(ec, chassisNames);
-+ },
-+ "xyz.openbmc_project.ObjectMapper",
-+ "/xyz/openbmc_project/object_mapper",
-+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
-+ "/xyz/openbmc_project/inventory", 0, interfaces);
-+}
-+
-+} // namespace utils
-+
-+} // namespace redfish
-diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
-index 5872350..1b4f75d 100644
---- a/redfish-core/include/utils/telemetry_utils.hpp
-+++ b/redfish-core/include/utils/telemetry_utils.hpp
-@@ -10,6 +10,8 @@ namespace telemetry
-
- constexpr const char* service = "xyz.openbmc_project.Telemetry";
- constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report";
-+constexpr const char* metricDefinitionUri =
-+ "/redfish/v1/TelemetryService/MetricDefinitions/";
- constexpr const char* metricReportDefinitionUri =
- "/redfish/v1/TelemetryService/MetricReportDefinitions/";
- constexpr const char* metricReportUri =
-diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp
-new file mode 100644
-index 0000000..347c297
---- /dev/null
-+++ b/redfish-core/lib/metric_definition.hpp
-@@ -0,0 +1,368 @@
-+#pragma once
-+
-+#include "async_resp.hpp"
-+#include "sensors.hpp"
-+#include "utils/get_chassis_names.hpp"
-+#include "utils/telemetry_utils.hpp"
-+
-+#include <registries/privilege_registry.hpp>
-+
-+namespace redfish
-+{
-+
-+namespace telemetry
-+{
-+
-+struct ValueVisitor
-+{
-+ ValueVisitor(boost::system::error_code& ec) : ec(ec)
-+ {}
-+
-+ template <class T>
-+ double operator()(T value) const
-+ {
-+ return static_cast<double>(value);
-+ }
-+
-+ double operator()(std::monostate) const
-+ {
-+ ec = boost::system::errc::make_error_code(
-+ boost::system::errc::invalid_argument);
-+ return double{};
-+ }
-+
-+ boost::system::error_code& ec;
-+};
-+
-+inline void getReadingRange(
-+ const std::string& service, const std::string& path,
-+ const std::string& property,
-+ std::function<void(boost::system::error_code, double)> callback)
-+{
-+ crow::connections::systemBus->async_method_call(
-+ [callback = std::move(callback)](
-+ boost::system::error_code ec,
-+ const std::variant<std::monostate, double, uint64_t, int64_t,
-+ uint32_t, int32_t, uint16_t, int16_t>&
-+ valueVariant) {
-+ if (ec)
-+ {
-+ callback(ec, double{});
-+ return;
-+ }
-+
-+ const double value = std::visit(ValueVisitor(ec), valueVariant);
-+
-+ callback(ec, value);
-+ },
-+ service, path, "org.freedesktop.DBus.Properties", "Get",
-+ "xyz.openbmc_project.Sensor.Value", property);
-+}
-+
-+inline void
-+ fillMinMaxReadingRange(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-+ const std::string& serviceName,
-+ const std::string& sensorPath)
-+{
-+ asyncResp->res.jsonValue["MetricType"] = "Numeric";
-+
-+ telemetry::getReadingRange(
-+ serviceName, sensorPath, "MinValue",
-+ [asyncResp](boost::system::error_code ec, double readingRange) {
-+ if (ec)
-+ {
-+ messages::internalError(asyncResp->res);
-+ return;
-+ }
-+
-+ if (std::isfinite(readingRange))
-+ {
-+ asyncResp->res.jsonValue["MetricType"] = "Gauge";
-+
-+ asyncResp->res.jsonValue["MinReadingRange"] = readingRange;
-+ }
-+ });
-+
-+ telemetry::getReadingRange(
-+ serviceName, sensorPath, "MaxValue",
-+ [asyncResp](boost::system::error_code ec, double readingRange) {
-+ if (ec)
-+ {
-+ messages::internalError(asyncResp->res);
-+ return;
-+ }
-+
-+ if (std::isfinite(readingRange))
-+ {
-+ asyncResp->res.jsonValue["MetricType"] = "Gauge";
-+
-+ asyncResp->res.jsonValue["MaxReadingRange"] = readingRange;
-+ }
-+ });
-+}
-+
-+inline void getSensorService(
-+ const std::string& sensorPath,
-+ std::function<void(boost::system::error_code, const std::string&)> callback)
-+{
-+ using ResultType = std::pair<
-+ std::string,
-+ std::vector<std::pair<std::string, std::vector<std::string>>>>;
-+
-+ crow::connections::systemBus->async_method_call(
-+ [sensorPath, callback = std::move(callback)](
-+ boost::system::error_code ec,
-+ const std::vector<ResultType>& result) {
-+ if (ec)
-+ {
-+ callback(ec, std::string{});
-+ return;
-+ }
-+
-+ for (const auto& [path, serviceToInterfaces] : result)
-+ {
-+ if (path == sensorPath)
-+ {
-+ for (const auto& [service, interfaces] :
-+ serviceToInterfaces)
-+ {
-+ callback(boost::system::errc::make_error_code(
-+ boost::system::errc::success),
-+ service);
-+ return;
-+ }
-+ }
-+ }
-+
-+ callback(boost::system::errc::make_error_code(
-+ boost::system::errc::no_such_file_or_directory),
-+ std::string{});
-+ },
-+ "xyz.openbmc_project.ObjectMapper",
-+ "/xyz/openbmc_project/object_mapper",
-+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
-+ "/xyz/openbmc_project/sensors", 2,
-+ std::array{"xyz.openbmc_project.Sensor.Value"});
-+}
-+
-+constexpr auto metricDefinitionMapping = std::array{
-+ std::pair{"fan_pwm", "Fan_Pwm"}, std::pair{"fan_tach", "Fan_Tach"}};
-+
-+std::string mapSensorToMetricDefinition(const std::string& sensorPath)
-+{
-+ sdbusplus::message::object_path sensorObjectPath{sensorPath};
-+
-+ const auto it = std::find_if(
-+ metricDefinitionMapping.begin(), metricDefinitionMapping.end(),
-+ [&sensorObjectPath](const auto& item) {
-+ return item.first == sensorObjectPath.parent_path().filename();
-+ });
-+
-+ const char* metricDefinitionPath =
-+ "/redfish/v1/TelemetryService/MetricDefinitions/";
-+
-+ if (it != metricDefinitionMapping.end())
-+ {
-+ return std::string{metricDefinitionPath} + it->second;
-+ }
-+
-+ return metricDefinitionPath + sensorObjectPath.filename();
-+}
-+
-+template <class Callback>
-+inline void mapRedfishUriToDbusPath(Callback&& callback)
-+{
-+ utils::getChassisNames([callback = std::move(callback)](
-+ boost::system::error_code ec,
-+ const std::vector<std::string>& chassisNames) {
-+ if (ec)
-+ {
-+ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value();
-+ callback(ec, {});
-+ return;
-+ }
-+
-+ auto counter = std::make_shared<std::pair<
-+ boost::container::flat_map<std::string, std::string>, size_t>>();
-+
-+ auto handleRetrieveUriToDbusMap =
-+ [counter, callback = std::move(callback)](
-+ 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);
-+ counter->second = 0u;
-+ callback(boost::system::errc::make_error_code(
-+ boost::system::errc::io_error),
-+ {});
-+ return;
-+ }
-+
-+ for (const auto& [key, value] : uriToDbus)
-+ {
-+ counter->first[key] = value;
-+ }
-+
-+ if (--counter->second == 0u)
-+ {
-+ callback(boost::system::errc::make_error_code(
-+ boost::system::errc::success),
-+ counter->first);
-+ }
-+ };
-+
-+ for (const std::string& chassisName : chassisNames)
-+ {
-+ for (const auto& [sensorNode, dbusPaths] : sensors::dbus::paths)
-+ {
-+ ++counter->second;
-+ retrieveUriToDbusMap(chassisName, sensorNode.data(),
-+ handleRetrieveUriToDbusMap);
-+ }
-+ }
-+ });
-+}
-+
-+} // namespace telemetry
-+
-+inline void requestRoutesMetricDefinitionCollection(App& app)
-+{
-+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/")
-+ .privileges(privileges::getTelemetryService)
-+ .methods(boost::beast::http::verb::get)(
-+ [](const crow::Request&,
-+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-+ telemetry::mapRedfishUriToDbusPath(
-+ [asyncResp](boost::system::error_code ec,
-+ const boost::container::flat_map<
-+ std::string, std::string>& uriToDbus) {
-+ if (ec)
-+ {
-+ messages::internalError(asyncResp->res);
-+ BMCWEB_LOG_ERROR
-+ << "mapRedfishUriToDbusPath error: "
-+ << ec.value();
-+ return;
-+ }
-+
-+ std::set<std::string> members;
-+
-+ for (const auto& [uri, dbusPath] : uriToDbus)
-+ {
-+ members.insert(
-+ telemetry::mapSensorToMetricDefinition(
-+ dbusPath));
-+ }
-+
-+ for (const std::string& odataId : members)
-+ {
-+ asyncResp->res.jsonValue["Members"].push_back(
-+ {{"@odata.id", odataId}});
-+ }
-+
-+ asyncResp->res.jsonValue["Members@odata.count"] =
-+ asyncResp->res.jsonValue["Members"].size();
-+ });
-+
-+ asyncResp->res.jsonValue["@odata.type"] =
-+ "#MetricDefinitionCollection."
-+ "MetricDefinitionCollection";
-+ asyncResp->res.jsonValue["@odata.id"] =
-+ "/redfish/v1/TelemetryService/MetricDefinitions";
-+ asyncResp->res.jsonValue["Name"] =
-+ "Metric Definition Collection";
-+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
-+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
-+ });
-+}
-+
-+inline void requestRoutesMetricDefinition(App& app)
-+{
-+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/<str>/")
-+ .privileges(privileges::getTelemetryService)
-+ .methods(
-+ boost::beast::http::verb::get)([](const crow::Request&,
-+ const std::shared_ptr<
-+ bmcweb::AsyncResp>& asyncResp,
-+ const std::string& name) {
-+ telemetry::mapRedfishUriToDbusPath(
-+ [asyncResp, name](
-+ boost::system::error_code ec,
-+ const boost::container::flat_map<std::string, std::string>&
-+ uriToDbus) {
-+ if (ec)
-+ {
-+ messages::internalError(asyncResp->res);
-+ BMCWEB_LOG_ERROR << "mapRedfishUriToDbusPath error: "
-+ << ec.value();
-+ return;
-+ }
-+
-+ std::string odataId = telemetry::metricDefinitionUri + name;
-+ boost::container::flat_map<std::string, std::string>
-+ matchingUris;
-+
-+ for (const auto& [uri, dbusPath] : uriToDbus)
-+ {
-+ if (telemetry::mapSensorToMetricDefinition(dbusPath) ==
-+ odataId)
-+ {
-+ matchingUris.emplace(uri, dbusPath);
-+ }
-+ }
-+
-+ if (matchingUris.empty())
-+ {
-+ messages::resourceNotFound(asyncResp->res,
-+ "MetricDefinition", name);
-+ return;
-+ }
-+
-+ std::string sensorPath = matchingUris.begin()->second;
-+
-+ telemetry::getSensorService(
-+ sensorPath,
-+ [asyncResp, name, odataId = std::move(odataId),
-+ sensorPath, matchingUris = std::move(matchingUris)](
-+ boost::system::error_code ec,
-+ const std::string& serviceName) {
-+ if (ec)
-+ {
-+ messages::internalError(asyncResp->res);
-+ BMCWEB_LOG_ERROR << "getServiceSensorFailed: "
-+ << ec.value();
-+ return;
-+ }
-+
-+ asyncResp->res.jsonValue["Id"] = name;
-+ asyncResp->res.jsonValue["Name"] = name;
-+ asyncResp->res.jsonValue["@odata.id"] = odataId;
-+ asyncResp->res.jsonValue["@odata.type"] =
-+ "#MetricDefinition.v1_0_3.MetricDefinition";
-+ asyncResp->res.jsonValue["MetricDataType"] =
-+ "Decimal";
-+ asyncResp->res.jsonValue["IsLinear"] = true;
-+ asyncResp->res.jsonValue["Units"] =
-+ sensors::toReadingUnits(
-+ sdbusplus::message::object_path{sensorPath}
-+ .parent_path()
-+ .filename());
-+
-+ for (const auto& [uri, dbusPath] : matchingUris)
-+ {
-+ asyncResp->res.jsonValue["MetricProperties"]
-+ .push_back(uri);
-+ }
-+
-+ telemetry::fillMinMaxReadingRange(
-+ asyncResp, serviceName, sensorPath);
-+ });
-+ });
-+ });
-+}
-+
-+} // namespace redfish
-diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
-index 8ecc591..027b51b 100644
---- a/redfish-core/lib/telemetry_service.hpp
-+++ b/redfish-core/lib/telemetry_service.hpp
-@@ -18,11 +18,12 @@ inline void handleTelemetryServiceGet(
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TelemetryService";
- asyncResp->res.jsonValue["Id"] = "TelemetryService";
- asyncResp->res.jsonValue["Name"] = "Telemetry Service";
--
- asyncResp->res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
- "/redfish/v1/TelemetryService/MetricReportDefinitions";
- asyncResp->res.jsonValue["MetricReports"]["@odata.id"] =
- "/redfish/v1/TelemetryService/MetricReports";
-+ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] =
-+ "/redfish/v1/TelemetryService/MetricDefinitions";
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
---
-2.25.1