1081ebf06SWludzik, Jozef #pragma once 2081ebf06SWludzik, Jozef 33ccb3adbSEd Tanous #include "app.hpp" 43ccb3adbSEd Tanous #include "dbus_utility.hpp" 5479e899dSKrzysztof Grobelny #include "generated/enums/metric_report_definition.hpp" 63ccb3adbSEd Tanous #include "query.hpp" 73ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 84dbb8aeaSWludzik, Jozef #include "sensors.hpp" 93ccb3adbSEd Tanous #include "utils/collection.hpp" 103ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 11081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp" 12081ebf06SWludzik, Jozef #include "utils/time_utils.hpp" 13081ebf06SWludzik, Jozef 144dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp> 15ef4c65b7SEd Tanous #include <boost/url/format.hpp> 1689474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 1789474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 184dbb8aeaSWludzik, Jozef 197a1dbc48SGeorge Liu #include <array> 20fe04d49cSNan Zhou #include <map> 21f19ab44aSSzymon Dompke #include <optional> 22f19ab44aSSzymon Dompke #include <span> 23f19ab44aSSzymon Dompke #include <string> 247a1dbc48SGeorge Liu #include <string_view> 25081ebf06SWludzik, Jozef #include <tuple> 26f19ab44aSSzymon Dompke #include <utility> 27081ebf06SWludzik, Jozef #include <variant> 28f19ab44aSSzymon Dompke #include <vector> 29081ebf06SWludzik, Jozef 30081ebf06SWludzik, Jozef namespace redfish 31081ebf06SWludzik, Jozef { 32081ebf06SWludzik, Jozef 33081ebf06SWludzik, Jozef namespace telemetry 34081ebf06SWludzik, Jozef { 35081ebf06SWludzik, Jozef 36479e899dSKrzysztof Grobelny using ReadingParameters = std::vector<std::tuple< 37479e899dSKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>>, 38479e899dSKrzysztof Grobelny std::string, std::string, uint64_t>>; 39479e899dSKrzysztof Grobelny 40479e899dSKrzysztof Grobelny inline metric_report_definition::ReportActionsEnum 41479e899dSKrzysztof Grobelny toRedfishReportAction(std::string_view dbusValue) 42479e899dSKrzysztof Grobelny { 43479e899dSKrzysztof Grobelny if (dbusValue == 44479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate") 45479e899dSKrzysztof Grobelny { 46479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum::RedfishEvent; 47479e899dSKrzysztof Grobelny } 48479e899dSKrzysztof Grobelny if (dbusValue == 49479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection") 50479e899dSKrzysztof Grobelny { 51479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum:: 52479e899dSKrzysztof Grobelny LogToMetricReportsCollection; 53479e899dSKrzysztof Grobelny } 54479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum::Invalid; 55479e899dSKrzysztof Grobelny } 56479e899dSKrzysztof Grobelny 57479e899dSKrzysztof Grobelny inline std::string toDbusReportAction(std::string_view redfishValue) 58479e899dSKrzysztof Grobelny { 59479e899dSKrzysztof Grobelny if (redfishValue == "RedfishEvent") 60479e899dSKrzysztof Grobelny { 61479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate"; 62479e899dSKrzysztof Grobelny } 63479e899dSKrzysztof Grobelny if (redfishValue == "LogToMetricReportsCollection") 64479e899dSKrzysztof Grobelny { 65479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection"; 66479e899dSKrzysztof Grobelny } 67479e899dSKrzysztof Grobelny return ""; 68479e899dSKrzysztof Grobelny } 69479e899dSKrzysztof Grobelny 70479e899dSKrzysztof Grobelny inline metric_report_definition::MetricReportDefinitionType 71479e899dSKrzysztof Grobelny toRedfishReportingType(std::string_view dbusValue) 72479e899dSKrzysztof Grobelny { 73479e899dSKrzysztof Grobelny if (dbusValue == 74479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange") 75479e899dSKrzysztof Grobelny { 76479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::OnChange; 77479e899dSKrzysztof Grobelny } 78479e899dSKrzysztof Grobelny if (dbusValue == 79479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest") 80479e899dSKrzysztof Grobelny { 81479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::OnRequest; 82479e899dSKrzysztof Grobelny } 83479e899dSKrzysztof Grobelny if (dbusValue == 84479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic") 85479e899dSKrzysztof Grobelny { 86479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::Periodic; 87479e899dSKrzysztof Grobelny } 88479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::Invalid; 89479e899dSKrzysztof Grobelny } 90479e899dSKrzysztof Grobelny 91479e899dSKrzysztof Grobelny inline std::string toDbusReportingType(std::string_view redfishValue) 92479e899dSKrzysztof Grobelny { 93479e899dSKrzysztof Grobelny if (redfishValue == "OnChange") 94479e899dSKrzysztof Grobelny { 95479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange"; 96479e899dSKrzysztof Grobelny } 97479e899dSKrzysztof Grobelny if (redfishValue == "OnRequest") 98479e899dSKrzysztof Grobelny { 99479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest"; 100479e899dSKrzysztof Grobelny } 101479e899dSKrzysztof Grobelny if (redfishValue == "Periodic") 102479e899dSKrzysztof Grobelny { 103479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic"; 104479e899dSKrzysztof Grobelny } 105479e899dSKrzysztof Grobelny return ""; 106479e899dSKrzysztof Grobelny } 107479e899dSKrzysztof Grobelny 108479e899dSKrzysztof Grobelny inline metric_report_definition::CollectionTimeScope 109479e899dSKrzysztof Grobelny toRedfishCollectionTimeScope(std::string_view dbusValue) 110479e899dSKrzysztof Grobelny { 111479e899dSKrzysztof Grobelny if (dbusValue == 112479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point") 113479e899dSKrzysztof Grobelny { 114479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Point; 115479e899dSKrzysztof Grobelny } 116479e899dSKrzysztof Grobelny if (dbusValue == 117479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval") 118479e899dSKrzysztof Grobelny { 119479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Interval; 120479e899dSKrzysztof Grobelny } 121479e899dSKrzysztof Grobelny if (dbusValue == 122479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval") 123479e899dSKrzysztof Grobelny { 124479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::StartupInterval; 125479e899dSKrzysztof Grobelny } 126479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Invalid; 127479e899dSKrzysztof Grobelny } 128479e899dSKrzysztof Grobelny 129479e899dSKrzysztof Grobelny inline std::string toDbusCollectionTimeScope(std::string_view redfishValue) 130479e899dSKrzysztof Grobelny { 131479e899dSKrzysztof Grobelny if (redfishValue == "Point") 132479e899dSKrzysztof Grobelny { 133479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point"; 134479e899dSKrzysztof Grobelny } 135479e899dSKrzysztof Grobelny if (redfishValue == "Interval") 136479e899dSKrzysztof Grobelny { 137479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval"; 138479e899dSKrzysztof Grobelny } 139479e899dSKrzysztof Grobelny if (redfishValue == "StartupInterval") 140479e899dSKrzysztof Grobelny { 141479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval"; 142479e899dSKrzysztof Grobelny } 143479e899dSKrzysztof Grobelny return ""; 144479e899dSKrzysztof Grobelny } 145479e899dSKrzysztof Grobelny 146479e899dSKrzysztof Grobelny inline metric_report_definition::ReportUpdatesEnum 147479e899dSKrzysztof Grobelny toRedfishReportUpdates(std::string_view dbusValue) 148479e899dSKrzysztof Grobelny { 149479e899dSKrzysztof Grobelny if (dbusValue == 150479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite") 151479e899dSKrzysztof Grobelny { 152479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::Overwrite; 153479e899dSKrzysztof Grobelny } 154479e899dSKrzysztof Grobelny if (dbusValue == 155479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull") 156479e899dSKrzysztof Grobelny { 157479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::AppendWrapsWhenFull; 158479e899dSKrzysztof Grobelny } 159479e899dSKrzysztof Grobelny if (dbusValue == 160479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull") 161479e899dSKrzysztof Grobelny { 162479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::AppendStopsWhenFull; 163479e899dSKrzysztof Grobelny } 164479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::Invalid; 165479e899dSKrzysztof Grobelny } 166479e899dSKrzysztof Grobelny 167479e899dSKrzysztof Grobelny inline std::string toDbusReportUpdates(std::string_view redfishValue) 168479e899dSKrzysztof Grobelny { 169479e899dSKrzysztof Grobelny if (redfishValue == "Overwrite") 170479e899dSKrzysztof Grobelny { 171479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite"; 172479e899dSKrzysztof Grobelny } 173479e899dSKrzysztof Grobelny if (redfishValue == "AppendWrapsWhenFull") 174479e899dSKrzysztof Grobelny { 175479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull"; 176479e899dSKrzysztof Grobelny } 177479e899dSKrzysztof Grobelny if (redfishValue == "AppendStopsWhenFull") 178479e899dSKrzysztof Grobelny { 179479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull"; 180479e899dSKrzysztof Grobelny } 181479e899dSKrzysztof Grobelny return ""; 182479e899dSKrzysztof Grobelny } 183081ebf06SWludzik, Jozef 184f19ab44aSSzymon Dompke inline std::optional<nlohmann::json::array_t> getLinkedTriggers( 185f19ab44aSSzymon Dompke std::span<const sdbusplus::message::object_path> triggerPaths) 186f19ab44aSSzymon Dompke { 187f19ab44aSSzymon Dompke nlohmann::json::array_t triggers; 188f19ab44aSSzymon Dompke 189f19ab44aSSzymon Dompke for (const sdbusplus::message::object_path& path : triggerPaths) 190f19ab44aSSzymon Dompke { 191f19ab44aSSzymon Dompke if (path.parent_path() != 192f19ab44aSSzymon Dompke "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService") 193f19ab44aSSzymon Dompke { 194f19ab44aSSzymon Dompke BMCWEB_LOG_ERROR << "Property Triggers contains invalid value: " 195f19ab44aSSzymon Dompke << path.str; 196f19ab44aSSzymon Dompke return std::nullopt; 197f19ab44aSSzymon Dompke } 198f19ab44aSSzymon Dompke 199f19ab44aSSzymon Dompke std::string id = path.filename(); 200f19ab44aSSzymon Dompke if (id.empty()) 201f19ab44aSSzymon Dompke { 202f19ab44aSSzymon Dompke BMCWEB_LOG_ERROR << "Property Triggers contains invalid value: " 203f19ab44aSSzymon Dompke << path.str; 204f19ab44aSSzymon Dompke return std::nullopt; 205f19ab44aSSzymon Dompke } 206f19ab44aSSzymon Dompke nlohmann::json::object_t trigger; 207f19ab44aSSzymon Dompke trigger["@odata.id"] = 208f19ab44aSSzymon Dompke boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id); 209f19ab44aSSzymon Dompke triggers.emplace_back(std::move(trigger)); 210f19ab44aSSzymon Dompke } 211f19ab44aSSzymon Dompke 212f19ab44aSSzymon Dompke return triggers; 213f19ab44aSSzymon Dompke } 214f19ab44aSSzymon Dompke 215b9d36b47SEd Tanous inline void 216b9d36b47SEd Tanous fillReportDefinition(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 217b9d36b47SEd Tanous const std::string& id, 218479e899dSKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) 219081ebf06SWludzik, Jozef { 220479e899dSKrzysztof Grobelny std::vector<std::string> reportActions; 221479e899dSKrzysztof Grobelny ReadingParameters readingParams; 222479e899dSKrzysztof Grobelny std::string reportingType; 223479e899dSKrzysztof Grobelny std::string reportUpdates; 224479e899dSKrzysztof Grobelny std::string name; 225479e899dSKrzysztof Grobelny uint64_t appendLimit = 0; 226479e899dSKrzysztof Grobelny uint64_t interval = 0; 227479e899dSKrzysztof Grobelny bool enabled = false; 228f19ab44aSSzymon Dompke std::vector<sdbusplus::message::object_path> triggers; 22989474494SKrzysztof Grobelny 23089474494SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 231479e899dSKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "ReportingType", 232479e899dSKrzysztof Grobelny reportingType, "Interval", interval, "ReportActions", reportActions, 233479e899dSKrzysztof Grobelny "ReportUpdates", reportUpdates, "AppendLimit", appendLimit, 234f19ab44aSSzymon Dompke "ReadingParameters", readingParams, "Name", name, "Enabled", enabled, 235f19ab44aSSzymon Dompke "Triggers", triggers); 23689474494SKrzysztof Grobelny 23789474494SKrzysztof Grobelny if (!success) 238081ebf06SWludzik, Jozef { 239081ebf06SWludzik, Jozef messages::internalError(asyncResp->res); 240081ebf06SWludzik, Jozef return; 241081ebf06SWludzik, Jozef } 242081ebf06SWludzik, Jozef 243479e899dSKrzysztof Grobelny metric_report_definition::MetricReportDefinitionType redfishReportingType = 244479e899dSKrzysztof Grobelny toRedfishReportingType(reportingType); 245479e899dSKrzysztof Grobelny if (redfishReportingType == 246479e899dSKrzysztof Grobelny metric_report_definition::MetricReportDefinitionType::Invalid) 247081ebf06SWludzik, Jozef { 248479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 249479e899dSKrzysztof Grobelny return; 250081ebf06SWludzik, Jozef } 25189474494SKrzysztof Grobelny 252479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReportDefinitionType"] = 253479e899dSKrzysztof Grobelny redfishReportingType; 254479e899dSKrzysztof Grobelny 255f19ab44aSSzymon Dompke std::optional<nlohmann::json::array_t> linkedTriggers = 256f19ab44aSSzymon Dompke getLinkedTriggers(triggers); 257f19ab44aSSzymon Dompke if (!linkedTriggers) 258f19ab44aSSzymon Dompke { 259f19ab44aSSzymon Dompke messages::internalError(asyncResp->res); 260f19ab44aSSzymon Dompke return; 261f19ab44aSSzymon Dompke } 262f19ab44aSSzymon Dompke 263f19ab44aSSzymon Dompke asyncResp->res.jsonValue["Links"]["Triggers"] = std::move(*linkedTriggers); 264f19ab44aSSzymon Dompke 265479e899dSKrzysztof Grobelny nlohmann::json::array_t redfishReportActions; 266479e899dSKrzysztof Grobelny for (const std::string& action : reportActions) 267081ebf06SWludzik, Jozef { 268479e899dSKrzysztof Grobelny metric_report_definition::ReportActionsEnum redfishAction = 269479e899dSKrzysztof Grobelny toRedfishReportAction(action); 270479e899dSKrzysztof Grobelny if (redfishAction == 271479e899dSKrzysztof Grobelny metric_report_definition::ReportActionsEnum::Invalid) 272479e899dSKrzysztof Grobelny { 273479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 274479e899dSKrzysztof Grobelny return; 275081ebf06SWludzik, Jozef } 276081ebf06SWludzik, Jozef 277479e899dSKrzysztof Grobelny redfishReportActions.emplace_back(redfishAction); 278479e899dSKrzysztof Grobelny } 279479e899dSKrzysztof Grobelny 280479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions); 281479e899dSKrzysztof Grobelny 282479e899dSKrzysztof Grobelny nlohmann::json::array_t metrics = nlohmann::json::array(); 283479e899dSKrzysztof Grobelny for (const auto& [sensorData, collectionFunction, collectionTimeScope, 284479e899dSKrzysztof Grobelny collectionDuration] : readingParams) 28589474494SKrzysztof Grobelny { 286479e899dSKrzysztof Grobelny nlohmann::json::array_t metricProperties; 287479e899dSKrzysztof Grobelny 288479e899dSKrzysztof Grobelny for (const auto& [sensorPath, sensorMetadata] : sensorData) 289081ebf06SWludzik, Jozef { 290479e899dSKrzysztof Grobelny metricProperties.emplace_back(sensorMetadata); 291479e899dSKrzysztof Grobelny } 292479e899dSKrzysztof Grobelny 293613dabeaSEd Tanous nlohmann::json::object_t metric; 294479e899dSKrzysztof Grobelny 295479e899dSKrzysztof Grobelny metric_report_definition::CalculationAlgorithmEnum 296479e899dSKrzysztof Grobelny redfishCollectionFunction = 297479e899dSKrzysztof Grobelny telemetry::toRedfishCollectionFunction(collectionFunction); 298479e899dSKrzysztof Grobelny if (redfishCollectionFunction == 299479e899dSKrzysztof Grobelny metric_report_definition::CalculationAlgorithmEnum::Invalid) 300479e899dSKrzysztof Grobelny { 301479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 302479e899dSKrzysztof Grobelny return; 303479e899dSKrzysztof Grobelny } 304479e899dSKrzysztof Grobelny metric["CollectionFunction"] = redfishCollectionFunction; 305479e899dSKrzysztof Grobelny 306479e899dSKrzysztof Grobelny metric_report_definition::CollectionTimeScope 307479e899dSKrzysztof Grobelny redfishCollectionTimeScope = 308479e899dSKrzysztof Grobelny toRedfishCollectionTimeScope(collectionTimeScope); 309479e899dSKrzysztof Grobelny if (redfishCollectionTimeScope == 310479e899dSKrzysztof Grobelny metric_report_definition::CollectionTimeScope::Invalid) 311479e899dSKrzysztof Grobelny { 312479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 313479e899dSKrzysztof Grobelny return; 314479e899dSKrzysztof Grobelny } 315479e899dSKrzysztof Grobelny metric["CollectionTimeScope"] = redfishCollectionTimeScope; 316479e899dSKrzysztof Grobelny 317479e899dSKrzysztof Grobelny metric["MetricProperties"] = std::move(metricProperties); 318479e899dSKrzysztof Grobelny metric["CollectionDuration"] = time_utils::toDurationString( 319479e899dSKrzysztof Grobelny std::chrono::milliseconds(collectionDuration)); 320b2ba3072SPatrick Williams metrics.emplace_back(std::move(metric)); 321081ebf06SWludzik, Jozef } 322479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Metrics"] = std::move(metrics); 323479e899dSKrzysztof Grobelny 324479e899dSKrzysztof Grobelny if (enabled) 325479e899dSKrzysztof Grobelny { 326479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 327479e899dSKrzysztof Grobelny } 328479e899dSKrzysztof Grobelny else 329479e899dSKrzysztof Grobelny { 330479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Status"]["State"] = "Disabled"; 33189474494SKrzysztof Grobelny } 33289474494SKrzysztof Grobelny 333479e899dSKrzysztof Grobelny metric_report_definition::ReportUpdatesEnum redfishReportUpdates = 334479e899dSKrzysztof Grobelny toRedfishReportUpdates(reportUpdates); 335479e899dSKrzysztof Grobelny if (redfishReportUpdates == 336479e899dSKrzysztof Grobelny metric_report_definition::ReportUpdatesEnum::Invalid) 33789474494SKrzysztof Grobelny { 338479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 339479e899dSKrzysztof Grobelny return; 34089474494SKrzysztof Grobelny } 341479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["ReportUpdates"] = redfishReportUpdates; 34289474494SKrzysztof Grobelny 343479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReportDefinitionEnabled"] = enabled; 344479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["AppendLimit"] = appendLimit; 345479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Name"] = name; 346081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = 347479e899dSKrzysztof Grobelny time_utils::toDurationString(std::chrono::milliseconds(interval)); 348479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["@odata.type"] = 349479e899dSKrzysztof Grobelny "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; 350479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 351479e899dSKrzysztof Grobelny "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id); 352479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Id"] = id; 353479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format( 354479e899dSKrzysztof Grobelny "/redfish/v1/TelemetryService/MetricReports/{}", id); 35589474494SKrzysztof Grobelny } 35689474494SKrzysztof Grobelny 3574dbb8aeaSWludzik, Jozef struct AddReportArgs 3584dbb8aeaSWludzik, Jozef { 359479e899dSKrzysztof Grobelny struct MetricArgs 360479e899dSKrzysztof Grobelny { 361479e899dSKrzysztof Grobelny std::vector<std::string> uris; 362479e899dSKrzysztof Grobelny std::string collectionFunction; 363479e899dSKrzysztof Grobelny std::string collectionTimeScope; 364479e899dSKrzysztof Grobelny uint64_t collectionDuration = 0; 365479e899dSKrzysztof Grobelny }; 366479e899dSKrzysztof Grobelny 367479e899dSKrzysztof Grobelny std::string id; 3684dbb8aeaSWludzik, Jozef std::string name; 3694dbb8aeaSWludzik, Jozef std::string reportingType; 370479e899dSKrzysztof Grobelny std::string reportUpdates; 371479e899dSKrzysztof Grobelny uint64_t appendLimit = std::numeric_limits<uint64_t>::max(); 372479e899dSKrzysztof Grobelny std::vector<std::string> reportActions; 373479e899dSKrzysztof Grobelny uint64_t interval = std::numeric_limits<uint64_t>::max(); 374479e899dSKrzysztof Grobelny std::vector<MetricArgs> metrics; 375479e899dSKrzysztof Grobelny bool metricReportDefinitionEnabled = true; 3764dbb8aeaSWludzik, Jozef }; 3774dbb8aeaSWludzik, Jozef 3784dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res, 379479e899dSKrzysztof Grobelny const std::vector<std::string>& actions, 3804dbb8aeaSWludzik, Jozef AddReportArgs& args) 3814dbb8aeaSWludzik, Jozef { 3824dbb8aeaSWludzik, Jozef size_t index = 0; 383479e899dSKrzysztof Grobelny for (const std::string& action : actions) 3844dbb8aeaSWludzik, Jozef { 385479e899dSKrzysztof Grobelny std::string dbusReportAction = toDbusReportAction(action); 386479e899dSKrzysztof Grobelny if (dbusReportAction.empty()) 3874dbb8aeaSWludzik, Jozef { 388479e899dSKrzysztof Grobelny messages::propertyValueNotInList(res, nlohmann::json(action).dump(), 389479e899dSKrzysztof Grobelny "ReportActions/" + 390479e899dSKrzysztof Grobelny std::to_string(index)); 3914dbb8aeaSWludzik, Jozef return false; 3924dbb8aeaSWludzik, Jozef } 393479e899dSKrzysztof Grobelny 394479e899dSKrzysztof Grobelny args.reportActions.emplace_back(std::move(dbusReportAction)); 3954dbb8aeaSWludzik, Jozef index++; 3964dbb8aeaSWludzik, Jozef } 3974dbb8aeaSWludzik, Jozef return true; 3984dbb8aeaSWludzik, Jozef } 3994dbb8aeaSWludzik, Jozef 400479e899dSKrzysztof Grobelny inline bool getUserMetric(crow::Response& res, nlohmann::json& metric, 401479e899dSKrzysztof Grobelny AddReportArgs::MetricArgs& metricArgs) 402479e899dSKrzysztof Grobelny { 403479e899dSKrzysztof Grobelny std::optional<std::vector<std::string>> uris; 404479e899dSKrzysztof Grobelny std::optional<std::string> collectionDurationStr; 405479e899dSKrzysztof Grobelny std::optional<std::string> collectionFunction; 406479e899dSKrzysztof Grobelny std::optional<std::string> collectionTimeScopeStr; 407479e899dSKrzysztof Grobelny 408479e899dSKrzysztof Grobelny if (!json_util::readJson(metric, res, "MetricProperties", uris, 409479e899dSKrzysztof Grobelny "CollectionFunction", collectionFunction, 410479e899dSKrzysztof Grobelny "CollectionTimeScope", collectionTimeScopeStr, 411479e899dSKrzysztof Grobelny "CollectionDuration", collectionDurationStr)) 412479e899dSKrzysztof Grobelny { 413479e899dSKrzysztof Grobelny return false; 414479e899dSKrzysztof Grobelny } 415479e899dSKrzysztof Grobelny 416479e899dSKrzysztof Grobelny if (uris) 417479e899dSKrzysztof Grobelny { 418479e899dSKrzysztof Grobelny metricArgs.uris = std::move(*uris); 419479e899dSKrzysztof Grobelny } 420479e899dSKrzysztof Grobelny 421479e899dSKrzysztof Grobelny if (collectionFunction) 422479e899dSKrzysztof Grobelny { 423479e899dSKrzysztof Grobelny std::string dbusCollectionFunction = 424479e899dSKrzysztof Grobelny telemetry::toDbusCollectionFunction(*collectionFunction); 425479e899dSKrzysztof Grobelny if (dbusCollectionFunction.empty()) 426479e899dSKrzysztof Grobelny { 427479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionFunction", 428479e899dSKrzysztof Grobelny *collectionFunction); 429479e899dSKrzysztof Grobelny return false; 430479e899dSKrzysztof Grobelny } 431479e899dSKrzysztof Grobelny metricArgs.collectionFunction = std::move(dbusCollectionFunction); 432479e899dSKrzysztof Grobelny } 433479e899dSKrzysztof Grobelny 434479e899dSKrzysztof Grobelny if (collectionTimeScopeStr) 435479e899dSKrzysztof Grobelny { 436479e899dSKrzysztof Grobelny std::string dbusCollectionTimeScope = 437479e899dSKrzysztof Grobelny toDbusCollectionTimeScope(*collectionTimeScopeStr); 438479e899dSKrzysztof Grobelny if (dbusCollectionTimeScope.empty()) 439479e899dSKrzysztof Grobelny { 440479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionTimeScope", 441479e899dSKrzysztof Grobelny *collectionTimeScopeStr); 442479e899dSKrzysztof Grobelny return false; 443479e899dSKrzysztof Grobelny } 444479e899dSKrzysztof Grobelny metricArgs.collectionTimeScope = std::move(dbusCollectionTimeScope); 445479e899dSKrzysztof Grobelny } 446479e899dSKrzysztof Grobelny 447479e899dSKrzysztof Grobelny if (collectionDurationStr) 448479e899dSKrzysztof Grobelny { 449479e899dSKrzysztof Grobelny std::optional<std::chrono::milliseconds> duration = 450479e899dSKrzysztof Grobelny time_utils::fromDurationString(*collectionDurationStr); 451479e899dSKrzysztof Grobelny 452479e899dSKrzysztof Grobelny if (!duration || duration->count() < 0) 453479e899dSKrzysztof Grobelny { 454479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionDuration", 455479e899dSKrzysztof Grobelny *collectionDurationStr); 456479e899dSKrzysztof Grobelny return false; 457479e899dSKrzysztof Grobelny } 458479e899dSKrzysztof Grobelny 459479e899dSKrzysztof Grobelny metricArgs.collectionDuration = 460479e899dSKrzysztof Grobelny static_cast<uint64_t>(duration->count()); 461479e899dSKrzysztof Grobelny } 462479e899dSKrzysztof Grobelny 463479e899dSKrzysztof Grobelny return true; 464479e899dSKrzysztof Grobelny } 465479e899dSKrzysztof Grobelny 466479e899dSKrzysztof Grobelny inline bool getUserMetrics(crow::Response& res, 467479e899dSKrzysztof Grobelny std::span<nlohmann::json> metrics, 468479e899dSKrzysztof Grobelny std::vector<AddReportArgs::MetricArgs>& result) 469479e899dSKrzysztof Grobelny { 470479e899dSKrzysztof Grobelny result.reserve(metrics.size()); 471479e899dSKrzysztof Grobelny 472479e899dSKrzysztof Grobelny for (nlohmann::json& m : metrics) 473479e899dSKrzysztof Grobelny { 474479e899dSKrzysztof Grobelny AddReportArgs::MetricArgs metricArgs; 475479e899dSKrzysztof Grobelny 476479e899dSKrzysztof Grobelny if (!getUserMetric(res, m, metricArgs)) 477479e899dSKrzysztof Grobelny { 478479e899dSKrzysztof Grobelny return false; 479479e899dSKrzysztof Grobelny } 480479e899dSKrzysztof Grobelny 481479e899dSKrzysztof Grobelny result.emplace_back(std::move(metricArgs)); 482479e899dSKrzysztof Grobelny } 483479e899dSKrzysztof Grobelny 484479e899dSKrzysztof Grobelny return true; 485479e899dSKrzysztof Grobelny } 486479e899dSKrzysztof Grobelny 4874dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req, 4884dbb8aeaSWludzik, Jozef AddReportArgs& args) 4894dbb8aeaSWludzik, Jozef { 490479e899dSKrzysztof Grobelny std::optional<std::string> id; 491479e899dSKrzysztof Grobelny std::optional<std::string> name; 492479e899dSKrzysztof Grobelny std::optional<std::string> reportingTypeStr; 493479e899dSKrzysztof Grobelny std::optional<std::string> reportUpdatesStr; 494479e899dSKrzysztof Grobelny std::optional<uint64_t> appendLimit; 495479e899dSKrzysztof Grobelny std::optional<bool> metricReportDefinitionEnabled; 496479e899dSKrzysztof Grobelny std::optional<std::vector<nlohmann::json>> metrics; 497479e899dSKrzysztof Grobelny std::optional<std::vector<std::string>> reportActionsStr; 4984dbb8aeaSWludzik, Jozef std::optional<nlohmann::json> schedule; 499479e899dSKrzysztof Grobelny 500479e899dSKrzysztof Grobelny if (!json_util::readJsonPatch( 501479e899dSKrzysztof Grobelny req, res, "Id", id, "Name", name, "Metrics", metrics, 502479e899dSKrzysztof Grobelny "MetricReportDefinitionType", reportingTypeStr, "ReportUpdates", 503479e899dSKrzysztof Grobelny reportUpdatesStr, "AppendLimit", appendLimit, "ReportActions", 504479e899dSKrzysztof Grobelny reportActionsStr, "Schedule", schedule, 505479e899dSKrzysztof Grobelny "MetricReportDefinitionEnabled", metricReportDefinitionEnabled)) 5064dbb8aeaSWludzik, Jozef { 5074dbb8aeaSWludzik, Jozef return false; 5084dbb8aeaSWludzik, Jozef } 5094dbb8aeaSWludzik, Jozef 510479e899dSKrzysztof Grobelny if (id) 511479e899dSKrzysztof Grobelny { 512479e899dSKrzysztof Grobelny constexpr const char* allowedCharactersInId = 5134dbb8aeaSWludzik, Jozef "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 514479e899dSKrzysztof Grobelny if (id->empty() || 515479e899dSKrzysztof Grobelny id->find_first_not_of(allowedCharactersInId) != std::string::npos) 5164dbb8aeaSWludzik, Jozef { 517479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "Id", *id); 5184dbb8aeaSWludzik, Jozef return false; 5194dbb8aeaSWludzik, Jozef } 520479e899dSKrzysztof Grobelny args.id = *id; 521479e899dSKrzysztof Grobelny } 5224dbb8aeaSWludzik, Jozef 523479e899dSKrzysztof Grobelny if (name) 5244dbb8aeaSWludzik, Jozef { 525479e899dSKrzysztof Grobelny args.name = *name; 526479e899dSKrzysztof Grobelny } 527479e899dSKrzysztof Grobelny 528479e899dSKrzysztof Grobelny if (reportingTypeStr) 529479e899dSKrzysztof Grobelny { 530479e899dSKrzysztof Grobelny std::string dbusReportingType = toDbusReportingType(*reportingTypeStr); 531479e899dSKrzysztof Grobelny if (dbusReportingType.empty()) 532479e899dSKrzysztof Grobelny { 533479e899dSKrzysztof Grobelny messages::propertyValueNotInList(res, *reportingTypeStr, 5344dbb8aeaSWludzik, Jozef "MetricReportDefinitionType"); 5354dbb8aeaSWludzik, Jozef return false; 5364dbb8aeaSWludzik, Jozef } 537479e899dSKrzysztof Grobelny args.reportingType = dbusReportingType; 538479e899dSKrzysztof Grobelny } 5394dbb8aeaSWludzik, Jozef 540479e899dSKrzysztof Grobelny if (reportUpdatesStr) 541479e899dSKrzysztof Grobelny { 542479e899dSKrzysztof Grobelny std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr); 543479e899dSKrzysztof Grobelny if (dbusReportUpdates.empty()) 544479e899dSKrzysztof Grobelny { 545479e899dSKrzysztof Grobelny messages::propertyValueNotInList(res, *reportUpdatesStr, 546479e899dSKrzysztof Grobelny "ReportUpdates"); 547479e899dSKrzysztof Grobelny return false; 548479e899dSKrzysztof Grobelny } 549479e899dSKrzysztof Grobelny args.reportUpdates = dbusReportUpdates; 550479e899dSKrzysztof Grobelny } 551479e899dSKrzysztof Grobelny 552479e899dSKrzysztof Grobelny if (appendLimit) 553479e899dSKrzysztof Grobelny { 554479e899dSKrzysztof Grobelny args.appendLimit = *appendLimit; 555479e899dSKrzysztof Grobelny } 556479e899dSKrzysztof Grobelny 557479e899dSKrzysztof Grobelny if (metricReportDefinitionEnabled) 558479e899dSKrzysztof Grobelny { 559479e899dSKrzysztof Grobelny args.metricReportDefinitionEnabled = *metricReportDefinitionEnabled; 560479e899dSKrzysztof Grobelny } 561479e899dSKrzysztof Grobelny 562479e899dSKrzysztof Grobelny if (reportActionsStr) 563479e899dSKrzysztof Grobelny { 564479e899dSKrzysztof Grobelny if (!toDbusReportActions(res, *reportActionsStr, args)) 5654dbb8aeaSWludzik, Jozef { 5664dbb8aeaSWludzik, Jozef return false; 5674dbb8aeaSWludzik, Jozef } 568479e899dSKrzysztof Grobelny } 5694dbb8aeaSWludzik, Jozef 570479e899dSKrzysztof Grobelny if (reportingTypeStr == "Periodic") 5714dbb8aeaSWludzik, Jozef { 5724dbb8aeaSWludzik, Jozef if (!schedule) 5734dbb8aeaSWludzik, Jozef { 5744dbb8aeaSWludzik, Jozef messages::createFailedMissingReqProperties(res, "Schedule"); 5754dbb8aeaSWludzik, Jozef return false; 5764dbb8aeaSWludzik, Jozef } 5774dbb8aeaSWludzik, Jozef 5784dbb8aeaSWludzik, Jozef std::string durationStr; 5794dbb8aeaSWludzik, Jozef if (!json_util::readJson(*schedule, res, "RecurrenceInterval", 5804dbb8aeaSWludzik, Jozef durationStr)) 5814dbb8aeaSWludzik, Jozef { 5824dbb8aeaSWludzik, Jozef return false; 5834dbb8aeaSWludzik, Jozef } 5844dbb8aeaSWludzik, Jozef 5854dbb8aeaSWludzik, Jozef std::optional<std::chrono::milliseconds> durationNum = 5864dbb8aeaSWludzik, Jozef time_utils::fromDurationString(durationStr); 587479e899dSKrzysztof Grobelny if (!durationNum || durationNum->count() < 0) 5884dbb8aeaSWludzik, Jozef { 5894dbb8aeaSWludzik, Jozef messages::propertyValueIncorrect(res, "RecurrenceInterval", 5904dbb8aeaSWludzik, Jozef durationStr); 5914dbb8aeaSWludzik, Jozef return false; 5924dbb8aeaSWludzik, Jozef } 5934dbb8aeaSWludzik, Jozef args.interval = static_cast<uint64_t>(durationNum->count()); 5944dbb8aeaSWludzik, Jozef } 5954dbb8aeaSWludzik, Jozef 596479e899dSKrzysztof Grobelny if (metrics) 5974dbb8aeaSWludzik, Jozef { 598479e899dSKrzysztof Grobelny if (!getUserMetrics(res, *metrics, args.metrics)) 5994dbb8aeaSWludzik, Jozef { 6004dbb8aeaSWludzik, Jozef return false; 6014dbb8aeaSWludzik, Jozef } 6024dbb8aeaSWludzik, Jozef } 6034dbb8aeaSWludzik, Jozef 6044dbb8aeaSWludzik, Jozef return true; 6054dbb8aeaSWludzik, Jozef } 6064dbb8aeaSWludzik, Jozef 607ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics( 6088d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 609479e899dSKrzysztof Grobelny std::span<const AddReportArgs::MetricArgs> metrics, 6104dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>>& matched) 6114dbb8aeaSWludzik, Jozef { 612ca1600c1SSzymon Dompke for (const auto& metric : metrics) 6134dbb8aeaSWludzik, Jozef { 614479e899dSKrzysztof Grobelny std::optional<IncorrectMetricUri> error = 615479e899dSKrzysztof Grobelny getChassisSensorNode(metric.uris, matched); 616ca1600c1SSzymon Dompke if (error) 6174dbb8aeaSWludzik, Jozef { 618ca1600c1SSzymon Dompke messages::propertyValueIncorrect(asyncResp->res, error->uri, 6194dbb8aeaSWludzik, Jozef "MetricProperties/" + 620ca1600c1SSzymon Dompke std::to_string(error->index)); 6214dbb8aeaSWludzik, Jozef return false; 6224dbb8aeaSWludzik, Jozef } 6234dbb8aeaSWludzik, Jozef } 6244dbb8aeaSWludzik, Jozef return true; 6254dbb8aeaSWludzik, Jozef } 6264dbb8aeaSWludzik, Jozef 6274dbb8aeaSWludzik, Jozef class AddReport 6284dbb8aeaSWludzik, Jozef { 6294dbb8aeaSWludzik, Jozef public: 6308d1b46d7Szhanghch05 AddReport(AddReportArgs argsIn, 6318a592810SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 6328a592810SEd Tanous asyncResp(asyncRespIn), 6338d1b46d7Szhanghch05 args{std::move(argsIn)} 6344dbb8aeaSWludzik, Jozef {} 635479e899dSKrzysztof Grobelny 6364dbb8aeaSWludzik, Jozef ~AddReport() 6374dbb8aeaSWludzik, Jozef { 638479e899dSKrzysztof Grobelny boost::asio::post(crow::connections::systemBus->get_io_context(), 639479e899dSKrzysztof Grobelny std::bind_front(&performAddReport, asyncResp, args, 640479e899dSKrzysztof Grobelny std::move(uriToDbus))); 641479e899dSKrzysztof Grobelny } 642479e899dSKrzysztof Grobelny 643479e899dSKrzysztof Grobelny static void performAddReport( 644479e899dSKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 645479e899dSKrzysztof Grobelny const AddReportArgs& args, 646479e899dSKrzysztof Grobelny const boost::container::flat_map<std::string, std::string>& uriToDbus) 647479e899dSKrzysztof Grobelny { 6484dbb8aeaSWludzik, Jozef if (asyncResp->res.result() != boost::beast::http::status::ok) 6494dbb8aeaSWludzik, Jozef { 6504dbb8aeaSWludzik, Jozef return; 6514dbb8aeaSWludzik, Jozef } 6524dbb8aeaSWludzik, Jozef 6534dbb8aeaSWludzik, Jozef telemetry::ReadingParameters readingParams; 6544dbb8aeaSWludzik, Jozef readingParams.reserve(args.metrics.size()); 6554dbb8aeaSWludzik, Jozef 656479e899dSKrzysztof Grobelny for (const auto& metric : args.metrics) 6574dbb8aeaSWludzik, Jozef { 658479e899dSKrzysztof Grobelny std::vector< 659479e899dSKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>> 660479e899dSKrzysztof Grobelny sensorParams; 661479e899dSKrzysztof Grobelny sensorParams.reserve(metric.uris.size()); 662479e899dSKrzysztof Grobelny 663479e899dSKrzysztof Grobelny for (size_t i = 0; i < metric.uris.size(); i++) 6644dbb8aeaSWludzik, Jozef { 665479e899dSKrzysztof Grobelny const std::string& uri = metric.uris[i]; 6664dbb8aeaSWludzik, Jozef auto el = uriToDbus.find(uri); 6674dbb8aeaSWludzik, Jozef if (el == uriToDbus.end()) 6684dbb8aeaSWludzik, Jozef { 6690fda0f12SGeorge Liu BMCWEB_LOG_ERROR 6700fda0f12SGeorge Liu << "Failed to find DBus sensor corresponding to URI " 6714dbb8aeaSWludzik, Jozef << uri; 6724dbb8aeaSWludzik, Jozef messages::propertyValueNotInList(asyncResp->res, uri, 6734dbb8aeaSWludzik, Jozef "MetricProperties/" + 6744dbb8aeaSWludzik, Jozef std::to_string(i)); 6754dbb8aeaSWludzik, Jozef return; 6764dbb8aeaSWludzik, Jozef } 6774dbb8aeaSWludzik, Jozef 6784dbb8aeaSWludzik, Jozef const std::string& dbusPath = el->second; 679479e899dSKrzysztof Grobelny sensorParams.emplace_back(dbusPath, uri); 6804dbb8aeaSWludzik, Jozef } 681479e899dSKrzysztof Grobelny 682479e899dSKrzysztof Grobelny readingParams.emplace_back( 683479e899dSKrzysztof Grobelny std::move(sensorParams), metric.collectionFunction, 684479e899dSKrzysztof Grobelny metric.collectionTimeScope, metric.collectionDuration); 6854dbb8aeaSWludzik, Jozef } 686479e899dSKrzysztof Grobelny 6874dbb8aeaSWludzik, Jozef crow::connections::systemBus->async_method_call( 688479e899dSKrzysztof Grobelny [asyncResp, id = args.id, uriToDbus]( 6895e7e2dc5SEd Tanous const boost::system::error_code& ec, const std::string&) { 6904dbb8aeaSWludzik, Jozef if (ec == boost::system::errc::file_exists) 6914dbb8aeaSWludzik, Jozef { 6924dbb8aeaSWludzik, Jozef messages::resourceAlreadyExists( 693479e899dSKrzysztof Grobelny asyncResp->res, "MetricReportDefinition", "Id", id); 6944dbb8aeaSWludzik, Jozef return; 6954dbb8aeaSWludzik, Jozef } 6964dbb8aeaSWludzik, Jozef if (ec == boost::system::errc::too_many_files_open) 6974dbb8aeaSWludzik, Jozef { 698479e899dSKrzysztof Grobelny messages::createLimitReachedForResource(asyncResp->res); 6994dbb8aeaSWludzik, Jozef return; 7004dbb8aeaSWludzik, Jozef } 7014dbb8aeaSWludzik, Jozef if (ec == boost::system::errc::argument_list_too_long) 7024dbb8aeaSWludzik, Jozef { 7034dbb8aeaSWludzik, Jozef nlohmann::json metricProperties = nlohmann::json::array(); 7044dbb8aeaSWludzik, Jozef for (const auto& [uri, _] : uriToDbus) 7054dbb8aeaSWludzik, Jozef { 7064dbb8aeaSWludzik, Jozef metricProperties.emplace_back(uri); 7074dbb8aeaSWludzik, Jozef } 708479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(asyncResp->res, 709479e899dSKrzysztof Grobelny metricProperties.dump(), 710479e899dSKrzysztof Grobelny "MetricProperties"); 7114dbb8aeaSWludzik, Jozef return; 7124dbb8aeaSWludzik, Jozef } 7134dbb8aeaSWludzik, Jozef if (ec) 7144dbb8aeaSWludzik, Jozef { 715479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 7164dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 7174dbb8aeaSWludzik, Jozef return; 7184dbb8aeaSWludzik, Jozef } 7194dbb8aeaSWludzik, Jozef 720479e899dSKrzysztof Grobelny messages::created(asyncResp->res); 7214dbb8aeaSWludzik, Jozef }, 7224dbb8aeaSWludzik, Jozef telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", 7234dbb8aeaSWludzik, Jozef "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", 724479e899dSKrzysztof Grobelny "TelemetryService/" + args.id, args.name, args.reportingType, 725479e899dSKrzysztof Grobelny args.reportUpdates, args.appendLimit, args.reportActions, 726479e899dSKrzysztof Grobelny args.interval, readingParams, args.metricReportDefinitionEnabled); 7274dbb8aeaSWludzik, Jozef } 7284dbb8aeaSWludzik, Jozef 729ecd6a3a2SEd Tanous AddReport(const AddReport&) = delete; 730ecd6a3a2SEd Tanous AddReport(AddReport&&) = delete; 731ecd6a3a2SEd Tanous AddReport& operator=(const AddReport&) = delete; 732ecd6a3a2SEd Tanous AddReport& operator=(AddReport&&) = delete; 733ecd6a3a2SEd Tanous 734fe04d49cSNan Zhou void insert(const std::map<std::string, std::string>& el) 7354dbb8aeaSWludzik, Jozef { 7364dbb8aeaSWludzik, Jozef uriToDbus.insert(el.begin(), el.end()); 7374dbb8aeaSWludzik, Jozef } 7384dbb8aeaSWludzik, Jozef 7394dbb8aeaSWludzik, Jozef private: 740479e899dSKrzysztof Grobelny std::shared_ptr<bmcweb::AsyncResp> asyncResp; 7414dbb8aeaSWludzik, Jozef AddReportArgs args; 7424dbb8aeaSWludzik, Jozef boost::container::flat_map<std::string, std::string> uriToDbus{}; 7434dbb8aeaSWludzik, Jozef }; 744081ebf06SWludzik, Jozef } // namespace telemetry 745081ebf06SWludzik, Jozef 746*dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete( 747*dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 748*dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 749*dd1c4a9cSSzymon Dompke 750*dd1c4a9cSSzymon Dompke { 751*dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 752*dd1c4a9cSSzymon Dompke { 753*dd1c4a9cSSzymon Dompke return; 754*dd1c4a9cSSzymon Dompke } 755*dd1c4a9cSSzymon Dompke 756*dd1c4a9cSSzymon Dompke const std::string reportPath = telemetry::getDbusReportPath(id); 757*dd1c4a9cSSzymon Dompke 758*dd1c4a9cSSzymon Dompke crow::connections::systemBus->async_method_call( 759*dd1c4a9cSSzymon Dompke [asyncResp, id](const boost::system::error_code& ec) { 760*dd1c4a9cSSzymon Dompke /* 761*dd1c4a9cSSzymon Dompke * boost::system::errc and std::errc are missing value 762*dd1c4a9cSSzymon Dompke * for EBADR error that is defined in Linux. 763*dd1c4a9cSSzymon Dompke */ 764*dd1c4a9cSSzymon Dompke if (ec.value() == EBADR) 765*dd1c4a9cSSzymon Dompke { 766*dd1c4a9cSSzymon Dompke messages::resourceNotFound(asyncResp->res, "MetricReportDefinition", 767*dd1c4a9cSSzymon Dompke id); 768*dd1c4a9cSSzymon Dompke return; 769*dd1c4a9cSSzymon Dompke } 770*dd1c4a9cSSzymon Dompke 771*dd1c4a9cSSzymon Dompke if (ec) 772*dd1c4a9cSSzymon Dompke { 773*dd1c4a9cSSzymon Dompke BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 774*dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 775*dd1c4a9cSSzymon Dompke return; 776*dd1c4a9cSSzymon Dompke } 777*dd1c4a9cSSzymon Dompke 778*dd1c4a9cSSzymon Dompke asyncResp->res.result(boost::beast::http::status::no_content); 779*dd1c4a9cSSzymon Dompke }, 780*dd1c4a9cSSzymon Dompke telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 781*dd1c4a9cSSzymon Dompke "Delete"); 782*dd1c4a9cSSzymon Dompke } 783*dd1c4a9cSSzymon Dompke 7847e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app) 785081ebf06SWludzik, Jozef { 7867e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 787ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinitionCollection) 7887e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 78945ca1b86SEd Tanous [&app](const crow::Request& req, 7907e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7913ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 79245ca1b86SEd Tanous { 79345ca1b86SEd Tanous return; 79445ca1b86SEd Tanous } 79545ca1b86SEd Tanous 7968d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 7978d1b46d7Szhanghch05 "#MetricReportDefinitionCollection." 798081ebf06SWludzik, Jozef "MetricReportDefinitionCollection"; 7998d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 800ae9031f0SWilly Tu "/redfish/v1/TelemetryService/MetricReportDefinitions"; 801002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; 8027a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces{ 8037a1dbc48SGeorge Liu telemetry::reportInterface}; 8044028ff77SEd Tanous collection_util::getCollectionMembers( 805ae9031f0SWilly Tu asyncResp, 806ae9031f0SWilly Tu boost::urls::url( 807ae9031f0SWilly Tu "/redfish/v1/TelemetryService/MetricReportDefinitions"), 808ae9031f0SWilly Tu interfaces, 8094028ff77SEd Tanous "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); 8107e860f15SJohn Edward Broadbent }); 8114dbb8aeaSWludzik, Jozef 8127e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 813ed398213SEd Tanous .privileges(redfish::privileges::postMetricReportDefinitionCollection) 814002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 815002d39b4SEd Tanous [&app](const crow::Request& req, 8167e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8173ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 81845ca1b86SEd Tanous { 81945ca1b86SEd Tanous return; 82045ca1b86SEd Tanous } 82145ca1b86SEd Tanous 8224dbb8aeaSWludzik, Jozef telemetry::AddReportArgs args; 8238d1b46d7Szhanghch05 if (!telemetry::getUserParameters(asyncResp->res, req, args)) 8244dbb8aeaSWludzik, Jozef { 8254dbb8aeaSWludzik, Jozef return; 8264dbb8aeaSWludzik, Jozef } 8274dbb8aeaSWludzik, Jozef 8284dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>> 8294dbb8aeaSWludzik, Jozef chassisSensors; 830002d39b4SEd Tanous if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, 831002d39b4SEd Tanous chassisSensors)) 8324dbb8aeaSWludzik, Jozef { 8334dbb8aeaSWludzik, Jozef return; 8344dbb8aeaSWludzik, Jozef } 8354dbb8aeaSWludzik, Jozef 836002d39b4SEd Tanous auto addReportReq = 837002d39b4SEd Tanous std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 8384dbb8aeaSWludzik, Jozef for (const auto& [chassis, sensorType] : chassisSensors) 8394dbb8aeaSWludzik, Jozef { 8404dbb8aeaSWludzik, Jozef retrieveUriToDbusMap( 841021d32cfSKrzysztof Grobelny chassis, sensorType, 842002d39b4SEd Tanous [asyncResp, addReportReq]( 843002d39b4SEd Tanous const boost::beast::http::status status, 844fe04d49cSNan Zhou const std::map<std::string, std::string>& uriToDbus) { 8454dbb8aeaSWludzik, Jozef if (status != boost::beast::http::status::ok) 8464dbb8aeaSWludzik, Jozef { 8477e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 8480fda0f12SGeorge Liu << "Failed to retrieve URI to dbus sensors map with err " 8494dbb8aeaSWludzik, Jozef << static_cast<unsigned>(status); 8504dbb8aeaSWludzik, Jozef return; 8514dbb8aeaSWludzik, Jozef } 8524dbb8aeaSWludzik, Jozef addReportReq->insert(uriToDbus); 8534dbb8aeaSWludzik, Jozef }); 8544dbb8aeaSWludzik, Jozef } 8557e860f15SJohn Edward Broadbent }); 856081ebf06SWludzik, Jozef } 857081ebf06SWludzik, Jozef 8587e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app) 859081ebf06SWludzik, Jozef { 8607e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8617e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 862ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 8637e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 86445ca1b86SEd Tanous [&app](const crow::Request& req, 8657e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8667e860f15SJohn Edward Broadbent const std::string& id) { 8673ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 86845ca1b86SEd Tanous { 86945ca1b86SEd Tanous return; 87045ca1b86SEd Tanous } 87145ca1b86SEd Tanous 87289474494SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 87389474494SKrzysztof Grobelny *crow::connections::systemBus, telemetry::service, 87489474494SKrzysztof Grobelny telemetry::getDbusReportPath(id), telemetry::reportInterface, 875168e20c1SEd Tanous [asyncResp, 8765e7e2dc5SEd Tanous id](const boost::system::error_code& ec, 877479e899dSKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) { 878081ebf06SWludzik, Jozef if (ec.value() == EBADR || 879081ebf06SWludzik, Jozef ec == boost::system::errc::host_unreachable) 880081ebf06SWludzik, Jozef { 881002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, 882002d39b4SEd Tanous "MetricReportDefinition", id); 883081ebf06SWludzik, Jozef return; 884081ebf06SWludzik, Jozef } 885081ebf06SWludzik, Jozef if (ec) 886081ebf06SWludzik, Jozef { 887081ebf06SWludzik, Jozef BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 888081ebf06SWludzik, Jozef messages::internalError(asyncResp->res); 889081ebf06SWludzik, Jozef return; 890081ebf06SWludzik, Jozef } 891081ebf06SWludzik, Jozef 892479e899dSKrzysztof Grobelny telemetry::fillReportDefinition(asyncResp, id, properties); 89389474494SKrzysztof Grobelny }); 8947e860f15SJohn Edward Broadbent }); 895479e899dSKrzysztof Grobelny 8967e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8977e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 898ed398213SEd Tanous .privileges(redfish::privileges::deleteMetricReportDefinitionCollection) 8997e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 900*dd1c4a9cSSzymon Dompke std::bind_front(handleMetricReportDelete, std::ref(app))); 9014dbb8aeaSWludzik, Jozef } 902081ebf06SWludzik, Jozef } // namespace redfish 903