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 } 708*14fbced6SEd Tanous messages::propertyValueIncorrect( 709*14fbced6SEd Tanous asyncResp->res, metricProperties, "MetricProperties"); 7104dbb8aeaSWludzik, Jozef return; 7114dbb8aeaSWludzik, Jozef } 7124dbb8aeaSWludzik, Jozef if (ec) 7134dbb8aeaSWludzik, Jozef { 714479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 7154dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 7164dbb8aeaSWludzik, Jozef return; 7174dbb8aeaSWludzik, Jozef } 7184dbb8aeaSWludzik, Jozef 719479e899dSKrzysztof Grobelny messages::created(asyncResp->res); 7204dbb8aeaSWludzik, Jozef }, 7214dbb8aeaSWludzik, Jozef telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", 7224dbb8aeaSWludzik, Jozef "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", 723479e899dSKrzysztof Grobelny "TelemetryService/" + args.id, args.name, args.reportingType, 724479e899dSKrzysztof Grobelny args.reportUpdates, args.appendLimit, args.reportActions, 725479e899dSKrzysztof Grobelny args.interval, readingParams, args.metricReportDefinitionEnabled); 7264dbb8aeaSWludzik, Jozef } 7274dbb8aeaSWludzik, Jozef 728ecd6a3a2SEd Tanous AddReport(const AddReport&) = delete; 729ecd6a3a2SEd Tanous AddReport(AddReport&&) = delete; 730ecd6a3a2SEd Tanous AddReport& operator=(const AddReport&) = delete; 731ecd6a3a2SEd Tanous AddReport& operator=(AddReport&&) = delete; 732ecd6a3a2SEd Tanous 733fe04d49cSNan Zhou void insert(const std::map<std::string, std::string>& el) 7344dbb8aeaSWludzik, Jozef { 7354dbb8aeaSWludzik, Jozef uriToDbus.insert(el.begin(), el.end()); 7364dbb8aeaSWludzik, Jozef } 7374dbb8aeaSWludzik, Jozef 7384dbb8aeaSWludzik, Jozef private: 739479e899dSKrzysztof Grobelny std::shared_ptr<bmcweb::AsyncResp> asyncResp; 7404dbb8aeaSWludzik, Jozef AddReportArgs args; 7414dbb8aeaSWludzik, Jozef boost::container::flat_map<std::string, std::string> uriToDbus{}; 7424dbb8aeaSWludzik, Jozef }; 743081ebf06SWludzik, Jozef } // namespace telemetry 744081ebf06SWludzik, Jozef 7454220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead( 7464220be3bSEd Tanous App& app, const crow::Request& req, 7474220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7484220be3bSEd Tanous { 7494220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 7504220be3bSEd Tanous { 7514220be3bSEd Tanous return; 7524220be3bSEd Tanous } 7534220be3bSEd Tanous asyncResp->res.addHeader( 7544220be3bSEd Tanous boost::beast::http::field::link, 7554220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby"); 7564220be3bSEd Tanous } 7574220be3bSEd Tanous 7584220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet( 759fc0edbe3SEd Tanous App& app, const crow::Request& req, 760fc0edbe3SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 761fc0edbe3SEd Tanous { 762fc0edbe3SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 763fc0edbe3SEd Tanous { 764fc0edbe3SEd Tanous return; 765fc0edbe3SEd Tanous } 766fc0edbe3SEd Tanous 767fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 768fc0edbe3SEd Tanous "#MetricReportDefinitionCollection." 769fc0edbe3SEd Tanous "MetricReportDefinitionCollection"; 770fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 771fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"; 772fc0edbe3SEd Tanous asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; 773fc0edbe3SEd Tanous constexpr std::array<std::string_view, 1> interfaces{ 774fc0edbe3SEd Tanous telemetry::reportInterface}; 775fc0edbe3SEd Tanous collection_util::getCollectionMembers( 776fc0edbe3SEd Tanous asyncResp, 777fc0edbe3SEd Tanous boost::urls::url( 778fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"), 779fc0edbe3SEd Tanous interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); 780fc0edbe3SEd Tanous } 781fc0edbe3SEd Tanous 78286a5ac98SEd Tanous inline void 7834220be3bSEd Tanous handleMetricReportHead(App& app, const crow::Request& req, 7844220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7854220be3bSEd Tanous const std::string& /*id*/) 7864220be3bSEd Tanous { 7874220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 7884220be3bSEd Tanous { 7894220be3bSEd Tanous return; 7904220be3bSEd Tanous } 7914220be3bSEd Tanous asyncResp->res.addHeader( 7924220be3bSEd Tanous boost::beast::http::field::link, 7934220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 7944220be3bSEd Tanous } 7954220be3bSEd Tanous 7964220be3bSEd Tanous inline void 79786a5ac98SEd Tanous handleMetricReportGet(App& app, const crow::Request& req, 79886a5ac98SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 79986a5ac98SEd Tanous const std::string& id) 80086a5ac98SEd Tanous { 80186a5ac98SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 80286a5ac98SEd Tanous { 80386a5ac98SEd Tanous return; 80486a5ac98SEd Tanous } 8054220be3bSEd Tanous asyncResp->res.addHeader( 8064220be3bSEd Tanous boost::beast::http::field::link, 8074220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 80886a5ac98SEd Tanous 80986a5ac98SEd Tanous sdbusplus::asio::getAllProperties( 81086a5ac98SEd Tanous *crow::connections::systemBus, telemetry::service, 81186a5ac98SEd Tanous telemetry::getDbusReportPath(id), telemetry::reportInterface, 81286a5ac98SEd Tanous [asyncResp, id](const boost::system::error_code& ec, 81386a5ac98SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 81486a5ac98SEd Tanous if (ec.value() == EBADR || ec == boost::system::errc::host_unreachable) 81586a5ac98SEd Tanous { 81686a5ac98SEd Tanous messages::resourceNotFound(asyncResp->res, "MetricReportDefinition", 81786a5ac98SEd Tanous id); 81886a5ac98SEd Tanous return; 81986a5ac98SEd Tanous } 82086a5ac98SEd Tanous if (ec) 82186a5ac98SEd Tanous { 82286a5ac98SEd Tanous BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 82386a5ac98SEd Tanous messages::internalError(asyncResp->res); 82486a5ac98SEd Tanous return; 82586a5ac98SEd Tanous } 82686a5ac98SEd Tanous 82786a5ac98SEd Tanous telemetry::fillReportDefinition(asyncResp, id, properties); 82886a5ac98SEd Tanous }); 82986a5ac98SEd Tanous } 83086a5ac98SEd Tanous 831dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete( 832dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 833dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 834dd1c4a9cSSzymon Dompke 835dd1c4a9cSSzymon Dompke { 836dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 837dd1c4a9cSSzymon Dompke { 838dd1c4a9cSSzymon Dompke return; 839dd1c4a9cSSzymon Dompke } 840dd1c4a9cSSzymon Dompke 841dd1c4a9cSSzymon Dompke const std::string reportPath = telemetry::getDbusReportPath(id); 842dd1c4a9cSSzymon Dompke 843dd1c4a9cSSzymon Dompke crow::connections::systemBus->async_method_call( 844dd1c4a9cSSzymon Dompke [asyncResp, id](const boost::system::error_code& ec) { 845dd1c4a9cSSzymon Dompke /* 846dd1c4a9cSSzymon Dompke * boost::system::errc and std::errc are missing value 847dd1c4a9cSSzymon Dompke * for EBADR error that is defined in Linux. 848dd1c4a9cSSzymon Dompke */ 849dd1c4a9cSSzymon Dompke if (ec.value() == EBADR) 850dd1c4a9cSSzymon Dompke { 851dd1c4a9cSSzymon Dompke messages::resourceNotFound(asyncResp->res, "MetricReportDefinition", 852dd1c4a9cSSzymon Dompke id); 853dd1c4a9cSSzymon Dompke return; 854dd1c4a9cSSzymon Dompke } 855dd1c4a9cSSzymon Dompke 856dd1c4a9cSSzymon Dompke if (ec) 857dd1c4a9cSSzymon Dompke { 858dd1c4a9cSSzymon Dompke BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 859dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 860dd1c4a9cSSzymon Dompke return; 861dd1c4a9cSSzymon Dompke } 862dd1c4a9cSSzymon Dompke 863dd1c4a9cSSzymon Dompke asyncResp->res.result(boost::beast::http::status::no_content); 864dd1c4a9cSSzymon Dompke }, 865dd1c4a9cSSzymon Dompke telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 866dd1c4a9cSSzymon Dompke "Delete"); 867dd1c4a9cSSzymon Dompke } 868dd1c4a9cSSzymon Dompke 8697e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app) 870081ebf06SWludzik, Jozef { 8717e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 8724220be3bSEd Tanous .privileges(redfish::privileges::headMetricReportDefinitionCollection) 8734220be3bSEd Tanous .methods(boost::beast::http::verb::head)(std::bind_front( 8744220be3bSEd Tanous handleMetricReportDefinitionCollectionHead, std::ref(app))); 8754220be3bSEd Tanous 8764220be3bSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 877ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinitionCollection) 8784220be3bSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 8794220be3bSEd Tanous handleMetricReportDefinitionCollectionGet, std::ref(app))); 8804dbb8aeaSWludzik, Jozef 8817e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 882ed398213SEd Tanous .privileges(redfish::privileges::postMetricReportDefinitionCollection) 883002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 884002d39b4SEd Tanous [&app](const crow::Request& req, 8857e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8863ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 88745ca1b86SEd Tanous { 88845ca1b86SEd Tanous return; 88945ca1b86SEd Tanous } 89045ca1b86SEd Tanous 8914dbb8aeaSWludzik, Jozef telemetry::AddReportArgs args; 8928d1b46d7Szhanghch05 if (!telemetry::getUserParameters(asyncResp->res, req, args)) 8934dbb8aeaSWludzik, Jozef { 8944dbb8aeaSWludzik, Jozef return; 8954dbb8aeaSWludzik, Jozef } 8964dbb8aeaSWludzik, Jozef 8974dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>> 8984dbb8aeaSWludzik, Jozef chassisSensors; 899002d39b4SEd Tanous if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, 900002d39b4SEd Tanous chassisSensors)) 9014dbb8aeaSWludzik, Jozef { 9024dbb8aeaSWludzik, Jozef return; 9034dbb8aeaSWludzik, Jozef } 9044dbb8aeaSWludzik, Jozef 905002d39b4SEd Tanous auto addReportReq = 906002d39b4SEd Tanous std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 9074dbb8aeaSWludzik, Jozef for (const auto& [chassis, sensorType] : chassisSensors) 9084dbb8aeaSWludzik, Jozef { 9094dbb8aeaSWludzik, Jozef retrieveUriToDbusMap( 910021d32cfSKrzysztof Grobelny chassis, sensorType, 911002d39b4SEd Tanous [asyncResp, addReportReq]( 912002d39b4SEd Tanous const boost::beast::http::status status, 913fe04d49cSNan Zhou const std::map<std::string, std::string>& uriToDbus) { 9144dbb8aeaSWludzik, Jozef if (status != boost::beast::http::status::ok) 9154dbb8aeaSWludzik, Jozef { 9167e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 9170fda0f12SGeorge Liu << "Failed to retrieve URI to dbus sensors map with err " 9184dbb8aeaSWludzik, Jozef << static_cast<unsigned>(status); 9194dbb8aeaSWludzik, Jozef return; 9204dbb8aeaSWludzik, Jozef } 9214dbb8aeaSWludzik, Jozef addReportReq->insert(uriToDbus); 9224dbb8aeaSWludzik, Jozef }); 9234dbb8aeaSWludzik, Jozef } 9247e860f15SJohn Edward Broadbent }); 925081ebf06SWludzik, Jozef } 926081ebf06SWludzik, Jozef 9277e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app) 928081ebf06SWludzik, Jozef { 9297e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9307e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 931ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 9324220be3bSEd Tanous .methods(boost::beast::http::verb::head)( 9334220be3bSEd Tanous std::bind_front(handleMetricReportHead, std::ref(app))); 9344220be3bSEd Tanous 9354220be3bSEd Tanous BMCWEB_ROUTE(app, 9364220be3bSEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 9374220be3bSEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 9387e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 93986a5ac98SEd Tanous std::bind_front(handleMetricReportGet, std::ref(app))); 940479e899dSKrzysztof Grobelny 9417e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9427e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 943ed398213SEd Tanous .privileges(redfish::privileges::deleteMetricReportDefinitionCollection) 9447e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 945dd1c4a9cSSzymon Dompke std::bind_front(handleMetricReportDelete, std::ref(app))); 9464dbb8aeaSWludzik, Jozef } 947081ebf06SWludzik, Jozef } // namespace redfish 948