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*4220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead( 747*4220be3bSEd Tanous App& app, const crow::Request& req, 748*4220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 749*4220be3bSEd Tanous { 750*4220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 751*4220be3bSEd Tanous { 752*4220be3bSEd Tanous return; 753*4220be3bSEd Tanous } 754*4220be3bSEd Tanous asyncResp->res.addHeader( 755*4220be3bSEd Tanous boost::beast::http::field::link, 756*4220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby"); 757*4220be3bSEd Tanous } 758*4220be3bSEd Tanous 759*4220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet( 760fc0edbe3SEd Tanous App& app, const crow::Request& req, 761fc0edbe3SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 762fc0edbe3SEd Tanous { 763fc0edbe3SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 764fc0edbe3SEd Tanous { 765fc0edbe3SEd Tanous return; 766fc0edbe3SEd Tanous } 767fc0edbe3SEd Tanous 768fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 769fc0edbe3SEd Tanous "#MetricReportDefinitionCollection." 770fc0edbe3SEd Tanous "MetricReportDefinitionCollection"; 771fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 772fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"; 773fc0edbe3SEd Tanous asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; 774fc0edbe3SEd Tanous constexpr std::array<std::string_view, 1> interfaces{ 775fc0edbe3SEd Tanous telemetry::reportInterface}; 776fc0edbe3SEd Tanous collection_util::getCollectionMembers( 777fc0edbe3SEd Tanous asyncResp, 778fc0edbe3SEd Tanous boost::urls::url( 779fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"), 780fc0edbe3SEd Tanous interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); 781fc0edbe3SEd Tanous } 782fc0edbe3SEd Tanous 78386a5ac98SEd Tanous inline void 784*4220be3bSEd Tanous handleMetricReportHead(App& app, const crow::Request& req, 785*4220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 786*4220be3bSEd Tanous const std::string& /*id*/) 787*4220be3bSEd Tanous { 788*4220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 789*4220be3bSEd Tanous { 790*4220be3bSEd Tanous return; 791*4220be3bSEd Tanous } 792*4220be3bSEd Tanous asyncResp->res.addHeader( 793*4220be3bSEd Tanous boost::beast::http::field::link, 794*4220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 795*4220be3bSEd Tanous } 796*4220be3bSEd Tanous 797*4220be3bSEd Tanous inline void 79886a5ac98SEd Tanous handleMetricReportGet(App& app, const crow::Request& req, 79986a5ac98SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 80086a5ac98SEd Tanous const std::string& id) 80186a5ac98SEd Tanous { 80286a5ac98SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 80386a5ac98SEd Tanous { 80486a5ac98SEd Tanous return; 80586a5ac98SEd Tanous } 806*4220be3bSEd Tanous asyncResp->res.addHeader( 807*4220be3bSEd Tanous boost::beast::http::field::link, 808*4220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 80986a5ac98SEd Tanous 81086a5ac98SEd Tanous sdbusplus::asio::getAllProperties( 81186a5ac98SEd Tanous *crow::connections::systemBus, telemetry::service, 81286a5ac98SEd Tanous telemetry::getDbusReportPath(id), telemetry::reportInterface, 81386a5ac98SEd Tanous [asyncResp, id](const boost::system::error_code& ec, 81486a5ac98SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 81586a5ac98SEd Tanous if (ec.value() == EBADR || ec == boost::system::errc::host_unreachable) 81686a5ac98SEd Tanous { 81786a5ac98SEd Tanous messages::resourceNotFound(asyncResp->res, "MetricReportDefinition", 81886a5ac98SEd Tanous id); 81986a5ac98SEd Tanous return; 82086a5ac98SEd Tanous } 82186a5ac98SEd Tanous if (ec) 82286a5ac98SEd Tanous { 82386a5ac98SEd Tanous BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 82486a5ac98SEd Tanous messages::internalError(asyncResp->res); 82586a5ac98SEd Tanous return; 82686a5ac98SEd Tanous } 82786a5ac98SEd Tanous 82886a5ac98SEd Tanous telemetry::fillReportDefinition(asyncResp, id, properties); 82986a5ac98SEd Tanous }); 83086a5ac98SEd Tanous } 83186a5ac98SEd Tanous 832dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete( 833dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 834dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 835dd1c4a9cSSzymon Dompke 836dd1c4a9cSSzymon Dompke { 837dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 838dd1c4a9cSSzymon Dompke { 839dd1c4a9cSSzymon Dompke return; 840dd1c4a9cSSzymon Dompke } 841dd1c4a9cSSzymon Dompke 842dd1c4a9cSSzymon Dompke const std::string reportPath = telemetry::getDbusReportPath(id); 843dd1c4a9cSSzymon Dompke 844dd1c4a9cSSzymon Dompke crow::connections::systemBus->async_method_call( 845dd1c4a9cSSzymon Dompke [asyncResp, id](const boost::system::error_code& ec) { 846dd1c4a9cSSzymon Dompke /* 847dd1c4a9cSSzymon Dompke * boost::system::errc and std::errc are missing value 848dd1c4a9cSSzymon Dompke * for EBADR error that is defined in Linux. 849dd1c4a9cSSzymon Dompke */ 850dd1c4a9cSSzymon Dompke if (ec.value() == EBADR) 851dd1c4a9cSSzymon Dompke { 852dd1c4a9cSSzymon Dompke messages::resourceNotFound(asyncResp->res, "MetricReportDefinition", 853dd1c4a9cSSzymon Dompke id); 854dd1c4a9cSSzymon Dompke return; 855dd1c4a9cSSzymon Dompke } 856dd1c4a9cSSzymon Dompke 857dd1c4a9cSSzymon Dompke if (ec) 858dd1c4a9cSSzymon Dompke { 859dd1c4a9cSSzymon Dompke BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 860dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 861dd1c4a9cSSzymon Dompke return; 862dd1c4a9cSSzymon Dompke } 863dd1c4a9cSSzymon Dompke 864dd1c4a9cSSzymon Dompke asyncResp->res.result(boost::beast::http::status::no_content); 865dd1c4a9cSSzymon Dompke }, 866dd1c4a9cSSzymon Dompke telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 867dd1c4a9cSSzymon Dompke "Delete"); 868dd1c4a9cSSzymon Dompke } 869dd1c4a9cSSzymon Dompke 8707e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app) 871081ebf06SWludzik, Jozef { 8727e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 873*4220be3bSEd Tanous .privileges(redfish::privileges::headMetricReportDefinitionCollection) 874*4220be3bSEd Tanous .methods(boost::beast::http::verb::head)(std::bind_front( 875*4220be3bSEd Tanous handleMetricReportDefinitionCollectionHead, std::ref(app))); 876*4220be3bSEd Tanous 877*4220be3bSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 878ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinitionCollection) 879*4220be3bSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 880*4220be3bSEd Tanous handleMetricReportDefinitionCollectionGet, std::ref(app))); 8814dbb8aeaSWludzik, Jozef 8827e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 883ed398213SEd Tanous .privileges(redfish::privileges::postMetricReportDefinitionCollection) 884002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 885002d39b4SEd Tanous [&app](const crow::Request& req, 8867e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8873ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 88845ca1b86SEd Tanous { 88945ca1b86SEd Tanous return; 89045ca1b86SEd Tanous } 89145ca1b86SEd Tanous 8924dbb8aeaSWludzik, Jozef telemetry::AddReportArgs args; 8938d1b46d7Szhanghch05 if (!telemetry::getUserParameters(asyncResp->res, req, args)) 8944dbb8aeaSWludzik, Jozef { 8954dbb8aeaSWludzik, Jozef return; 8964dbb8aeaSWludzik, Jozef } 8974dbb8aeaSWludzik, Jozef 8984dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>> 8994dbb8aeaSWludzik, Jozef chassisSensors; 900002d39b4SEd Tanous if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, 901002d39b4SEd Tanous chassisSensors)) 9024dbb8aeaSWludzik, Jozef { 9034dbb8aeaSWludzik, Jozef return; 9044dbb8aeaSWludzik, Jozef } 9054dbb8aeaSWludzik, Jozef 906002d39b4SEd Tanous auto addReportReq = 907002d39b4SEd Tanous std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 9084dbb8aeaSWludzik, Jozef for (const auto& [chassis, sensorType] : chassisSensors) 9094dbb8aeaSWludzik, Jozef { 9104dbb8aeaSWludzik, Jozef retrieveUriToDbusMap( 911021d32cfSKrzysztof Grobelny chassis, sensorType, 912002d39b4SEd Tanous [asyncResp, addReportReq]( 913002d39b4SEd Tanous const boost::beast::http::status status, 914fe04d49cSNan Zhou const std::map<std::string, std::string>& uriToDbus) { 9154dbb8aeaSWludzik, Jozef if (status != boost::beast::http::status::ok) 9164dbb8aeaSWludzik, Jozef { 9177e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 9180fda0f12SGeorge Liu << "Failed to retrieve URI to dbus sensors map with err " 9194dbb8aeaSWludzik, Jozef << static_cast<unsigned>(status); 9204dbb8aeaSWludzik, Jozef return; 9214dbb8aeaSWludzik, Jozef } 9224dbb8aeaSWludzik, Jozef addReportReq->insert(uriToDbus); 9234dbb8aeaSWludzik, Jozef }); 9244dbb8aeaSWludzik, Jozef } 9257e860f15SJohn Edward Broadbent }); 926081ebf06SWludzik, Jozef } 927081ebf06SWludzik, Jozef 9287e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app) 929081ebf06SWludzik, Jozef { 9307e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9317e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 932ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 933*4220be3bSEd Tanous .methods(boost::beast::http::verb::head)( 934*4220be3bSEd Tanous std::bind_front(handleMetricReportHead, std::ref(app))); 935*4220be3bSEd Tanous 936*4220be3bSEd Tanous BMCWEB_ROUTE(app, 937*4220be3bSEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 938*4220be3bSEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 9397e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 94086a5ac98SEd Tanous std::bind_front(handleMetricReportGet, std::ref(app))); 941479e899dSKrzysztof Grobelny 9427e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9437e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 944ed398213SEd Tanous .privileges(redfish::privileges::deleteMetricReportDefinitionCollection) 9457e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 946dd1c4a9cSSzymon Dompke std::bind_front(handleMetricReportDelete, std::ref(app))); 9474dbb8aeaSWludzik, Jozef } 948081ebf06SWludzik, Jozef } // namespace redfish 949