140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3081ebf06SWludzik, Jozef #pragma once 4081ebf06SWludzik, Jozef 53ccb3adbSEd Tanous #include "app.hpp" 6d7857201SEd Tanous #include "async_resp.hpp" 7d7857201SEd Tanous #include "dbus_singleton.hpp" 83ccb3adbSEd Tanous #include "dbus_utility.hpp" 9d7857201SEd Tanous #include "error_messages.hpp" 10479e899dSKrzysztof Grobelny #include "generated/enums/metric_report_definition.hpp" 11539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 12d7857201SEd Tanous #include "http_request.hpp" 13d7857201SEd Tanous #include "http_response.hpp" 14d7857201SEd Tanous #include "logging.hpp" 153ccb3adbSEd Tanous #include "query.hpp" 163ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 174dbb8aeaSWludzik, Jozef #include "sensors.hpp" 183ccb3adbSEd Tanous #include "utils/collection.hpp" 193ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 205b90429aSEd Tanous #include "utils/json_utils.hpp" 21081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp" 22081ebf06SWludzik, Jozef #include "utils/time_utils.hpp" 23081ebf06SWludzik, Jozef 24d7857201SEd Tanous #include <asm-generic/errno.h> 25d7857201SEd Tanous #include <systemd/sd-bus.h> 26d7857201SEd Tanous 27d7857201SEd Tanous #include <boost/asio/post.hpp> 28d7857201SEd Tanous #include <boost/beast/http/field.hpp> 29d7857201SEd Tanous #include <boost/beast/http/status.hpp> 30d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 314dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp> 32d7857201SEd Tanous #include <boost/container/flat_set.hpp> 33ef4c65b7SEd Tanous #include <boost/url/format.hpp> 34d7857201SEd Tanous #include <boost/url/url.hpp> 35d7857201SEd Tanous #include <nlohmann/json.hpp> 36d7857201SEd Tanous #include <sdbusplus/message.hpp> 37d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 3889474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 394dbb8aeaSWludzik, Jozef 407a1dbc48SGeorge Liu #include <array> 41d7857201SEd Tanous #include <chrono> 42d7857201SEd Tanous #include <cstddef> 43d7857201SEd Tanous #include <cstdint> 44d7857201SEd Tanous #include <functional> 45d7857201SEd Tanous #include <limits> 46fe04d49cSNan Zhou #include <map> 47d7857201SEd Tanous #include <memory> 48f19ab44aSSzymon Dompke #include <optional> 49f19ab44aSSzymon Dompke #include <span> 50f19ab44aSSzymon Dompke #include <string> 517a1dbc48SGeorge Liu #include <string_view> 52081ebf06SWludzik, Jozef #include <tuple> 53f19ab44aSSzymon Dompke #include <utility> 54081ebf06SWludzik, Jozef #include <variant> 55f19ab44aSSzymon Dompke #include <vector> 56081ebf06SWludzik, Jozef 57081ebf06SWludzik, Jozef namespace redfish 58081ebf06SWludzik, Jozef { 59081ebf06SWludzik, Jozef 60081ebf06SWludzik, Jozef namespace telemetry 61081ebf06SWludzik, Jozef { 62081ebf06SWludzik, Jozef 63479e899dSKrzysztof Grobelny using ReadingParameters = std::vector<std::tuple< 64479e899dSKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>>, 65479e899dSKrzysztof Grobelny std::string, std::string, uint64_t>>; 66479e899dSKrzysztof Grobelny 67*2169e896SMichal Orzel inline bool formatMessageOnError(crow::Response& res, const std::string& id, 689e6c388aSLukasz Kazmierczak const boost::system::error_code& ec) 699e6c388aSLukasz Kazmierczak { 709e6c388aSLukasz Kazmierczak if (ec.value() == EBADR || ec == boost::system::errc::host_unreachable) 719e6c388aSLukasz Kazmierczak { 729e6c388aSLukasz Kazmierczak messages::resourceNotFound(res, "MetricReportDefinition", id); 73*2169e896SMichal Orzel return true; 749e6c388aSLukasz Kazmierczak } 759e6c388aSLukasz Kazmierczak 769e6c388aSLukasz Kazmierczak if (ec == boost::system::errc::file_exists) 779e6c388aSLukasz Kazmierczak { 789e6c388aSLukasz Kazmierczak messages::resourceAlreadyExists(res, "MetricReportDefinition", "Id", 799e6c388aSLukasz Kazmierczak id); 80*2169e896SMichal Orzel return true; 819e6c388aSLukasz Kazmierczak } 829e6c388aSLukasz Kazmierczak 839e6c388aSLukasz Kazmierczak if (ec == boost::system::errc::too_many_files_open) 849e6c388aSLukasz Kazmierczak { 859e6c388aSLukasz Kazmierczak messages::createLimitReachedForResource(res); 86*2169e896SMichal Orzel return true; 879e6c388aSLukasz Kazmierczak } 889e6c388aSLukasz Kazmierczak 899e6c388aSLukasz Kazmierczak if (ec) 909e6c388aSLukasz Kazmierczak { 919e6c388aSLukasz Kazmierczak BMCWEB_LOG_ERROR("DBUS response error {}", ec); 929e6c388aSLukasz Kazmierczak messages::internalError(res); 93*2169e896SMichal Orzel return true; 949e6c388aSLukasz Kazmierczak } 959e6c388aSLukasz Kazmierczak 96*2169e896SMichal Orzel return false; 979e6c388aSLukasz Kazmierczak } 989e6c388aSLukasz Kazmierczak 99504af5a0SPatrick Williams inline metric_report_definition::ReportActionsEnum toRedfishReportAction( 100504af5a0SPatrick Williams std::string_view dbusValue) 101479e899dSKrzysztof Grobelny { 102479e899dSKrzysztof Grobelny if (dbusValue == 103479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate") 104479e899dSKrzysztof Grobelny { 105479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum::RedfishEvent; 106479e899dSKrzysztof Grobelny } 107479e899dSKrzysztof Grobelny if (dbusValue == 108479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection") 109479e899dSKrzysztof Grobelny { 110479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum:: 111479e899dSKrzysztof Grobelny LogToMetricReportsCollection; 112479e899dSKrzysztof Grobelny } 113479e899dSKrzysztof Grobelny return metric_report_definition::ReportActionsEnum::Invalid; 114479e899dSKrzysztof Grobelny } 115479e899dSKrzysztof Grobelny 116479e899dSKrzysztof Grobelny inline std::string toDbusReportAction(std::string_view redfishValue) 117479e899dSKrzysztof Grobelny { 118479e899dSKrzysztof Grobelny if (redfishValue == "RedfishEvent") 119479e899dSKrzysztof Grobelny { 120479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate"; 121479e899dSKrzysztof Grobelny } 122479e899dSKrzysztof Grobelny if (redfishValue == "LogToMetricReportsCollection") 123479e899dSKrzysztof Grobelny { 124479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection"; 125479e899dSKrzysztof Grobelny } 126479e899dSKrzysztof Grobelny return ""; 127479e899dSKrzysztof Grobelny } 128479e899dSKrzysztof Grobelny 129479e899dSKrzysztof Grobelny inline metric_report_definition::MetricReportDefinitionType 130479e899dSKrzysztof Grobelny toRedfishReportingType(std::string_view dbusValue) 131479e899dSKrzysztof Grobelny { 132479e899dSKrzysztof Grobelny if (dbusValue == 133479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange") 134479e899dSKrzysztof Grobelny { 135479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::OnChange; 136479e899dSKrzysztof Grobelny } 137479e899dSKrzysztof Grobelny if (dbusValue == 138479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest") 139479e899dSKrzysztof Grobelny { 140479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::OnRequest; 141479e899dSKrzysztof Grobelny } 142479e899dSKrzysztof Grobelny if (dbusValue == 143479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic") 144479e899dSKrzysztof Grobelny { 145479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::Periodic; 146479e899dSKrzysztof Grobelny } 147479e899dSKrzysztof Grobelny return metric_report_definition::MetricReportDefinitionType::Invalid; 148479e899dSKrzysztof Grobelny } 149479e899dSKrzysztof Grobelny 150479e899dSKrzysztof Grobelny inline std::string toDbusReportingType(std::string_view redfishValue) 151479e899dSKrzysztof Grobelny { 152479e899dSKrzysztof Grobelny if (redfishValue == "OnChange") 153479e899dSKrzysztof Grobelny { 154479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange"; 155479e899dSKrzysztof Grobelny } 156479e899dSKrzysztof Grobelny if (redfishValue == "OnRequest") 157479e899dSKrzysztof Grobelny { 158479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest"; 159479e899dSKrzysztof Grobelny } 160479e899dSKrzysztof Grobelny if (redfishValue == "Periodic") 161479e899dSKrzysztof Grobelny { 162479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic"; 163479e899dSKrzysztof Grobelny } 164479e899dSKrzysztof Grobelny return ""; 165479e899dSKrzysztof Grobelny } 166479e899dSKrzysztof Grobelny 167479e899dSKrzysztof Grobelny inline metric_report_definition::CollectionTimeScope 168479e899dSKrzysztof Grobelny toRedfishCollectionTimeScope(std::string_view dbusValue) 169479e899dSKrzysztof Grobelny { 170479e899dSKrzysztof Grobelny if (dbusValue == 171479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point") 172479e899dSKrzysztof Grobelny { 173479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Point; 174479e899dSKrzysztof Grobelny } 175479e899dSKrzysztof Grobelny if (dbusValue == 176479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval") 177479e899dSKrzysztof Grobelny { 178479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Interval; 179479e899dSKrzysztof Grobelny } 180479e899dSKrzysztof Grobelny if (dbusValue == 181479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval") 182479e899dSKrzysztof Grobelny { 183479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::StartupInterval; 184479e899dSKrzysztof Grobelny } 185479e899dSKrzysztof Grobelny return metric_report_definition::CollectionTimeScope::Invalid; 186479e899dSKrzysztof Grobelny } 187479e899dSKrzysztof Grobelny 188479e899dSKrzysztof Grobelny inline std::string toDbusCollectionTimeScope(std::string_view redfishValue) 189479e899dSKrzysztof Grobelny { 190479e899dSKrzysztof Grobelny if (redfishValue == "Point") 191479e899dSKrzysztof Grobelny { 192479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point"; 193479e899dSKrzysztof Grobelny } 194479e899dSKrzysztof Grobelny if (redfishValue == "Interval") 195479e899dSKrzysztof Grobelny { 196479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval"; 197479e899dSKrzysztof Grobelny } 198479e899dSKrzysztof Grobelny if (redfishValue == "StartupInterval") 199479e899dSKrzysztof Grobelny { 200479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval"; 201479e899dSKrzysztof Grobelny } 202479e899dSKrzysztof Grobelny return ""; 203479e899dSKrzysztof Grobelny } 204479e899dSKrzysztof Grobelny 205504af5a0SPatrick Williams inline metric_report_definition::ReportUpdatesEnum toRedfishReportUpdates( 206504af5a0SPatrick Williams std::string_view dbusValue) 207479e899dSKrzysztof Grobelny { 208479e899dSKrzysztof Grobelny if (dbusValue == 209479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite") 210479e899dSKrzysztof Grobelny { 211479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::Overwrite; 212479e899dSKrzysztof Grobelny } 213479e899dSKrzysztof Grobelny if (dbusValue == 214479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull") 215479e899dSKrzysztof Grobelny { 216479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::AppendWrapsWhenFull; 217479e899dSKrzysztof Grobelny } 218479e899dSKrzysztof Grobelny if (dbusValue == 219479e899dSKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull") 220479e899dSKrzysztof Grobelny { 221479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::AppendStopsWhenFull; 222479e899dSKrzysztof Grobelny } 223479e899dSKrzysztof Grobelny return metric_report_definition::ReportUpdatesEnum::Invalid; 224479e899dSKrzysztof Grobelny } 225479e899dSKrzysztof Grobelny 226479e899dSKrzysztof Grobelny inline std::string toDbusReportUpdates(std::string_view redfishValue) 227479e899dSKrzysztof Grobelny { 228479e899dSKrzysztof Grobelny if (redfishValue == "Overwrite") 229479e899dSKrzysztof Grobelny { 230479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite"; 231479e899dSKrzysztof Grobelny } 232479e899dSKrzysztof Grobelny if (redfishValue == "AppendWrapsWhenFull") 233479e899dSKrzysztof Grobelny { 234479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull"; 235479e899dSKrzysztof Grobelny } 236479e899dSKrzysztof Grobelny if (redfishValue == "AppendStopsWhenFull") 237479e899dSKrzysztof Grobelny { 238479e899dSKrzysztof Grobelny return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull"; 239479e899dSKrzysztof Grobelny } 240479e899dSKrzysztof Grobelny return ""; 241479e899dSKrzysztof Grobelny } 242081ebf06SWludzik, Jozef 243f19ab44aSSzymon Dompke inline std::optional<nlohmann::json::array_t> getLinkedTriggers( 244f19ab44aSSzymon Dompke std::span<const sdbusplus::message::object_path> triggerPaths) 245f19ab44aSSzymon Dompke { 246f19ab44aSSzymon Dompke nlohmann::json::array_t triggers; 247f19ab44aSSzymon Dompke 248f19ab44aSSzymon Dompke for (const sdbusplus::message::object_path& path : triggerPaths) 249f19ab44aSSzymon Dompke { 250f19ab44aSSzymon Dompke if (path.parent_path() != 251f19ab44aSSzymon Dompke "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService") 252f19ab44aSSzymon Dompke { 25362598e31SEd Tanous BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}", 25462598e31SEd Tanous path.str); 255f19ab44aSSzymon Dompke return std::nullopt; 256f19ab44aSSzymon Dompke } 257f19ab44aSSzymon Dompke 258f19ab44aSSzymon Dompke std::string id = path.filename(); 259f19ab44aSSzymon Dompke if (id.empty()) 260f19ab44aSSzymon Dompke { 26162598e31SEd Tanous BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}", 26262598e31SEd Tanous path.str); 263f19ab44aSSzymon Dompke return std::nullopt; 264f19ab44aSSzymon Dompke } 265f19ab44aSSzymon Dompke nlohmann::json::object_t trigger; 266f19ab44aSSzymon Dompke trigger["@odata.id"] = 267f19ab44aSSzymon Dompke boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id); 268f19ab44aSSzymon Dompke triggers.emplace_back(std::move(trigger)); 269f19ab44aSSzymon Dompke } 270f19ab44aSSzymon Dompke 271f19ab44aSSzymon Dompke return triggers; 272f19ab44aSSzymon Dompke } 273f19ab44aSSzymon Dompke 274bd79bce8SPatrick Williams inline void fillReportDefinition( 275bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 276479e899dSKrzysztof Grobelny const dbus::utility::DBusPropertiesMap& properties) 277081ebf06SWludzik, Jozef { 278479e899dSKrzysztof Grobelny std::vector<std::string> reportActions; 279479e899dSKrzysztof Grobelny ReadingParameters readingParams; 280479e899dSKrzysztof Grobelny std::string reportingType; 281479e899dSKrzysztof Grobelny std::string reportUpdates; 282479e899dSKrzysztof Grobelny std::string name; 283479e899dSKrzysztof Grobelny uint64_t appendLimit = 0; 284479e899dSKrzysztof Grobelny uint64_t interval = 0; 285479e899dSKrzysztof Grobelny bool enabled = false; 286f19ab44aSSzymon Dompke std::vector<sdbusplus::message::object_path> triggers; 28789474494SKrzysztof Grobelny 28889474494SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 289479e899dSKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "ReportingType", 290479e899dSKrzysztof Grobelny reportingType, "Interval", interval, "ReportActions", reportActions, 291479e899dSKrzysztof Grobelny "ReportUpdates", reportUpdates, "AppendLimit", appendLimit, 292f19ab44aSSzymon Dompke "ReadingParameters", readingParams, "Name", name, "Enabled", enabled, 293f19ab44aSSzymon Dompke "Triggers", triggers); 29489474494SKrzysztof Grobelny 29589474494SKrzysztof Grobelny if (!success) 296081ebf06SWludzik, Jozef { 297081ebf06SWludzik, Jozef messages::internalError(asyncResp->res); 298081ebf06SWludzik, Jozef return; 299081ebf06SWludzik, Jozef } 300081ebf06SWludzik, Jozef 301479e899dSKrzysztof Grobelny metric_report_definition::MetricReportDefinitionType redfishReportingType = 302479e899dSKrzysztof Grobelny toRedfishReportingType(reportingType); 303479e899dSKrzysztof Grobelny if (redfishReportingType == 304479e899dSKrzysztof Grobelny metric_report_definition::MetricReportDefinitionType::Invalid) 305081ebf06SWludzik, Jozef { 306479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 307479e899dSKrzysztof Grobelny return; 308081ebf06SWludzik, Jozef } 30989474494SKrzysztof Grobelny 310479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReportDefinitionType"] = 311479e899dSKrzysztof Grobelny redfishReportingType; 312479e899dSKrzysztof Grobelny 313f19ab44aSSzymon Dompke std::optional<nlohmann::json::array_t> linkedTriggers = 314f19ab44aSSzymon Dompke getLinkedTriggers(triggers); 315f19ab44aSSzymon Dompke if (!linkedTriggers) 316f19ab44aSSzymon Dompke { 317f19ab44aSSzymon Dompke messages::internalError(asyncResp->res); 318f19ab44aSSzymon Dompke return; 319f19ab44aSSzymon Dompke } 320f19ab44aSSzymon Dompke 321f19ab44aSSzymon Dompke asyncResp->res.jsonValue["Links"]["Triggers"] = std::move(*linkedTriggers); 322f19ab44aSSzymon Dompke 323479e899dSKrzysztof Grobelny nlohmann::json::array_t redfishReportActions; 324479e899dSKrzysztof Grobelny for (const std::string& action : reportActions) 325081ebf06SWludzik, Jozef { 326479e899dSKrzysztof Grobelny metric_report_definition::ReportActionsEnum redfishAction = 327479e899dSKrzysztof Grobelny toRedfishReportAction(action); 328479e899dSKrzysztof Grobelny if (redfishAction == 329479e899dSKrzysztof Grobelny metric_report_definition::ReportActionsEnum::Invalid) 330479e899dSKrzysztof Grobelny { 331479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 332479e899dSKrzysztof Grobelny return; 333081ebf06SWludzik, Jozef } 334081ebf06SWludzik, Jozef 335479e899dSKrzysztof Grobelny redfishReportActions.emplace_back(redfishAction); 336479e899dSKrzysztof Grobelny } 337479e899dSKrzysztof Grobelny 338479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions); 339479e899dSKrzysztof Grobelny 34082b286fbSEd Tanous nlohmann::json::array_t metrics; 341479e899dSKrzysztof Grobelny for (const auto& [sensorData, collectionFunction, collectionTimeScope, 342479e899dSKrzysztof Grobelny collectionDuration] : readingParams) 34389474494SKrzysztof Grobelny { 344479e899dSKrzysztof Grobelny nlohmann::json::array_t metricProperties; 345479e899dSKrzysztof Grobelny 346479e899dSKrzysztof Grobelny for (const auto& [sensorPath, sensorMetadata] : sensorData) 347081ebf06SWludzik, Jozef { 348479e899dSKrzysztof Grobelny metricProperties.emplace_back(sensorMetadata); 349479e899dSKrzysztof Grobelny } 350479e899dSKrzysztof Grobelny 351613dabeaSEd Tanous nlohmann::json::object_t metric; 352479e899dSKrzysztof Grobelny 353479e899dSKrzysztof Grobelny metric_report_definition::CalculationAlgorithmEnum 354479e899dSKrzysztof Grobelny redfishCollectionFunction = 355479e899dSKrzysztof Grobelny telemetry::toRedfishCollectionFunction(collectionFunction); 356479e899dSKrzysztof Grobelny if (redfishCollectionFunction == 357479e899dSKrzysztof Grobelny metric_report_definition::CalculationAlgorithmEnum::Invalid) 358479e899dSKrzysztof Grobelny { 359479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 360479e899dSKrzysztof Grobelny return; 361479e899dSKrzysztof Grobelny } 362479e899dSKrzysztof Grobelny metric["CollectionFunction"] = redfishCollectionFunction; 363479e899dSKrzysztof Grobelny 364479e899dSKrzysztof Grobelny metric_report_definition::CollectionTimeScope 365479e899dSKrzysztof Grobelny redfishCollectionTimeScope = 366479e899dSKrzysztof Grobelny toRedfishCollectionTimeScope(collectionTimeScope); 367479e899dSKrzysztof Grobelny if (redfishCollectionTimeScope == 368479e899dSKrzysztof Grobelny metric_report_definition::CollectionTimeScope::Invalid) 369479e899dSKrzysztof Grobelny { 370479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 371479e899dSKrzysztof Grobelny return; 372479e899dSKrzysztof Grobelny } 373479e899dSKrzysztof Grobelny metric["CollectionTimeScope"] = redfishCollectionTimeScope; 374479e899dSKrzysztof Grobelny 375479e899dSKrzysztof Grobelny metric["MetricProperties"] = std::move(metricProperties); 376479e899dSKrzysztof Grobelny metric["CollectionDuration"] = time_utils::toDurationString( 377479e899dSKrzysztof Grobelny std::chrono::milliseconds(collectionDuration)); 378b2ba3072SPatrick Williams metrics.emplace_back(std::move(metric)); 379081ebf06SWludzik, Jozef } 380479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Metrics"] = std::move(metrics); 381479e899dSKrzysztof Grobelny 382479e899dSKrzysztof Grobelny if (enabled) 383479e899dSKrzysztof Grobelny { 384539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 385479e899dSKrzysztof Grobelny } 386479e899dSKrzysztof Grobelny else 387479e899dSKrzysztof Grobelny { 388539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Disabled; 38989474494SKrzysztof Grobelny } 39089474494SKrzysztof Grobelny 391479e899dSKrzysztof Grobelny metric_report_definition::ReportUpdatesEnum redfishReportUpdates = 392479e899dSKrzysztof Grobelny toRedfishReportUpdates(reportUpdates); 393479e899dSKrzysztof Grobelny if (redfishReportUpdates == 394479e899dSKrzysztof Grobelny metric_report_definition::ReportUpdatesEnum::Invalid) 39589474494SKrzysztof Grobelny { 396479e899dSKrzysztof Grobelny messages::internalError(asyncResp->res); 397479e899dSKrzysztof Grobelny return; 39889474494SKrzysztof Grobelny } 399479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["ReportUpdates"] = redfishReportUpdates; 40089474494SKrzysztof Grobelny 401479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReportDefinitionEnabled"] = enabled; 402479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["AppendLimit"] = appendLimit; 403479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Name"] = name; 404081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = 405479e899dSKrzysztof Grobelny time_utils::toDurationString(std::chrono::milliseconds(interval)); 406479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["@odata.type"] = 407479e899dSKrzysztof Grobelny "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; 408479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 409479e899dSKrzysztof Grobelny "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id); 410479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["Id"] = id; 411479e899dSKrzysztof Grobelny asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format( 412479e899dSKrzysztof Grobelny "/redfish/v1/TelemetryService/MetricReports/{}", id); 41389474494SKrzysztof Grobelny } 41489474494SKrzysztof Grobelny 4154dbb8aeaSWludzik, Jozef struct AddReportArgs 4164dbb8aeaSWludzik, Jozef { 417479e899dSKrzysztof Grobelny struct MetricArgs 418479e899dSKrzysztof Grobelny { 419479e899dSKrzysztof Grobelny std::vector<std::string> uris; 420479e899dSKrzysztof Grobelny std::string collectionFunction; 421479e899dSKrzysztof Grobelny std::string collectionTimeScope; 422479e899dSKrzysztof Grobelny uint64_t collectionDuration = 0; 423479e899dSKrzysztof Grobelny }; 424479e899dSKrzysztof Grobelny 425479e899dSKrzysztof Grobelny std::string id; 4264dbb8aeaSWludzik, Jozef std::string name; 4274dbb8aeaSWludzik, Jozef std::string reportingType; 428479e899dSKrzysztof Grobelny std::string reportUpdates; 429479e899dSKrzysztof Grobelny uint64_t appendLimit = std::numeric_limits<uint64_t>::max(); 430479e899dSKrzysztof Grobelny std::vector<std::string> reportActions; 431479e899dSKrzysztof Grobelny uint64_t interval = std::numeric_limits<uint64_t>::max(); 432479e899dSKrzysztof Grobelny std::vector<MetricArgs> metrics; 433479e899dSKrzysztof Grobelny bool metricReportDefinitionEnabled = true; 4344dbb8aeaSWludzik, Jozef }; 4354dbb8aeaSWludzik, Jozef 4364dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res, 437479e899dSKrzysztof Grobelny const std::vector<std::string>& actions, 4389e6c388aSLukasz Kazmierczak std::vector<std::string>& outReportActions) 4394dbb8aeaSWludzik, Jozef { 4404dbb8aeaSWludzik, Jozef size_t index = 0; 441479e899dSKrzysztof Grobelny for (const std::string& action : actions) 4424dbb8aeaSWludzik, Jozef { 443479e899dSKrzysztof Grobelny std::string dbusReportAction = toDbusReportAction(action); 444479e899dSKrzysztof Grobelny if (dbusReportAction.empty()) 4454dbb8aeaSWludzik, Jozef { 4469e6c388aSLukasz Kazmierczak messages::propertyValueNotInList( 4479e6c388aSLukasz Kazmierczak res, action, "ReportActions/" + std::to_string(index)); 4484dbb8aeaSWludzik, Jozef return false; 4494dbb8aeaSWludzik, Jozef } 450479e899dSKrzysztof Grobelny 4519e6c388aSLukasz Kazmierczak outReportActions.emplace_back(std::move(dbusReportAction)); 4524dbb8aeaSWludzik, Jozef index++; 4534dbb8aeaSWludzik, Jozef } 4544dbb8aeaSWludzik, Jozef return true; 4554dbb8aeaSWludzik, Jozef } 4564dbb8aeaSWludzik, Jozef 457b14f357fSEd Tanous inline bool getUserMetric(crow::Response& res, nlohmann::json::object_t& metric, 458479e899dSKrzysztof Grobelny AddReportArgs::MetricArgs& metricArgs) 459479e899dSKrzysztof Grobelny { 460479e899dSKrzysztof Grobelny std::optional<std::vector<std::string>> uris; 461479e899dSKrzysztof Grobelny std::optional<std::string> collectionDurationStr; 462479e899dSKrzysztof Grobelny std::optional<std::string> collectionFunction; 463479e899dSKrzysztof Grobelny std::optional<std::string> collectionTimeScopeStr; 464479e899dSKrzysztof Grobelny 465afc474aeSMyung Bae if (!json_util::readJsonObject( // 466afc474aeSMyung Bae metric, res, // 467afc474aeSMyung Bae "CollectionDuration", collectionDurationStr, // 468afc474aeSMyung Bae "CollectionFunction", collectionFunction, // 469afc474aeSMyung Bae "CollectionTimeScope", collectionTimeScopeStr, // 470afc474aeSMyung Bae "MetricProperties", uris // 471afc474aeSMyung Bae )) 472479e899dSKrzysztof Grobelny { 473479e899dSKrzysztof Grobelny return false; 474479e899dSKrzysztof Grobelny } 475479e899dSKrzysztof Grobelny 476479e899dSKrzysztof Grobelny if (uris) 477479e899dSKrzysztof Grobelny { 478479e899dSKrzysztof Grobelny metricArgs.uris = std::move(*uris); 479479e899dSKrzysztof Grobelny } 480479e899dSKrzysztof Grobelny 481479e899dSKrzysztof Grobelny if (collectionFunction) 482479e899dSKrzysztof Grobelny { 483479e899dSKrzysztof Grobelny std::string dbusCollectionFunction = 484479e899dSKrzysztof Grobelny telemetry::toDbusCollectionFunction(*collectionFunction); 485479e899dSKrzysztof Grobelny if (dbusCollectionFunction.empty()) 486479e899dSKrzysztof Grobelny { 487479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionFunction", 488479e899dSKrzysztof Grobelny *collectionFunction); 489479e899dSKrzysztof Grobelny return false; 490479e899dSKrzysztof Grobelny } 491479e899dSKrzysztof Grobelny metricArgs.collectionFunction = std::move(dbusCollectionFunction); 492479e899dSKrzysztof Grobelny } 493479e899dSKrzysztof Grobelny 494479e899dSKrzysztof Grobelny if (collectionTimeScopeStr) 495479e899dSKrzysztof Grobelny { 496479e899dSKrzysztof Grobelny std::string dbusCollectionTimeScope = 497479e899dSKrzysztof Grobelny toDbusCollectionTimeScope(*collectionTimeScopeStr); 498479e899dSKrzysztof Grobelny if (dbusCollectionTimeScope.empty()) 499479e899dSKrzysztof Grobelny { 500479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionTimeScope", 501479e899dSKrzysztof Grobelny *collectionTimeScopeStr); 502479e899dSKrzysztof Grobelny return false; 503479e899dSKrzysztof Grobelny } 504479e899dSKrzysztof Grobelny metricArgs.collectionTimeScope = std::move(dbusCollectionTimeScope); 505479e899dSKrzysztof Grobelny } 506479e899dSKrzysztof Grobelny 507479e899dSKrzysztof Grobelny if (collectionDurationStr) 508479e899dSKrzysztof Grobelny { 509479e899dSKrzysztof Grobelny std::optional<std::chrono::milliseconds> duration = 510479e899dSKrzysztof Grobelny time_utils::fromDurationString(*collectionDurationStr); 511479e899dSKrzysztof Grobelny 512479e899dSKrzysztof Grobelny if (!duration || duration->count() < 0) 513479e899dSKrzysztof Grobelny { 514479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "CollectionDuration", 515479e899dSKrzysztof Grobelny *collectionDurationStr); 516479e899dSKrzysztof Grobelny return false; 517479e899dSKrzysztof Grobelny } 518479e899dSKrzysztof Grobelny 519479e899dSKrzysztof Grobelny metricArgs.collectionDuration = 520479e899dSKrzysztof Grobelny static_cast<uint64_t>(duration->count()); 521479e899dSKrzysztof Grobelny } 522479e899dSKrzysztof Grobelny 523479e899dSKrzysztof Grobelny return true; 524479e899dSKrzysztof Grobelny } 525479e899dSKrzysztof Grobelny 526479e899dSKrzysztof Grobelny inline bool getUserMetrics(crow::Response& res, 527b14f357fSEd Tanous std::span<nlohmann::json::object_t> metrics, 528479e899dSKrzysztof Grobelny std::vector<AddReportArgs::MetricArgs>& result) 529479e899dSKrzysztof Grobelny { 530479e899dSKrzysztof Grobelny result.reserve(metrics.size()); 531479e899dSKrzysztof Grobelny 532b14f357fSEd Tanous for (nlohmann::json::object_t& m : metrics) 533479e899dSKrzysztof Grobelny { 534479e899dSKrzysztof Grobelny AddReportArgs::MetricArgs metricArgs; 535479e899dSKrzysztof Grobelny 536479e899dSKrzysztof Grobelny if (!getUserMetric(res, m, metricArgs)) 537479e899dSKrzysztof Grobelny { 538479e899dSKrzysztof Grobelny return false; 539479e899dSKrzysztof Grobelny } 540479e899dSKrzysztof Grobelny 541479e899dSKrzysztof Grobelny result.emplace_back(std::move(metricArgs)); 542479e899dSKrzysztof Grobelny } 543479e899dSKrzysztof Grobelny 544479e899dSKrzysztof Grobelny return true; 545479e899dSKrzysztof Grobelny } 546479e899dSKrzysztof Grobelny 5474dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req, 5484dbb8aeaSWludzik, Jozef AddReportArgs& args) 5494dbb8aeaSWludzik, Jozef { 550479e899dSKrzysztof Grobelny std::optional<std::string> id; 551479e899dSKrzysztof Grobelny std::optional<std::string> name; 552479e899dSKrzysztof Grobelny std::optional<std::string> reportingTypeStr; 553479e899dSKrzysztof Grobelny std::optional<std::string> reportUpdatesStr; 554479e899dSKrzysztof Grobelny std::optional<uint64_t> appendLimit; 555479e899dSKrzysztof Grobelny std::optional<bool> metricReportDefinitionEnabled; 556b14f357fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> metrics; 557479e899dSKrzysztof Grobelny std::optional<std::vector<std::string>> reportActionsStr; 558b14f357fSEd Tanous std::optional<std::string> scheduleDurationStr; 559479e899dSKrzysztof Grobelny 560afc474aeSMyung Bae if (!json_util::readJsonPatch( // 561afc474aeSMyung Bae req, res, // 562afc474aeSMyung Bae "AppendLimit", appendLimit, // 563afc474aeSMyung Bae "Id", id, // 564afc474aeSMyung Bae "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, // 565afc474aeSMyung Bae "MetricReportDefinitionType", reportingTypeStr, // 566afc474aeSMyung Bae "Metrics", metrics, // 567afc474aeSMyung Bae "Name", name, // 568afc474aeSMyung Bae "ReportActions", reportActionsStr, // 569afc474aeSMyung Bae "ReportUpdates", reportUpdatesStr, // 570afc474aeSMyung Bae "Schedule/RecurrenceInterval", scheduleDurationStr // 571afc474aeSMyung Bae )) 5724dbb8aeaSWludzik, Jozef { 5734dbb8aeaSWludzik, Jozef return false; 5744dbb8aeaSWludzik, Jozef } 5754dbb8aeaSWludzik, Jozef 576479e899dSKrzysztof Grobelny if (id) 577479e899dSKrzysztof Grobelny { 578479e899dSKrzysztof Grobelny constexpr const char* allowedCharactersInId = 5794dbb8aeaSWludzik, Jozef "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 580479e899dSKrzysztof Grobelny if (id->empty() || 581479e899dSKrzysztof Grobelny id->find_first_not_of(allowedCharactersInId) != std::string::npos) 5824dbb8aeaSWludzik, Jozef { 583479e899dSKrzysztof Grobelny messages::propertyValueIncorrect(res, "Id", *id); 5844dbb8aeaSWludzik, Jozef return false; 5854dbb8aeaSWludzik, Jozef } 586479e899dSKrzysztof Grobelny args.id = *id; 587479e899dSKrzysztof Grobelny } 5884dbb8aeaSWludzik, Jozef 589479e899dSKrzysztof Grobelny if (name) 5904dbb8aeaSWludzik, Jozef { 591479e899dSKrzysztof Grobelny args.name = *name; 592479e899dSKrzysztof Grobelny } 593479e899dSKrzysztof Grobelny 594479e899dSKrzysztof Grobelny if (reportingTypeStr) 595479e899dSKrzysztof Grobelny { 596479e899dSKrzysztof Grobelny std::string dbusReportingType = toDbusReportingType(*reportingTypeStr); 597479e899dSKrzysztof Grobelny if (dbusReportingType.empty()) 598479e899dSKrzysztof Grobelny { 599479e899dSKrzysztof Grobelny messages::propertyValueNotInList(res, *reportingTypeStr, 6004dbb8aeaSWludzik, Jozef "MetricReportDefinitionType"); 6014dbb8aeaSWludzik, Jozef return false; 6024dbb8aeaSWludzik, Jozef } 603761cdfa5SEd Tanous args.reportingType = std::move(dbusReportingType); 604479e899dSKrzysztof Grobelny } 6054dbb8aeaSWludzik, Jozef 606479e899dSKrzysztof Grobelny if (reportUpdatesStr) 607479e899dSKrzysztof Grobelny { 608479e899dSKrzysztof Grobelny std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr); 609479e899dSKrzysztof Grobelny if (dbusReportUpdates.empty()) 610479e899dSKrzysztof Grobelny { 611479e899dSKrzysztof Grobelny messages::propertyValueNotInList(res, *reportUpdatesStr, 612479e899dSKrzysztof Grobelny "ReportUpdates"); 613479e899dSKrzysztof Grobelny return false; 614479e899dSKrzysztof Grobelny } 615761cdfa5SEd Tanous args.reportUpdates = std::move(dbusReportUpdates); 616479e899dSKrzysztof Grobelny } 617479e899dSKrzysztof Grobelny 618479e899dSKrzysztof Grobelny if (appendLimit) 619479e899dSKrzysztof Grobelny { 620479e899dSKrzysztof Grobelny args.appendLimit = *appendLimit; 621479e899dSKrzysztof Grobelny } 622479e899dSKrzysztof Grobelny 623479e899dSKrzysztof Grobelny if (metricReportDefinitionEnabled) 624479e899dSKrzysztof Grobelny { 625479e899dSKrzysztof Grobelny args.metricReportDefinitionEnabled = *metricReportDefinitionEnabled; 626479e899dSKrzysztof Grobelny } 627479e899dSKrzysztof Grobelny 628479e899dSKrzysztof Grobelny if (reportActionsStr) 629479e899dSKrzysztof Grobelny { 6309e6c388aSLukasz Kazmierczak if (!toDbusReportActions(res, *reportActionsStr, args.reportActions)) 6314dbb8aeaSWludzik, Jozef { 6324dbb8aeaSWludzik, Jozef return false; 6334dbb8aeaSWludzik, Jozef } 634479e899dSKrzysztof Grobelny } 6354dbb8aeaSWludzik, Jozef 636479e899dSKrzysztof Grobelny if (reportingTypeStr == "Periodic") 6374dbb8aeaSWludzik, Jozef { 638b14f357fSEd Tanous if (!scheduleDurationStr) 6394dbb8aeaSWludzik, Jozef { 6404dbb8aeaSWludzik, Jozef messages::createFailedMissingReqProperties(res, "Schedule"); 6414dbb8aeaSWludzik, Jozef return false; 6424dbb8aeaSWludzik, Jozef } 6434dbb8aeaSWludzik, Jozef 6444dbb8aeaSWludzik, Jozef std::optional<std::chrono::milliseconds> durationNum = 645b14f357fSEd Tanous time_utils::fromDurationString(*scheduleDurationStr); 646479e899dSKrzysztof Grobelny if (!durationNum || durationNum->count() < 0) 6474dbb8aeaSWludzik, Jozef { 6484dbb8aeaSWludzik, Jozef messages::propertyValueIncorrect(res, "RecurrenceInterval", 649b14f357fSEd Tanous *scheduleDurationStr); 6504dbb8aeaSWludzik, Jozef return false; 6514dbb8aeaSWludzik, Jozef } 6524dbb8aeaSWludzik, Jozef args.interval = static_cast<uint64_t>(durationNum->count()); 6534dbb8aeaSWludzik, Jozef } 6544dbb8aeaSWludzik, Jozef 655479e899dSKrzysztof Grobelny if (metrics) 6564dbb8aeaSWludzik, Jozef { 657479e899dSKrzysztof Grobelny if (!getUserMetrics(res, *metrics, args.metrics)) 6584dbb8aeaSWludzik, Jozef { 6594dbb8aeaSWludzik, Jozef return false; 6604dbb8aeaSWludzik, Jozef } 6614dbb8aeaSWludzik, Jozef } 6624dbb8aeaSWludzik, Jozef 6634dbb8aeaSWludzik, Jozef return true; 6644dbb8aeaSWludzik, Jozef } 6654dbb8aeaSWludzik, Jozef 666ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics( 6678d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 668479e899dSKrzysztof Grobelny std::span<const AddReportArgs::MetricArgs> metrics, 6694dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>>& matched) 6704dbb8aeaSWludzik, Jozef { 671ca1600c1SSzymon Dompke for (const auto& metric : metrics) 6724dbb8aeaSWludzik, Jozef { 673479e899dSKrzysztof Grobelny std::optional<IncorrectMetricUri> error = 674479e899dSKrzysztof Grobelny getChassisSensorNode(metric.uris, matched); 675ca1600c1SSzymon Dompke if (error) 6764dbb8aeaSWludzik, Jozef { 677bd79bce8SPatrick Williams messages::propertyValueIncorrect( 678bd79bce8SPatrick Williams asyncResp->res, error->uri, 679bd79bce8SPatrick Williams "MetricProperties/" + std::to_string(error->index)); 6804dbb8aeaSWludzik, Jozef return false; 6814dbb8aeaSWludzik, Jozef } 6824dbb8aeaSWludzik, Jozef } 6834dbb8aeaSWludzik, Jozef return true; 6844dbb8aeaSWludzik, Jozef } 6854dbb8aeaSWludzik, Jozef 686ba498310SKrzysztof Grobelny inline std::string toRedfishProperty(std::string_view dbusMessage) 687ba498310SKrzysztof Grobelny { 688ba498310SKrzysztof Grobelny if (dbusMessage == "Id") 689ba498310SKrzysztof Grobelny { 690ba498310SKrzysztof Grobelny return "Id"; 691ba498310SKrzysztof Grobelny } 692ba498310SKrzysztof Grobelny if (dbusMessage == "Name") 693ba498310SKrzysztof Grobelny { 694ba498310SKrzysztof Grobelny return "Name"; 695ba498310SKrzysztof Grobelny } 696ba498310SKrzysztof Grobelny if (dbusMessage == "ReportingType") 697ba498310SKrzysztof Grobelny { 698ba498310SKrzysztof Grobelny return "MetricReportDefinitionType"; 699ba498310SKrzysztof Grobelny } 700ba498310SKrzysztof Grobelny if (dbusMessage == "AppendLimit") 701ba498310SKrzysztof Grobelny { 702ba498310SKrzysztof Grobelny return "AppendLimit"; 703ba498310SKrzysztof Grobelny } 704ba498310SKrzysztof Grobelny if (dbusMessage == "ReportActions") 705ba498310SKrzysztof Grobelny { 706ba498310SKrzysztof Grobelny return "ReportActions"; 707ba498310SKrzysztof Grobelny } 708ba498310SKrzysztof Grobelny if (dbusMessage == "Interval") 709ba498310SKrzysztof Grobelny { 710ba498310SKrzysztof Grobelny return "RecurrenceInterval"; 711ba498310SKrzysztof Grobelny } 712ba498310SKrzysztof Grobelny if (dbusMessage == "ReportUpdates") 713ba498310SKrzysztof Grobelny { 714ba498310SKrzysztof Grobelny return "ReportUpdates"; 715ba498310SKrzysztof Grobelny } 716ba498310SKrzysztof Grobelny if (dbusMessage == "ReadingParameters") 717ba498310SKrzysztof Grobelny { 718ba498310SKrzysztof Grobelny return "Metrics"; 719ba498310SKrzysztof Grobelny } 720ba498310SKrzysztof Grobelny return ""; 721ba498310SKrzysztof Grobelny } 722ba498310SKrzysztof Grobelny 723ba498310SKrzysztof Grobelny inline bool handleParamError(crow::Response& res, const char* errorMessage, 724ba498310SKrzysztof Grobelny std::string_view key) 725ba498310SKrzysztof Grobelny { 726ba498310SKrzysztof Grobelny if (errorMessage == nullptr) 727ba498310SKrzysztof Grobelny { 728ba498310SKrzysztof Grobelny BMCWEB_LOG_ERROR("errorMessage was null"); 729ba498310SKrzysztof Grobelny return true; 730ba498310SKrzysztof Grobelny } 731ba498310SKrzysztof Grobelny std::string_view errorMessageSv(errorMessage); 732ba498310SKrzysztof Grobelny if (errorMessageSv.starts_with(key)) 733ba498310SKrzysztof Grobelny { 734ba498310SKrzysztof Grobelny std::string redfishProperty = toRedfishProperty(key); 735ba498310SKrzysztof Grobelny if (redfishProperty.empty()) 736ba498310SKrzysztof Grobelny { 737ba498310SKrzysztof Grobelny // Getting here means most possibly that toRedfishProperty has 738ba498310SKrzysztof Grobelny // incomplete implementation. Return internal error for now. 739ba498310SKrzysztof Grobelny BMCWEB_LOG_ERROR("{} has no corresponding Redfish property", key); 740ba498310SKrzysztof Grobelny messages::internalError(res); 741ba498310SKrzysztof Grobelny return false; 742ba498310SKrzysztof Grobelny } 743ba498310SKrzysztof Grobelny messages::propertyValueError(res, redfishProperty); 744ba498310SKrzysztof Grobelny return false; 745ba498310SKrzysztof Grobelny } 746ba498310SKrzysztof Grobelny 747ba498310SKrzysztof Grobelny return true; 748ba498310SKrzysztof Grobelny } 749ba498310SKrzysztof Grobelny 750ba498310SKrzysztof Grobelny inline void afterAddReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 751ba498310SKrzysztof Grobelny const AddReportArgs& args, 752ba498310SKrzysztof Grobelny const boost::system::error_code& ec, 753ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) 754ba498310SKrzysztof Grobelny { 755ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 756ba498310SKrzysztof Grobelny { 757ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 758ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 759ba498310SKrzysztof Grobelny { 760ba498310SKrzysztof Grobelny for (const auto& arg : 761ba498310SKrzysztof Grobelny {"Id", "Name", "ReportingType", "AppendLimit", "ReportActions", 762ba498310SKrzysztof Grobelny "Interval", "ReportUpdates", "ReadingParameters"}) 763ba498310SKrzysztof Grobelny { 764ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 765ba498310SKrzysztof Grobelny arg)) 766ba498310SKrzysztof Grobelny { 767ba498310SKrzysztof Grobelny return; 768ba498310SKrzysztof Grobelny } 769ba498310SKrzysztof Grobelny } 770ba498310SKrzysztof Grobelny } 771ba498310SKrzysztof Grobelny } 772*2169e896SMichal Orzel if (!formatMessageOnError(asyncResp->res, args.id, ec)) 773ba498310SKrzysztof Grobelny { 774*2169e896SMichal Orzel messages::created(asyncResp->res); 775ba498310SKrzysztof Grobelny } 776ba498310SKrzysztof Grobelny } 777ba498310SKrzysztof Grobelny 7784dbb8aeaSWludzik, Jozef class AddReport 7794dbb8aeaSWludzik, Jozef { 7804dbb8aeaSWludzik, Jozef public: 781891eaa7cSEd Tanous AddReport(AddReportArgs&& argsIn, 7828a592810SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 783bd79bce8SPatrick Williams asyncResp(asyncRespIn), args(std::move(argsIn)) 7844dbb8aeaSWludzik, Jozef {} 785479e899dSKrzysztof Grobelny 7864dbb8aeaSWludzik, Jozef ~AddReport() 7874dbb8aeaSWludzik, Jozef { 788479e899dSKrzysztof Grobelny boost::asio::post(crow::connections::systemBus->get_io_context(), 789479e899dSKrzysztof Grobelny std::bind_front(&performAddReport, asyncResp, args, 790479e899dSKrzysztof Grobelny std::move(uriToDbus))); 791479e899dSKrzysztof Grobelny } 792479e899dSKrzysztof Grobelny 793479e899dSKrzysztof Grobelny static void performAddReport( 794479e899dSKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 795479e899dSKrzysztof Grobelny const AddReportArgs& args, 796479e899dSKrzysztof Grobelny const boost::container::flat_map<std::string, std::string>& uriToDbus) 797479e899dSKrzysztof Grobelny { 7984dbb8aeaSWludzik, Jozef if (asyncResp->res.result() != boost::beast::http::status::ok) 7994dbb8aeaSWludzik, Jozef { 8004dbb8aeaSWludzik, Jozef return; 8014dbb8aeaSWludzik, Jozef } 8024dbb8aeaSWludzik, Jozef 8034dbb8aeaSWludzik, Jozef telemetry::ReadingParameters readingParams; 8044dbb8aeaSWludzik, Jozef readingParams.reserve(args.metrics.size()); 8054dbb8aeaSWludzik, Jozef 806479e899dSKrzysztof Grobelny for (const auto& metric : args.metrics) 8074dbb8aeaSWludzik, Jozef { 808479e899dSKrzysztof Grobelny std::vector< 809479e899dSKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>> 810479e899dSKrzysztof Grobelny sensorParams; 811479e899dSKrzysztof Grobelny sensorParams.reserve(metric.uris.size()); 812479e899dSKrzysztof Grobelny 813479e899dSKrzysztof Grobelny for (size_t i = 0; i < metric.uris.size(); i++) 8144dbb8aeaSWludzik, Jozef { 815479e899dSKrzysztof Grobelny const std::string& uri = metric.uris[i]; 8164dbb8aeaSWludzik, Jozef auto el = uriToDbus.find(uri); 8174dbb8aeaSWludzik, Jozef if (el == uriToDbus.end()) 8184dbb8aeaSWludzik, Jozef { 81962598e31SEd Tanous BMCWEB_LOG_ERROR( 82062598e31SEd Tanous "Failed to find DBus sensor corresponding to URI {}", 82162598e31SEd Tanous uri); 822bd79bce8SPatrick Williams messages::propertyValueNotInList( 823bd79bce8SPatrick Williams asyncResp->res, uri, 824bd79bce8SPatrick Williams "MetricProperties/" + std::to_string(i)); 8254dbb8aeaSWludzik, Jozef return; 8264dbb8aeaSWludzik, Jozef } 8274dbb8aeaSWludzik, Jozef 8284dbb8aeaSWludzik, Jozef const std::string& dbusPath = el->second; 829479e899dSKrzysztof Grobelny sensorParams.emplace_back(dbusPath, uri); 8304dbb8aeaSWludzik, Jozef } 831479e899dSKrzysztof Grobelny 832479e899dSKrzysztof Grobelny readingParams.emplace_back( 833479e899dSKrzysztof Grobelny std::move(sensorParams), metric.collectionFunction, 834479e899dSKrzysztof Grobelny metric.collectionTimeScope, metric.collectionDuration); 8354dbb8aeaSWludzik, Jozef } 836177612aaSEd Tanous dbus::utility::async_method_call( 837177612aaSEd Tanous asyncResp, 838ba498310SKrzysztof Grobelny [asyncResp, args](const boost::system::error_code& ec, 839ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg, 840ba498310SKrzysztof Grobelny const std::string& /*arg1*/) { 841ba498310SKrzysztof Grobelny afterAddReport(asyncResp, args, ec, msg); 8424dbb8aeaSWludzik, Jozef }, 8434dbb8aeaSWludzik, Jozef telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", 8444dbb8aeaSWludzik, Jozef "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", 845479e899dSKrzysztof Grobelny "TelemetryService/" + args.id, args.name, args.reportingType, 846479e899dSKrzysztof Grobelny args.reportUpdates, args.appendLimit, args.reportActions, 847479e899dSKrzysztof Grobelny args.interval, readingParams, args.metricReportDefinitionEnabled); 8484dbb8aeaSWludzik, Jozef } 8494dbb8aeaSWludzik, Jozef 850ecd6a3a2SEd Tanous AddReport(const AddReport&) = delete; 851ecd6a3a2SEd Tanous AddReport(AddReport&&) = delete; 852ecd6a3a2SEd Tanous AddReport& operator=(const AddReport&) = delete; 853ecd6a3a2SEd Tanous AddReport& operator=(AddReport&&) = delete; 854ecd6a3a2SEd Tanous 855fe04d49cSNan Zhou void insert(const std::map<std::string, std::string>& el) 8564dbb8aeaSWludzik, Jozef { 8574dbb8aeaSWludzik, Jozef uriToDbus.insert(el.begin(), el.end()); 8584dbb8aeaSWludzik, Jozef } 8594dbb8aeaSWludzik, Jozef 8604dbb8aeaSWludzik, Jozef private: 861ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 8624dbb8aeaSWludzik, Jozef AddReportArgs args; 86347f2934cSEd Tanous boost::container::flat_map<std::string, std::string> uriToDbus; 8644dbb8aeaSWludzik, Jozef }; 8659e6c388aSLukasz Kazmierczak 866ba498310SKrzysztof Grobelny inline std::optional< 867ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>>> 868ba498310SKrzysztof Grobelny sensorPathToUri( 869ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 870ba498310SKrzysztof Grobelny std::span<const std::string> uris, 871ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 872ba498310SKrzysztof Grobelny { 873ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>> 874ba498310SKrzysztof Grobelny result; 875ba498310SKrzysztof Grobelny 876ba498310SKrzysztof Grobelny for (const std::string& uri : uris) 877ba498310SKrzysztof Grobelny { 878ba498310SKrzysztof Grobelny auto it = metricPropertyToDbusPaths.find(uri); 879ba498310SKrzysztof Grobelny if (it == metricPropertyToDbusPaths.end()) 880ba498310SKrzysztof Grobelny { 881ba498310SKrzysztof Grobelny messages::propertyValueNotInList(asyncResp->res, uri, 882ba498310SKrzysztof Grobelny "MetricProperties"); 883ba498310SKrzysztof Grobelny return {}; 884ba498310SKrzysztof Grobelny } 885ba498310SKrzysztof Grobelny result.emplace_back(it->second, uri); 886ba498310SKrzysztof Grobelny } 887ba498310SKrzysztof Grobelny 888ba498310SKrzysztof Grobelny return result; 889ba498310SKrzysztof Grobelny } 890ba498310SKrzysztof Grobelny 891ba498310SKrzysztof Grobelny inline void afterSetReadingParams( 892ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 893ba498310SKrzysztof Grobelny const std::string& reportId, const boost::system::error_code& ec, 894ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) 895ba498310SKrzysztof Grobelny { 896ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 897ba498310SKrzysztof Grobelny { 898ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 899ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 900ba498310SKrzysztof Grobelny { 901ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReadingParameters"}) 902ba498310SKrzysztof Grobelny { 903ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 904ba498310SKrzysztof Grobelny arg)) 905ba498310SKrzysztof Grobelny { 906ba498310SKrzysztof Grobelny return; 907ba498310SKrzysztof Grobelny } 908ba498310SKrzysztof Grobelny } 909ba498310SKrzysztof Grobelny } 910ba498310SKrzysztof Grobelny } 911*2169e896SMichal Orzel if (!formatMessageOnError(asyncResp->res, reportId, ec)) 912ba498310SKrzysztof Grobelny { 913*2169e896SMichal Orzel messages::success(asyncResp->res); 914ba498310SKrzysztof Grobelny } 915ba498310SKrzysztof Grobelny } 916ba498310SKrzysztof Grobelny 917ba498310SKrzysztof Grobelny inline void setReadingParams( 918ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 919ba498310SKrzysztof Grobelny const std::string& reportId, ReadingParameters readingParams, 920ba498310SKrzysztof Grobelny const std::vector<std::vector<std::string>>& readingParamsUris, 921ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 922ba498310SKrzysztof Grobelny { 923ba498310SKrzysztof Grobelny if (asyncResp->res.result() != boost::beast::http::status::ok) 924ba498310SKrzysztof Grobelny { 925ba498310SKrzysztof Grobelny return; 926ba498310SKrzysztof Grobelny } 927ba498310SKrzysztof Grobelny 928ba498310SKrzysztof Grobelny for (size_t index = 0; index < readingParamsUris.size(); ++index) 929ba498310SKrzysztof Grobelny { 930ba498310SKrzysztof Grobelny std::span<const std::string> newUris = readingParamsUris[index]; 931ba498310SKrzysztof Grobelny 932ba498310SKrzysztof Grobelny const std::optional<std::vector< 933ba498310SKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>>> 934ba498310SKrzysztof Grobelny readingParam = 935ba498310SKrzysztof Grobelny sensorPathToUri(asyncResp, newUris, metricPropertyToDbusPaths); 936ba498310SKrzysztof Grobelny 937ba498310SKrzysztof Grobelny if (!readingParam) 938ba498310SKrzysztof Grobelny { 939ba498310SKrzysztof Grobelny return; 940ba498310SKrzysztof Grobelny } 941ba498310SKrzysztof Grobelny 942ba498310SKrzysztof Grobelny for (const std::tuple<sdbusplus::message::object_path, std::string>& 943ba498310SKrzysztof Grobelny value : *readingParam) 944ba498310SKrzysztof Grobelny { 945ba498310SKrzysztof Grobelny std::get<0>(readingParams[index]).emplace_back(value); 946ba498310SKrzysztof Grobelny } 947ba498310SKrzysztof Grobelny } 948ba498310SKrzysztof Grobelny 949177612aaSEd Tanous dbus::utility::async_method_call( 950177612aaSEd Tanous asyncResp, 951ba498310SKrzysztof Grobelny [asyncResp, reportId](const boost::system::error_code& ec, 952ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 953ba498310SKrzysztof Grobelny afterSetReadingParams(asyncResp, reportId, ec, msg); 954ba498310SKrzysztof Grobelny }, 955ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry", getDbusReportPath(reportId), 956ba498310SKrzysztof Grobelny "org.freedesktop.DBus.Properties", "Set", 957ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report", "ReadingParameters", 958ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{readingParams}); 959ba498310SKrzysztof Grobelny } 960ba498310SKrzysztof Grobelny 9619e6c388aSLukasz Kazmierczak class UpdateMetrics 9629e6c388aSLukasz Kazmierczak { 9639e6c388aSLukasz Kazmierczak public: 9649e6c388aSLukasz Kazmierczak UpdateMetrics(std::string_view idIn, 9659e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 966bd79bce8SPatrick Williams id(idIn), asyncResp(asyncRespIn) 9679e6c388aSLukasz Kazmierczak {} 9689e6c388aSLukasz Kazmierczak 9699e6c388aSLukasz Kazmierczak ~UpdateMetrics() 9709e6c388aSLukasz Kazmierczak { 971ba498310SKrzysztof Grobelny boost::asio::post( 972ba498310SKrzysztof Grobelny crow::connections::systemBus->get_io_context(), 973ba498310SKrzysztof Grobelny std::bind_front(&setReadingParams, asyncResp, id, 974ba498310SKrzysztof Grobelny std::move(readingParams), readingParamsUris, 975ba498310SKrzysztof Grobelny metricPropertyToDbusPaths)); 9769e6c388aSLukasz Kazmierczak } 9779e6c388aSLukasz Kazmierczak 9789e6c388aSLukasz Kazmierczak UpdateMetrics(const UpdateMetrics&) = delete; 9799e6c388aSLukasz Kazmierczak UpdateMetrics(UpdateMetrics&&) = delete; 9809e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(const UpdateMetrics&) = delete; 9819e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(UpdateMetrics&&) = delete; 9829e6c388aSLukasz Kazmierczak 9839e6c388aSLukasz Kazmierczak std::string id; 9849e6c388aSLukasz Kazmierczak std::map<std::string, std::string> metricPropertyToDbusPaths; 9859e6c388aSLukasz Kazmierczak 9869e6c388aSLukasz Kazmierczak void insert(const std::map<std::string, std::string>& 9879e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths) 9889e6c388aSLukasz Kazmierczak { 9899e6c388aSLukasz Kazmierczak metricPropertyToDbusPaths.insert( 9909e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.begin(), 9919e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.end()); 9929e6c388aSLukasz Kazmierczak } 9939e6c388aSLukasz Kazmierczak 994bd79bce8SPatrick Williams void emplace( 995bd79bce8SPatrick Williams std::span< 996bd79bce8SPatrick Williams const std::tuple<sdbusplus::message::object_path, std::string>> 9979e6c388aSLukasz Kazmierczak pathAndUri, 9989e6c388aSLukasz Kazmierczak const AddReportArgs::MetricArgs& metricArgs) 9999e6c388aSLukasz Kazmierczak { 10009e6c388aSLukasz Kazmierczak readingParamsUris.emplace_back(metricArgs.uris); 10019e6c388aSLukasz Kazmierczak readingParams.emplace_back( 10029e6c388aSLukasz Kazmierczak std::vector(pathAndUri.begin(), pathAndUri.end()), 10039e6c388aSLukasz Kazmierczak metricArgs.collectionFunction, metricArgs.collectionTimeScope, 10049e6c388aSLukasz Kazmierczak metricArgs.collectionDuration); 10059e6c388aSLukasz Kazmierczak } 10069e6c388aSLukasz Kazmierczak 10079e6c388aSLukasz Kazmierczak private: 10089e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 10099e6c388aSLukasz Kazmierczak std::vector<std::vector<std::string>> readingParamsUris; 101047f2934cSEd Tanous ReadingParameters readingParams; 10119e6c388aSLukasz Kazmierczak }; 10129e6c388aSLukasz Kazmierczak 1013504af5a0SPatrick Williams inline void setReportEnabled( 1014504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1015504af5a0SPatrick Williams bool enabled) 10169e6c388aSLukasz Kazmierczak { 1017177612aaSEd Tanous dbus::utility::async_method_call( 1018177612aaSEd Tanous asyncResp, 10199e6c388aSLukasz Kazmierczak [asyncResp, id = std::string(id)](const boost::system::error_code& ec) { 1020*2169e896SMichal Orzel formatMessageOnError(asyncResp->res, id, ec); 10219e6c388aSLukasz Kazmierczak }, 10229e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 10239e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 10249e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "Enabled", 10259e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{enabled}); 10269e6c388aSLukasz Kazmierczak } 10279e6c388aSLukasz Kazmierczak 1028ba498310SKrzysztof Grobelny inline void afterSetReportingProperties( 1029ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1030ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1031ba498310SKrzysztof Grobelny { 1032ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1033ba498310SKrzysztof Grobelny { 1034ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1035ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1036ba498310SKrzysztof Grobelny { 1037ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportingType", "Interval"}) 1038ba498310SKrzysztof Grobelny { 1039ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1040ba498310SKrzysztof Grobelny arg)) 1041ba498310SKrzysztof Grobelny { 1042ba498310SKrzysztof Grobelny return; 1043ba498310SKrzysztof Grobelny } 1044ba498310SKrzysztof Grobelny } 1045ba498310SKrzysztof Grobelny } 1046ba498310SKrzysztof Grobelny } 1047*2169e896SMichal Orzel if (!formatMessageOnError(asyncResp->res, id, ec)) 1048ba498310SKrzysztof Grobelny { 1049*2169e896SMichal Orzel asyncResp->res.result(boost::beast::http::status::no_content); 1050ba498310SKrzysztof Grobelny } 1051ba498310SKrzysztof Grobelny } 1052ba498310SKrzysztof Grobelny 10539e6c388aSLukasz Kazmierczak inline void setReportTypeAndInterval( 10549e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1055b4361d63SEd Tanous const std::optional<std::string>& reportingType, 1056b4361d63SEd Tanous const std::optional<std::string>& recurrenceIntervalStr) 10579e6c388aSLukasz Kazmierczak { 1058b4361d63SEd Tanous std::string dbusReportingType; 1059b4361d63SEd Tanous if (reportingType) 1060b4361d63SEd Tanous { 1061b4361d63SEd Tanous dbusReportingType = toDbusReportingType(*reportingType); 1062b4361d63SEd Tanous if (dbusReportingType.empty()) 1063b4361d63SEd Tanous { 1064b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, *reportingType, 1065b4361d63SEd Tanous "MetricReportDefinitionType"); 1066b4361d63SEd Tanous return; 1067b4361d63SEd Tanous } 1068b4361d63SEd Tanous } 1069b4361d63SEd Tanous 1070b4361d63SEd Tanous uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max(); 1071b4361d63SEd Tanous if (recurrenceIntervalStr) 1072b4361d63SEd Tanous { 1073b4361d63SEd Tanous std::optional<std::chrono::milliseconds> durationNum = 1074b4361d63SEd Tanous time_utils::fromDurationString(*recurrenceIntervalStr); 1075b4361d63SEd Tanous if (!durationNum || durationNum->count() < 0) 1076b4361d63SEd Tanous { 1077b4361d63SEd Tanous messages::propertyValueIncorrect( 1078b4361d63SEd Tanous asyncResp->res, "RecurrenceInterval", *recurrenceIntervalStr); 1079b4361d63SEd Tanous return; 1080b4361d63SEd Tanous } 1081b4361d63SEd Tanous 1082b4361d63SEd Tanous recurrenceInterval = static_cast<uint64_t>(durationNum->count()); 1083b4361d63SEd Tanous } 1084b4361d63SEd Tanous 1085177612aaSEd Tanous dbus::utility::async_method_call( 1086177612aaSEd Tanous asyncResp, 1087ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1088ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1089ba498310SKrzysztof Grobelny afterSetReportingProperties(asyncResp, id, ec, msg); 10909e6c388aSLukasz Kazmierczak }, 10919e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 10929e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "SetReportingProperties", 1093b4361d63SEd Tanous dbusReportingType, recurrenceInterval); 10949e6c388aSLukasz Kazmierczak } 10959e6c388aSLukasz Kazmierczak 1096ba498310SKrzysztof Grobelny inline void afterSetReportUpdates( 1097ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1098ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1099ba498310SKrzysztof Grobelny { 1100ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1101ba498310SKrzysztof Grobelny { 1102ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1103ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1104ba498310SKrzysztof Grobelny { 1105ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportUpdates"}) 1106ba498310SKrzysztof Grobelny { 1107ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1108ba498310SKrzysztof Grobelny arg)) 1109ba498310SKrzysztof Grobelny { 1110ba498310SKrzysztof Grobelny return; 1111ba498310SKrzysztof Grobelny } 1112ba498310SKrzysztof Grobelny } 1113ba498310SKrzysztof Grobelny } 1114ba498310SKrzysztof Grobelny } 1115*2169e896SMichal Orzel if (!formatMessageOnError(asyncResp->res, id, ec)) 1116ba498310SKrzysztof Grobelny { 1117*2169e896SMichal Orzel asyncResp->res.result(boost::beast::http::status::no_content); 1118ba498310SKrzysztof Grobelny } 1119ba498310SKrzysztof Grobelny } 1120ba498310SKrzysztof Grobelny 1121504af5a0SPatrick Williams inline void setReportUpdates( 1122504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1123504af5a0SPatrick Williams const std::string& reportUpdates) 11249e6c388aSLukasz Kazmierczak { 1125b4361d63SEd Tanous std::string dbusReportUpdates = toDbusReportUpdates(reportUpdates); 1126b4361d63SEd Tanous if (dbusReportUpdates.empty()) 1127b4361d63SEd Tanous { 1128b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, reportUpdates, 1129b4361d63SEd Tanous "ReportUpdates"); 1130b4361d63SEd Tanous return; 1131b4361d63SEd Tanous } 1132177612aaSEd Tanous dbus::utility::async_method_call( 1133177612aaSEd Tanous asyncResp, 1134ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1135ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1136ba498310SKrzysztof Grobelny afterSetReportUpdates(asyncResp, id, ec, msg); 11379e6c388aSLukasz Kazmierczak }, 11389e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11399e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 11409e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportUpdates", 1141ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{dbusReportUpdates}); 1142ba498310SKrzysztof Grobelny } 1143ba498310SKrzysztof Grobelny 1144ba498310SKrzysztof Grobelny inline void afterSetReportActions( 1145ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1146ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1147ba498310SKrzysztof Grobelny { 1148ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1149ba498310SKrzysztof Grobelny { 1150ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1151ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1152ba498310SKrzysztof Grobelny { 1153ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportActions"}) 1154ba498310SKrzysztof Grobelny { 1155ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1156ba498310SKrzysztof Grobelny arg)) 1157ba498310SKrzysztof Grobelny { 1158ba498310SKrzysztof Grobelny return; 1159ba498310SKrzysztof Grobelny } 1160ba498310SKrzysztof Grobelny } 1161ba498310SKrzysztof Grobelny } 1162ba498310SKrzysztof Grobelny } 1163ba498310SKrzysztof Grobelny 1164*2169e896SMichal Orzel if (!formatMessageOnError(asyncResp->res, id, ec)) 1165ba498310SKrzysztof Grobelny { 1166*2169e896SMichal Orzel asyncResp->res.result(boost::beast::http::status::no_content); 1167ba498310SKrzysztof Grobelny } 11689e6c388aSLukasz Kazmierczak } 11699e6c388aSLukasz Kazmierczak 1170bd79bce8SPatrick Williams inline void setReportActions( 1171bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1172b4361d63SEd Tanous const std::vector<std::string>& reportActions) 11739e6c388aSLukasz Kazmierczak { 1174b4361d63SEd Tanous std::vector<std::string> dbusReportActions; 1175b4361d63SEd Tanous if (!toDbusReportActions(asyncResp->res, reportActions, dbusReportActions)) 1176b4361d63SEd Tanous { 1177b4361d63SEd Tanous return; 1178b4361d63SEd Tanous } 1179b4361d63SEd Tanous 1180177612aaSEd Tanous dbus::utility::async_method_call( 1181177612aaSEd Tanous asyncResp, 1182ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1183ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1184ba498310SKrzysztof Grobelny afterSetReportActions(asyncResp, id, ec, msg); 11859e6c388aSLukasz Kazmierczak }, 11869e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11879e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 11889e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportActions", 11899e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{dbusReportActions}); 11909e6c388aSLukasz Kazmierczak } 11919e6c388aSLukasz Kazmierczak 1192bd79bce8SPatrick Williams inline void setReportMetrics( 1193bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1194a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>&& 1195a64919e8SBoleslaw Ogonczyk Makowski metrics) 11969e6c388aSLukasz Kazmierczak { 1197deae6a78SEd Tanous dbus::utility::getAllProperties( 1198deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1199deae6a78SEd Tanous telemetry::reportInterface, 1200ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id), redfishMetrics = std::move(metrics)]( 12019e6c388aSLukasz Kazmierczak boost::system::error_code ec, 12029e6c388aSLukasz Kazmierczak const dbus::utility::DBusPropertiesMap& properties) mutable { 1203*2169e896SMichal Orzel if (formatMessageOnError(asyncResp->res, id, ec)) 12049e6c388aSLukasz Kazmierczak { 12059e6c388aSLukasz Kazmierczak return; 12069e6c388aSLukasz Kazmierczak } 12079e6c388aSLukasz Kazmierczak 12089e6c388aSLukasz Kazmierczak ReadingParameters readingParams; 12099e6c388aSLukasz Kazmierczak 12109e6c388aSLukasz Kazmierczak const bool success = sdbusplus::unpackPropertiesNoThrow( 1211bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 1212bd79bce8SPatrick Williams "ReadingParameters", readingParams); 12139e6c388aSLukasz Kazmierczak 12149e6c388aSLukasz Kazmierczak if (!success) 12159e6c388aSLukasz Kazmierczak { 12169e6c388aSLukasz Kazmierczak messages::internalError(asyncResp->res); 12179e6c388aSLukasz Kazmierczak return; 12189e6c388aSLukasz Kazmierczak } 12199e6c388aSLukasz Kazmierczak 1220bd79bce8SPatrick Williams auto updateMetricsReq = 1221bd79bce8SPatrick Williams std::make_shared<UpdateMetrics>(id, asyncResp); 12229e6c388aSLukasz Kazmierczak 12239e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 12249e6c388aSLukasz Kazmierczak chassisSensors; 12259e6c388aSLukasz Kazmierczak 12269e6c388aSLukasz Kazmierczak size_t index = 0; 1227a64919e8SBoleslaw Ogonczyk Makowski for (std::variant<nlohmann::json::object_t, std::nullptr_t>& 1228a64919e8SBoleslaw Ogonczyk Makowski metricVariant : redfishMetrics) 12299e6c388aSLukasz Kazmierczak { 1230a64919e8SBoleslaw Ogonczyk Makowski nlohmann::json::object_t* metric = 1231a64919e8SBoleslaw Ogonczyk Makowski std::get_if<nlohmann::json::object_t>(&metricVariant); 1232a64919e8SBoleslaw Ogonczyk Makowski if (metric == nullptr) 1233a64919e8SBoleslaw Ogonczyk Makowski { 1234a64919e8SBoleslaw Ogonczyk Makowski index++; 1235a64919e8SBoleslaw Ogonczyk Makowski continue; 1236a64919e8SBoleslaw Ogonczyk Makowski } 1237a64919e8SBoleslaw Ogonczyk Makowski 12389e6c388aSLukasz Kazmierczak AddReportArgs::MetricArgs metricArgs; 12399e6c388aSLukasz Kazmierczak std::vector< 12409e6c388aSLukasz Kazmierczak std::tuple<sdbusplus::message::object_path, std::string>> 12419e6c388aSLukasz Kazmierczak pathAndUri; 12429e6c388aSLukasz Kazmierczak 12439e6c388aSLukasz Kazmierczak if (index < readingParams.size()) 12449e6c388aSLukasz Kazmierczak { 12459e6c388aSLukasz Kazmierczak const ReadingParameters::value_type& existing = 12469e6c388aSLukasz Kazmierczak readingParams[index]; 12479e6c388aSLukasz Kazmierczak 1248dac07cadSBoleslaw Ogonczyk Makowski if (metric->empty()) 1249dac07cadSBoleslaw Ogonczyk Makowski { 12509e6c388aSLukasz Kazmierczak pathAndUri = std::get<0>(existing); 1251dac07cadSBoleslaw Ogonczyk Makowski } 12529e6c388aSLukasz Kazmierczak metricArgs.collectionFunction = std::get<1>(existing); 12539e6c388aSLukasz Kazmierczak metricArgs.collectionTimeScope = std::get<2>(existing); 12549e6c388aSLukasz Kazmierczak metricArgs.collectionDuration = std::get<3>(existing); 12559e6c388aSLukasz Kazmierczak } 12569e6c388aSLukasz Kazmierczak 1257a64919e8SBoleslaw Ogonczyk Makowski if (!getUserMetric(asyncResp->res, *metric, metricArgs)) 12589e6c388aSLukasz Kazmierczak { 12599e6c388aSLukasz Kazmierczak return; 12609e6c388aSLukasz Kazmierczak } 12619e6c388aSLukasz Kazmierczak 12629e6c388aSLukasz Kazmierczak std::optional<IncorrectMetricUri> error = 12639e6c388aSLukasz Kazmierczak getChassisSensorNode(metricArgs.uris, chassisSensors); 12649e6c388aSLukasz Kazmierczak 12659e6c388aSLukasz Kazmierczak if (error) 12669e6c388aSLukasz Kazmierczak { 12679e6c388aSLukasz Kazmierczak messages::propertyValueIncorrect( 12689e6c388aSLukasz Kazmierczak asyncResp->res, error->uri, 12699e6c388aSLukasz Kazmierczak "MetricProperties/" + std::to_string(error->index)); 12709e6c388aSLukasz Kazmierczak return; 12719e6c388aSLukasz Kazmierczak } 12729e6c388aSLukasz Kazmierczak 12739e6c388aSLukasz Kazmierczak updateMetricsReq->emplace(pathAndUri, metricArgs); 12749e6c388aSLukasz Kazmierczak index++; 12759e6c388aSLukasz Kazmierczak } 12769e6c388aSLukasz Kazmierczak 12779e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 12789e6c388aSLukasz Kazmierczak { 12799e6c388aSLukasz Kazmierczak retrieveUriToDbusMap( 12809e6c388aSLukasz Kazmierczak chassis, sensorType, 12819e6c388aSLukasz Kazmierczak [asyncResp, updateMetricsReq]( 12829e6c388aSLukasz Kazmierczak const boost::beast::http::status status, 12839e6c388aSLukasz Kazmierczak const std::map<std::string, std::string>& uriToDbus) { 12849e6c388aSLukasz Kazmierczak if (status != boost::beast::http::status::ok) 12859e6c388aSLukasz Kazmierczak { 12869e6c388aSLukasz Kazmierczak BMCWEB_LOG_ERROR( 12879e6c388aSLukasz Kazmierczak "Failed to retrieve URI to dbus sensors map with err {}", 12889e6c388aSLukasz Kazmierczak static_cast<unsigned>(status)); 12899e6c388aSLukasz Kazmierczak return; 12909e6c388aSLukasz Kazmierczak } 12919e6c388aSLukasz Kazmierczak updateMetricsReq->insert(uriToDbus); 12929e6c388aSLukasz Kazmierczak }); 12939e6c388aSLukasz Kazmierczak } 12949e6c388aSLukasz Kazmierczak }); 12959e6c388aSLukasz Kazmierczak } 1296081ebf06SWludzik, Jozef 12974220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead( 12984220be3bSEd Tanous App& app, const crow::Request& req, 12994220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 13004220be3bSEd Tanous { 13014220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13024220be3bSEd Tanous { 13034220be3bSEd Tanous return; 13044220be3bSEd Tanous } 13054220be3bSEd Tanous asyncResp->res.addHeader( 13064220be3bSEd Tanous boost::beast::http::field::link, 13074220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby"); 13084220be3bSEd Tanous } 13094220be3bSEd Tanous 13104220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet( 1311fc0edbe3SEd Tanous App& app, const crow::Request& req, 1312fc0edbe3SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1313fc0edbe3SEd Tanous { 1314fc0edbe3SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1315fc0edbe3SEd Tanous { 1316fc0edbe3SEd Tanous return; 1317fc0edbe3SEd Tanous } 13189e6c388aSLukasz Kazmierczak asyncResp->res.addHeader( 13199e6c388aSLukasz Kazmierczak boost::beast::http::field::link, 13209e6c388aSLukasz Kazmierczak "</redfish/v1/JsonSchemas/MetricReportDefinition/MetricReportDefinition.json>; rel=describedby"); 1321fc0edbe3SEd Tanous 1322fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1323fc0edbe3SEd Tanous "#MetricReportDefinitionCollection." 1324fc0edbe3SEd Tanous "MetricReportDefinitionCollection"; 1325fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1326fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"; 1327fc0edbe3SEd Tanous asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; 1328fc0edbe3SEd Tanous constexpr std::array<std::string_view, 1> interfaces{ 1329fc0edbe3SEd Tanous telemetry::reportInterface}; 1330fc0edbe3SEd Tanous collection_util::getCollectionMembers( 1331fc0edbe3SEd Tanous asyncResp, 1332fc0edbe3SEd Tanous boost::urls::url( 1333fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"), 1334fc0edbe3SEd Tanous interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); 1335fc0edbe3SEd Tanous } 1336fc0edbe3SEd Tanous 1337bd79bce8SPatrick Williams inline void handleReportPatch( 1338bd79bce8SPatrick Williams App& app, const crow::Request& req, 1339bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id) 13409e6c388aSLukasz Kazmierczak { 13419e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13429e6c388aSLukasz Kazmierczak { 13439e6c388aSLukasz Kazmierczak return; 13449e6c388aSLukasz Kazmierczak } 13459e6c388aSLukasz Kazmierczak 13469e6c388aSLukasz Kazmierczak std::optional<std::string> reportingTypeStr; 13479e6c388aSLukasz Kazmierczak std::optional<std::string> reportUpdatesStr; 13489e6c388aSLukasz Kazmierczak std::optional<bool> metricReportDefinitionEnabled; 1349a64919e8SBoleslaw Ogonczyk Makowski std::optional< 1350a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 1351a64919e8SBoleslaw Ogonczyk Makowski metrics; 13529e6c388aSLukasz Kazmierczak std::optional<std::vector<std::string>> reportActionsStr; 1353b14f357fSEd Tanous std::optional<std::string> scheduleDurationStr; 13549e6c388aSLukasz Kazmierczak 1355afc474aeSMyung Bae if (!json_util::readJsonPatch( // 1356afc474aeSMyung Bae req, asyncResp->res, // 1357afc474aeSMyung Bae "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, // 1358afc474aeSMyung Bae "MetricReportDefinitionType", reportingTypeStr, // 1359afc474aeSMyung Bae "Metrics", metrics, // 1360afc474aeSMyung Bae "ReportActions", reportActionsStr, // 1361afc474aeSMyung Bae "ReportUpdates", reportUpdatesStr, // 1362afc474aeSMyung Bae "Schedule/RecurrenceInterval", scheduleDurationStr // 1363afc474aeSMyung Bae )) 13649e6c388aSLukasz Kazmierczak { 13659e6c388aSLukasz Kazmierczak return; 13669e6c388aSLukasz Kazmierczak } 13679e6c388aSLukasz Kazmierczak 13689e6c388aSLukasz Kazmierczak if (metricReportDefinitionEnabled) 13699e6c388aSLukasz Kazmierczak { 13709e6c388aSLukasz Kazmierczak setReportEnabled(asyncResp, id, *metricReportDefinitionEnabled); 13719e6c388aSLukasz Kazmierczak } 13729e6c388aSLukasz Kazmierczak 13739e6c388aSLukasz Kazmierczak if (reportUpdatesStr) 13749e6c388aSLukasz Kazmierczak { 1375b4361d63SEd Tanous setReportUpdates(asyncResp, id, *reportUpdatesStr); 13769e6c388aSLukasz Kazmierczak } 13779e6c388aSLukasz Kazmierczak 13789e6c388aSLukasz Kazmierczak if (reportActionsStr) 13799e6c388aSLukasz Kazmierczak { 1380b4361d63SEd Tanous setReportActions(asyncResp, id, *reportActionsStr); 13819e6c388aSLukasz Kazmierczak } 13829e6c388aSLukasz Kazmierczak 1383b14f357fSEd Tanous if (reportingTypeStr || scheduleDurationStr) 13849e6c388aSLukasz Kazmierczak { 1385b4361d63SEd Tanous setReportTypeAndInterval(asyncResp, id, reportingTypeStr, 1386b4361d63SEd Tanous scheduleDurationStr); 13879e6c388aSLukasz Kazmierczak } 13889e6c388aSLukasz Kazmierczak 13899e6c388aSLukasz Kazmierczak if (metrics) 13909e6c388aSLukasz Kazmierczak { 1391ba498310SKrzysztof Grobelny setReportMetrics(asyncResp, id, std::move(*metrics)); 13929e6c388aSLukasz Kazmierczak } 13939e6c388aSLukasz Kazmierczak } 13949e6c388aSLukasz Kazmierczak 13959e6c388aSLukasz Kazmierczak } // namespace telemetry 13969e6c388aSLukasz Kazmierczak 139795bdb5f0SEd Tanous inline void afterRetrieveUriToDbusMap( 139895bdb5f0SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/, 139995bdb5f0SEd Tanous const std::shared_ptr<telemetry::AddReport>& addReportReq, 140095bdb5f0SEd Tanous const boost::beast::http::status status, 140195bdb5f0SEd Tanous const std::map<std::string, std::string>& uriToDbus) 140295bdb5f0SEd Tanous { 140395bdb5f0SEd Tanous if (status != boost::beast::http::status::ok) 140495bdb5f0SEd Tanous { 140595bdb5f0SEd Tanous BMCWEB_LOG_ERROR( 140695bdb5f0SEd Tanous "Failed to retrieve URI to dbus sensors map with err {}", 140795bdb5f0SEd Tanous static_cast<unsigned>(status)); 140895bdb5f0SEd Tanous return; 140995bdb5f0SEd Tanous } 141095bdb5f0SEd Tanous addReportReq->insert(uriToDbus); 141195bdb5f0SEd Tanous } 141295bdb5f0SEd Tanous 14139e6c388aSLukasz Kazmierczak inline void handleMetricReportDefinitionsPost( 14149e6c388aSLukasz Kazmierczak App& app, const crow::Request& req, 14159e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 14169e6c388aSLukasz Kazmierczak { 14179e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14189e6c388aSLukasz Kazmierczak { 14199e6c388aSLukasz Kazmierczak return; 14209e6c388aSLukasz Kazmierczak } 14219e6c388aSLukasz Kazmierczak 14229e6c388aSLukasz Kazmierczak telemetry::AddReportArgs args; 14239e6c388aSLukasz Kazmierczak if (!telemetry::getUserParameters(asyncResp->res, req, args)) 14249e6c388aSLukasz Kazmierczak { 14259e6c388aSLukasz Kazmierczak return; 14269e6c388aSLukasz Kazmierczak } 14279e6c388aSLukasz Kazmierczak 14289e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 14299e6c388aSLukasz Kazmierczak chassisSensors; 14309e6c388aSLukasz Kazmierczak if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, 14319e6c388aSLukasz Kazmierczak chassisSensors)) 14329e6c388aSLukasz Kazmierczak { 14339e6c388aSLukasz Kazmierczak return; 14349e6c388aSLukasz Kazmierczak } 14359e6c388aSLukasz Kazmierczak 1436bd79bce8SPatrick Williams auto addReportReq = 1437bd79bce8SPatrick Williams std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 14389e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 14399e6c388aSLukasz Kazmierczak { 144095bdb5f0SEd Tanous retrieveUriToDbusMap(chassis, sensorType, 144195bdb5f0SEd Tanous std::bind_front(afterRetrieveUriToDbusMap, 144295bdb5f0SEd Tanous asyncResp, addReportReq)); 14439e6c388aSLukasz Kazmierczak } 14449e6c388aSLukasz Kazmierczak } 14459e6c388aSLukasz Kazmierczak 1446504af5a0SPatrick Williams inline void handleMetricReportHead( 1447504af5a0SPatrick Williams App& app, const crow::Request& req, 14484220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 14494220be3bSEd Tanous const std::string& /*id*/) 14504220be3bSEd Tanous { 14514220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14524220be3bSEd Tanous { 14534220be3bSEd Tanous return; 14544220be3bSEd Tanous } 14554220be3bSEd Tanous asyncResp->res.addHeader( 14564220be3bSEd Tanous boost::beast::http::field::link, 14574220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 14584220be3bSEd Tanous } 14594220be3bSEd Tanous 1460bd79bce8SPatrick Williams inline void handleMetricReportGet( 1461bd79bce8SPatrick Williams App& app, const crow::Request& req, 1462bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 146386a5ac98SEd Tanous { 146486a5ac98SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 146586a5ac98SEd Tanous { 146686a5ac98SEd Tanous return; 146786a5ac98SEd Tanous } 14684220be3bSEd Tanous asyncResp->res.addHeader( 14694220be3bSEd Tanous boost::beast::http::field::link, 14704220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 147186a5ac98SEd Tanous 1472deae6a78SEd Tanous dbus::utility::getAllProperties( 1473deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1474deae6a78SEd Tanous telemetry::reportInterface, 147586a5ac98SEd Tanous [asyncResp, id](const boost::system::error_code& ec, 147686a5ac98SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 1477*2169e896SMichal Orzel if (!telemetry::formatMessageOnError(asyncResp->res, id, ec)) 147886a5ac98SEd Tanous { 147986a5ac98SEd Tanous telemetry::fillReportDefinition(asyncResp, id, properties); 1480*2169e896SMichal Orzel } 148186a5ac98SEd Tanous }); 148286a5ac98SEd Tanous } 148386a5ac98SEd Tanous 1484dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete( 1485dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 1486dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 1487dd1c4a9cSSzymon Dompke 1488dd1c4a9cSSzymon Dompke { 1489dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1490dd1c4a9cSSzymon Dompke { 1491dd1c4a9cSSzymon Dompke return; 1492dd1c4a9cSSzymon Dompke } 1493dd1c4a9cSSzymon Dompke 1494dd1c4a9cSSzymon Dompke const std::string reportPath = telemetry::getDbusReportPath(id); 1495dd1c4a9cSSzymon Dompke 1496177612aaSEd Tanous dbus::utility::async_method_call( 1497177612aaSEd Tanous asyncResp, 1498dd1c4a9cSSzymon Dompke [asyncResp, id](const boost::system::error_code& ec) { 1499dd1c4a9cSSzymon Dompke /* 1500dd1c4a9cSSzymon Dompke * boost::system::errc and std::errc are missing value 1501dd1c4a9cSSzymon Dompke * for EBADR error that is defined in Linux. 1502dd1c4a9cSSzymon Dompke */ 1503dd1c4a9cSSzymon Dompke if (ec.value() == EBADR) 1504dd1c4a9cSSzymon Dompke { 1505bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1506bd79bce8SPatrick Williams "MetricReportDefinition", id); 1507dd1c4a9cSSzymon Dompke return; 1508dd1c4a9cSSzymon Dompke } 1509dd1c4a9cSSzymon Dompke 1510dd1c4a9cSSzymon Dompke if (ec) 1511dd1c4a9cSSzymon Dompke { 151262598e31SEd Tanous BMCWEB_LOG_ERROR("respHandler DBus error {}", ec); 1513dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 1514dd1c4a9cSSzymon Dompke return; 1515dd1c4a9cSSzymon Dompke } 1516dd1c4a9cSSzymon Dompke 1517dd1c4a9cSSzymon Dompke asyncResp->res.result(boost::beast::http::status::no_content); 1518dd1c4a9cSSzymon Dompke }, 1519dd1c4a9cSSzymon Dompke telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 1520dd1c4a9cSSzymon Dompke "Delete"); 1521dd1c4a9cSSzymon Dompke } 1522dd1c4a9cSSzymon Dompke 15237e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app) 1524081ebf06SWludzik, Jozef { 15257e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 15264220be3bSEd Tanous .privileges(redfish::privileges::headMetricReportDefinitionCollection) 15274220be3bSEd Tanous .methods(boost::beast::http::verb::head)(std::bind_front( 15289e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionHead, 15299e6c388aSLukasz Kazmierczak std::ref(app))); 15304220be3bSEd Tanous 15314220be3bSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1532ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinitionCollection) 15334220be3bSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 15349e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionGet, 15359e6c388aSLukasz Kazmierczak std::ref(app))); 15364dbb8aeaSWludzik, Jozef 15377e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1538ed398213SEd Tanous .privileges(redfish::privileges::postMetricReportDefinitionCollection) 1539002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 15409e6c388aSLukasz Kazmierczak std::bind_front(handleMetricReportDefinitionsPost, std::ref(app))); 1541081ebf06SWludzik, Jozef } 1542081ebf06SWludzik, Jozef 15437e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app) 1544081ebf06SWludzik, Jozef { 15457e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 15467e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 1547ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 15484220be3bSEd Tanous .methods(boost::beast::http::verb::head)( 15494220be3bSEd Tanous std::bind_front(handleMetricReportHead, std::ref(app))); 15504220be3bSEd Tanous 15514220be3bSEd Tanous BMCWEB_ROUTE(app, 15524220be3bSEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 15534220be3bSEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 15547e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 155586a5ac98SEd Tanous std::bind_front(handleMetricReportGet, std::ref(app))); 1556479e899dSKrzysztof Grobelny 15577e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 15587e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 15599e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::deleteMetricReportDefinition) 15607e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 1561dd1c4a9cSSzymon Dompke std::bind_front(handleMetricReportDelete, std::ref(app))); 15629e6c388aSLukasz Kazmierczak 15639e6c388aSLukasz Kazmierczak BMCWEB_ROUTE(app, 15649e6c388aSLukasz Kazmierczak "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 15659e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::patchMetricReportDefinition) 15669e6c388aSLukasz Kazmierczak .methods(boost::beast::http::verb::patch)( 15679e6c388aSLukasz Kazmierczak std::bind_front(telemetry::handleReportPatch, std::ref(app))); 15684dbb8aeaSWludzik, Jozef } 1569081ebf06SWludzik, Jozef } // namespace redfish 1570