From 7820421433349df28bd393e8d610d1848af0f1c8 Mon Sep 17 00:00:00 2001 From: "Wludzik, Jozef" Date: Mon, 27 Apr 2020 17:24:15 +0200 Subject: [PATCH 1/5] 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 - MonitoringService. Added schemes attributes that are supported by MonitoringService design. User is able to fetch basic information about reports if MonitoringService is present in OpenBMC. Tested: - Succesfully passed RedfishServiceValidator.py - Validated conversion to duration format using whole range of uint32_t type - Validated assigning value to JSON response using different closures and std::functions types Signed-off-by: Wludzik, Jozef Signed-off-by: Adrian Ambrożewicz Change-Id: Ie6b0b49f4ef5eeaef07d1209b6c349270c04d570 --- include/dbus_utility.hpp | 21 +++ redfish-core/include/redfish.hpp | 10 ++ redfish-core/include/utils/json_utils.hpp | 101 +++++++++++++ redfish-core/include/utils/telemetry_utils.hpp | 100 +++++++++++++ redfish-core/include/utils/time_utils.hpp | 97 +++++++++++++ redfish-core/lib/metric_report.hpp | 149 +++++++++++++++++++ redfish-core/lib/metric_report_definition.hpp | 193 +++++++++++++++++++++++++ redfish-core/lib/service_root.hpp | 2 + redfish-core/lib/telemetry_service.hpp | 92 ++++++++++++ 9 files changed, 765 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/include/dbus_utility.hpp b/include/dbus_utility.hpp index e1360f7..3df88d8 100644 --- a/include/dbus_utility.hpp +++ b/include/dbus_utility.hpp @@ -109,5 +109,26 @@ inline void checkDbusPathExists(const std::string& path, Callback&& callback) std::array()); } +template +inline void getSubTreePaths(Callback&& callback, const std::string& path, + int depth, Array& interfaces) +{ + crow::connections::systemBus->async_method_call( + callback, "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth, + interfaces); +} + +template +inline void getAllProperties(Callback&& callback, const std::string& service, + const std::string& path, + const std::string& interface) +{ + crow::connections::systemBus->async_method_call( + callback, service, path, "org.freedesktop.DBus.Properties", "GetAll", + interface); +} + } // namespace utility } // namespace dbus diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp index cc98e1a..3d4c117 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp @@ -25,6 +25,8 @@ #include "../lib/log_services.hpp" #include "../lib/managers.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" @@ -35,6 +37,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 @@ -202,6 +205,13 @@ class RedfishService nodes.emplace_back(std::make_unique(app)); nodes.emplace_back(std::make_unique(app)); + nodes.emplace_back(std::make_unique(app)); + nodes.emplace_back( + std::make_unique(app)); + nodes.emplace_back(std::make_unique(app)); + nodes.emplace_back(std::make_unique(app)); + nodes.emplace_back(std::make_unique(app)); + for (const auto& node : nodes) { node->initPrivileges(); diff --git a/redfish-core/include/utils/json_utils.hpp b/redfish-core/include/utils/json_utils.hpp index d578de4..fbb259d 100644 --- a/redfish-core/include/utils/json_utils.hpp +++ b/redfish-core/include/utils/json_utils.hpp @@ -13,15 +13,19 @@ // See the License for the specific language governing permissions and // limitations under the License. */ + #pragma once #include #include +#include #include #include #include +#include +#include namespace redfish { @@ -436,5 +440,102 @@ bool getValueFromJsonObject(nlohmann::json& jsonData, const std::string& key, return details::unpackValue(jsonValue, key, value); } +template +struct IsStdFunction +{ + static constexpr bool value = false; +}; + +template +struct IsStdFunction> +{ + static constexpr bool value = true; +}; + +template +constexpr bool is_std_function_v = IsStdFunction::value; + +/** + * @brief Assign dbus property to http response attribute if property is stored + * on the map. + */ +template +bool assignIfPresent( + const boost::container::flat_map>& ret, + const char* propertyName, nlohmann::json& attribute, const S& convert) +{ + if constexpr (is_std_function_v) + { + if (!convert) + { + BMCWEB_LOG_ERROR << "Passed empty target as convert argument"; + return false; + } + } + + auto found = ret.find(propertyName); + if (found != ret.end()) + { + auto property = std::get_if(&found->second); + if (property) + { + attribute = convert(*property); + return true; + } + else + { + BMCWEB_LOG_ERROR << "Variant does not contain this type"; + } + } + else + { + BMCWEB_LOG_ERROR << "Element not found in map"; + } + + return false; +} + +template +bool assignIfPresent( + const boost::container::flat_map>& ret, + const char* propertyName, nlohmann::json& attribute) +{ + return assignIfPresent(ret, propertyName, attribute, + [](const T& v) -> T { return v; }); +} + +template +bool assignIfPresent( + const boost::container::flat_map>& ret, + const char* attributeName, crow::Response& res) +{ + return assignIfPresent(ret, attributeName, res.jsonValue[attributeName]); +} + +/** + * @brief Translate dbusPaths received from ObjectMapper into Redfish + * collection members and fill http response with those information. + */ +inline void dbusPathsToMembersArray(crow::Response& res, + const std::vector& reports, + const char* path) +{ + nlohmann::json& members = res.jsonValue["Members"]; + members = nlohmann::json::array(); + + for (const std::string& objpath : reports) + { + std::size_t lastPos = objpath.rfind("/"); + if (lastPos == std::string::npos) + { + BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; + continue; + } + members.push_back({{"@odata.id", path + objpath.substr(lastPos + 1)}}); + } + + res.jsonValue["Members@odata.count"] = members.size(); +} + } // namespace json_util } // namespace redfish diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp new file mode 100644 index 0000000..05ed00f --- /dev/null +++ b/redfish-core/include/utils/telemetry_utils.hpp @@ -0,0 +1,100 @@ +/* +// 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 + +namespace redfish +{ + +namespace telemetry +{ + +static constexpr const char* metricReportDefinitionUri = + "/redfish/v1/TelemetryService/MetricReportDefinitions/"; +static constexpr const char* metricReportUri = + "/redfish/v1/TelemetryService/MetricReports/"; +static constexpr const char* reportInterface = + "xyz.openbmc_project.MonitoringService.Report"; +static constexpr const char* telemetryPath = + "/xyz/openbmc_project/MonitoringService/Reports/TelemetryService"; + +static void getReportCollection(const std::shared_ptr& asyncResp, + const char* uri) +{ + const std::array interfaces = {reportInterface}; + + dbus::utility::getSubTreePaths( + [asyncResp, uri](const boost::system::error_code ec, + const std::vector& reports) { + if (ec == boost::system::errc::no_such_file_or_directory) + { + asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); + asyncResp->res.jsonValue["Members@odata.count"] = 0; + return; + } + + if (ec) + { + messages::internalError(asyncResp->res); + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + return; + } + + json_util::dbusPathsToMembersArray(asyncResp->res, reports, uri); + }, + telemetryPath, 1, interfaces); +} + +template +static void getReport(const std::shared_ptr& asyncResp, + const std::string& id, const char* schemaType, + const Callback&& callback) +{ + const std::array interfaces = {reportInterface}; + + dbus::utility::getSubTreePaths( + [asyncResp, id, schemaType, + callback](const boost::system::error_code ec, + const std::vector& reports) { + if (ec == boost::system::errc::no_such_file_or_directory) + { + messages::resourceNotFound(asyncResp->res, schemaType, id); + return; + } + + if (ec) + { + messages::internalError(asyncResp->res); + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + return; + } + + const std::string target = "/xyz/openbmc_project/" + "MonitoringService/Reports/" + "TelemetryService/" + + id; + auto path = std::find(reports.begin(), reports.end(), target); + if (path == std::end(reports)) + { + messages::resourceNotFound(asyncResp->res, schemaType, id); + return; + } + callback(asyncResp, *path, id); + }, + telemetryPath, 1, interfaces); +} +} // 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..0256b3f --- /dev/null +++ b/redfish-core/include/utils/time_utils.hpp @@ -0,0 +1,97 @@ +/* +// Copyright (c) 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 + +#include +#include +#include +#include + +namespace redfish +{ + +namespace time_utils +{ + +namespace details +{ + +template +std::string toDurationFormatItem(std::chrono::milliseconds& duration, + const char* postfix) +{ + const auto t = std::chrono::duration_cast(duration); + if (t.count() == 0) + { + return ""; + } + + std::stringstream ss; + if constexpr (std::is_same::value) + { + ss << static_cast(t.count()) / + static_cast(std::chrono::milliseconds::period::den); + } + else + { + ss << t.count(); + } + ss << postfix; + duration -= t; + return ss.str(); +} + +} // namespace details + +/** + * @brief Convert time value into duration format that is based on ISO 8601. + * Pattern: "-?P(\\d+D)?(T(\\d+H)?(\\d+M)?(\\d+(.\\d+)?S)?)?" + * Reference: "Redfish Telemetry White Paper". + */ +std::string toDurationFormat(const uint32_t ms) +{ + std::chrono::milliseconds duration(ms); + if (duration.count() == 0) + { + return "PT0S"; + } + + std::string fmt; + fmt.reserve(sizeof("PxxxDTxxHxxMxx.xxxxxxS")); + + using Days = std::chrono::duration>; + + fmt += "P"; + fmt += details::toDurationFormatItem(duration, "D"); + if (duration.count() == 0) + { + return fmt; + } + + fmt += "T"; + fmt += details::toDurationFormatItem(duration, "H"); + fmt += details::toDurationFormatItem(duration, "M"); + fmt += + details::toDurationFormatItem(duration, "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..a52d680 --- /dev/null +++ b/redfish-core/lib/metric_report.hpp @@ -0,0 +1,149 @@ +/* +// 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 "utils/telemetry_utils.hpp" + +#include + +#include +#include + +namespace redfish +{ + +class MetricReportCollection : public Node +{ + public: + MetricReportCollection(CrowApp& app) : Node(app, telemetry::metricReportUri) + { + 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& req, + const std::vector& params) 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(res); + telemetry::getReportCollection(asyncResp, telemetry::metricReportUri); + } +}; + +class MetricReport : public Node +{ + public: + MetricReport(CrowApp& app) : + Node(app, std::string(telemetry::metricReportUri) + "/", + 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& req, + const std::vector& params) override + { + auto asyncResp = std::make_shared(res); + + if (params.size() != 1) + { + messages::internalError(asyncResp->res); + return; + } + + const std::string& id = params[0]; + telemetry::getReport(asyncResp, id, schemaType, getReportProperties); + } + + using Readings = + std::vector>; + using MetricValues = std::vector>; + + static MetricValues toMetricValues(const Readings& readings) + { + MetricValues metricValues; + + for (auto& [id, metadata, sensorValue, timestamp] : readings) + { + metricValues.push_back({ + {"MetricId", id}, + {"MetricProperty", metadata}, + {"MetricValue", std::to_string(sensorValue)}, + {"Timestamp", crow::utility::getDateTime(timestamp)}, + }); + } + + return metricValues; + } + + static void getReportProperties(const std::shared_ptr asyncResp, + const std::string& reportPath, + const std::string& id) + { + 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; + + dbus::utility::getAllProperties( + [asyncResp]( + const boost::system::error_code ec, + const boost::container::flat_map< + std::string, std::variant>& ret) { + if (ec) + { + messages::internalError(asyncResp->res); + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + return; + } + + json_util::assignIfPresent( + ret, "Timestamp", asyncResp->res.jsonValue["Timestamp"], + crow::utility::getDateTime); + json_util::assignIfPresent( + ret, "Readings", asyncResp->res.jsonValue["MetricValues"], + toMetricValues); + }, + "xyz.openbmc_project.MonitoringService", reportPath, + "xyz.openbmc_project.MonitoringService.Report"); + } + + 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..d82ae59 --- /dev/null +++ b/redfish-core/lib/metric_report_definition.hpp @@ -0,0 +1,193 @@ +/* +// 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 "utils/telemetry_utils.hpp" +#include "utils/time_utils.hpp" + +#include + +#include +#include + +namespace redfish +{ + +class MetricReportDefinitionCollection : public Node +{ + public: + MetricReportDefinitionCollection(CrowApp& app) : + Node(app, telemetry::metricReportDefinitionUri) + { + 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& req, + const std::vector& params) 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(res); + telemetry::getReportCollection(asyncResp, + telemetry::metricReportDefinitionUri); + } +}; + +class MetricReportDefinition : public Node +{ + public: + MetricReportDefinition(CrowApp& app) : + Node(app, std::string(telemetry::metricReportDefinitionUri) + "/", + 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& req, + const std::vector& params) override + { + auto asyncResp = std::make_shared(res); + + if (params.size() != 1) + { + messages::internalError(asyncResp->res); + return; + } + + const std::string& id = params[0]; + + telemetry::getReport(asyncResp, id, schemaType, + getReportDefinitonProperties); + } + + static std::vector + toReportActions(const std::vector& actions) + { + const boost::container::flat_map + reportActions = { + {"Event", "RedfishEvent"}, + {"Log", "LogToMetricReportsCollection"}, + }; + + std::vector out; + for (auto& action : actions) + { + auto found = reportActions.find(action); + if (found != reportActions.end()) + { + out.emplace_back(found->second); + } + } + return out; + } + + using ReadingParameters = + std::vector, + std::string, std::string, std::string>>; + using Metrics = std::vector>>>; + + static Metrics toMetrics(const ReadingParameters& params) + { + Metrics metrics; + + for (auto& [sensorPaths, operationType, id, metadata] : params) + { + metrics.push_back({ + {"MetricId", id}, + {"MetricProperties", std::vector() = {metadata}}, + }); + } + + return metrics; + } + + static void + getReportDefinitonProperties(const std::shared_ptr asyncResp, + const std::string& reportPath, + const std::string& id) + { + 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"; + + dbus::utility::getAllProperties( + [asyncResp](const boost::system::error_code ec, + const boost::container::flat_map< + std::string, + std::variant, + uint32_t, ReadingParameters>>& ret) { + if (ec) + { + messages::internalError(asyncResp->res); + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + return; + } + + json_util::assignIfPresent>( + ret, "ReportAction", + asyncResp->res.jsonValue["ReportActions"], toReportActions); + auto assigned = json_util::assignIfPresent( + ret, "ReportingType", + asyncResp->res.jsonValue["MetricReportDefinitionType"]); + if (assigned && + asyncResp->res.jsonValue["MetricReportDefinitionType"] == + "Periodic") + { + json_util::assignIfPresent( + ret, "ScanPeriod", + asyncResp->res + .jsonValue["Schedule"]["RecurrenceInterval"], + time_utils::toDurationFormat); + } + json_util::assignIfPresent( + ret, "ReadingParameters", + asyncResp->res.jsonValue["Metrics"], toMetrics); + }, + "xyz.openbmc_project.MonitoringService", reportPath, + "xyz.openbmc_project.MonitoringService.Report"); + } + + public: + 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 b6bd6e0..3302390 100644 --- a/redfish-core/lib/service_root.hpp +++ b/redfish-core/lib/service_root.hpp @@ -69,6 +69,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..a410700 --- /dev/null +++ b/redfish-core/lib/telemetry_service.hpp @@ -0,0 +1,92 @@ +/* +// 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 "utils/time_utils.hpp" + +#include + +#include + +namespace redfish +{ + +class TelemetryService : public Node +{ + public: + TelemetryService(CrowApp& 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& req, + const std::vector& params) override + { + res.jsonValue["@odata.type"] = + "#TelemetryService.v1_2_0.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"; + + getMonitoringServiceProperties(res); + } + + void getMonitoringServiceProperties(crow::Response& res) + { + auto asyncResp = std::make_shared(res); + dbus::utility::getAllProperties( + [asyncResp]( + const boost::system::error_code ec, + const boost::container::flat_map>& ret) { + if (ec) + { + asyncResp->res.jsonValue["Status"]["State"] = "Absent"; + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + return; + } + + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; + + json_util::assignIfPresent(ret, "MaxReports", + asyncResp->res); + json_util::assignIfPresent( + ret, "PollRateResolution", + asyncResp->res.jsonValue["MinCollectionInterval"], + time_utils::toDurationFormat); + }, + "xyz.openbmc_project.MonitoringService", + "/xyz/openbmc_project/MonitoringService/Reports", + "xyz.openbmc_project.MonitoringService.ReportsManagement"); + } +}; +} // namespace redfish -- 2.16.6