diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch | 717 |
1 files changed, 0 insertions, 717 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch deleted file mode 100644 index 208831338..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch +++ /dev/null @@ -1,717 +0,0 @@ -From d50e4ce193703c008d3293acd03e1c0542c0c215 Mon Sep 17 00:00:00 2001 -From: "Wludzik, Jozef" <jozef.wludzik@intel.com> -Date: Mon, 27 Apr 2020 17:24:15 +0200 -Subject: [PATCH] Redfish TelemetryService schema implementation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Added TelemetryService, MetricReports, MetricReportCollection, -MetricReportDefinition and MetricReportDefinitionCollection schemas -with GET method support. Added TelemetryService URI to root service. -Implemented communication with backend - Telemetry. -Added schemes attributes that are supported by Telemetry service -design. User is able to fetch basic information about reports if -Telemetry service is present in OpenBMC. -Added util function that converts decimal value into duration format -that is described by ISO 8601 and Redfish specification. - -Tested: - - Succesfully passed RedfishServiceValidator.py - - Verified DBus method calls to Telemetry service - - Verified all possible pages that are displayed to user when: - - Reports are fully defined in Telemetry - - Reports are partially available in Telemetry - - Telemetry is disabled - - Verified time_utils::toDurationString() output - -Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com> -Signed-off-by: Adrian Ambrożewicz <adrian.ambrozewicz@linux.intel.com> -Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com> -Change-Id: Ie6b0b49f4ef5eeaef07d1209b6c349270c04d570 ---- - redfish-core/include/redfish.hpp | 10 + - .../include/utils/telemetry_utils.hpp | 71 +++++++ - redfish-core/include/utils/time_utils.hpp | 78 ++++++++ - redfish-core/lib/metric_report.hpp | 162 +++++++++++++++ - redfish-core/lib/metric_report_definition.hpp | 186 ++++++++++++++++++ - redfish-core/lib/service_root.hpp | 2 + - redfish-core/lib/telemetry_service.hpp | 93 +++++++++ - 7 files changed, 602 insertions(+) - create mode 100644 redfish-core/include/utils/telemetry_utils.hpp - create mode 100644 redfish-core/include/utils/time_utils.hpp - create mode 100644 redfish-core/lib/metric_report.hpp - create mode 100644 redfish-core/lib/metric_report_definition.hpp - create mode 100644 redfish-core/lib/telemetry_service.hpp - -diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index dabf78e..b366e24 100644 ---- a/redfish-core/include/redfish.hpp -+++ b/redfish-core/include/redfish.hpp -@@ -25,6 +25,8 @@ - #include "../lib/managers.hpp" - #include "../lib/memory.hpp" - #include "../lib/message_registries.hpp" -+#include "../lib/metric_report.hpp" -+#include "../lib/metric_report_definition.hpp" - #include "../lib/network_protocol.hpp" - #include "../lib/pcie.hpp" - #include "../lib/power.hpp" -@@ -36,6 +38,7 @@ - #include "../lib/storage.hpp" - #include "../lib/systems.hpp" - #include "../lib/task.hpp" -+#include "../lib/telemetry_service.hpp" - #include "../lib/thermal.hpp" - #include "../lib/update_service.hpp" - #ifdef BMCWEB_ENABLE_VM_NBDPROXY -@@ -212,6 +215,13 @@ class RedfishService - nodes.emplace_back(std::make_unique<HypervisorInterface>(app)); - nodes.emplace_back(std::make_unique<HypervisorSystem>(app)); - -+ nodes.emplace_back(std::make_unique<TelemetryService>(app)); -+ nodes.emplace_back( -+ std::make_unique<MetricReportDefinitionCollection>(app)); -+ nodes.emplace_back(std::make_unique<MetricReportDefinition>(app)); -+ nodes.emplace_back(std::make_unique<MetricReportCollection>(app)); -+ nodes.emplace_back(std::make_unique<MetricReport>(app)); -+ - for (const auto& node : nodes) - { - node->initPrivileges(); -diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp -new file mode 100644 -index 0000000..8caee2d ---- /dev/null -+++ b/redfish-core/include/utils/telemetry_utils.hpp -@@ -0,0 +1,71 @@ -+#pragma once -+ -+namespace redfish -+{ -+ -+namespace telemetry -+{ -+ -+constexpr const char* service = "xyz.openbmc_project.Telemetry"; -+constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report"; -+constexpr const char* metricReportDefinitionUri = -+ "/redfish/v1/TelemetryService/MetricReportDefinitions/"; -+constexpr const char* metricReportUri = -+ "/redfish/v1/TelemetryService/MetricReports/"; -+ -+inline void getReportCollection(const std::shared_ptr<AsyncResp>& asyncResp, -+ const std::string& uri) -+{ -+ const std::array<const char*, 1> interfaces = {reportInterface}; -+ -+ crow::connections::systemBus->async_method_call( -+ [asyncResp, uri](const boost::system::error_code ec, -+ const std::vector<std::string>& reportPaths) { -+ if (ec) -+ { -+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); -+ asyncResp->res.jsonValue["Members@odata.count"] = 0; -+ return; -+ } -+ -+ nlohmann::json& members = asyncResp->res.jsonValue["Members"]; -+ members = nlohmann::json::array(); -+ -+ for (const std::string& path : reportPaths) -+ { -+ std::size_t pos = path.rfind('/'); -+ if (pos == std::string::npos) -+ { -+ BMCWEB_LOG_ERROR << "Failed to find '/' in " << path; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ if (path.size() <= (pos + 1)) -+ { -+ BMCWEB_LOG_ERROR << "Failed to parse path " << path; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ members.push_back({{"@odata.id", uri + path.substr(pos + 1)}}); -+ } -+ -+ asyncResp->res.jsonValue["Members@odata.count"] = members.size(); -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", -+ "/xyz/openbmc_project/Telemetry/Reports/TelemetryService", 1, -+ interfaces); -+} -+ -+inline std::string getDbusReportPath(const std::string& id) -+{ -+ std::string path = -+ "/xyz/openbmc_project/Telemetry/Reports/TelemetryService/" + id; -+ dbus::utility::escapePathForDbus(path); -+ return path; -+} -+ -+} // namespace telemetry -+} // namespace redfish -diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp -new file mode 100644 -index 0000000..dd4ea75 ---- /dev/null -+++ b/redfish-core/include/utils/time_utils.hpp -@@ -0,0 +1,78 @@ -+#pragma once -+ -+#include <chrono> -+#include <string> -+ -+namespace redfish -+{ -+ -+namespace time_utils -+{ -+ -+namespace details -+{ -+ -+inline void leftZeroPadding(std::string& str, const std::size_t padding) -+{ -+ if (str.size() < padding) -+ { -+ str.insert(0, padding - str.size(), '0'); -+ } -+} -+} // namespace details -+ -+/** -+ * @brief Convert time value into duration format that is based on ISO 8601. -+ * Example output: "P12DT1M5.5S" -+ * Ref: Redfish Specification, Section 9.4.4. Duration values -+ */ -+std::string toDurationString(std::chrono::milliseconds ms) -+{ -+ if (ms < std::chrono::milliseconds::zero()) -+ { -+ return ""; -+ } -+ -+ std::string fmt; -+ fmt.reserve(sizeof("PxxxxxxxxxxxxDTxxHxxMxx.xxxxxxS")); -+ -+ using Days = std::chrono::duration<long, std::ratio<24 * 60 * 60>>; -+ Days days = std::chrono::floor<Days>(ms); -+ ms -= days; -+ -+ std::chrono::hours hours = std::chrono::floor<std::chrono::hours>(ms); -+ ms -= hours; -+ -+ std::chrono::minutes minutes = std::chrono::floor<std::chrono::minutes>(ms); -+ ms -= minutes; -+ -+ std::chrono::seconds seconds = std::chrono::floor<std::chrono::seconds>(ms); -+ ms -= seconds; -+ -+ fmt = "P"; -+ if (days.count() > 0) -+ { -+ fmt += std::to_string(days.count()) + "D"; -+ } -+ fmt += "T"; -+ if (hours.count() > 0) -+ { -+ fmt += std::to_string(hours.count()) + "H"; -+ } -+ if (minutes.count() > 0) -+ { -+ fmt += std::to_string(minutes.count()) + "M"; -+ } -+ if (seconds.count() != 0 || ms.count() != 0) -+ { -+ fmt += std::to_string(seconds.count()) + "."; -+ std::string msStr = std::to_string(ms.count()); -+ details::leftZeroPadding(msStr, 3); -+ fmt += msStr + "S"; -+ } -+ -+ return fmt; -+} -+ -+} // namespace time_utils -+} // namespace redfish -diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -new file mode 100644 -index 0000000..050304c ---- /dev/null -+++ b/redfish-core/lib/metric_report.hpp -@@ -0,0 +1,162 @@ -+#pragma once -+ -+#include "node.hpp" -+#include "utils/telemetry_utils.hpp" -+ -+namespace redfish -+{ -+ -+class MetricReportCollection : public Node -+{ -+ public: -+ MetricReportCollection(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricReports/") -+ { -+ 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"] = -+ "#MetricReportCollection.MetricReportCollection"; -+ res.jsonValue["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricReports"; -+ res.jsonValue["Name"] = "Metric Report Collection"; -+ -+ auto asyncResp = std::make_shared<AsyncResp>(res); -+ telemetry::getReportCollection(asyncResp, telemetry::metricReportUri); -+ } -+}; -+ -+class MetricReport : public Node -+{ -+ public: -+ MetricReport(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricReports/<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]; -+ const std::string reportPath = telemetry::getDbusReportPath(id); -+ -+ crow::connections::systemBus->async_method_call( -+ [asyncResp, id, reportPath](const boost::system::error_code& ec) { -+ if (ec.value() == EBADR) -+ { -+ messages::resourceNotFound(asyncResp->res, schemaType, id); -+ return; -+ } -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ crow::connections::systemBus->async_method_call( -+ [asyncResp, -+ id](const boost::system::error_code ec, -+ const std::variant<TimestampReadings>& ret) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ fillReport(asyncResp, id, ret); -+ }, -+ telemetry::service, reportPath, -+ "org.freedesktop.DBus.Properties", "Get", -+ telemetry::reportInterface, "Readings"); -+ }, -+ telemetry::service, reportPath, telemetry::reportInterface, -+ "Update"); -+ } -+ -+ using Readings = -+ std::vector<std::tuple<std::string, std::string, double, uint64_t>>; -+ using TimestampReadings = std::tuple<uint64_t, Readings>; -+ -+ static nlohmann::json toMetricValues(const Readings& readings) -+ { -+ nlohmann::json metricValues = nlohmann::json::array_t(); -+ -+ for (auto& [id, metadata, sensorValue, timestamp] : readings) -+ { -+ nlohmann::json metadataJson = nlohmann::json::parse(metadata); -+ metricValues.push_back({ -+ {"MetricId", id}, -+ {"MetricDefinition", metadataJson.contains("MetricDefinition") -+ ? metadataJson["MetricDefinition"] -+ : nlohmann::json()}, -+ {"MetricProperty", metadataJson.contains("MetricProperty") -+ ? metadataJson["MetricProperty"] -+ : nlohmann::json()}, -+ {"MetricValue", std::to_string(sensorValue)}, -+ {"Timestamp", -+ crow::utility::getDateTime(static_cast<time_t>(timestamp))}, -+ }); -+ } -+ -+ return metricValues; -+ } -+ -+ static void fillReport(const std::shared_ptr<AsyncResp>& asyncResp, -+ const std::string& id, -+ const std::variant<TimestampReadings>& var) -+ { -+ asyncResp->res.jsonValue["@odata.type"] = schemaType; -+ asyncResp->res.jsonValue["@odata.id"] = telemetry::metricReportUri + id; -+ asyncResp->res.jsonValue["Id"] = id; -+ asyncResp->res.jsonValue["Name"] = id; -+ asyncResp->res.jsonValue["MetricReportDefinition"]["@odata.id"] = -+ telemetry::metricReportDefinitionUri + id; -+ -+ const TimestampReadings* timestampReadings = -+ std::get_if<TimestampReadings>(&var); -+ if (!timestampReadings) -+ { -+ BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ const auto& [timestamp, readings] = *timestampReadings; -+ asyncResp->res.jsonValue["Timestamp"] = -+ crow::utility::getDateTime(static_cast<time_t>(timestamp)); -+ asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings); -+ } -+ -+ static constexpr const char* schemaType = -+ "#MetricReport.v1_3_0.MetricReport"; -+}; -+} // namespace redfish -diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp -new file mode 100644 -index 0000000..48c56e6 ---- /dev/null -+++ b/redfish-core/lib/metric_report_definition.hpp -@@ -0,0 +1,186 @@ -+#pragma once -+ -+#include "node.hpp" -+#include "utils/telemetry_utils.hpp" -+#include "utils/time_utils.hpp" -+ -+#include <tuple> -+#include <variant> -+ -+namespace redfish -+{ -+ -+class MetricReportDefinitionCollection : public Node -+{ -+ public: -+ MetricReportDefinitionCollection(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") -+ { -+ 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"] = "#MetricReportDefinitionCollection." -+ "MetricReportDefinitionCollection"; -+ res.jsonValue["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricReportDefinitions"; -+ res.jsonValue["Name"] = "Metric Definition Collection"; -+ -+ auto asyncResp = std::make_shared<AsyncResp>(res); -+ telemetry::getReportCollection(asyncResp, -+ telemetry::metricReportDefinitionUri); -+ } -+}; -+ -+class MetricReportDefinition : public Node -+{ -+ public: -+ MetricReportDefinition(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/<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]; -+ crow::connections::systemBus->async_method_call( -+ [asyncResp, -+ id](const boost::system::error_code ec, -+ const std::vector<std::pair< -+ std::string, std::variant<bool, ReadingParameters, -+ std::string, uint64_t>>>& ret) { -+ if (ec.value() == EBADR) -+ { -+ messages::resourceNotFound(asyncResp->res, schemaType, id); -+ return; -+ } -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ fillReportDefinition(asyncResp, id, ret); -+ }, -+ telemetry::service, telemetry::getDbusReportPath(id), -+ "org.freedesktop.DBus.Properties", "GetAll", -+ telemetry::reportInterface); -+ } -+ -+ using ReadingParameters = -+ std::vector<std::tuple<std::vector<sdbusplus::message::object_path>, -+ std::string, std::string, std::string>>; -+ -+ static void fillReportDefinition( -+ const std::shared_ptr<AsyncResp>& asyncResp, const std::string& id, -+ const std::vector< -+ std::pair<std::string, std::variant<bool, ReadingParameters, -+ std::string, uint64_t>>>& ret) -+ { -+ asyncResp->res.jsonValue["@odata.type"] = schemaType; -+ 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) -+ { -+ if (key == "EmitsReadingsUpdate") -+ { -+ emitsReadingsUpdate = std::get_if<bool>(&var); -+ } -+ else if (key == "LogToMetricReportsCollection") -+ { -+ logToMetricReportsCollection = std::get_if<bool>(&var); -+ } -+ 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") -+ { -+ interval = std::get_if<uint64_t>(&var); -+ } -+ } -+ 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"); -+ } -+ if (*logToMetricReportsCollection) -+ { -+ redfishReportActions.emplace_back("LogToMetricReportsCollection"); -+ } -+ -+ nlohmann::json metrics = nlohmann::json::array(); -+ for (auto& [sensorPaths, operationType, id, metadata] : *readingParams) -+ { -+ nlohmann::json metadataJson = nlohmann::json::parse(metadata); -+ metrics.push_back({ -+ {"MetricId", id}, -+ {"MetricProperties", metadataJson.contains("MetricProperties") -+ ? metadataJson["MetricProperties"] -+ : nlohmann::json()}, -+ }); -+ } -+ 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)); -+ } -+ -+ static constexpr const char* schemaType = -+ "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; -+}; -+} // namespace redfish -diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp -index 629280c..3df5ec5 100644 ---- a/redfish-core/lib/service_root.hpp -+++ b/redfish-core/lib/service_root.hpp -@@ -68,6 +68,8 @@ class ServiceRoot : public Node - res.jsonValue["Tasks"] = {{"@odata.id", "/redfish/v1/TaskService"}}; - res.jsonValue["EventService"] = { - {"@odata.id", "/redfish/v1/EventService"}}; -+ res.jsonValue["TelemetryService"] = { -+ {"@odata.id", "/redfish/v1/TelemetryService"}}; - res.end(); - } - -diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -new file mode 100644 -index 0000000..a6acc34 ---- /dev/null -+++ b/redfish-core/lib/telemetry_service.hpp -@@ -0,0 +1,93 @@ -+#pragma once -+ -+#include "node.hpp" -+#include "utils/telemetry_utils.hpp" -+ -+#include <variant> -+ -+namespace redfish -+{ -+ -+class TelemetryService : public Node -+{ -+ public: -+ TelemetryService(App& app) : Node(app, "/redfish/v1/TelemetryService/") -+ { -+ 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"] = -+ "#TelemetryService.v1_2_1.TelemetryService"; -+ res.jsonValue["@odata.id"] = "/redfish/v1/TelemetryService"; -+ res.jsonValue["Id"] = "TelemetryService"; -+ res.jsonValue["Name"] = "Telemetry Service"; -+ -+ res.jsonValue["LogService"]["@odata.id"] = -+ "/redfish/v1/Managers/bmc/LogServices/Journal"; -+ res.jsonValue["MetricReportDefinitions"]["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricReportDefinitions"; -+ res.jsonValue["MetricReports"]["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricReports"; -+ -+ auto asyncResp = std::make_shared<AsyncResp>(res); -+ crow::connections::systemBus->async_method_call( -+ [asyncResp]( -+ const boost::system::error_code ec, -+ const std::vector<std::pair< -+ std::string, std::variant<uint32_t, uint64_t>>>& ret) { -+ if (ec == boost::system::errc::host_unreachable) -+ { -+ asyncResp->res.jsonValue["Status"]["State"] = "Absent"; -+ return; -+ } -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; -+ -+ const size_t* maxReports = nullptr; -+ const uint64_t* minInterval = nullptr; -+ for (const auto& [key, var] : ret) -+ { -+ if (key == "MaxReports") -+ { -+ maxReports = std::get_if<size_t>(&var); -+ } -+ else if (key == "MinInterval") -+ { -+ minInterval = std::get_if<uint64_t>(&var); -+ } -+ } -+ if (!maxReports || !minInterval) -+ { -+ BMCWEB_LOG_ERROR -+ << "Property type mismatch or property is missing"; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ asyncResp->res.jsonValue["MaxReports"] = *maxReports; -+ asyncResp->res.jsonValue["MinCollectionInterval"] = -+ time_utils::toDurationString(std::chrono::milliseconds( -+ static_cast<time_t>(*minInterval))); -+ }, -+ telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", -+ "org.freedesktop.DBus.Properties", "GetAll", -+ "xyz.openbmc_project.Telemetry.ReportManager"); -+ } -+}; -+} // namespace redfish --- -2.17.1 - |