1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3081ebf06SWludzik, Jozef #pragma once 4081ebf06SWludzik, Jozef 53ccb3adbSEd Tanous #include "app.hpp" 63ccb3adbSEd Tanous #include "dbus_utility.hpp" 7479e899dSKrzysztof Grobelny #include "generated/enums/metric_report_definition.hpp" 8539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 93ccb3adbSEd Tanous #include "query.hpp" 103ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 114dbb8aeaSWludzik, Jozef #include "sensors.hpp" 123ccb3adbSEd Tanous #include "utils/collection.hpp" 133ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 145b90429aSEd Tanous #include "utils/json_utils.hpp" 15081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp" 16081ebf06SWludzik, Jozef #include "utils/time_utils.hpp" 17081ebf06SWludzik, Jozef 184dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp> 19ef4c65b7SEd Tanous #include <boost/url/format.hpp> 2089474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 2189474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 224dbb8aeaSWludzik, Jozef 237a1dbc48SGeorge Liu #include <array> 24fe04d49cSNan Zhou #include <map> 25f19ab44aSSzymon Dompke #include <optional> 26f19ab44aSSzymon Dompke #include <span> 27f19ab44aSSzymon Dompke #include <string> 287a1dbc48SGeorge Liu #include <string_view> 29081ebf06SWludzik, Jozef #include <tuple> 30f19ab44aSSzymon Dompke #include <utility> 31081ebf06SWludzik, Jozef #include <variant> 32f19ab44aSSzymon Dompke #include <vector> 33081ebf06SWludzik, Jozef 34081ebf06SWludzik, Jozef namespace redfish 35081ebf06SWludzik, Jozef { 36081ebf06SWludzik, Jozef 37081ebf06SWludzik, Jozef namespace telemetry 38081ebf06SWludzik, Jozef { 39081ebf06SWludzik, Jozef 40479e899dSKrzysztof Grobelny using ReadingParameters = std::vector<std::tuple< 41479e899dSKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>>, 42479e899dSKrzysztof Grobelny std::string, std::string, uint64_t>>; 43479e899dSKrzysztof Grobelny 449e6c388aSLukasz Kazmierczak inline bool verifyCommonErrors(crow::Response& res, const std::string& id, 459e6c388aSLukasz Kazmierczak const boost::system::error_code& ec) 469e6c388aSLukasz Kazmierczak { 479e6c388aSLukasz Kazmierczak if (ec.value() == EBADR || ec == boost::system::errc::host_unreachable) 489e6c388aSLukasz Kazmierczak { 499e6c388aSLukasz Kazmierczak messages::resourceNotFound(res, "MetricReportDefinition", id); 509e6c388aSLukasz Kazmierczak return false; 519e6c388aSLukasz Kazmierczak } 529e6c388aSLukasz Kazmierczak 539e6c388aSLukasz Kazmierczak if (ec == boost::system::errc::file_exists) 549e6c388aSLukasz Kazmierczak { 559e6c388aSLukasz Kazmierczak messages::resourceAlreadyExists(res, "MetricReportDefinition", "Id", 569e6c388aSLukasz Kazmierczak id); 579e6c388aSLukasz Kazmierczak return false; 589e6c388aSLukasz Kazmierczak } 599e6c388aSLukasz Kazmierczak 609e6c388aSLukasz Kazmierczak if (ec == boost::system::errc::too_many_files_open) 619e6c388aSLukasz Kazmierczak { 629e6c388aSLukasz Kazmierczak messages::createLimitReachedForResource(res); 639e6c388aSLukasz Kazmierczak return false; 649e6c388aSLukasz Kazmierczak } 659e6c388aSLukasz Kazmierczak 669e6c388aSLukasz Kazmierczak if (ec) 679e6c388aSLukasz Kazmierczak { 689e6c388aSLukasz Kazmierczak BMCWEB_LOG_ERROR("DBUS response error {}", ec); 699e6c388aSLukasz Kazmierczak messages::internalError(res); 709e6c388aSLukasz Kazmierczak return false; 719e6c388aSLukasz Kazmierczak } 729e6c388aSLukasz Kazmierczak 739e6c388aSLukasz Kazmierczak return true; 749e6c388aSLukasz Kazmierczak } 759e6c388aSLukasz Kazmierczak 76479e899dSKrzysztof Grobelny inline metric_report_definition::ReportActionsEnum 77479e899dSKrzysztof Grobelny toRedfishReportAction(std::string_view dbusValue) 78479e899dSKrzysztof Grobelny { 79479e899dSKrzysztof Grobelny if (dbusValue == 80479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate") 81479e899dSKrzysztof Grobelny { 82479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum::RedfishEvent; 83479e899dSKrzysztof Grobelny } 84479e899dSKrzysztof Grobelny if (dbusValue == 85479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection") 86479e899dSKrzysztof Grobelny { 87479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum:: 88479e899dSKrzysztof Grobelny LogToMetricReportsCollection; 89479e899dSKrzysztof Grobelny } 90479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum::Invalid; 91479e899dSKrzysztof Grobelny } 92479e899dSKrzysztof Grobelny 93479e899dSKrzysztof Grobelny inline std::string toDbusReportAction(std::string_view redfishValue) 94479e899dSKrzysztof Grobelny { 95479e899dSKrzysztof Grobelny if (redfishValue == "RedfishEvent") 96479e899dSKrzysztof Grobelny { 97479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate"; 98479e899dSKrzysztof Grobelny } 99479e899dSKrzysztof Grobelny if (redfishValue == "LogToMetricReportsCollection") 100479e899dSKrzysztof Grobelny { 101479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection"; 102479e899dSKrzysztof Grobelny } 103479e899dSKrzysztof Grobelny return ""; 104479e899dSKrzysztof Grobelny } 105479e899dSKrzysztof Grobelny 106479e899dSKrzysztof Grobelny inline metric_report_definition::MetricReportDefinitionType 107479e899dSKrzysztof Grobelny toRedfishReportingType(std::string_view dbusValue) 108479e899dSKrzysztof Grobelny { 109479e899dSKrzysztof Grobelny if (dbusValue == 110479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange") 111479e899dSKrzysztof Grobelny { 112479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::OnChange; 113479e899dSKrzysztof Grobelny } 114479e899dSKrzysztof Grobelny if (dbusValue == 115479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest") 116479e899dSKrzysztof Grobelny { 117479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::OnRequest; 118479e899dSKrzysztof Grobelny } 119479e899dSKrzysztof Grobelny if (dbusValue == 120479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic") 121479e899dSKrzysztof Grobelny { 122479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::Periodic; 123479e899dSKrzysztof Grobelny } 124479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::Invalid; 125479e899dSKrzysztof Grobelny } 126479e899dSKrzysztof Grobelny 127479e899dSKrzysztof Grobelny inline std::string toDbusReportingType(std::string_view redfishValue) 128479e899dSKrzysztof Grobelny { 129479e899dSKrzysztof Grobelny if (redfishValue == "OnChange") 130479e899dSKrzysztof Grobelny { 131479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange"; 132479e899dSKrzysztof Grobelny } 133479e899dSKrzysztof Grobelny if (redfishValue == "OnRequest") 134479e899dSKrzysztof Grobelny { 135479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest"; 136479e899dSKrzysztof Grobelny } 137479e899dSKrzysztof Grobelny if (redfishValue == "Periodic") 138479e899dSKrzysztof Grobelny { 139479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic"; 140479e899dSKrzysztof Grobelny } 141479e899dSKrzysztof Grobelny return ""; 142479e899dSKrzysztof Grobelny } 143479e899dSKrzysztof Grobelny 144479e899dSKrzysztof Grobelny inline metric_report_definition::CollectionTimeScope 145479e899dSKrzysztof Grobelny toRedfishCollectionTimeScope(std::string_view dbusValue) 146479e899dSKrzysztof Grobelny { 147479e899dSKrzysztof Grobelny if (dbusValue == 148479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point") 149479e899dSKrzysztof Grobelny { 150479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Point; 151479e899dSKrzysztof Grobelny } 152479e899dSKrzysztof Grobelny if (dbusValue == 153479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval") 154479e899dSKrzysztof Grobelny { 155479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Interval; 156479e899dSKrzysztof Grobelny } 157479e899dSKrzysztof Grobelny if (dbusValue == 158479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval") 159479e899dSKrzysztof Grobelny { 160479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::StartupInterval; 161479e899dSKrzysztof Grobelny } 162479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Invalid; 163479e899dSKrzysztof Grobelny } 164479e899dSKrzysztof Grobelny 165479e899dSKrzysztof Grobelny inline std::string toDbusCollectionTimeScope(std::string_view redfishValue) 166479e899dSKrzysztof Grobelny { 167479e899dSKrzysztof Grobelny if (redfishValue == "Point") 168479e899dSKrzysztof Grobelny { 169479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point"; 170479e899dSKrzysztof Grobelny } 171479e899dSKrzysztof Grobelny if (redfishValue == "Interval") 172479e899dSKrzysztof Grobelny { 173479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval"; 174479e899dSKrzysztof Grobelny } 175479e899dSKrzysztof Grobelny if (redfishValue == "StartupInterval") 176479e899dSKrzysztof Grobelny { 177479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval"; 178479e899dSKrzysztof Grobelny } 179479e899dSKrzysztof Grobelny return ""; 180479e899dSKrzysztof Grobelny } 181479e899dSKrzysztof Grobelny 182479e899dSKrzysztof Grobelny inline metric_report_definition::ReportUpdatesEnum 183479e899dSKrzysztof Grobelny toRedfishReportUpdates(std::string_view dbusValue) 184479e899dSKrzysztof Grobelny { 185479e899dSKrzysztof Grobelny if (dbusValue == 186479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite") 187479e899dSKrzysztof Grobelny { 188479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::Overwrite; 189479e899dSKrzysztof Grobelny } 190479e899dSKrzysztof Grobelny if (dbusValue == 191479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull") 192479e899dSKrzysztof Grobelny { 193479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::AppendWrapsWhenFull; 194479e899dSKrzysztof Grobelny } 195479e899dSKrzysztof Grobelny if (dbusValue == 196479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull") 197479e899dSKrzysztof Grobelny { 198479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::AppendStopsWhenFull; 199479e899dSKrzysztof Grobelny } 200479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::Invalid; 201479e899dSKrzysztof Grobelny } 202479e899dSKrzysztof Grobelny 203479e899dSKrzysztof Grobelny inline std::string toDbusReportUpdates(std::string_view redfishValue) 204479e899dSKrzysztof Grobelny { 205479e899dSKrzysztof Grobelny if (redfishValue == "Overwrite") 206479e899dSKrzysztof Grobelny { 207479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite"; 208479e899dSKrzysztof Grobelny } 209479e899dSKrzysztof Grobelny if (redfishValue == "AppendWrapsWhenFull") 210479e899dSKrzysztof Grobelny { 211479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull"; 212479e899dSKrzysztof Grobelny } 213479e899dSKrzysztof Grobelny if (redfishValue == "AppendStopsWhenFull") 214479e899dSKrzysztof Grobelny { 215479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull"; 216479e899dSKrzysztof Grobelny } 217479e899dSKrzysztof Grobelny return ""; 218479e899dSKrzysztof Grobelny } 219081ebf06SWludzik, Jozef 220f19ab44aSSzymon Dompke inline std::optional<nlohmann::json::array_t> getLinkedTriggers( 221f19ab44aSSzymon Dompke std::span<const sdbusplus::message::object_path> triggerPaths) 222f19ab44aSSzymon Dompke { 223f19ab44aSSzymon Dompke nlohmann::json::array_t triggers; 224f19ab44aSSzymon Dompke 225f19ab44aSSzymon Dompke for (const sdbusplus::message::object_path& path : triggerPaths) 226f19ab44aSSzymon Dompke { 227f19ab44aSSzymon Dompke if (path.parent_path() != 228f19ab44aSSzymon Dompke "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService") 229f19ab44aSSzymon Dompke { 23062598e31SEd Tanous BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}", 23162598e31SEd Tanous path.str); 232f19ab44aSSzymon Dompke return std::nullopt; 233f19ab44aSSzymon Dompke } 234f19ab44aSSzymon Dompke 235f19ab44aSSzymon Dompke std::string id = path.filename(); 236f19ab44aSSzymon Dompke if (id.empty()) 237f19ab44aSSzymon Dompke { 23862598e31SEd Tanous BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}", 23962598e31SEd Tanous path.str); 240f19ab44aSSzymon Dompke return std::nullopt; 241f19ab44aSSzymon Dompke } 242f19ab44aSSzymon Dompke nlohmann::json::object_t trigger; 243f19ab44aSSzymon Dompke trigger["@odata.id"] = 244f19ab44aSSzymon Dompke boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id); 245f19ab44aSSzymon Dompke triggers.emplace_back(std::move(trigger)); 246f19ab44aSSzymon Dompke } 247f19ab44aSSzymon Dompke 248f19ab44aSSzymon Dompke return triggers; 249f19ab44aSSzymon Dompke } 250f19ab44aSSzymon Dompke 251bd79bce8SPatrick Williams inline void fillReportDefinition( 252bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 253479e899dSKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) 254081ebf06SWludzik, Jozef { 255479e899dSKrzysztof Grobelny std::vector<std::string> reportActions; 256479e899dSKrzysztof Grobelny ReadingParameters readingParams; 257479e899dSKrzysztof Grobelny std::string reportingType; 258479e899dSKrzysztof Grobelny std::string reportUpdates; 259479e899dSKrzysztof Grobelny std::string name; 260479e899dSKrzysztof Grobelny uint64_t appendLimit = 0; 261479e899dSKrzysztof Grobelny uint64_t interval = 0; 262479e899dSKrzysztof Grobelny bool enabled = false; 263f19ab44aSSzymon Dompke std::vector<sdbusplus::message::object_path> triggers; 26489474494SKrzysztof Grobelny 26589474494SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 266479e899dSKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "ReportingType", 267479e899dSKrzysztof Grobelny reportingType, "Interval", interval, "ReportActions", reportActions, 268479e899dSKrzysztof Grobelny "ReportUpdates", reportUpdates, "AppendLimit", appendLimit, 269f19ab44aSSzymon Dompke "ReadingParameters", readingParams, "Name", name, "Enabled", enabled, 270f19ab44aSSzymon Dompke "Triggers", triggers); 27189474494SKrzysztof Grobelny 27289474494SKrzysztof Grobelny if (!success) 273081ebf06SWludzik, Jozef { 274081ebf06SWludzik, Jozef messages::internalError(asyncResp->res); 275081ebf06SWludzik, Jozef return; 276081ebf06SWludzik, Jozef } 277081ebf06SWludzik, Jozef 278479e899dSKrzysztof Grobelny metric_report_definition::MetricReportDefinitionType redfishReportingType = 279479e899dSKrzysztof Grobelny toRedfishReportingType(reportingType); 280479e899dSKrzysztof Grobelny if (redfishReportingType == 281479e899dSKrzysztof Grobelny metric_report_definition::MetricReportDefinitionType::Invalid) 282081ebf06SWludzik, Jozef { 283479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 284479e899dSKrzysztof Grobelny return; 285081ebf06SWludzik, Jozef } 28689474494SKrzysztof Grobelny 287479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReportDefinitionType"] = 288479e899dSKrzysztof Grobelny redfishReportingType; 289479e899dSKrzysztof Grobelny 290f19ab44aSSzymon Dompke std::optional<nlohmann::json::array_t> linkedTriggers = 291f19ab44aSSzymon Dompke getLinkedTriggers(triggers); 292f19ab44aSSzymon Dompke if (!linkedTriggers) 293f19ab44aSSzymon Dompke { 294f19ab44aSSzymon Dompke messages::internalError(asyncResp->res); 295f19ab44aSSzymon Dompke return; 296f19ab44aSSzymon Dompke } 297f19ab44aSSzymon Dompke 298f19ab44aSSzymon Dompke asyncResp->res.jsonValue["Links"]["Triggers"] = std::move(*linkedTriggers); 299f19ab44aSSzymon Dompke 300479e899dSKrzysztof Grobelny nlohmann::json::array_t redfishReportActions; 301479e899dSKrzysztof Grobelny for (const std::string& action : reportActions) 302081ebf06SWludzik, Jozef { 303479e899dSKrzysztof Grobelny metric_report_definition::ReportActionsEnum redfishAction = 304479e899dSKrzysztof Grobelny toRedfishReportAction(action); 305479e899dSKrzysztof Grobelny if (redfishAction == 306479e899dSKrzysztof Grobelny metric_report_definition::ReportActionsEnum::Invalid) 307479e899dSKrzysztof Grobelny { 308479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 309479e899dSKrzysztof Grobelny return; 310081ebf06SWludzik, Jozef } 311081ebf06SWludzik, Jozef 312479e899dSKrzysztof Grobelny redfishReportActions.emplace_back(redfishAction); 313479e899dSKrzysztof Grobelny } 314479e899dSKrzysztof Grobelny 315479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions); 316479e899dSKrzysztof Grobelny 317479e899dSKrzysztof Grobelny nlohmann::json::array_t metrics = nlohmann::json::array(); 318479e899dSKrzysztof Grobelny for (const auto& [sensorData, collectionFunction, collectionTimeScope, 319479e899dSKrzysztof Grobelny collectionDuration] : readingParams) 32089474494SKrzysztof Grobelny { 321479e899dSKrzysztof Grobelny nlohmann::json::array_t metricProperties; 322479e899dSKrzysztof Grobelny 323479e899dSKrzysztof Grobelny for (const auto& [sensorPath, sensorMetadata] : sensorData) 324081ebf06SWludzik, Jozef { 325479e899dSKrzysztof Grobelny metricProperties.emplace_back(sensorMetadata); 326479e899dSKrzysztof Grobelny } 327479e899dSKrzysztof Grobelny 328613dabeaSEd Tanous nlohmann::json::object_t metric; 329479e899dSKrzysztof Grobelny 330479e899dSKrzysztof Grobelny metric_report_definition::CalculationAlgorithmEnum 331479e899dSKrzysztof Grobelny redfishCollectionFunction = 332479e899dSKrzysztof Grobelny telemetry::toRedfishCollectionFunction(collectionFunction); 333479e899dSKrzysztof Grobelny if (redfishCollectionFunction == 334479e899dSKrzysztof Grobelny metric_report_definition::CalculationAlgorithmEnum::Invalid) 335479e899dSKrzysztof Grobelny { 336479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 337479e899dSKrzysztof Grobelny return; 338479e899dSKrzysztof Grobelny } 339479e899dSKrzysztof Grobelny metric["CollectionFunction"] = redfishCollectionFunction; 340479e899dSKrzysztof Grobelny 341479e899dSKrzysztof Grobelny metric_report_definition::CollectionTimeScope 342479e899dSKrzysztof Grobelny redfishCollectionTimeScope = 343479e899dSKrzysztof Grobelny toRedfishCollectionTimeScope(collectionTimeScope); 344479e899dSKrzysztof Grobelny if (redfishCollectionTimeScope == 345479e899dSKrzysztof Grobelny metric_report_definition::CollectionTimeScope::Invalid) 346479e899dSKrzysztof Grobelny { 347479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 348479e899dSKrzysztof Grobelny return; 349479e899dSKrzysztof Grobelny } 350479e899dSKrzysztof Grobelny metric["CollectionTimeScope"] = redfishCollectionTimeScope; 351479e899dSKrzysztof Grobelny 352479e899dSKrzysztof Grobelny metric["MetricProperties"] = std::move(metricProperties); 353479e899dSKrzysztof Grobelny metric["CollectionDuration"] = time_utils::toDurationString( 354479e899dSKrzysztof Grobelny std::chrono::milliseconds(collectionDuration)); 355b2ba3072SPatrick Williams metrics.emplace_back(std::move(metric)); 356081ebf06SWludzik, Jozef } 357479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Metrics"] = std::move(metrics); 358479e899dSKrzysztof Grobelny 359479e899dSKrzysztof Grobelny if (enabled) 360479e899dSKrzysztof Grobelny { 361539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 362479e899dSKrzysztof Grobelny } 363479e899dSKrzysztof Grobelny else 364479e899dSKrzysztof Grobelny { 365539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Disabled; 36689474494SKrzysztof Grobelny } 36789474494SKrzysztof Grobelny 368479e899dSKrzysztof Grobelny metric_report_definition::ReportUpdatesEnum redfishReportUpdates = 369479e899dSKrzysztof Grobelny toRedfishReportUpdates(reportUpdates); 370479e899dSKrzysztof Grobelny if (redfishReportUpdates == 371479e899dSKrzysztof Grobelny metric_report_definition::ReportUpdatesEnum::Invalid) 37289474494SKrzysztof Grobelny { 373479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 374479e899dSKrzysztof Grobelny return; 37589474494SKrzysztof Grobelny } 376479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["ReportUpdates"] = redfishReportUpdates; 37789474494SKrzysztof Grobelny 378479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReportDefinitionEnabled"] = enabled; 379479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["AppendLimit"] = appendLimit; 380479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Name"] = name; 381081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = 382479e899dSKrzysztof Grobelny time_utils::toDurationString(std::chrono::milliseconds(interval)); 383479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["@odata.type"] = 384479e899dSKrzysztof Grobelny "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; 385479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 386479e899dSKrzysztof Grobelny "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id); 387479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Id"] = id; 388479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format( 389479e899dSKrzysztof Grobelny "/redfish/v1/TelemetryService/MetricReports/{}", id); 39089474494SKrzysztof Grobelny } 39189474494SKrzysztof Grobelny 3924dbb8aeaSWludzik, Jozef struct AddReportArgs 3934dbb8aeaSWludzik, Jozef { 394479e899dSKrzysztof Grobelny struct MetricArgs 395479e899dSKrzysztof Grobelny { 396479e899dSKrzysztof Grobelny std::vector<std::string> uris; 397479e899dSKrzysztof Grobelny std::string collectionFunction; 398479e899dSKrzysztof Grobelny std::string collectionTimeScope; 399479e899dSKrzysztof Grobelny uint64_t collectionDuration = 0; 400479e899dSKrzysztof Grobelny }; 401479e899dSKrzysztof Grobelny 402479e899dSKrzysztof Grobelny std::string id; 4034dbb8aeaSWludzik, Jozef std::string name; 4044dbb8aeaSWludzik, Jozef std::string reportingType; 405479e899dSKrzysztof Grobelny std::string reportUpdates; 406479e899dSKrzysztof Grobelny uint64_t appendLimit = std::numeric_limits<uint64_t>::max(); 407479e899dSKrzysztof Grobelny std::vector<std::string> reportActions; 408479e899dSKrzysztof Grobelny uint64_t interval = std::numeric_limits<uint64_t>::max(); 409479e899dSKrzysztof Grobelny std::vector<MetricArgs> metrics; 410479e899dSKrzysztof Grobelny bool metricReportDefinitionEnabled = true; 4114dbb8aeaSWludzik, Jozef }; 4124dbb8aeaSWludzik, Jozef 4134dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res, 414479e899dSKrzysztof Grobelny const std::vector<std::string>& actions, 4159e6c388aSLukasz Kazmierczak std::vector<std::string>& outReportActions) 4164dbb8aeaSWludzik, Jozef { 4174dbb8aeaSWludzik, Jozef size_t index = 0; 418479e899dSKrzysztof Grobelny for (const std::string& action : actions) 4194dbb8aeaSWludzik, Jozef { 420479e899dSKrzysztof Grobelny std::string dbusReportAction = toDbusReportAction(action); 421479e899dSKrzysztof Grobelny if (dbusReportAction.empty()) 4224dbb8aeaSWludzik, Jozef { 4239e6c388aSLukasz Kazmierczak messages::propertyValueNotInList( 4249e6c388aSLukasz Kazmierczak res, action, "ReportActions/" + std::to_string(index)); 4254dbb8aeaSWludzik, Jozef return false; 4264dbb8aeaSWludzik, Jozef } 427479e899dSKrzysztof Grobelny 4289e6c388aSLukasz Kazmierczak outReportActions.emplace_back(std::move(dbusReportAction)); 4294dbb8aeaSWludzik, Jozef index++; 4304dbb8aeaSWludzik, Jozef } 4314dbb8aeaSWludzik, Jozef return true; 4324dbb8aeaSWludzik, Jozef } 4334dbb8aeaSWludzik, Jozef 434b14f357fSEd Tanous inline bool getUserMetric(crow::Response& res, nlohmann::json::object_t& metric, 435479e899dSKrzysztof Grobelny AddReportArgs::MetricArgs& metricArgs) 436479e899dSKrzysztof Grobelny { 437479e899dSKrzysztof Grobelny std::optional<std::vector<std::string>> uris; 438479e899dSKrzysztof Grobelny std::optional<std::string> collectionDurationStr; 439479e899dSKrzysztof Grobelny std::optional<std::string> collectionFunction; 440479e899dSKrzysztof Grobelny std::optional<std::string> collectionTimeScopeStr; 441479e899dSKrzysztof Grobelny 442afc474aeSMyung Bae if (!json_util::readJsonObject( // 443afc474aeSMyung Bae metric, res, // 444afc474aeSMyung Bae "CollectionDuration", collectionDurationStr, // 445afc474aeSMyung Bae "CollectionFunction", collectionFunction, // 446afc474aeSMyung Bae "CollectionTimeScope", collectionTimeScopeStr, // 447afc474aeSMyung Bae "MetricProperties", uris // 448afc474aeSMyung Bae )) 449479e899dSKrzysztof Grobelny { 450479e899dSKrzysztof Grobelny return false; 451479e899dSKrzysztof Grobelny } 452479e899dSKrzysztof Grobelny 453479e899dSKrzysztof Grobelny if (uris) 454479e899dSKrzysztof Grobelny { 455479e899dSKrzysztof Grobelny metricArgs.uris = std::move(*uris); 456479e899dSKrzysztof Grobelny } 457479e899dSKrzysztof Grobelny 458479e899dSKrzysztof Grobelny if (collectionFunction) 459479e899dSKrzysztof Grobelny { 460479e899dSKrzysztof Grobelny std::string dbusCollectionFunction = 461479e899dSKrzysztof Grobelny telemetry::toDbusCollectionFunction(*collectionFunction); 462479e899dSKrzysztof Grobelny if (dbusCollectionFunction.empty()) 463479e899dSKrzysztof Grobelny { 464479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionFunction", 465479e899dSKrzysztof Grobelny *collectionFunction); 466479e899dSKrzysztof Grobelny return false; 467479e899dSKrzysztof Grobelny } 468479e899dSKrzysztof Grobelny metricArgs.collectionFunction = std::move(dbusCollectionFunction); 469479e899dSKrzysztof Grobelny } 470479e899dSKrzysztof Grobelny 471479e899dSKrzysztof Grobelny if (collectionTimeScopeStr) 472479e899dSKrzysztof Grobelny { 473479e899dSKrzysztof Grobelny std::string dbusCollectionTimeScope = 474479e899dSKrzysztof Grobelny toDbusCollectionTimeScope(*collectionTimeScopeStr); 475479e899dSKrzysztof Grobelny if (dbusCollectionTimeScope.empty()) 476479e899dSKrzysztof Grobelny { 477479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionTimeScope", 478479e899dSKrzysztof Grobelny *collectionTimeScopeStr); 479479e899dSKrzysztof Grobelny return false; 480479e899dSKrzysztof Grobelny } 481479e899dSKrzysztof Grobelny metricArgs.collectionTimeScope = std::move(dbusCollectionTimeScope); 482479e899dSKrzysztof Grobelny } 483479e899dSKrzysztof Grobelny 484479e899dSKrzysztof Grobelny if (collectionDurationStr) 485479e899dSKrzysztof Grobelny { 486479e899dSKrzysztof Grobelny std::optional<std::chrono::milliseconds> duration = 487479e899dSKrzysztof Grobelny time_utils::fromDurationString(*collectionDurationStr); 488479e899dSKrzysztof Grobelny 489479e899dSKrzysztof Grobelny if (!duration || duration->count() < 0) 490479e899dSKrzysztof Grobelny { 491479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionDuration", 492479e899dSKrzysztof Grobelny *collectionDurationStr); 493479e899dSKrzysztof Grobelny return false; 494479e899dSKrzysztof Grobelny } 495479e899dSKrzysztof Grobelny 496479e899dSKrzysztof Grobelny metricArgs.collectionDuration = 497479e899dSKrzysztof Grobelny static_cast<uint64_t>(duration->count()); 498479e899dSKrzysztof Grobelny } 499479e899dSKrzysztof Grobelny 500479e899dSKrzysztof Grobelny return true; 501479e899dSKrzysztof Grobelny } 502479e899dSKrzysztof Grobelny 503479e899dSKrzysztof Grobelny inline bool getUserMetrics(crow::Response& res, 504b14f357fSEd Tanous std::span<nlohmann::json::object_t> metrics, 505479e899dSKrzysztof Grobelny std::vector<AddReportArgs::MetricArgs>& result) 506479e899dSKrzysztof Grobelny { 507479e899dSKrzysztof Grobelny result.reserve(metrics.size()); 508479e899dSKrzysztof Grobelny 509b14f357fSEd Tanous for (nlohmann::json::object_t& m : metrics) 510479e899dSKrzysztof Grobelny { 511479e899dSKrzysztof Grobelny AddReportArgs::MetricArgs metricArgs; 512479e899dSKrzysztof Grobelny 513479e899dSKrzysztof Grobelny if (!getUserMetric(res, m, metricArgs)) 514479e899dSKrzysztof Grobelny { 515479e899dSKrzysztof Grobelny return false; 516479e899dSKrzysztof Grobelny } 517479e899dSKrzysztof Grobelny 518479e899dSKrzysztof Grobelny result.emplace_back(std::move(metricArgs)); 519479e899dSKrzysztof Grobelny } 520479e899dSKrzysztof Grobelny 521479e899dSKrzysztof Grobelny return true; 522479e899dSKrzysztof Grobelny } 523479e899dSKrzysztof Grobelny 5244dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req, 5254dbb8aeaSWludzik, Jozef AddReportArgs& args) 5264dbb8aeaSWludzik, Jozef { 527479e899dSKrzysztof Grobelny std::optional<std::string> id; 528479e899dSKrzysztof Grobelny std::optional<std::string> name; 529479e899dSKrzysztof Grobelny std::optional<std::string> reportingTypeStr; 530479e899dSKrzysztof Grobelny std::optional<std::string> reportUpdatesStr; 531479e899dSKrzysztof Grobelny std::optional<uint64_t> appendLimit; 532479e899dSKrzysztof Grobelny std::optional<bool> metricReportDefinitionEnabled; 533b14f357fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> metrics; 534479e899dSKrzysztof Grobelny std::optional<std::vector<std::string>> reportActionsStr; 535b14f357fSEd Tanous std::optional<std::string> scheduleDurationStr; 536479e899dSKrzysztof Grobelny 537afc474aeSMyung Bae if (!json_util::readJsonPatch( // 538afc474aeSMyung Bae req, res, // 539afc474aeSMyung Bae "AppendLimit", appendLimit, // 540afc474aeSMyung Bae "Id", id, // 541afc474aeSMyung Bae "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, // 542afc474aeSMyung Bae "MetricReportDefinitionType", reportingTypeStr, // 543afc474aeSMyung Bae "Metrics", metrics, // 544afc474aeSMyung Bae "Name", name, // 545afc474aeSMyung Bae "ReportActions", reportActionsStr, // 546afc474aeSMyung Bae "ReportUpdates", reportUpdatesStr, // 547afc474aeSMyung Bae "Schedule/RecurrenceInterval", scheduleDurationStr // 548afc474aeSMyung Bae )) 5494dbb8aeaSWludzik, Jozef { 5504dbb8aeaSWludzik, Jozef return false; 5514dbb8aeaSWludzik, Jozef } 5524dbb8aeaSWludzik, Jozef 553479e899dSKrzysztof Grobelny if (id) 554479e899dSKrzysztof Grobelny { 555479e899dSKrzysztof Grobelny constexpr const char* allowedCharactersInId = 5564dbb8aeaSWludzik, Jozef "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 557479e899dSKrzysztof Grobelny if (id->empty() || 558479e899dSKrzysztof Grobelny id->find_first_not_of(allowedCharactersInId) != std::string::npos) 5594dbb8aeaSWludzik, Jozef { 560479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "Id", *id); 5614dbb8aeaSWludzik, Jozef return false; 5624dbb8aeaSWludzik, Jozef } 563479e899dSKrzysztof Grobelny args.id = *id; 564479e899dSKrzysztof Grobelny } 5654dbb8aeaSWludzik, Jozef 566479e899dSKrzysztof Grobelny if (name) 5674dbb8aeaSWludzik, Jozef { 568479e899dSKrzysztof Grobelny args.name = *name; 569479e899dSKrzysztof Grobelny } 570479e899dSKrzysztof Grobelny 571479e899dSKrzysztof Grobelny if (reportingTypeStr) 572479e899dSKrzysztof Grobelny { 573479e899dSKrzysztof Grobelny std::string dbusReportingType = toDbusReportingType(*reportingTypeStr); 574479e899dSKrzysztof Grobelny if (dbusReportingType.empty()) 575479e899dSKrzysztof Grobelny { 576479e899dSKrzysztof Grobelny messages::propertyValueNotInList(res, *reportingTypeStr, 5774dbb8aeaSWludzik, Jozef "MetricReportDefinitionType"); 5784dbb8aeaSWludzik, Jozef return false; 5794dbb8aeaSWludzik, Jozef } 580479e899dSKrzysztof Grobelny args.reportingType = dbusReportingType; 581479e899dSKrzysztof Grobelny } 5824dbb8aeaSWludzik, Jozef 583479e899dSKrzysztof Grobelny if (reportUpdatesStr) 584479e899dSKrzysztof Grobelny { 585479e899dSKrzysztof Grobelny std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr); 586479e899dSKrzysztof Grobelny if (dbusReportUpdates.empty()) 587479e899dSKrzysztof Grobelny { 588479e899dSKrzysztof Grobelny messages::propertyValueNotInList(res, *reportUpdatesStr, 589479e899dSKrzysztof Grobelny "ReportUpdates"); 590479e899dSKrzysztof Grobelny return false; 591479e899dSKrzysztof Grobelny } 592479e899dSKrzysztof Grobelny args.reportUpdates = dbusReportUpdates; 593479e899dSKrzysztof Grobelny } 594479e899dSKrzysztof Grobelny 595479e899dSKrzysztof Grobelny if (appendLimit) 596479e899dSKrzysztof Grobelny { 597479e899dSKrzysztof Grobelny args.appendLimit = *appendLimit; 598479e899dSKrzysztof Grobelny } 599479e899dSKrzysztof Grobelny 600479e899dSKrzysztof Grobelny if (metricReportDefinitionEnabled) 601479e899dSKrzysztof Grobelny { 602479e899dSKrzysztof Grobelny args.metricReportDefinitionEnabled = *metricReportDefinitionEnabled; 603479e899dSKrzysztof Grobelny } 604479e899dSKrzysztof Grobelny 605479e899dSKrzysztof Grobelny if (reportActionsStr) 606479e899dSKrzysztof Grobelny { 6079e6c388aSLukasz Kazmierczak if (!toDbusReportActions(res, *reportActionsStr, args.reportActions)) 6084dbb8aeaSWludzik, Jozef { 6094dbb8aeaSWludzik, Jozef return false; 6104dbb8aeaSWludzik, Jozef } 611479e899dSKrzysztof Grobelny } 6124dbb8aeaSWludzik, Jozef 613479e899dSKrzysztof Grobelny if (reportingTypeStr == "Periodic") 6144dbb8aeaSWludzik, Jozef { 615b14f357fSEd Tanous if (!scheduleDurationStr) 6164dbb8aeaSWludzik, Jozef { 6174dbb8aeaSWludzik, Jozef messages::createFailedMissingReqProperties(res, "Schedule"); 6184dbb8aeaSWludzik, Jozef return false; 6194dbb8aeaSWludzik, Jozef } 6204dbb8aeaSWludzik, Jozef 6214dbb8aeaSWludzik, Jozef std::optional<std::chrono::milliseconds> durationNum = 622b14f357fSEd Tanous time_utils::fromDurationString(*scheduleDurationStr); 623479e899dSKrzysztof Grobelny if (!durationNum || durationNum->count() < 0) 6244dbb8aeaSWludzik, Jozef { 6254dbb8aeaSWludzik, Jozef messages::propertyValueIncorrect(res, "RecurrenceInterval", 626b14f357fSEd Tanous *scheduleDurationStr); 6274dbb8aeaSWludzik, Jozef return false; 6284dbb8aeaSWludzik, Jozef } 6294dbb8aeaSWludzik, Jozef args.interval = static_cast<uint64_t>(durationNum->count()); 6304dbb8aeaSWludzik, Jozef } 6314dbb8aeaSWludzik, Jozef 632479e899dSKrzysztof Grobelny if (metrics) 6334dbb8aeaSWludzik, Jozef { 634479e899dSKrzysztof Grobelny if (!getUserMetrics(res, *metrics, args.metrics)) 6354dbb8aeaSWludzik, Jozef { 6364dbb8aeaSWludzik, Jozef return false; 6374dbb8aeaSWludzik, Jozef } 6384dbb8aeaSWludzik, Jozef } 6394dbb8aeaSWludzik, Jozef 6404dbb8aeaSWludzik, Jozef return true; 6414dbb8aeaSWludzik, Jozef } 6424dbb8aeaSWludzik, Jozef 643ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics( 6448d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 645479e899dSKrzysztof Grobelny std::span<const AddReportArgs::MetricArgs> metrics, 6464dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>>& matched) 6474dbb8aeaSWludzik, Jozef { 648ca1600c1SSzymon Dompke for (const auto& metric : metrics) 6494dbb8aeaSWludzik, Jozef { 650479e899dSKrzysztof Grobelny std::optional<IncorrectMetricUri> error = 651479e899dSKrzysztof Grobelny getChassisSensorNode(metric.uris, matched); 652ca1600c1SSzymon Dompke if (error) 6534dbb8aeaSWludzik, Jozef { 654bd79bce8SPatrick Williams messages::propertyValueIncorrect( 655bd79bce8SPatrick Williams asyncResp->res, error->uri, 656bd79bce8SPatrick Williams "MetricProperties/" + std::to_string(error->index)); 6574dbb8aeaSWludzik, Jozef return false; 6584dbb8aeaSWludzik, Jozef } 6594dbb8aeaSWludzik, Jozef } 6604dbb8aeaSWludzik, Jozef return true; 6614dbb8aeaSWludzik, Jozef } 6624dbb8aeaSWludzik, Jozef 663ba498310SKrzysztof Grobelny inline std::string toRedfishProperty(std::string_view dbusMessage) 664ba498310SKrzysztof Grobelny { 665ba498310SKrzysztof Grobelny if (dbusMessage == "Id") 666ba498310SKrzysztof Grobelny { 667ba498310SKrzysztof Grobelny return "Id"; 668ba498310SKrzysztof Grobelny } 669ba498310SKrzysztof Grobelny if (dbusMessage == "Name") 670ba498310SKrzysztof Grobelny { 671ba498310SKrzysztof Grobelny return "Name"; 672ba498310SKrzysztof Grobelny } 673ba498310SKrzysztof Grobelny if (dbusMessage == "ReportingType") 674ba498310SKrzysztof Grobelny { 675ba498310SKrzysztof Grobelny return "MetricReportDefinitionType"; 676ba498310SKrzysztof Grobelny } 677ba498310SKrzysztof Grobelny if (dbusMessage == "AppendLimit") 678ba498310SKrzysztof Grobelny { 679ba498310SKrzysztof Grobelny return "AppendLimit"; 680ba498310SKrzysztof Grobelny } 681ba498310SKrzysztof Grobelny if (dbusMessage == "ReportActions") 682ba498310SKrzysztof Grobelny { 683ba498310SKrzysztof Grobelny return "ReportActions"; 684ba498310SKrzysztof Grobelny } 685ba498310SKrzysztof Grobelny if (dbusMessage == "Interval") 686ba498310SKrzysztof Grobelny { 687ba498310SKrzysztof Grobelny return "RecurrenceInterval"; 688ba498310SKrzysztof Grobelny } 689ba498310SKrzysztof Grobelny if (dbusMessage == "ReportUpdates") 690ba498310SKrzysztof Grobelny { 691ba498310SKrzysztof Grobelny return "ReportUpdates"; 692ba498310SKrzysztof Grobelny } 693ba498310SKrzysztof Grobelny if (dbusMessage == "ReadingParameters") 694ba498310SKrzysztof Grobelny { 695ba498310SKrzysztof Grobelny return "Metrics"; 696ba498310SKrzysztof Grobelny } 697ba498310SKrzysztof Grobelny return ""; 698ba498310SKrzysztof Grobelny } 699ba498310SKrzysztof Grobelny 700ba498310SKrzysztof Grobelny inline bool handleParamError(crow::Response& res, const char* errorMessage, 701ba498310SKrzysztof Grobelny std::string_view key) 702ba498310SKrzysztof Grobelny { 703ba498310SKrzysztof Grobelny if (errorMessage == nullptr) 704ba498310SKrzysztof Grobelny { 705ba498310SKrzysztof Grobelny BMCWEB_LOG_ERROR("errorMessage was null"); 706ba498310SKrzysztof Grobelny return true; 707ba498310SKrzysztof Grobelny } 708ba498310SKrzysztof Grobelny std::string_view errorMessageSv(errorMessage); 709ba498310SKrzysztof Grobelny if (errorMessageSv.starts_with(key)) 710ba498310SKrzysztof Grobelny { 711ba498310SKrzysztof Grobelny std::string redfishProperty = toRedfishProperty(key); 712ba498310SKrzysztof Grobelny if (redfishProperty.empty()) 713ba498310SKrzysztof Grobelny { 714ba498310SKrzysztof Grobelny // Getting here means most possibly that toRedfishProperty has 715ba498310SKrzysztof Grobelny // incomplete implementation. Return internal error for now. 716ba498310SKrzysztof Grobelny BMCWEB_LOG_ERROR("{} has no corresponding Redfish property", key); 717ba498310SKrzysztof Grobelny messages::internalError(res); 718ba498310SKrzysztof Grobelny return false; 719ba498310SKrzysztof Grobelny } 720ba498310SKrzysztof Grobelny messages::propertyValueError(res, redfishProperty); 721ba498310SKrzysztof Grobelny return false; 722ba498310SKrzysztof Grobelny } 723ba498310SKrzysztof Grobelny 724ba498310SKrzysztof Grobelny return true; 725ba498310SKrzysztof Grobelny } 726ba498310SKrzysztof Grobelny 727ba498310SKrzysztof Grobelny inline void afterAddReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 728ba498310SKrzysztof Grobelny const AddReportArgs& args, 729ba498310SKrzysztof Grobelny const boost::system::error_code& ec, 730ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) 731ba498310SKrzysztof Grobelny { 732ba498310SKrzysztof Grobelny if (!ec) 733ba498310SKrzysztof Grobelny { 734ba498310SKrzysztof Grobelny messages::created(asyncResp->res); 735ba498310SKrzysztof Grobelny return; 736ba498310SKrzysztof Grobelny } 737ba498310SKrzysztof Grobelny 738ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 739ba498310SKrzysztof Grobelny { 740ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 741ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 742ba498310SKrzysztof Grobelny { 743ba498310SKrzysztof Grobelny for (const auto& arg : 744ba498310SKrzysztof Grobelny {"Id", "Name", "ReportingType", "AppendLimit", "ReportActions", 745ba498310SKrzysztof Grobelny "Interval", "ReportUpdates", "ReadingParameters"}) 746ba498310SKrzysztof Grobelny { 747ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 748ba498310SKrzysztof Grobelny arg)) 749ba498310SKrzysztof Grobelny { 750ba498310SKrzysztof Grobelny return; 751ba498310SKrzysztof Grobelny } 752ba498310SKrzysztof Grobelny } 753ba498310SKrzysztof Grobelny } 754ba498310SKrzysztof Grobelny } 755ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, args.id, ec)) 756ba498310SKrzysztof Grobelny { 757ba498310SKrzysztof Grobelny return; 758ba498310SKrzysztof Grobelny } 759ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 760ba498310SKrzysztof Grobelny } 761ba498310SKrzysztof Grobelny 7624dbb8aeaSWludzik, Jozef class AddReport 7634dbb8aeaSWludzik, Jozef { 7644dbb8aeaSWludzik, Jozef public: 765891eaa7cSEd Tanous AddReport(AddReportArgs&& argsIn, 7668a592810SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 767bd79bce8SPatrick Williams asyncResp(asyncRespIn), args(std::move(argsIn)) 7684dbb8aeaSWludzik, Jozef {} 769479e899dSKrzysztof Grobelny 7704dbb8aeaSWludzik, Jozef ~AddReport() 7714dbb8aeaSWludzik, Jozef { 772479e899dSKrzysztof Grobelny boost::asio::post(crow::connections::systemBus->get_io_context(), 773479e899dSKrzysztof Grobelny std::bind_front(&performAddReport, asyncResp, args, 774479e899dSKrzysztof Grobelny std::move(uriToDbus))); 775479e899dSKrzysztof Grobelny } 776479e899dSKrzysztof Grobelny 777479e899dSKrzysztof Grobelny static void performAddReport( 778479e899dSKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 779479e899dSKrzysztof Grobelny const AddReportArgs& args, 780479e899dSKrzysztof Grobelny const boost::container::flat_map<std::string, std::string>& uriToDbus) 781479e899dSKrzysztof Grobelny { 7824dbb8aeaSWludzik, Jozef if (asyncResp->res.result() != boost::beast::http::status::ok) 7834dbb8aeaSWludzik, Jozef { 7844dbb8aeaSWludzik, Jozef return; 7854dbb8aeaSWludzik, Jozef } 7864dbb8aeaSWludzik, Jozef 7874dbb8aeaSWludzik, Jozef telemetry::ReadingParameters readingParams; 7884dbb8aeaSWludzik, Jozef readingParams.reserve(args.metrics.size()); 7894dbb8aeaSWludzik, Jozef 790479e899dSKrzysztof Grobelny for (const auto& metric : args.metrics) 7914dbb8aeaSWludzik, Jozef { 792479e899dSKrzysztof Grobelny std::vector< 793479e899dSKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>> 794479e899dSKrzysztof Grobelny sensorParams; 795479e899dSKrzysztof Grobelny sensorParams.reserve(metric.uris.size()); 796479e899dSKrzysztof Grobelny 797479e899dSKrzysztof Grobelny for (size_t i = 0; i < metric.uris.size(); i++) 7984dbb8aeaSWludzik, Jozef { 799479e899dSKrzysztof Grobelny const std::string& uri = metric.uris[i]; 8004dbb8aeaSWludzik, Jozef auto el = uriToDbus.find(uri); 8014dbb8aeaSWludzik, Jozef if (el == uriToDbus.end()) 8024dbb8aeaSWludzik, Jozef { 80362598e31SEd Tanous BMCWEB_LOG_ERROR( 80462598e31SEd Tanous "Failed to find DBus sensor corresponding to URI {}", 80562598e31SEd Tanous uri); 806bd79bce8SPatrick Williams messages::propertyValueNotInList( 807bd79bce8SPatrick Williams asyncResp->res, uri, 808bd79bce8SPatrick Williams "MetricProperties/" + std::to_string(i)); 8094dbb8aeaSWludzik, Jozef return; 8104dbb8aeaSWludzik, Jozef } 8114dbb8aeaSWludzik, Jozef 8124dbb8aeaSWludzik, Jozef const std::string& dbusPath = el->second; 813479e899dSKrzysztof Grobelny sensorParams.emplace_back(dbusPath, uri); 8144dbb8aeaSWludzik, Jozef } 815479e899dSKrzysztof Grobelny 816479e899dSKrzysztof Grobelny readingParams.emplace_back( 817479e899dSKrzysztof Grobelny std::move(sensorParams), metric.collectionFunction, 818479e899dSKrzysztof Grobelny metric.collectionTimeScope, metric.collectionDuration); 8194dbb8aeaSWludzik, Jozef } 8204dbb8aeaSWludzik, Jozef crow::connections::systemBus->async_method_call( 821ba498310SKrzysztof Grobelny [asyncResp, args](const boost::system::error_code& ec, 822ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg, 823ba498310SKrzysztof Grobelny const std::string& /*arg1*/) { 824ba498310SKrzysztof Grobelny afterAddReport(asyncResp, args, ec, msg); 8254dbb8aeaSWludzik, Jozef }, 8264dbb8aeaSWludzik, Jozef telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", 8274dbb8aeaSWludzik, Jozef "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", 828479e899dSKrzysztof Grobelny "TelemetryService/" + args.id, args.name, args.reportingType, 829479e899dSKrzysztof Grobelny args.reportUpdates, args.appendLimit, args.reportActions, 830479e899dSKrzysztof Grobelny args.interval, readingParams, args.metricReportDefinitionEnabled); 8314dbb8aeaSWludzik, Jozef } 8324dbb8aeaSWludzik, Jozef 833ecd6a3a2SEd Tanous AddReport(const AddReport&) = delete; 834ecd6a3a2SEd Tanous AddReport(AddReport&&) = delete; 835ecd6a3a2SEd Tanous AddReport& operator=(const AddReport&) = delete; 836ecd6a3a2SEd Tanous AddReport& operator=(AddReport&&) = delete; 837ecd6a3a2SEd Tanous 838fe04d49cSNan Zhou void insert(const std::map<std::string, std::string>& el) 8394dbb8aeaSWludzik, Jozef { 8404dbb8aeaSWludzik, Jozef uriToDbus.insert(el.begin(), el.end()); 8414dbb8aeaSWludzik, Jozef } 8424dbb8aeaSWludzik, Jozef 8434dbb8aeaSWludzik, Jozef private: 844ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 8454dbb8aeaSWludzik, Jozef AddReportArgs args; 84647f2934cSEd Tanous boost::container::flat_map<std::string, std::string> uriToDbus; 8474dbb8aeaSWludzik, Jozef }; 8489e6c388aSLukasz Kazmierczak 849ba498310SKrzysztof Grobelny inline std::optional< 850ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>>> 851ba498310SKrzysztof Grobelny sensorPathToUri( 852ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 853ba498310SKrzysztof Grobelny std::span<const std::string> uris, 854ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 855ba498310SKrzysztof Grobelny { 856ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>> 857ba498310SKrzysztof Grobelny result; 858ba498310SKrzysztof Grobelny 859ba498310SKrzysztof Grobelny for (const std::string& uri : uris) 860ba498310SKrzysztof Grobelny { 861ba498310SKrzysztof Grobelny auto it = metricPropertyToDbusPaths.find(uri); 862ba498310SKrzysztof Grobelny if (it == metricPropertyToDbusPaths.end()) 863ba498310SKrzysztof Grobelny { 864ba498310SKrzysztof Grobelny messages::propertyValueNotInList(asyncResp->res, uri, 865ba498310SKrzysztof Grobelny "MetricProperties"); 866ba498310SKrzysztof Grobelny return {}; 867ba498310SKrzysztof Grobelny } 868ba498310SKrzysztof Grobelny result.emplace_back(it->second, uri); 869ba498310SKrzysztof Grobelny } 870ba498310SKrzysztof Grobelny 871ba498310SKrzysztof Grobelny return result; 872ba498310SKrzysztof Grobelny } 873ba498310SKrzysztof Grobelny 874ba498310SKrzysztof Grobelny inline void afterSetReadingParams( 875ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 876ba498310SKrzysztof Grobelny const std::string& reportId, const boost::system::error_code& ec, 877ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) 878ba498310SKrzysztof Grobelny { 879ba498310SKrzysztof Grobelny if (!ec) 880ba498310SKrzysztof Grobelny { 881ba498310SKrzysztof Grobelny messages::success(asyncResp->res); 882ba498310SKrzysztof Grobelny return; 883ba498310SKrzysztof Grobelny } 884ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 885ba498310SKrzysztof Grobelny { 886ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 887ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 888ba498310SKrzysztof Grobelny { 889ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReadingParameters"}) 890ba498310SKrzysztof Grobelny { 891ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 892ba498310SKrzysztof Grobelny arg)) 893ba498310SKrzysztof Grobelny { 894ba498310SKrzysztof Grobelny return; 895ba498310SKrzysztof Grobelny } 896ba498310SKrzysztof Grobelny } 897ba498310SKrzysztof Grobelny } 898ba498310SKrzysztof Grobelny } 899ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, reportId, ec)) 900ba498310SKrzysztof Grobelny { 901ba498310SKrzysztof Grobelny return; 902ba498310SKrzysztof Grobelny } 903ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 904ba498310SKrzysztof Grobelny } 905ba498310SKrzysztof Grobelny 906ba498310SKrzysztof Grobelny inline void setReadingParams( 907ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 908ba498310SKrzysztof Grobelny const std::string& reportId, ReadingParameters readingParams, 909ba498310SKrzysztof Grobelny const std::vector<std::vector<std::string>>& readingParamsUris, 910ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 911ba498310SKrzysztof Grobelny { 912ba498310SKrzysztof Grobelny if (asyncResp->res.result() != boost::beast::http::status::ok) 913ba498310SKrzysztof Grobelny { 914ba498310SKrzysztof Grobelny return; 915ba498310SKrzysztof Grobelny } 916ba498310SKrzysztof Grobelny 917ba498310SKrzysztof Grobelny for (size_t index = 0; index < readingParamsUris.size(); ++index) 918ba498310SKrzysztof Grobelny { 919ba498310SKrzysztof Grobelny std::span<const std::string> newUris = readingParamsUris[index]; 920ba498310SKrzysztof Grobelny 921ba498310SKrzysztof Grobelny const std::optional<std::vector< 922ba498310SKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>>> 923ba498310SKrzysztof Grobelny readingParam = 924ba498310SKrzysztof Grobelny sensorPathToUri(asyncResp, newUris, metricPropertyToDbusPaths); 925ba498310SKrzysztof Grobelny 926ba498310SKrzysztof Grobelny if (!readingParam) 927ba498310SKrzysztof Grobelny { 928ba498310SKrzysztof Grobelny return; 929ba498310SKrzysztof Grobelny } 930ba498310SKrzysztof Grobelny 931ba498310SKrzysztof Grobelny for (const std::tuple<sdbusplus::message::object_path, std::string>& 932ba498310SKrzysztof Grobelny value : *readingParam) 933ba498310SKrzysztof Grobelny { 934ba498310SKrzysztof Grobelny std::get<0>(readingParams[index]).emplace_back(value); 935ba498310SKrzysztof Grobelny } 936ba498310SKrzysztof Grobelny } 937ba498310SKrzysztof Grobelny 938ba498310SKrzysztof Grobelny crow::connections::systemBus->async_method_call( 939ba498310SKrzysztof Grobelny [asyncResp, reportId](const boost::system::error_code& ec, 940ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 941ba498310SKrzysztof Grobelny afterSetReadingParams(asyncResp, reportId, ec, msg); 942ba498310SKrzysztof Grobelny }, 943ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry", getDbusReportPath(reportId), 944ba498310SKrzysztof Grobelny "org.freedesktop.DBus.Properties", "Set", 945ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report", "ReadingParameters", 946ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{readingParams}); 947ba498310SKrzysztof Grobelny } 948ba498310SKrzysztof Grobelny 9499e6c388aSLukasz Kazmierczak class UpdateMetrics 9509e6c388aSLukasz Kazmierczak { 9519e6c388aSLukasz Kazmierczak public: 9529e6c388aSLukasz Kazmierczak UpdateMetrics(std::string_view idIn, 9539e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 954bd79bce8SPatrick Williams id(idIn), asyncResp(asyncRespIn) 9559e6c388aSLukasz Kazmierczak {} 9569e6c388aSLukasz Kazmierczak 9579e6c388aSLukasz Kazmierczak ~UpdateMetrics() 9589e6c388aSLukasz Kazmierczak { 959ba498310SKrzysztof Grobelny boost::asio::post( 960ba498310SKrzysztof Grobelny crow::connections::systemBus->get_io_context(), 961ba498310SKrzysztof Grobelny std::bind_front(&setReadingParams, asyncResp, id, 962ba498310SKrzysztof Grobelny std::move(readingParams), readingParamsUris, 963ba498310SKrzysztof Grobelny metricPropertyToDbusPaths)); 9649e6c388aSLukasz Kazmierczak } 9659e6c388aSLukasz Kazmierczak 9669e6c388aSLukasz Kazmierczak UpdateMetrics(const UpdateMetrics&) = delete; 9679e6c388aSLukasz Kazmierczak UpdateMetrics(UpdateMetrics&&) = delete; 9689e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(const UpdateMetrics&) = delete; 9699e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(UpdateMetrics&&) = delete; 9709e6c388aSLukasz Kazmierczak 9719e6c388aSLukasz Kazmierczak std::string id; 9729e6c388aSLukasz Kazmierczak std::map<std::string, std::string> metricPropertyToDbusPaths; 9739e6c388aSLukasz Kazmierczak 9749e6c388aSLukasz Kazmierczak void insert(const std::map<std::string, std::string>& 9759e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths) 9769e6c388aSLukasz Kazmierczak { 9779e6c388aSLukasz Kazmierczak metricPropertyToDbusPaths.insert( 9789e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.begin(), 9799e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.end()); 9809e6c388aSLukasz Kazmierczak } 9819e6c388aSLukasz Kazmierczak 982bd79bce8SPatrick Williams void emplace( 983bd79bce8SPatrick Williams std::span< 984bd79bce8SPatrick Williams const std::tuple<sdbusplus::message::object_path, std::string>> 9859e6c388aSLukasz Kazmierczak pathAndUri, 9869e6c388aSLukasz Kazmierczak const AddReportArgs::MetricArgs& metricArgs) 9879e6c388aSLukasz Kazmierczak { 9889e6c388aSLukasz Kazmierczak readingParamsUris.emplace_back(metricArgs.uris); 9899e6c388aSLukasz Kazmierczak readingParams.emplace_back( 9909e6c388aSLukasz Kazmierczak std::vector(pathAndUri.begin(), pathAndUri.end()), 9919e6c388aSLukasz Kazmierczak metricArgs.collectionFunction, metricArgs.collectionTimeScope, 9929e6c388aSLukasz Kazmierczak metricArgs.collectionDuration); 9939e6c388aSLukasz Kazmierczak } 9949e6c388aSLukasz Kazmierczak 9959e6c388aSLukasz Kazmierczak private: 9969e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 9979e6c388aSLukasz Kazmierczak std::vector<std::vector<std::string>> readingParamsUris; 99847f2934cSEd Tanous ReadingParameters readingParams; 9999e6c388aSLukasz Kazmierczak }; 10009e6c388aSLukasz Kazmierczak 10019e6c388aSLukasz Kazmierczak inline void 10029e6c388aSLukasz Kazmierczak setReportEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10039e6c388aSLukasz Kazmierczak std::string_view id, bool enabled) 10049e6c388aSLukasz Kazmierczak { 10059e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 10069e6c388aSLukasz Kazmierczak [asyncResp, id = std::string(id)](const boost::system::error_code& ec) { 10079e6c388aSLukasz Kazmierczak if (!verifyCommonErrors(asyncResp->res, id, ec)) 10089e6c388aSLukasz Kazmierczak { 10099e6c388aSLukasz Kazmierczak return; 10109e6c388aSLukasz Kazmierczak } 10119e6c388aSLukasz Kazmierczak }, 10129e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 10139e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 10149e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "Enabled", 10159e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{enabled}); 10169e6c388aSLukasz Kazmierczak } 10179e6c388aSLukasz Kazmierczak 1018ba498310SKrzysztof Grobelny inline void afterSetReportingProperties( 1019ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1020ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1021ba498310SKrzysztof Grobelny { 1022ba498310SKrzysztof Grobelny if (!ec) 1023ba498310SKrzysztof Grobelny { 1024ba498310SKrzysztof Grobelny asyncResp->res.result(boost::beast::http::status::no_content); 1025ba498310SKrzysztof Grobelny return; 1026ba498310SKrzysztof Grobelny } 1027ba498310SKrzysztof Grobelny 1028ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1029ba498310SKrzysztof Grobelny { 1030ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1031ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1032ba498310SKrzysztof Grobelny { 1033ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportingType", "Interval"}) 1034ba498310SKrzysztof Grobelny { 1035ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1036ba498310SKrzysztof Grobelny arg)) 1037ba498310SKrzysztof Grobelny { 1038ba498310SKrzysztof Grobelny return; 1039ba498310SKrzysztof Grobelny } 1040ba498310SKrzysztof Grobelny } 1041ba498310SKrzysztof Grobelny } 1042ba498310SKrzysztof Grobelny } 1043ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1044ba498310SKrzysztof Grobelny { 1045ba498310SKrzysztof Grobelny return; 1046ba498310SKrzysztof Grobelny } 1047ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 1048ba498310SKrzysztof Grobelny } 1049ba498310SKrzysztof Grobelny 10509e6c388aSLukasz Kazmierczak inline void setReportTypeAndInterval( 10519e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1052b4361d63SEd Tanous const std::optional<std::string>& reportingType, 1053b4361d63SEd Tanous const std::optional<std::string>& recurrenceIntervalStr) 10549e6c388aSLukasz Kazmierczak { 1055b4361d63SEd Tanous std::string dbusReportingType; 1056b4361d63SEd Tanous if (reportingType) 1057b4361d63SEd Tanous { 1058b4361d63SEd Tanous dbusReportingType = toDbusReportingType(*reportingType); 1059b4361d63SEd Tanous if (dbusReportingType.empty()) 1060b4361d63SEd Tanous { 1061b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, *reportingType, 1062b4361d63SEd Tanous "MetricReportDefinitionType"); 1063b4361d63SEd Tanous return; 1064b4361d63SEd Tanous } 1065b4361d63SEd Tanous } 1066b4361d63SEd Tanous 1067b4361d63SEd Tanous uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max(); 1068b4361d63SEd Tanous if (recurrenceIntervalStr) 1069b4361d63SEd Tanous { 1070b4361d63SEd Tanous std::optional<std::chrono::milliseconds> durationNum = 1071b4361d63SEd Tanous time_utils::fromDurationString(*recurrenceIntervalStr); 1072b4361d63SEd Tanous if (!durationNum || durationNum->count() < 0) 1073b4361d63SEd Tanous { 1074b4361d63SEd Tanous messages::propertyValueIncorrect( 1075b4361d63SEd Tanous asyncResp->res, "RecurrenceInterval", *recurrenceIntervalStr); 1076b4361d63SEd Tanous return; 1077b4361d63SEd Tanous } 1078b4361d63SEd Tanous 1079b4361d63SEd Tanous recurrenceInterval = static_cast<uint64_t>(durationNum->count()); 1080b4361d63SEd Tanous } 1081b4361d63SEd Tanous 10829e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 1083ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1084ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1085ba498310SKrzysztof Grobelny afterSetReportingProperties(asyncResp, id, ec, msg); 10869e6c388aSLukasz Kazmierczak }, 10879e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 10889e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "SetReportingProperties", 1089b4361d63SEd Tanous dbusReportingType, recurrenceInterval); 10909e6c388aSLukasz Kazmierczak } 10919e6c388aSLukasz Kazmierczak 1092ba498310SKrzysztof Grobelny inline void afterSetReportUpdates( 1093ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1094ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1095ba498310SKrzysztof Grobelny { 1096ba498310SKrzysztof Grobelny if (!ec) 1097ba498310SKrzysztof Grobelny { 1098ba498310SKrzysztof Grobelny asyncResp->res.result(boost::beast::http::status::no_content); 1099ba498310SKrzysztof Grobelny return; 1100ba498310SKrzysztof Grobelny } 1101ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1102ba498310SKrzysztof Grobelny { 1103ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1104ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1105ba498310SKrzysztof Grobelny { 1106ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportUpdates"}) 1107ba498310SKrzysztof Grobelny { 1108ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1109ba498310SKrzysztof Grobelny arg)) 1110ba498310SKrzysztof Grobelny { 1111ba498310SKrzysztof Grobelny return; 1112ba498310SKrzysztof Grobelny } 1113ba498310SKrzysztof Grobelny } 1114ba498310SKrzysztof Grobelny } 1115ba498310SKrzysztof Grobelny } 1116ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1117ba498310SKrzysztof Grobelny { 1118ba498310SKrzysztof Grobelny return; 1119ba498310SKrzysztof Grobelny } 1120ba498310SKrzysztof Grobelny } 1121ba498310SKrzysztof Grobelny 11229e6c388aSLukasz Kazmierczak inline void 11239e6c388aSLukasz Kazmierczak setReportUpdates(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11249e6c388aSLukasz Kazmierczak std::string_view id, const std::string& reportUpdates) 11259e6c388aSLukasz Kazmierczak { 1126b4361d63SEd Tanous std::string dbusReportUpdates = toDbusReportUpdates(reportUpdates); 1127b4361d63SEd Tanous if (dbusReportUpdates.empty()) 1128b4361d63SEd Tanous { 1129b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, reportUpdates, 1130b4361d63SEd Tanous "ReportUpdates"); 1131b4361d63SEd Tanous return; 1132b4361d63SEd Tanous } 11339e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 1134ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1135ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1136ba498310SKrzysztof Grobelny afterSetReportUpdates(asyncResp, id, ec, msg); 11379e6c388aSLukasz Kazmierczak }, 11389e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11399e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 11409e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportUpdates", 1141ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{dbusReportUpdates}); 1142ba498310SKrzysztof Grobelny } 1143ba498310SKrzysztof Grobelny 1144ba498310SKrzysztof Grobelny inline void afterSetReportActions( 1145ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1146ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1147ba498310SKrzysztof Grobelny { 1148ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1149ba498310SKrzysztof Grobelny { 1150ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1151ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1152ba498310SKrzysztof Grobelny { 1153ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportActions"}) 1154ba498310SKrzysztof Grobelny { 1155ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1156ba498310SKrzysztof Grobelny arg)) 1157ba498310SKrzysztof Grobelny { 1158ba498310SKrzysztof Grobelny return; 1159ba498310SKrzysztof Grobelny } 1160ba498310SKrzysztof Grobelny } 1161ba498310SKrzysztof Grobelny } 1162ba498310SKrzysztof Grobelny } 1163ba498310SKrzysztof Grobelny 1164ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1165ba498310SKrzysztof Grobelny { 1166ba498310SKrzysztof Grobelny return; 1167ba498310SKrzysztof Grobelny } 1168ba498310SKrzysztof Grobelny 1169ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 11709e6c388aSLukasz Kazmierczak } 11719e6c388aSLukasz Kazmierczak 1172bd79bce8SPatrick Williams inline void setReportActions( 1173bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1174b4361d63SEd Tanous const std::vector<std::string>& reportActions) 11759e6c388aSLukasz Kazmierczak { 1176b4361d63SEd Tanous std::vector<std::string> dbusReportActions; 1177b4361d63SEd Tanous if (!toDbusReportActions(asyncResp->res, reportActions, dbusReportActions)) 1178b4361d63SEd Tanous { 1179b4361d63SEd Tanous return; 1180b4361d63SEd Tanous } 1181b4361d63SEd Tanous 11829e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 1183ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1184ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1185ba498310SKrzysztof Grobelny afterSetReportActions(asyncResp, id, ec, msg); 11869e6c388aSLukasz Kazmierczak }, 11879e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11889e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 11899e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportActions", 11909e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{dbusReportActions}); 11919e6c388aSLukasz Kazmierczak } 11929e6c388aSLukasz Kazmierczak 1193bd79bce8SPatrick Williams inline void setReportMetrics( 1194bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1195a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>&& 1196a64919e8SBoleslaw Ogonczyk Makowski metrics) 11979e6c388aSLukasz Kazmierczak { 1198deae6a78SEd Tanous dbus::utility::getAllProperties( 1199deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1200deae6a78SEd Tanous telemetry::reportInterface, 1201ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id), redfishMetrics = std::move(metrics)]( 12029e6c388aSLukasz Kazmierczak boost::system::error_code ec, 12039e6c388aSLukasz Kazmierczak const dbus::utility::DBusPropertiesMap& properties) mutable { 1204ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 12059e6c388aSLukasz Kazmierczak { 12069e6c388aSLukasz Kazmierczak return; 12079e6c388aSLukasz Kazmierczak } 12089e6c388aSLukasz Kazmierczak 12099e6c388aSLukasz Kazmierczak ReadingParameters readingParams; 12109e6c388aSLukasz Kazmierczak 12119e6c388aSLukasz Kazmierczak const bool success = sdbusplus::unpackPropertiesNoThrow( 1212bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 1213bd79bce8SPatrick Williams "ReadingParameters", readingParams); 12149e6c388aSLukasz Kazmierczak 12159e6c388aSLukasz Kazmierczak if (!success) 12169e6c388aSLukasz Kazmierczak { 12179e6c388aSLukasz Kazmierczak messages::internalError(asyncResp->res); 12189e6c388aSLukasz Kazmierczak return; 12199e6c388aSLukasz Kazmierczak } 12209e6c388aSLukasz Kazmierczak 1221bd79bce8SPatrick Williams auto updateMetricsReq = 1222bd79bce8SPatrick Williams std::make_shared<UpdateMetrics>(id, asyncResp); 12239e6c388aSLukasz Kazmierczak 12249e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 12259e6c388aSLukasz Kazmierczak chassisSensors; 12269e6c388aSLukasz Kazmierczak 12279e6c388aSLukasz Kazmierczak size_t index = 0; 1228a64919e8SBoleslaw Ogonczyk Makowski for (std::variant<nlohmann::json::object_t, std::nullptr_t>& 1229a64919e8SBoleslaw Ogonczyk Makowski metricVariant : redfishMetrics) 12309e6c388aSLukasz Kazmierczak { 1231a64919e8SBoleslaw Ogonczyk Makowski nlohmann::json::object_t* metric = 1232a64919e8SBoleslaw Ogonczyk Makowski std::get_if<nlohmann::json::object_t>(&metricVariant); 1233a64919e8SBoleslaw Ogonczyk Makowski if (metric == nullptr) 1234a64919e8SBoleslaw Ogonczyk Makowski { 1235a64919e8SBoleslaw Ogonczyk Makowski index++; 1236a64919e8SBoleslaw Ogonczyk Makowski continue; 1237a64919e8SBoleslaw Ogonczyk Makowski } 1238a64919e8SBoleslaw Ogonczyk Makowski 12399e6c388aSLukasz Kazmierczak AddReportArgs::MetricArgs metricArgs; 12409e6c388aSLukasz Kazmierczak std::vector< 12419e6c388aSLukasz Kazmierczak std::tuple<sdbusplus::message::object_path, std::string>> 12429e6c388aSLukasz Kazmierczak pathAndUri; 12439e6c388aSLukasz Kazmierczak 12449e6c388aSLukasz Kazmierczak if (index < readingParams.size()) 12459e6c388aSLukasz Kazmierczak { 12469e6c388aSLukasz Kazmierczak const ReadingParameters::value_type& existing = 12479e6c388aSLukasz Kazmierczak readingParams[index]; 12489e6c388aSLukasz Kazmierczak 1249dac07cadSBoleslaw Ogonczyk Makowski if (metric->empty()) 1250dac07cadSBoleslaw Ogonczyk Makowski { 12519e6c388aSLukasz Kazmierczak pathAndUri = std::get<0>(existing); 1252dac07cadSBoleslaw Ogonczyk Makowski } 12539e6c388aSLukasz Kazmierczak metricArgs.collectionFunction = std::get<1>(existing); 12549e6c388aSLukasz Kazmierczak metricArgs.collectionTimeScope = std::get<2>(existing); 12559e6c388aSLukasz Kazmierczak metricArgs.collectionDuration = std::get<3>(existing); 12569e6c388aSLukasz Kazmierczak } 12579e6c388aSLukasz Kazmierczak 1258a64919e8SBoleslaw Ogonczyk Makowski if (!getUserMetric(asyncResp->res, *metric, metricArgs)) 12599e6c388aSLukasz Kazmierczak { 12609e6c388aSLukasz Kazmierczak return; 12619e6c388aSLukasz Kazmierczak } 12629e6c388aSLukasz Kazmierczak 12639e6c388aSLukasz Kazmierczak std::optional<IncorrectMetricUri> error = 12649e6c388aSLukasz Kazmierczak getChassisSensorNode(metricArgs.uris, chassisSensors); 12659e6c388aSLukasz Kazmierczak 12669e6c388aSLukasz Kazmierczak if (error) 12679e6c388aSLukasz Kazmierczak { 12689e6c388aSLukasz Kazmierczak messages::propertyValueIncorrect( 12699e6c388aSLukasz Kazmierczak asyncResp->res, error->uri, 12709e6c388aSLukasz Kazmierczak "MetricProperties/" + std::to_string(error->index)); 12719e6c388aSLukasz Kazmierczak return; 12729e6c388aSLukasz Kazmierczak } 12739e6c388aSLukasz Kazmierczak 12749e6c388aSLukasz Kazmierczak updateMetricsReq->emplace(pathAndUri, metricArgs); 12759e6c388aSLukasz Kazmierczak index++; 12769e6c388aSLukasz Kazmierczak } 12779e6c388aSLukasz Kazmierczak 12789e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 12799e6c388aSLukasz Kazmierczak { 12809e6c388aSLukasz Kazmierczak retrieveUriToDbusMap( 12819e6c388aSLukasz Kazmierczak chassis, sensorType, 12829e6c388aSLukasz Kazmierczak [asyncResp, updateMetricsReq]( 12839e6c388aSLukasz Kazmierczak const boost::beast::http::status status, 12849e6c388aSLukasz Kazmierczak const std::map<std::string, std::string>& uriToDbus) { 12859e6c388aSLukasz Kazmierczak if (status != boost::beast::http::status::ok) 12869e6c388aSLukasz Kazmierczak { 12879e6c388aSLukasz Kazmierczak BMCWEB_LOG_ERROR( 12889e6c388aSLukasz Kazmierczak "Failed to retrieve URI to dbus sensors map with err {}", 12899e6c388aSLukasz Kazmierczak static_cast<unsigned>(status)); 12909e6c388aSLukasz Kazmierczak return; 12919e6c388aSLukasz Kazmierczak } 12929e6c388aSLukasz Kazmierczak updateMetricsReq->insert(uriToDbus); 12939e6c388aSLukasz Kazmierczak }); 12949e6c388aSLukasz Kazmierczak } 12959e6c388aSLukasz Kazmierczak }); 12969e6c388aSLukasz Kazmierczak } 1297081ebf06SWludzik, Jozef 12984220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead( 12994220be3bSEd Tanous App& app, const crow::Request& req, 13004220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 13014220be3bSEd Tanous { 13024220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13034220be3bSEd Tanous { 13044220be3bSEd Tanous return; 13054220be3bSEd Tanous } 13064220be3bSEd Tanous asyncResp->res.addHeader( 13074220be3bSEd Tanous boost::beast::http::field::link, 13084220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby"); 13094220be3bSEd Tanous } 13104220be3bSEd Tanous 13114220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet( 1312fc0edbe3SEd Tanous App& app, const crow::Request& req, 1313fc0edbe3SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1314fc0edbe3SEd Tanous { 1315fc0edbe3SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1316fc0edbe3SEd Tanous { 1317fc0edbe3SEd Tanous return; 1318fc0edbe3SEd Tanous } 13199e6c388aSLukasz Kazmierczak asyncResp->res.addHeader( 13209e6c388aSLukasz Kazmierczak boost::beast::http::field::link, 13219e6c388aSLukasz Kazmierczak "</redfish/v1/JsonSchemas/MetricReportDefinition/MetricReportDefinition.json>; rel=describedby"); 1322fc0edbe3SEd Tanous 1323fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1324fc0edbe3SEd Tanous "#MetricReportDefinitionCollection." 1325fc0edbe3SEd Tanous "MetricReportDefinitionCollection"; 1326fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1327fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"; 1328fc0edbe3SEd Tanous asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; 1329fc0edbe3SEd Tanous constexpr std::array<std::string_view, 1> interfaces{ 1330fc0edbe3SEd Tanous telemetry::reportInterface}; 1331fc0edbe3SEd Tanous collection_util::getCollectionMembers( 1332fc0edbe3SEd Tanous asyncResp, 1333fc0edbe3SEd Tanous boost::urls::url( 1334fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"), 1335fc0edbe3SEd Tanous interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); 1336fc0edbe3SEd Tanous } 1337fc0edbe3SEd Tanous 1338bd79bce8SPatrick Williams inline void handleReportPatch( 1339bd79bce8SPatrick Williams App& app, const crow::Request& req, 1340bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id) 13419e6c388aSLukasz Kazmierczak { 13429e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13439e6c388aSLukasz Kazmierczak { 13449e6c388aSLukasz Kazmierczak return; 13459e6c388aSLukasz Kazmierczak } 13469e6c388aSLukasz Kazmierczak 13479e6c388aSLukasz Kazmierczak std::optional<std::string> reportingTypeStr; 13489e6c388aSLukasz Kazmierczak std::optional<std::string> reportUpdatesStr; 13499e6c388aSLukasz Kazmierczak std::optional<bool> metricReportDefinitionEnabled; 1350a64919e8SBoleslaw Ogonczyk Makowski std::optional< 1351a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 1352a64919e8SBoleslaw Ogonczyk Makowski metrics; 13539e6c388aSLukasz Kazmierczak std::optional<std::vector<std::string>> reportActionsStr; 1354b14f357fSEd Tanous std::optional<std::string> scheduleDurationStr; 13559e6c388aSLukasz Kazmierczak 1356afc474aeSMyung Bae if (!json_util::readJsonPatch( // 1357afc474aeSMyung Bae req, asyncResp->res, // 1358afc474aeSMyung Bae "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, // 1359afc474aeSMyung Bae "MetricReportDefinitionType", reportingTypeStr, // 1360afc474aeSMyung Bae "Metrics", metrics, // 1361afc474aeSMyung Bae "ReportActions", reportActionsStr, // 1362afc474aeSMyung Bae "ReportUpdates", reportUpdatesStr, // 1363afc474aeSMyung Bae "Schedule/RecurrenceInterval", scheduleDurationStr // 1364afc474aeSMyung Bae )) 13659e6c388aSLukasz Kazmierczak { 13669e6c388aSLukasz Kazmierczak return; 13679e6c388aSLukasz Kazmierczak } 13689e6c388aSLukasz Kazmierczak 13699e6c388aSLukasz Kazmierczak if (metricReportDefinitionEnabled) 13709e6c388aSLukasz Kazmierczak { 13719e6c388aSLukasz Kazmierczak setReportEnabled(asyncResp, id, *metricReportDefinitionEnabled); 13729e6c388aSLukasz Kazmierczak } 13739e6c388aSLukasz Kazmierczak 13749e6c388aSLukasz Kazmierczak if (reportUpdatesStr) 13759e6c388aSLukasz Kazmierczak { 1376b4361d63SEd Tanous setReportUpdates(asyncResp, id, *reportUpdatesStr); 13779e6c388aSLukasz Kazmierczak } 13789e6c388aSLukasz Kazmierczak 13799e6c388aSLukasz Kazmierczak if (reportActionsStr) 13809e6c388aSLukasz Kazmierczak { 1381b4361d63SEd Tanous setReportActions(asyncResp, id, *reportActionsStr); 13829e6c388aSLukasz Kazmierczak } 13839e6c388aSLukasz Kazmierczak 1384b14f357fSEd Tanous if (reportingTypeStr || scheduleDurationStr) 13859e6c388aSLukasz Kazmierczak { 1386b4361d63SEd Tanous setReportTypeAndInterval(asyncResp, id, reportingTypeStr, 1387b4361d63SEd Tanous scheduleDurationStr); 13889e6c388aSLukasz Kazmierczak } 13899e6c388aSLukasz Kazmierczak 13909e6c388aSLukasz Kazmierczak if (metrics) 13919e6c388aSLukasz Kazmierczak { 1392ba498310SKrzysztof Grobelny setReportMetrics(asyncResp, id, std::move(*metrics)); 13939e6c388aSLukasz Kazmierczak } 13949e6c388aSLukasz Kazmierczak } 13959e6c388aSLukasz Kazmierczak 1396bd79bce8SPatrick Williams inline void handleReportDelete( 1397bd79bce8SPatrick Williams App& app, const crow::Request& req, 1398bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id) 13999e6c388aSLukasz Kazmierczak { 14009e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14019e6c388aSLukasz Kazmierczak { 14029e6c388aSLukasz Kazmierczak return; 14039e6c388aSLukasz Kazmierczak } 14049e6c388aSLukasz Kazmierczak 14059e6c388aSLukasz Kazmierczak const std::string reportPath = getDbusReportPath(id); 14069e6c388aSLukasz Kazmierczak 14079e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 14089e6c388aSLukasz Kazmierczak [asyncResp, 14099e6c388aSLukasz Kazmierczak reportId = std::string(id)](const boost::system::error_code& ec) { 14109e6c388aSLukasz Kazmierczak if (!verifyCommonErrors(asyncResp->res, reportId, ec)) 14119e6c388aSLukasz Kazmierczak { 14129e6c388aSLukasz Kazmierczak return; 14139e6c388aSLukasz Kazmierczak } 14149e6c388aSLukasz Kazmierczak asyncResp->res.result(boost::beast::http::status::no_content); 14159e6c388aSLukasz Kazmierczak }, 14169e6c388aSLukasz Kazmierczak service, reportPath, "xyz.openbmc_project.Object.Delete", "Delete"); 14179e6c388aSLukasz Kazmierczak } 14189e6c388aSLukasz Kazmierczak } // namespace telemetry 14199e6c388aSLukasz Kazmierczak 142095bdb5f0SEd Tanous inline void afterRetrieveUriToDbusMap( 142195bdb5f0SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/, 142295bdb5f0SEd Tanous const std::shared_ptr<telemetry::AddReport>& addReportReq, 142395bdb5f0SEd Tanous const boost::beast::http::status status, 142495bdb5f0SEd Tanous const std::map<std::string, std::string>& uriToDbus) 142595bdb5f0SEd Tanous { 142695bdb5f0SEd Tanous if (status != boost::beast::http::status::ok) 142795bdb5f0SEd Tanous { 142895bdb5f0SEd Tanous BMCWEB_LOG_ERROR( 142995bdb5f0SEd Tanous "Failed to retrieve URI to dbus sensors map with err {}", 143095bdb5f0SEd Tanous static_cast<unsigned>(status)); 143195bdb5f0SEd Tanous return; 143295bdb5f0SEd Tanous } 143395bdb5f0SEd Tanous addReportReq->insert(uriToDbus); 143495bdb5f0SEd Tanous } 143595bdb5f0SEd Tanous 14369e6c388aSLukasz Kazmierczak inline void handleMetricReportDefinitionsPost( 14379e6c388aSLukasz Kazmierczak App& app, const crow::Request& req, 14389e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 14399e6c388aSLukasz Kazmierczak { 14409e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14419e6c388aSLukasz Kazmierczak { 14429e6c388aSLukasz Kazmierczak return; 14439e6c388aSLukasz Kazmierczak } 14449e6c388aSLukasz Kazmierczak 14459e6c388aSLukasz Kazmierczak telemetry::AddReportArgs args; 14469e6c388aSLukasz Kazmierczak if (!telemetry::getUserParameters(asyncResp->res, req, args)) 14479e6c388aSLukasz Kazmierczak { 14489e6c388aSLukasz Kazmierczak return; 14499e6c388aSLukasz Kazmierczak } 14509e6c388aSLukasz Kazmierczak 14519e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 14529e6c388aSLukasz Kazmierczak chassisSensors; 14539e6c388aSLukasz Kazmierczak if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, 14549e6c388aSLukasz Kazmierczak chassisSensors)) 14559e6c388aSLukasz Kazmierczak { 14569e6c388aSLukasz Kazmierczak return; 14579e6c388aSLukasz Kazmierczak } 14589e6c388aSLukasz Kazmierczak 1459bd79bce8SPatrick Williams auto addReportReq = 1460bd79bce8SPatrick Williams std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 14619e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 14629e6c388aSLukasz Kazmierczak { 146395bdb5f0SEd Tanous retrieveUriToDbusMap(chassis, sensorType, 146495bdb5f0SEd Tanous std::bind_front(afterRetrieveUriToDbusMap, 146595bdb5f0SEd Tanous asyncResp, addReportReq)); 14669e6c388aSLukasz Kazmierczak } 14679e6c388aSLukasz Kazmierczak } 14689e6c388aSLukasz Kazmierczak 14699e6c388aSLukasz Kazmierczak inline void 14704220be3bSEd Tanous handleMetricReportHead(App& app, const crow::Request& req, 14714220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 14724220be3bSEd Tanous const std::string& /*id*/) 14734220be3bSEd Tanous { 14744220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14754220be3bSEd Tanous { 14764220be3bSEd Tanous return; 14774220be3bSEd Tanous } 14784220be3bSEd Tanous asyncResp->res.addHeader( 14794220be3bSEd Tanous boost::beast::http::field::link, 14804220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 14814220be3bSEd Tanous } 14824220be3bSEd Tanous 1483bd79bce8SPatrick Williams inline void handleMetricReportGet( 1484bd79bce8SPatrick Williams App& app, const crow::Request& req, 1485bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 148686a5ac98SEd Tanous { 148786a5ac98SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 148886a5ac98SEd Tanous { 148986a5ac98SEd Tanous return; 149086a5ac98SEd Tanous } 14914220be3bSEd Tanous asyncResp->res.addHeader( 14924220be3bSEd Tanous boost::beast::http::field::link, 14934220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 149486a5ac98SEd Tanous 1495deae6a78SEd Tanous dbus::utility::getAllProperties( 1496deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1497deae6a78SEd Tanous telemetry::reportInterface, 149886a5ac98SEd Tanous [asyncResp, id](const boost::system::error_code& ec, 149986a5ac98SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 15009e6c388aSLukasz Kazmierczak if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec)) 150186a5ac98SEd Tanous { 150286a5ac98SEd Tanous return; 150386a5ac98SEd Tanous } 150486a5ac98SEd Tanous 150586a5ac98SEd Tanous telemetry::fillReportDefinition(asyncResp, id, properties); 150686a5ac98SEd Tanous }); 150786a5ac98SEd Tanous } 150886a5ac98SEd Tanous 1509dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete( 1510dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 1511dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 1512dd1c4a9cSSzymon Dompke 1513dd1c4a9cSSzymon Dompke { 1514dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1515dd1c4a9cSSzymon Dompke { 1516dd1c4a9cSSzymon Dompke return; 1517dd1c4a9cSSzymon Dompke } 1518dd1c4a9cSSzymon Dompke 1519dd1c4a9cSSzymon Dompke const std::string reportPath = telemetry::getDbusReportPath(id); 1520dd1c4a9cSSzymon Dompke 1521dd1c4a9cSSzymon Dompke crow::connections::systemBus->async_method_call( 1522dd1c4a9cSSzymon Dompke [asyncResp, id](const boost::system::error_code& ec) { 1523dd1c4a9cSSzymon Dompke /* 1524dd1c4a9cSSzymon Dompke * boost::system::errc and std::errc are missing value 1525dd1c4a9cSSzymon Dompke * for EBADR error that is defined in Linux. 1526dd1c4a9cSSzymon Dompke */ 1527dd1c4a9cSSzymon Dompke if (ec.value() == EBADR) 1528dd1c4a9cSSzymon Dompke { 1529bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1530bd79bce8SPatrick Williams "MetricReportDefinition", id); 1531dd1c4a9cSSzymon Dompke return; 1532dd1c4a9cSSzymon Dompke } 1533dd1c4a9cSSzymon Dompke 1534dd1c4a9cSSzymon Dompke if (ec) 1535dd1c4a9cSSzymon Dompke { 153662598e31SEd Tanous BMCWEB_LOG_ERROR("respHandler DBus error {}", ec); 1537dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 1538dd1c4a9cSSzymon Dompke return; 1539dd1c4a9cSSzymon Dompke } 1540dd1c4a9cSSzymon Dompke 1541dd1c4a9cSSzymon Dompke asyncResp->res.result(boost::beast::http::status::no_content); 1542dd1c4a9cSSzymon Dompke }, 1543dd1c4a9cSSzymon Dompke telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 1544dd1c4a9cSSzymon Dompke "Delete"); 1545dd1c4a9cSSzymon Dompke } 1546dd1c4a9cSSzymon Dompke 15477e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app) 1548081ebf06SWludzik, Jozef { 15497e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 15504220be3bSEd Tanous .privileges(redfish::privileges::headMetricReportDefinitionCollection) 15514220be3bSEd Tanous .methods(boost::beast::http::verb::head)(std::bind_front( 15529e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionHead, 15539e6c388aSLukasz Kazmierczak std::ref(app))); 15544220be3bSEd Tanous 15554220be3bSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1556ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinitionCollection) 15574220be3bSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 15589e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionGet, 15599e6c388aSLukasz Kazmierczak std::ref(app))); 15604dbb8aeaSWludzik, Jozef 15617e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1562ed398213SEd Tanous .privileges(redfish::privileges::postMetricReportDefinitionCollection) 1563002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 15649e6c388aSLukasz Kazmierczak std::bind_front(handleMetricReportDefinitionsPost, std::ref(app))); 1565081ebf06SWludzik, Jozef } 1566081ebf06SWludzik, Jozef 15677e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app) 1568081ebf06SWludzik, Jozef { 15697e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 15707e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 1571ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 15724220be3bSEd Tanous .methods(boost::beast::http::verb::head)( 15734220be3bSEd Tanous std::bind_front(handleMetricReportHead, std::ref(app))); 15744220be3bSEd Tanous 15754220be3bSEd Tanous BMCWEB_ROUTE(app, 15764220be3bSEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 15774220be3bSEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 15787e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 157986a5ac98SEd Tanous std::bind_front(handleMetricReportGet, std::ref(app))); 1580479e899dSKrzysztof Grobelny 15817e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 15827e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 15839e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::deleteMetricReportDefinition) 15847e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 1585dd1c4a9cSSzymon Dompke std::bind_front(handleMetricReportDelete, std::ref(app))); 15869e6c388aSLukasz Kazmierczak 15879e6c388aSLukasz Kazmierczak BMCWEB_ROUTE(app, 15889e6c388aSLukasz Kazmierczak "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 15899e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::patchMetricReportDefinition) 15909e6c388aSLukasz Kazmierczak .methods(boost::beast::http::verb::patch)( 15919e6c388aSLukasz Kazmierczak std::bind_front(telemetry::handleReportPatch, std::ref(app))); 15924dbb8aeaSWludzik, Jozef } 1593081ebf06SWludzik, Jozef } // namespace redfish 1594