diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch | 539 |
1 files changed, 0 insertions, 539 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch deleted file mode 100644 index 5b1d93664..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch +++ /dev/null @@ -1,539 +0,0 @@ -From b369c09460b46902878da10a106e3b3400fd776e Mon Sep 17 00:00:00 2001 -From: "Wludzik, Jozef" <jozef.wludzik@intel.com> -Date: Mon, 8 Jun 2020 17:15:54 +0200 -Subject: [PATCH 09/10] Add support for MetricDefinition scheme - -Added MetricDefinition node to redfish core. Now user is able to -get all possible metrics that are present in system and are -supported by TelemetryService. - -Tested: - - Succesfully passed RedfishServiceValidator.py - - Validated a presence of MetricDefinition members - -Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com> -Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com> -Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00 - -%% original patch: 0005-Add-support-for-MetricDefinition-scheme.patch - -Change-Id: Ibcb7a858c9118c8af5ff1167a055b044f0d8db77 ---- - redfish-core/include/redfish.hpp | 3 + - redfish-core/include/utils/telemetry_utils.hpp | 2 + - redfish-core/lib/metric_definition.hpp | 300 +++++++++++++++++++++++++ - redfish-core/lib/metric_report.hpp | 65 +++++- - redfish-core/lib/sensors.hpp | 43 +++- - redfish-core/lib/telemetry_service.hpp | 2 + - 6 files changed, 402 insertions(+), 13 deletions(-) - create mode 100644 redfish-core/lib/metric_definition.hpp - -diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index 2587b37..705f490 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" -@@ -211,6 +212,8 @@ class RedfishService - nodes.emplace_back(std::make_unique<HypervisorSystem>(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 6c4e810..bb747c4 100644 ---- a/redfish-core/include/utils/telemetry_utils.hpp -+++ b/redfish-core/include/utils/telemetry_utils.hpp -@@ -22,6 +22,8 @@ namespace redfish - namespace telemetry - { - -+static constexpr const char* metricDefinitionUri = -+ "/redfish/v1/TelemetryService/MetricDefinitions/"; - static constexpr const char* metricReportDefinitionUri = - "/redfish/v1/TelemetryService/MetricReportDefinitions/"; - static 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..1417efa ---- /dev/null -+++ b/redfish-core/lib/metric_definition.hpp -@@ -0,0 +1,300 @@ -+/* -+// Copyright (c) 2018-2020 Intel Corporation -+// -+// Licensed under the Apache License, Version 2.0 (the "License"); -+// you may not use this file except in compliance with the License. -+// You may obtain a copy of the License at -+// -+// http://www.apache.org/licenses/LICENSE-2.0 -+// -+// Unless required by applicable law or agreed to in writing, software -+// distributed under the License is distributed on an "AS IS" BASIS, -+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+// See the License for the specific language governing permissions and -+// limitations under the License. -+*/ -+ -+#pragma once -+ -+#include "node.hpp" -+#include "sensors.hpp" -+#include "utils/telemetry_utils.hpp" -+ -+namespace redfish -+{ -+ -+namespace chassis -+{ -+template <typename F> -+static inline void getChassisNames(F&& callback) -+{ -+ const std::array<const char*, 2> interfaces = { -+ "xyz.openbmc_project.Inventory.Item.Board", -+ "xyz.openbmc_project.Inventory.Item.Chassis"}; -+ -+ dbus::utility::getSubTreePaths( -+ [callback{std::move(callback)}](const boost::system::error_code ec, -+ std::vector<std::string>& chassisList) { -+ if (ec) -+ { -+ return; -+ } -+ -+ std::vector<std::string> chassisNames; -+ chassisNames.reserve(chassisList.size()); -+ for (auto& chassisPath : chassisList) -+ { -+ auto pos = chassisPath.rfind("/"); -+ if (pos == std::string::npos) -+ { -+ continue; -+ } -+ chassisNames.push_back(chassisPath.substr(pos + 1)); -+ } -+ -+ callback(chassisNames); -+ }, -+ "/xyz/openbmc_project/inventory", 0, interfaces); -+} -+} // namespace chassis -+ -+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"] = sensors::dbus::types.size(); -+ -+ auto asyncResp = std::make_shared<AsyncResp>(res); -+ auto collectionReduce = std::make_shared<CollectionGather>(asyncResp); -+ chassis::getChassisNames( -+ [asyncResp, -+ collectionReduce](const std::vector<std::string>& chassisNames) { -+ for (auto& chassisName : chassisNames) -+ { -+ for (auto& [sensorNode, _] : sensors::dbus::types) -+ { -+ BMCWEB_LOG_INFO << "Chassis: " << chassisName -+ << " sensor: " << sensorNode; -+ retrieveUriToDbusMap( -+ chassisName, sensorNode.data(), -+ [asyncResp, collectionReduce]( -+ const boost::beast::http::status, -+ const boost::container::flat_map< -+ std::string, std::string>& uriToDbus) { -+ *collectionReduce += uriToDbus; -+ }); -+ } -+ } -+ }); -+ } -+ -+ class CollectionGather -+ { -+ public: -+ CollectionGather(const std::shared_ptr<AsyncResp>& asyncResp) : -+ asyncResp{asyncResp} -+ { -+ dbusTypes.reserve(sensors::dbus::paths.size()); -+ } -+ -+ ~CollectionGather() -+ { -+ json_util::dbusPathsToMembersArray( -+ asyncResp->res, -+ std::vector<std::string>(dbusTypes.begin(), dbusTypes.end()), -+ telemetry::metricDefinitionUri); -+ } -+ -+ CollectionGather& operator+=( -+ const boost::container::flat_map<std::string, std::string>& rhs) -+ { -+ for (auto& [_, dbusSensor] : rhs) -+ { -+ auto pos = dbusSensor.rfind("/"); -+ if (pos == std::string::npos) -+ { -+ BMCWEB_LOG_ERROR << "Received invalid DBus Sensor Path = " -+ << dbusSensor; -+ continue; -+ } -+ -+ this->dbusTypes.insert(dbusSensor.substr(0, pos)); -+ } -+ return *this; -+ } -+ -+ private: -+ const std::shared_ptr<AsyncResp> asyncResp; -+ boost::container::flat_set<std::string> dbusTypes; -+ }; -+}; -+ -+class MetricDefinition : public Node -+{ -+ public: -+ MetricDefinition(App& app) : -+ Node(app, std::string(telemetry::metricDefinitionUri) + "<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]; -+ -+ size_t sensorIndex = 0; -+ for (auto& name : sensors::dbus::names) -+ { -+ if (name == id) -+ { -+ break; -+ } -+ sensorIndex++; -+ } -+ if (sensorIndex >= sensors::dbus::max) -+ { -+ messages::resourceNotFound(asyncResp->res, schemaType, id); -+ return; -+ } -+ -+ auto definitionGather = -+ std::make_shared<DefinitionGather>(asyncResp, id); -+ chassis::getChassisNames( -+ [asyncResp, definitionGather, -+ sensorIndex](const std::vector<std::string>& chassisNames) { -+ for (auto& chassisName : chassisNames) -+ { -+ for (auto& [sensorNode, dbusPaths] : sensors::dbus::types) -+ { -+ auto found = -+ std::find(dbusPaths.begin(), dbusPaths.end(), -+ sensors::dbus::paths[sensorIndex]); -+ if (found == dbusPaths.end()) -+ { -+ continue; -+ } -+ -+ retrieveUriToDbusMap( -+ chassisName, sensorNode.data(), -+ [asyncResp, definitionGather]( -+ const boost::beast::http::status, -+ const boost::container::flat_map< -+ std::string, std::string>& uriToDbus) { -+ *definitionGather += uriToDbus; -+ }); -+ } -+ } -+ }); -+ } -+ -+ class DefinitionGather -+ { -+ public: -+ DefinitionGather(const std::shared_ptr<AsyncResp>& asyncResp, -+ const std::string& id) : -+ id(id), -+ asyncResp{asyncResp} -+ {} -+ ~DefinitionGather() -+ { -+ if (redfishSensors.empty()) -+ { -+ messages::resourceNotFound(asyncResp->res, schemaType, id); -+ return; -+ } -+ -+ asyncResp->res.jsonValue["MetricProperties"] = -+ nlohmann::json::array(); -+ auto& members = asyncResp->res.jsonValue["MetricProperties"]; -+ for (auto& redfishSensor : redfishSensors) -+ { -+ members.push_back(redfishSensor); -+ } -+ -+ asyncResp->res.jsonValue["Id"] = id; -+ asyncResp->res.jsonValue["Name"] = id; -+ asyncResp->res.jsonValue["@odata.id"] = -+ telemetry::metricDefinitionUri + id; -+ asyncResp->res.jsonValue["@odata.type"] = schemaType; -+ asyncResp->res.jsonValue["MetricDataType"] = "Decimal"; -+ asyncResp->res.jsonValue["MetricType"] = "Numeric"; -+ asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; -+ asyncResp->res.jsonValue["IsLinear"] = true; -+ asyncResp->res.jsonValue["TimestampAccuracy"] = "PT0.1S"; -+ auto unit = sensorUnits.find(id); -+ if (unit != sensorUnits.end()) -+ { -+ asyncResp->res.jsonValue["Units"] = unit->second; -+ } -+ } -+ -+ DefinitionGather& operator+=( -+ const boost::container::flat_map<std::string, std::string>& rhs) -+ { -+ for (auto& [redfishSensor, dbusSensor] : rhs) -+ { -+ if (dbusSensor.find(id) != std::string::npos) -+ { -+ this->redfishSensors.push_back(redfishSensor); -+ } -+ } -+ return *this; -+ } -+ -+ const std::string id; -+ -+ private: -+ const std::shared_ptr<AsyncResp> asyncResp; -+ std::vector<std::string> redfishSensors; -+ const boost::container::flat_map<std::string, std::string> sensorUnits = -+ {{sensors::dbus::names[sensors::dbus::voltage], "V"}, -+ {sensors::dbus::names[sensors::dbus::power], "W"}, -+ {sensors::dbus::names[sensors::dbus::current], "A"}, -+ {sensors::dbus::names[sensors::dbus::fan_tach], "RPM"}, -+ {sensors::dbus::names[sensors::dbus::temperature], "Cel"}, -+ {sensors::dbus::names[sensors::dbus::utilization], "%"}, -+ {sensors::dbus::names[sensors::dbus::fan_pwm], "Duty cycle"}}; -+ }; -+ -+ static constexpr const char* schemaType = -+ "#MetricDefinition.v1_0_3.MetricDefinition"; -+}; -+ -+} // namespace redfish -diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index 768cce9..bcb0d3e 100644 ---- a/redfish-core/lib/metric_report.hpp -+++ b/redfish-core/lib/metric_report.hpp -@@ -91,6 +91,9 @@ class MetricReport : public Node - using Readings = - std::vector<std::tuple<std::string, std::string, double, int32_t>>; - using MetricValues = std::vector<std::map<std::string, std::string>>; -+ using ReadingParameters = -+ std::vector<std::tuple<std::vector<sdbusplus::message::object_path>, -+ std::string, std::string, std::string>>; - - static MetricValues toMetricValues(const Readings& readings) - { -@@ -109,6 +112,49 @@ class MetricReport : public Node - return metricValues; - } - -+ static void addMetricDefinition(nlohmann::json& metrics, -+ const ReadingParameters& params) -+ { -+ for (auto& metric : metrics) -+ { -+ if (!metric.contains("MetricId")) -+ { -+ continue; -+ } -+ -+ auto& id = metric["MetricId"].get_ref<std::string&>(); -+ auto param = -+ std::find_if(params.begin(), params.end(), [id](const auto& x) { -+ return id == std::get<2>(x); -+ }); -+ if (param == params.end()) -+ { -+ continue; -+ } -+ -+ auto& dbusPaths = -+ std::get<std::vector<sdbusplus::message::object_path>>(*param); -+ if (dbusPaths.size() > 1) -+ { -+ continue; -+ } -+ -+ auto dbusPath = dbusPaths.begin(); -+ for (size_t i = 0; i < sensors::dbus::paths.size(); i++) -+ { -+ if (dbusPath->str.find(sensors::dbus::paths[i]) == -+ std::string::npos) -+ { -+ continue; -+ } -+ metric["MetricDefinition"]["@odata.id"] = -+ telemetry::metricDefinitionUri + -+ std::string(sensors::dbus::names[i]); -+ break; -+ } -+ } -+ } -+ - static void getReportProperties(const std::shared_ptr<AsyncResp> asyncResp, - const std::string& reportPath, - const std::string& id) -@@ -124,7 +170,8 @@ class MetricReport : public Node - [asyncResp]( - const boost::system::error_code ec, - const boost::container::flat_map< -- std::string, std::variant<Readings, int32_t>>& ret) { -+ std::string, -+ std::variant<Readings, int32_t, ReadingParameters>>& ret) { - if (ec) - { - messages::internalError(asyncResp->res); -@@ -138,6 +185,22 @@ class MetricReport : public Node - json_util::assignIfPresent<Readings>( - ret, "Readings", asyncResp->res.jsonValue["MetricValues"], - toMetricValues); -+ -+ auto found = ret.find("ReadingParameters"); -+ if (found != ret.end()) -+ { -+ auto params = -+ std::get_if<ReadingParameters>(&found->second); -+ if (params) -+ { -+ auto& jsonValue = asyncResp->res.jsonValue; -+ if (jsonValue.contains("MetricValues")) -+ { -+ addMetricDefinition(jsonValue["MetricValues"], -+ *params); -+ } -+ } -+ } - }, - "xyz.openbmc_project.MonitoringService", reportPath, - "xyz.openbmc_project.MonitoringService.Report"); -diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp -index 567cb0c..2f7f70b 100644 ---- a/redfish-core/lib/sensors.hpp -+++ b/redfish-core/lib/sensors.hpp -@@ -54,20 +54,39 @@ static constexpr std::string_view thermal = "Thermal"; - - namespace dbus - { -+ -+enum Index -+{ -+ voltage = 0, -+ power, -+ current, -+ fan_tach, -+ temperature, -+ fan_pwm, -+ utilization, -+ max -+}; -+ -+static constexpr std::array<const char*, max> names = { -+ "voltage", "power", "current", "fan_tach", -+ "temperature", "fan_pwm", "utilization"}; -+ -+static constexpr std::array<const char*, max> paths = { -+ "/xyz/openbmc_project/sensors/voltage", -+ "/xyz/openbmc_project/sensors/power", -+ "/xyz/openbmc_project/sensors/current", -+ "/xyz/openbmc_project/sensors/fan_tach", -+ "/xyz/openbmc_project/sensors/temperature", -+ "/xyz/openbmc_project/sensors/fan_pwm", -+ "/xyz/openbmc_project/sensors/utilization"}; -+ - static const boost::container::flat_map<std::string_view, - std::vector<const char*>> -- types = {{node::power, -- {"/xyz/openbmc_project/sensors/voltage", -- "/xyz/openbmc_project/sensors/power"}}, -- {node::sensors, -- {"/xyz/openbmc_project/sensors/power", -- "/xyz/openbmc_project/sensors/current", -- "/xyz/openbmc_project/sensors/utilization"}}, -- {node::thermal, -- {"/xyz/openbmc_project/sensors/fan_tach", -- "/xyz/openbmc_project/sensors/temperature", -- "/xyz/openbmc_project/sensors/fan_pwm"}}}; --} -+ types = { -+ {node::power, {paths[voltage], paths[power]}}, -+ {node::sensors, {paths[power], paths[current], paths[utilization]}}, -+ {node::thermal, {paths[fan_tach], paths[temperature], paths[fan_pwm]}}}; -+} // namespace dbus - } // namespace sensors - - /** -diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -index b849781..efbef6e 100644 ---- a/redfish-core/lib/telemetry_service.hpp -+++ b/redfish-core/lib/telemetry_service.hpp -@@ -52,6 +52,8 @@ class TelemetryService : public Node - - res.jsonValue["LogService"]["@odata.id"] = - "/redfish/v1/Managers/bmc/LogServices/Journal"; -+ res.jsonValue["MetricDefinitions"]["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricDefinitions"; - res.jsonValue["MetricReportDefinitions"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricReportDefinitions"; - res.jsonValue["MetricReports"]["@odata.id"] = --- -2.16.6 - |