From 8ba1bcc3503cafb33b1a06356d4f8f92ae23e39a Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny Date: Thu, 17 Jun 2021 13:37:57 +0000 Subject: [PATCH] Switched bmcweb to use new telemetry service API Added support for multiple MetricProperties. Added support for new parameters: CollectionTimeScope, CollectionDuration. Tested: - It is possible to create MetricReportDefinitions with multiple MetricProperties. - Stub values for new parameters are correctly passed to telemetry service. - All existing telemetry service functionalities remain unchanged. Change-Id: I2cd17069e3ea015c8f5571c29278f1d50536272a Signed-off-by: Krzysztof Grobelny --- redfish-core/lib/metric_report_definition.hpp | 212 ++++++++++-------- 1 file changed, 114 insertions(+), 98 deletions(-) diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp index a0c4f1d..7c26787 100644 --- a/redfish-core/lib/metric_report_definition.hpp +++ b/redfish-core/lib/metric_report_definition.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -17,87 +19,90 @@ namespace redfish namespace telemetry { -using ReadingParameters = - std::vector>; +using ReadingParameters = std::vector< + std::tuple, std::string, + std::string, std::string, std::string, uint64_t>>; inline void fillReportDefinition( const std::shared_ptr& asyncResp, const std::string& id, const std::vector< - std::pair>>& ret) + std::pair>>& + properties) { - asyncResp->res.jsonValue["@odata.type"] = - "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; - 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) + try { - if (key == "EmitsReadingsUpdate") + bool emitsReadingsUpdate = false; + bool logToMetricReportsCollection = false; + ReadingParameters readingParams; + std::string reportingType; + uint64_t interval = 0u; + + sdbusplus::unpackProperties( + properties, "EmitsReadingsUpdate", emitsReadingsUpdate, + "LogToMetricReportsCollection", logToMetricReportsCollection, + "ReadingParametersFutureVersion", readingParams, "ReportingType", + reportingType, "Interval", interval); + + std::vector redfishReportActions; + redfishReportActions.reserve(2); + if (emitsReadingsUpdate) { - emitsReadingsUpdate = std::get_if(&var); + redfishReportActions.emplace_back("RedfishEvent"); } - else if (key == "LogToMetricReportsCollection") + if (logToMetricReportsCollection) { - logToMetricReportsCollection = std::get_if(&var); + redfishReportActions.emplace_back("LogToMetricReportsCollection"); } - else if (key == "ReadingParameters") - { - readingParams = std::get_if(&var); - } - else if (key == "ReportingType") - { - reportingType = std::get_if(&var); - } - else if (key == "Interval") + + nlohmann::json metrics = nlohmann::json::array(); + for (auto& [sensorPath, operationType, id, metadata, + collectionTimeScope, collectionDuration] : readingParams) { - interval = std::get_if(&var); + std::vector metricProperties; + + nlohmann::json parsedMetadata = nlohmann::json::parse(metadata); + if (!json_util::readJson(parsedMetadata, asyncResp->res, + "MetricProperties", metricProperties)) + { + BMCWEB_LOG_ERROR << "Failed to read metadata"; + messages::internalError(asyncResp->res); + return; + } + + metrics.push_back({ + {"MetricId", id}, + {"MetricProperties", std::move(metricProperties)}, + }); } - } - if (!emitsReadingsUpdate || !logToMetricReportsCollection || - !readingParams || !reportingType || !interval) - { - BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; - messages::internalError(asyncResp->res); - return; - } - std::vector redfishReportActions; - redfishReportActions.reserve(2); - if (*emitsReadingsUpdate) - { - redfishReportActions.emplace_back("RedfishEvent"); + asyncResp->res.jsonValue["@odata.type"] = + "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; + 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"; + 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)); } - if (*logToMetricReportsCollection) + catch (const sdbusplus::exception::UnpackPropertyError& error) { - redfishReportActions.emplace_back("LogToMetricReportsCollection"); + BMCWEB_LOG_ERROR << error.what() << ", property: " + << error.propertyName + ", reason: " << error.reason; + messages::internalError(asyncResp->res); } - - nlohmann::json metrics = nlohmann::json::array(); - for (auto& [sensorPath, operationType, id, metadata] : *readingParams) + catch (const nlohmann::json::parse_error& e) { - metrics.push_back({ - {"MetricId", id}, - {"MetricProperties", {metadata}}, - }); + BMCWEB_LOG_ERROR << "Failed to parse metadata: " << e.what(); + messages::internalError(asyncResp->res); } - 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)); } struct AddReportArgs @@ -275,6 +280,11 @@ class AddReport for (const auto& [id, uris] : args.metrics) { + std::vector dbusPaths; + dbusPaths.reserve(uris.size()); + nlohmann::json metadata; + metadata["MetricProperties"] = nlohmann::json::array(); + for (size_t i = 0; i < uris.size(); i++) { const std::string& uri = uris[i]; @@ -291,8 +301,12 @@ class AddReport } const std::string& dbusPath = el->second; - readingParams.emplace_back(dbusPath, "SINGLE", id, uri); + dbusPaths.emplace_back(dbusPath); + metadata["MetricProperties"].emplace_back(uri); } + + readingParams.emplace_back(dbusPaths, "SINGLE", id, metadata.dump(), + "Point", 0u); } const std::shared_ptr aResp = asyncResp; crow::connections::systemBus->async_method_call( @@ -330,10 +344,10 @@ class AddReport messages::created(aResp->res); }, telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", - "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", - "TelemetryService/" + args.name, args.reportingType, - args.emitsReadingsUpdate, args.logToMetricReportsCollection, - args.interval, readingParams); + "xyz.openbmc_project.Telemetry.ReportManager", + "AddReportFutureVersion", "TelemetryService/" + args.name, + args.reportingType, args.emitsReadingsUpdate, + args.logToMetricReportsCollection, args.interval, readingParams); } void insert(const boost::container::flat_map& el) @@ -415,37 +429,39 @@ inline void requestRoutesMetricReportDefinition(App& app) BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions//") .privileges(redfish::privileges::getMetricReportDefinition) - .methods(boost::beast::http::verb::get)( - [](const crow::Request&, - const std::shared_ptr& asyncResp, - const std::string& id) { - crow::connections::systemBus->async_method_call( - [asyncResp, id]( - const boost::system::error_code ec, - const std::vector>>& ret) { - if (ec.value() == EBADR || - ec == boost::system::errc::host_unreachable) - { - messages::resourceNotFound( - asyncResp->res, "MetricReportDefinition", id); - return; - } - if (ec) - { - BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; - messages::internalError(asyncResp->res); - return; - } + .methods( + boost::beast::http::verb::get)([](const crow::Request&, + const std::shared_ptr< + bmcweb::AsyncResp>& asyncResp, + const std::string& id) { + sdbusplus::asio::getAllProperties( + *crow::connections::systemBus, telemetry::service, + telemetry::getDbusReportPath(id), telemetry::reportInterface, + [asyncResp, + id](boost::system::error_code ec, + const std::vector>>& + properties) { + if (ec.value() == EBADR || + ec == boost::system::errc::host_unreachable) + { + messages::resourceNotFound( + asyncResp->res, "MetricReportDefinition", id); + return; + } + if (ec) + { + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + messages::internalError(asyncResp->res); + return; + } + + telemetry::fillReportDefinition(asyncResp, id, properties); + }); + }); - telemetry::fillReportDefinition(asyncResp, id, ret); - }, - telemetry::service, telemetry::getDbusReportPath(id), - "org.freedesktop.DBus.Properties", "GetAll", - telemetry::reportInterface); - }); BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions//") .privileges(redfish::privileges::deleteMetricReportDefinitionCollection) -- 2.25.1