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 679e6c388aSLukasz Kazmierczak inline bool verifyCommonErrors(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); 739e6c388aSLukasz Kazmierczak return false; 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); 809e6c388aSLukasz Kazmierczak return false; 819e6c388aSLukasz Kazmierczak } 829e6c388aSLukasz Kazmierczak 839e6c388aSLukasz Kazmierczak if (ec == boost::system::errc::too_many_files_open) 849e6c388aSLukasz Kazmierczak { 859e6c388aSLukasz Kazmierczak messages::createLimitReachedForResource(res); 869e6c388aSLukasz Kazmierczak return false; 879e6c388aSLukasz Kazmierczak } 889e6c388aSLukasz Kazmierczak 899e6c388aSLukasz Kazmierczak if (ec) 909e6c388aSLukasz Kazmierczak { 919e6c388aSLukasz Kazmierczak BMCWEB_LOG_ERROR("DBUS response error {}", ec); 929e6c388aSLukasz Kazmierczak messages::internalError(res); 939e6c388aSLukasz Kazmierczak return false; 949e6c388aSLukasz Kazmierczak } 959e6c388aSLukasz Kazmierczak 969e6c388aSLukasz Kazmierczak return true; 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 340479e899dSKrzysztof Grobelny nlohmann::json::array_t metrics = nlohmann::json::array(); 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 } 603479e899dSKrzysztof Grobelny args.reportingType = 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 } 615479e899dSKrzysztof Grobelny args.reportUpdates = 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) 756ba498310SKrzysztof Grobelny { 757ba498310SKrzysztof Grobelny messages::created(asyncResp->res); 758ba498310SKrzysztof Grobelny return; 759ba498310SKrzysztof Grobelny } 760ba498310SKrzysztof Grobelny 761ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 762ba498310SKrzysztof Grobelny { 763ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 764ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 765ba498310SKrzysztof Grobelny { 766ba498310SKrzysztof Grobelny for (const auto& arg : 767ba498310SKrzysztof Grobelny {"Id", "Name", "ReportingType", "AppendLimit", "ReportActions", 768ba498310SKrzysztof Grobelny "Interval", "ReportUpdates", "ReadingParameters"}) 769ba498310SKrzysztof Grobelny { 770ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 771ba498310SKrzysztof Grobelny arg)) 772ba498310SKrzysztof Grobelny { 773ba498310SKrzysztof Grobelny return; 774ba498310SKrzysztof Grobelny } 775ba498310SKrzysztof Grobelny } 776ba498310SKrzysztof Grobelny } 777ba498310SKrzysztof Grobelny } 778ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, args.id, ec)) 779ba498310SKrzysztof Grobelny { 780ba498310SKrzysztof Grobelny return; 781ba498310SKrzysztof Grobelny } 782ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 783ba498310SKrzysztof Grobelny } 784ba498310SKrzysztof Grobelny 7854dbb8aeaSWludzik, Jozef class AddReport 7864dbb8aeaSWludzik, Jozef { 7874dbb8aeaSWludzik, Jozef public: 788891eaa7cSEd Tanous AddReport(AddReportArgs&& argsIn, 7898a592810SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 790bd79bce8SPatrick Williams asyncResp(asyncRespIn), args(std::move(argsIn)) 7914dbb8aeaSWludzik, Jozef {} 792479e899dSKrzysztof Grobelny 7934dbb8aeaSWludzik, Jozef ~AddReport() 7944dbb8aeaSWludzik, Jozef { 795479e899dSKrzysztof Grobelny boost::asio::post(crow::connections::systemBus->get_io_context(), 796479e899dSKrzysztof Grobelny std::bind_front(&performAddReport, asyncResp, args, 797479e899dSKrzysztof Grobelny std::move(uriToDbus))); 798479e899dSKrzysztof Grobelny } 799479e899dSKrzysztof Grobelny 800479e899dSKrzysztof Grobelny static void performAddReport( 801479e899dSKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 802479e899dSKrzysztof Grobelny const AddReportArgs& args, 803479e899dSKrzysztof Grobelny const boost::container::flat_map<std::string, std::string>& uriToDbus) 804479e899dSKrzysztof Grobelny { 8054dbb8aeaSWludzik, Jozef if (asyncResp->res.result() != boost::beast::http::status::ok) 8064dbb8aeaSWludzik, Jozef { 8074dbb8aeaSWludzik, Jozef return; 8084dbb8aeaSWludzik, Jozef } 8094dbb8aeaSWludzik, Jozef 8104dbb8aeaSWludzik, Jozef telemetry::ReadingParameters readingParams; 8114dbb8aeaSWludzik, Jozef readingParams.reserve(args.metrics.size()); 8124dbb8aeaSWludzik, Jozef 813479e899dSKrzysztof Grobelny for (const auto& metric : args.metrics) 8144dbb8aeaSWludzik, Jozef { 815479e899dSKrzysztof Grobelny std::vector< 816479e899dSKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>> 817479e899dSKrzysztof Grobelny sensorParams; 818479e899dSKrzysztof Grobelny sensorParams.reserve(metric.uris.size()); 819479e899dSKrzysztof Grobelny 820479e899dSKrzysztof Grobelny for (size_t i = 0; i < metric.uris.size(); i++) 8214dbb8aeaSWludzik, Jozef { 822479e899dSKrzysztof Grobelny const std::string& uri = metric.uris[i]; 8234dbb8aeaSWludzik, Jozef auto el = uriToDbus.find(uri); 8244dbb8aeaSWludzik, Jozef if (el == uriToDbus.end()) 8254dbb8aeaSWludzik, Jozef { 82662598e31SEd Tanous BMCWEB_LOG_ERROR( 82762598e31SEd Tanous "Failed to find DBus sensor corresponding to URI {}", 82862598e31SEd Tanous uri); 829bd79bce8SPatrick Williams messages::propertyValueNotInList( 830bd79bce8SPatrick Williams asyncResp->res, uri, 831bd79bce8SPatrick Williams "MetricProperties/" + std::to_string(i)); 8324dbb8aeaSWludzik, Jozef return; 8334dbb8aeaSWludzik, Jozef } 8344dbb8aeaSWludzik, Jozef 8354dbb8aeaSWludzik, Jozef const std::string& dbusPath = el->second; 836479e899dSKrzysztof Grobelny sensorParams.emplace_back(dbusPath, uri); 8374dbb8aeaSWludzik, Jozef } 838479e899dSKrzysztof Grobelny 839479e899dSKrzysztof Grobelny readingParams.emplace_back( 840479e899dSKrzysztof Grobelny std::move(sensorParams), metric.collectionFunction, 841479e899dSKrzysztof Grobelny metric.collectionTimeScope, metric.collectionDuration); 8424dbb8aeaSWludzik, Jozef } 843*177612aaSEd Tanous dbus::utility::async_method_call( 844*177612aaSEd Tanous asyncResp, 845ba498310SKrzysztof Grobelny [asyncResp, args](const boost::system::error_code& ec, 846ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg, 847ba498310SKrzysztof Grobelny const std::string& /*arg1*/) { 848ba498310SKrzysztof Grobelny afterAddReport(asyncResp, args, ec, msg); 8494dbb8aeaSWludzik, Jozef }, 8504dbb8aeaSWludzik, Jozef telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", 8514dbb8aeaSWludzik, Jozef "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", 852479e899dSKrzysztof Grobelny "TelemetryService/" + args.id, args.name, args.reportingType, 853479e899dSKrzysztof Grobelny args.reportUpdates, args.appendLimit, args.reportActions, 854479e899dSKrzysztof Grobelny args.interval, readingParams, args.metricReportDefinitionEnabled); 8554dbb8aeaSWludzik, Jozef } 8564dbb8aeaSWludzik, Jozef 857ecd6a3a2SEd Tanous AddReport(const AddReport&) = delete; 858ecd6a3a2SEd Tanous AddReport(AddReport&&) = delete; 859ecd6a3a2SEd Tanous AddReport& operator=(const AddReport&) = delete; 860ecd6a3a2SEd Tanous AddReport& operator=(AddReport&&) = delete; 861ecd6a3a2SEd Tanous 862fe04d49cSNan Zhou void insert(const std::map<std::string, std::string>& el) 8634dbb8aeaSWludzik, Jozef { 8644dbb8aeaSWludzik, Jozef uriToDbus.insert(el.begin(), el.end()); 8654dbb8aeaSWludzik, Jozef } 8664dbb8aeaSWludzik, Jozef 8674dbb8aeaSWludzik, Jozef private: 868ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 8694dbb8aeaSWludzik, Jozef AddReportArgs args; 87047f2934cSEd Tanous boost::container::flat_map<std::string, std::string> uriToDbus; 8714dbb8aeaSWludzik, Jozef }; 8729e6c388aSLukasz Kazmierczak 873ba498310SKrzysztof Grobelny inline std::optional< 874ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>>> 875ba498310SKrzysztof Grobelny sensorPathToUri( 876ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 877ba498310SKrzysztof Grobelny std::span<const std::string> uris, 878ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 879ba498310SKrzysztof Grobelny { 880ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>> 881ba498310SKrzysztof Grobelny result; 882ba498310SKrzysztof Grobelny 883ba498310SKrzysztof Grobelny for (const std::string& uri : uris) 884ba498310SKrzysztof Grobelny { 885ba498310SKrzysztof Grobelny auto it = metricPropertyToDbusPaths.find(uri); 886ba498310SKrzysztof Grobelny if (it == metricPropertyToDbusPaths.end()) 887ba498310SKrzysztof Grobelny { 888ba498310SKrzysztof Grobelny messages::propertyValueNotInList(asyncResp->res, uri, 889ba498310SKrzysztof Grobelny "MetricProperties"); 890ba498310SKrzysztof Grobelny return {}; 891ba498310SKrzysztof Grobelny } 892ba498310SKrzysztof Grobelny result.emplace_back(it->second, uri); 893ba498310SKrzysztof Grobelny } 894ba498310SKrzysztof Grobelny 895ba498310SKrzysztof Grobelny return result; 896ba498310SKrzysztof Grobelny } 897ba498310SKrzysztof Grobelny 898ba498310SKrzysztof Grobelny inline void afterSetReadingParams( 899ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 900ba498310SKrzysztof Grobelny const std::string& reportId, const boost::system::error_code& ec, 901ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) 902ba498310SKrzysztof Grobelny { 903ba498310SKrzysztof Grobelny if (!ec) 904ba498310SKrzysztof Grobelny { 905ba498310SKrzysztof Grobelny messages::success(asyncResp->res); 906ba498310SKrzysztof Grobelny return; 907ba498310SKrzysztof Grobelny } 908ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 909ba498310SKrzysztof Grobelny { 910ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 911ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 912ba498310SKrzysztof Grobelny { 913ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReadingParameters"}) 914ba498310SKrzysztof Grobelny { 915ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 916ba498310SKrzysztof Grobelny arg)) 917ba498310SKrzysztof Grobelny { 918ba498310SKrzysztof Grobelny return; 919ba498310SKrzysztof Grobelny } 920ba498310SKrzysztof Grobelny } 921ba498310SKrzysztof Grobelny } 922ba498310SKrzysztof Grobelny } 923ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, reportId, ec)) 924ba498310SKrzysztof Grobelny { 925ba498310SKrzysztof Grobelny return; 926ba498310SKrzysztof Grobelny } 927ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 928ba498310SKrzysztof Grobelny } 929ba498310SKrzysztof Grobelny 930ba498310SKrzysztof Grobelny inline void setReadingParams( 931ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 932ba498310SKrzysztof Grobelny const std::string& reportId, ReadingParameters readingParams, 933ba498310SKrzysztof Grobelny const std::vector<std::vector<std::string>>& readingParamsUris, 934ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 935ba498310SKrzysztof Grobelny { 936ba498310SKrzysztof Grobelny if (asyncResp->res.result() != boost::beast::http::status::ok) 937ba498310SKrzysztof Grobelny { 938ba498310SKrzysztof Grobelny return; 939ba498310SKrzysztof Grobelny } 940ba498310SKrzysztof Grobelny 941ba498310SKrzysztof Grobelny for (size_t index = 0; index < readingParamsUris.size(); ++index) 942ba498310SKrzysztof Grobelny { 943ba498310SKrzysztof Grobelny std::span<const std::string> newUris = readingParamsUris[index]; 944ba498310SKrzysztof Grobelny 945ba498310SKrzysztof Grobelny const std::optional<std::vector< 946ba498310SKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>>> 947ba498310SKrzysztof Grobelny readingParam = 948ba498310SKrzysztof Grobelny sensorPathToUri(asyncResp, newUris, metricPropertyToDbusPaths); 949ba498310SKrzysztof Grobelny 950ba498310SKrzysztof Grobelny if (!readingParam) 951ba498310SKrzysztof Grobelny { 952ba498310SKrzysztof Grobelny return; 953ba498310SKrzysztof Grobelny } 954ba498310SKrzysztof Grobelny 955ba498310SKrzysztof Grobelny for (const std::tuple<sdbusplus::message::object_path, std::string>& 956ba498310SKrzysztof Grobelny value : *readingParam) 957ba498310SKrzysztof Grobelny { 958ba498310SKrzysztof Grobelny std::get<0>(readingParams[index]).emplace_back(value); 959ba498310SKrzysztof Grobelny } 960ba498310SKrzysztof Grobelny } 961ba498310SKrzysztof Grobelny 962*177612aaSEd Tanous dbus::utility::async_method_call( 963*177612aaSEd Tanous asyncResp, 964ba498310SKrzysztof Grobelny [asyncResp, reportId](const boost::system::error_code& ec, 965ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 966ba498310SKrzysztof Grobelny afterSetReadingParams(asyncResp, reportId, ec, msg); 967ba498310SKrzysztof Grobelny }, 968ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry", getDbusReportPath(reportId), 969ba498310SKrzysztof Grobelny "org.freedesktop.DBus.Properties", "Set", 970ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report", "ReadingParameters", 971ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{readingParams}); 972ba498310SKrzysztof Grobelny } 973ba498310SKrzysztof Grobelny 9749e6c388aSLukasz Kazmierczak class UpdateMetrics 9759e6c388aSLukasz Kazmierczak { 9769e6c388aSLukasz Kazmierczak public: 9779e6c388aSLukasz Kazmierczak UpdateMetrics(std::string_view idIn, 9789e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 979bd79bce8SPatrick Williams id(idIn), asyncResp(asyncRespIn) 9809e6c388aSLukasz Kazmierczak {} 9819e6c388aSLukasz Kazmierczak 9829e6c388aSLukasz Kazmierczak ~UpdateMetrics() 9839e6c388aSLukasz Kazmierczak { 984ba498310SKrzysztof Grobelny boost::asio::post( 985ba498310SKrzysztof Grobelny crow::connections::systemBus->get_io_context(), 986ba498310SKrzysztof Grobelny std::bind_front(&setReadingParams, asyncResp, id, 987ba498310SKrzysztof Grobelny std::move(readingParams), readingParamsUris, 988ba498310SKrzysztof Grobelny metricPropertyToDbusPaths)); 9899e6c388aSLukasz Kazmierczak } 9909e6c388aSLukasz Kazmierczak 9919e6c388aSLukasz Kazmierczak UpdateMetrics(const UpdateMetrics&) = delete; 9929e6c388aSLukasz Kazmierczak UpdateMetrics(UpdateMetrics&&) = delete; 9939e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(const UpdateMetrics&) = delete; 9949e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(UpdateMetrics&&) = delete; 9959e6c388aSLukasz Kazmierczak 9969e6c388aSLukasz Kazmierczak std::string id; 9979e6c388aSLukasz Kazmierczak std::map<std::string, std::string> metricPropertyToDbusPaths; 9989e6c388aSLukasz Kazmierczak 9999e6c388aSLukasz Kazmierczak void insert(const std::map<std::string, std::string>& 10009e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths) 10019e6c388aSLukasz Kazmierczak { 10029e6c388aSLukasz Kazmierczak metricPropertyToDbusPaths.insert( 10039e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.begin(), 10049e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.end()); 10059e6c388aSLukasz Kazmierczak } 10069e6c388aSLukasz Kazmierczak 1007bd79bce8SPatrick Williams void emplace( 1008bd79bce8SPatrick Williams std::span< 1009bd79bce8SPatrick Williams const std::tuple<sdbusplus::message::object_path, std::string>> 10109e6c388aSLukasz Kazmierczak pathAndUri, 10119e6c388aSLukasz Kazmierczak const AddReportArgs::MetricArgs& metricArgs) 10129e6c388aSLukasz Kazmierczak { 10139e6c388aSLukasz Kazmierczak readingParamsUris.emplace_back(metricArgs.uris); 10149e6c388aSLukasz Kazmierczak readingParams.emplace_back( 10159e6c388aSLukasz Kazmierczak std::vector(pathAndUri.begin(), pathAndUri.end()), 10169e6c388aSLukasz Kazmierczak metricArgs.collectionFunction, metricArgs.collectionTimeScope, 10179e6c388aSLukasz Kazmierczak metricArgs.collectionDuration); 10189e6c388aSLukasz Kazmierczak } 10199e6c388aSLukasz Kazmierczak 10209e6c388aSLukasz Kazmierczak private: 10219e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 10229e6c388aSLukasz Kazmierczak std::vector<std::vector<std::string>> readingParamsUris; 102347f2934cSEd Tanous ReadingParameters readingParams; 10249e6c388aSLukasz Kazmierczak }; 10259e6c388aSLukasz Kazmierczak 1026504af5a0SPatrick Williams inline void setReportEnabled( 1027504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1028504af5a0SPatrick Williams bool enabled) 10299e6c388aSLukasz Kazmierczak { 1030*177612aaSEd Tanous dbus::utility::async_method_call( 1031*177612aaSEd Tanous asyncResp, 10329e6c388aSLukasz Kazmierczak [asyncResp, id = std::string(id)](const boost::system::error_code& ec) { 10339e6c388aSLukasz Kazmierczak if (!verifyCommonErrors(asyncResp->res, id, ec)) 10349e6c388aSLukasz Kazmierczak { 10359e6c388aSLukasz Kazmierczak return; 10369e6c388aSLukasz Kazmierczak } 10379e6c388aSLukasz Kazmierczak }, 10389e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 10399e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 10409e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "Enabled", 10419e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{enabled}); 10429e6c388aSLukasz Kazmierczak } 10439e6c388aSLukasz Kazmierczak 1044ba498310SKrzysztof Grobelny inline void afterSetReportingProperties( 1045ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1046ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1047ba498310SKrzysztof Grobelny { 1048ba498310SKrzysztof Grobelny if (!ec) 1049ba498310SKrzysztof Grobelny { 1050ba498310SKrzysztof Grobelny asyncResp->res.result(boost::beast::http::status::no_content); 1051ba498310SKrzysztof Grobelny return; 1052ba498310SKrzysztof Grobelny } 1053ba498310SKrzysztof Grobelny 1054ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1055ba498310SKrzysztof Grobelny { 1056ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1057ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1058ba498310SKrzysztof Grobelny { 1059ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportingType", "Interval"}) 1060ba498310SKrzysztof Grobelny { 1061ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1062ba498310SKrzysztof Grobelny arg)) 1063ba498310SKrzysztof Grobelny { 1064ba498310SKrzysztof Grobelny return; 1065ba498310SKrzysztof Grobelny } 1066ba498310SKrzysztof Grobelny } 1067ba498310SKrzysztof Grobelny } 1068ba498310SKrzysztof Grobelny } 1069ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1070ba498310SKrzysztof Grobelny { 1071ba498310SKrzysztof Grobelny return; 1072ba498310SKrzysztof Grobelny } 1073ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 1074ba498310SKrzysztof Grobelny } 1075ba498310SKrzysztof Grobelny 10769e6c388aSLukasz Kazmierczak inline void setReportTypeAndInterval( 10779e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1078b4361d63SEd Tanous const std::optional<std::string>& reportingType, 1079b4361d63SEd Tanous const std::optional<std::string>& recurrenceIntervalStr) 10809e6c388aSLukasz Kazmierczak { 1081b4361d63SEd Tanous std::string dbusReportingType; 1082b4361d63SEd Tanous if (reportingType) 1083b4361d63SEd Tanous { 1084b4361d63SEd Tanous dbusReportingType = toDbusReportingType(*reportingType); 1085b4361d63SEd Tanous if (dbusReportingType.empty()) 1086b4361d63SEd Tanous { 1087b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, *reportingType, 1088b4361d63SEd Tanous "MetricReportDefinitionType"); 1089b4361d63SEd Tanous return; 1090b4361d63SEd Tanous } 1091b4361d63SEd Tanous } 1092b4361d63SEd Tanous 1093b4361d63SEd Tanous uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max(); 1094b4361d63SEd Tanous if (recurrenceIntervalStr) 1095b4361d63SEd Tanous { 1096b4361d63SEd Tanous std::optional<std::chrono::milliseconds> durationNum = 1097b4361d63SEd Tanous time_utils::fromDurationString(*recurrenceIntervalStr); 1098b4361d63SEd Tanous if (!durationNum || durationNum->count() < 0) 1099b4361d63SEd Tanous { 1100b4361d63SEd Tanous messages::propertyValueIncorrect( 1101b4361d63SEd Tanous asyncResp->res, "RecurrenceInterval", *recurrenceIntervalStr); 1102b4361d63SEd Tanous return; 1103b4361d63SEd Tanous } 1104b4361d63SEd Tanous 1105b4361d63SEd Tanous recurrenceInterval = static_cast<uint64_t>(durationNum->count()); 1106b4361d63SEd Tanous } 1107b4361d63SEd Tanous 1108*177612aaSEd Tanous dbus::utility::async_method_call( 1109*177612aaSEd Tanous asyncResp, 1110ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1111ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1112ba498310SKrzysztof Grobelny afterSetReportingProperties(asyncResp, id, ec, msg); 11139e6c388aSLukasz Kazmierczak }, 11149e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11159e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "SetReportingProperties", 1116b4361d63SEd Tanous dbusReportingType, recurrenceInterval); 11179e6c388aSLukasz Kazmierczak } 11189e6c388aSLukasz Kazmierczak 1119ba498310SKrzysztof Grobelny inline void afterSetReportUpdates( 1120ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1121ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1122ba498310SKrzysztof Grobelny { 1123ba498310SKrzysztof Grobelny if (!ec) 1124ba498310SKrzysztof Grobelny { 1125ba498310SKrzysztof Grobelny asyncResp->res.result(boost::beast::http::status::no_content); 1126ba498310SKrzysztof Grobelny return; 1127ba498310SKrzysztof Grobelny } 1128ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1129ba498310SKrzysztof Grobelny { 1130ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1131ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1132ba498310SKrzysztof Grobelny { 1133ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportUpdates"}) 1134ba498310SKrzysztof Grobelny { 1135ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1136ba498310SKrzysztof Grobelny arg)) 1137ba498310SKrzysztof Grobelny { 1138ba498310SKrzysztof Grobelny return; 1139ba498310SKrzysztof Grobelny } 1140ba498310SKrzysztof Grobelny } 1141ba498310SKrzysztof Grobelny } 1142ba498310SKrzysztof Grobelny } 1143ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1144ba498310SKrzysztof Grobelny { 1145ba498310SKrzysztof Grobelny return; 1146ba498310SKrzysztof Grobelny } 1147ba498310SKrzysztof Grobelny } 1148ba498310SKrzysztof Grobelny 1149504af5a0SPatrick Williams inline void setReportUpdates( 1150504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1151504af5a0SPatrick Williams const std::string& reportUpdates) 11529e6c388aSLukasz Kazmierczak { 1153b4361d63SEd Tanous std::string dbusReportUpdates = toDbusReportUpdates(reportUpdates); 1154b4361d63SEd Tanous if (dbusReportUpdates.empty()) 1155b4361d63SEd Tanous { 1156b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, reportUpdates, 1157b4361d63SEd Tanous "ReportUpdates"); 1158b4361d63SEd Tanous return; 1159b4361d63SEd Tanous } 1160*177612aaSEd Tanous dbus::utility::async_method_call( 1161*177612aaSEd Tanous asyncResp, 1162ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1163ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1164ba498310SKrzysztof Grobelny afterSetReportUpdates(asyncResp, id, ec, msg); 11659e6c388aSLukasz Kazmierczak }, 11669e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11679e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 11689e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportUpdates", 1169ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{dbusReportUpdates}); 1170ba498310SKrzysztof Grobelny } 1171ba498310SKrzysztof Grobelny 1172ba498310SKrzysztof Grobelny inline void afterSetReportActions( 1173ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1174ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1175ba498310SKrzysztof Grobelny { 1176ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1177ba498310SKrzysztof Grobelny { 1178ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1179ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1180ba498310SKrzysztof Grobelny { 1181ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportActions"}) 1182ba498310SKrzysztof Grobelny { 1183ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1184ba498310SKrzysztof Grobelny arg)) 1185ba498310SKrzysztof Grobelny { 1186ba498310SKrzysztof Grobelny return; 1187ba498310SKrzysztof Grobelny } 1188ba498310SKrzysztof Grobelny } 1189ba498310SKrzysztof Grobelny } 1190ba498310SKrzysztof Grobelny } 1191ba498310SKrzysztof Grobelny 1192ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1193ba498310SKrzysztof Grobelny { 1194ba498310SKrzysztof Grobelny return; 1195ba498310SKrzysztof Grobelny } 1196ba498310SKrzysztof Grobelny 1197ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 11989e6c388aSLukasz Kazmierczak } 11999e6c388aSLukasz Kazmierczak 1200bd79bce8SPatrick Williams inline void setReportActions( 1201bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1202b4361d63SEd Tanous const std::vector<std::string>& reportActions) 12039e6c388aSLukasz Kazmierczak { 1204b4361d63SEd Tanous std::vector<std::string> dbusReportActions; 1205b4361d63SEd Tanous if (!toDbusReportActions(asyncResp->res, reportActions, dbusReportActions)) 1206b4361d63SEd Tanous { 1207b4361d63SEd Tanous return; 1208b4361d63SEd Tanous } 1209b4361d63SEd Tanous 1210*177612aaSEd Tanous dbus::utility::async_method_call( 1211*177612aaSEd Tanous asyncResp, 1212ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1213ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1214ba498310SKrzysztof Grobelny afterSetReportActions(asyncResp, id, ec, msg); 12159e6c388aSLukasz Kazmierczak }, 12169e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 12179e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 12189e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportActions", 12199e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{dbusReportActions}); 12209e6c388aSLukasz Kazmierczak } 12219e6c388aSLukasz Kazmierczak 1222bd79bce8SPatrick Williams inline void setReportMetrics( 1223bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1224a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>&& 1225a64919e8SBoleslaw Ogonczyk Makowski metrics) 12269e6c388aSLukasz Kazmierczak { 1227deae6a78SEd Tanous dbus::utility::getAllProperties( 1228deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1229deae6a78SEd Tanous telemetry::reportInterface, 1230ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id), redfishMetrics = std::move(metrics)]( 12319e6c388aSLukasz Kazmierczak boost::system::error_code ec, 12329e6c388aSLukasz Kazmierczak const dbus::utility::DBusPropertiesMap& properties) mutable { 1233ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 12349e6c388aSLukasz Kazmierczak { 12359e6c388aSLukasz Kazmierczak return; 12369e6c388aSLukasz Kazmierczak } 12379e6c388aSLukasz Kazmierczak 12389e6c388aSLukasz Kazmierczak ReadingParameters readingParams; 12399e6c388aSLukasz Kazmierczak 12409e6c388aSLukasz Kazmierczak const bool success = sdbusplus::unpackPropertiesNoThrow( 1241bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 1242bd79bce8SPatrick Williams "ReadingParameters", readingParams); 12439e6c388aSLukasz Kazmierczak 12449e6c388aSLukasz Kazmierczak if (!success) 12459e6c388aSLukasz Kazmierczak { 12469e6c388aSLukasz Kazmierczak messages::internalError(asyncResp->res); 12479e6c388aSLukasz Kazmierczak return; 12489e6c388aSLukasz Kazmierczak } 12499e6c388aSLukasz Kazmierczak 1250bd79bce8SPatrick Williams auto updateMetricsReq = 1251bd79bce8SPatrick Williams std::make_shared<UpdateMetrics>(id, asyncResp); 12529e6c388aSLukasz Kazmierczak 12539e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 12549e6c388aSLukasz Kazmierczak chassisSensors; 12559e6c388aSLukasz Kazmierczak 12569e6c388aSLukasz Kazmierczak size_t index = 0; 1257a64919e8SBoleslaw Ogonczyk Makowski for (std::variant<nlohmann::json::object_t, std::nullptr_t>& 1258a64919e8SBoleslaw Ogonczyk Makowski metricVariant : redfishMetrics) 12599e6c388aSLukasz Kazmierczak { 1260a64919e8SBoleslaw Ogonczyk Makowski nlohmann::json::object_t* metric = 1261a64919e8SBoleslaw Ogonczyk Makowski std::get_if<nlohmann::json::object_t>(&metricVariant); 1262a64919e8SBoleslaw Ogonczyk Makowski if (metric == nullptr) 1263a64919e8SBoleslaw Ogonczyk Makowski { 1264a64919e8SBoleslaw Ogonczyk Makowski index++; 1265a64919e8SBoleslaw Ogonczyk Makowski continue; 1266a64919e8SBoleslaw Ogonczyk Makowski } 1267a64919e8SBoleslaw Ogonczyk Makowski 12689e6c388aSLukasz Kazmierczak AddReportArgs::MetricArgs metricArgs; 12699e6c388aSLukasz Kazmierczak std::vector< 12709e6c388aSLukasz Kazmierczak std::tuple<sdbusplus::message::object_path, std::string>> 12719e6c388aSLukasz Kazmierczak pathAndUri; 12729e6c388aSLukasz Kazmierczak 12739e6c388aSLukasz Kazmierczak if (index < readingParams.size()) 12749e6c388aSLukasz Kazmierczak { 12759e6c388aSLukasz Kazmierczak const ReadingParameters::value_type& existing = 12769e6c388aSLukasz Kazmierczak readingParams[index]; 12779e6c388aSLukasz Kazmierczak 1278dac07cadSBoleslaw Ogonczyk Makowski if (metric->empty()) 1279dac07cadSBoleslaw Ogonczyk Makowski { 12809e6c388aSLukasz Kazmierczak pathAndUri = std::get<0>(existing); 1281dac07cadSBoleslaw Ogonczyk Makowski } 12829e6c388aSLukasz Kazmierczak metricArgs.collectionFunction = std::get<1>(existing); 12839e6c388aSLukasz Kazmierczak metricArgs.collectionTimeScope = std::get<2>(existing); 12849e6c388aSLukasz Kazmierczak metricArgs.collectionDuration = std::get<3>(existing); 12859e6c388aSLukasz Kazmierczak } 12869e6c388aSLukasz Kazmierczak 1287a64919e8SBoleslaw Ogonczyk Makowski if (!getUserMetric(asyncResp->res, *metric, metricArgs)) 12889e6c388aSLukasz Kazmierczak { 12899e6c388aSLukasz Kazmierczak return; 12909e6c388aSLukasz Kazmierczak } 12919e6c388aSLukasz Kazmierczak 12929e6c388aSLukasz Kazmierczak std::optional<IncorrectMetricUri> error = 12939e6c388aSLukasz Kazmierczak getChassisSensorNode(metricArgs.uris, chassisSensors); 12949e6c388aSLukasz Kazmierczak 12959e6c388aSLukasz Kazmierczak if (error) 12969e6c388aSLukasz Kazmierczak { 12979e6c388aSLukasz Kazmierczak messages::propertyValueIncorrect( 12989e6c388aSLukasz Kazmierczak asyncResp->res, error->uri, 12999e6c388aSLukasz Kazmierczak "MetricProperties/" + std::to_string(error->index)); 13009e6c388aSLukasz Kazmierczak return; 13019e6c388aSLukasz Kazmierczak } 13029e6c388aSLukasz Kazmierczak 13039e6c388aSLukasz Kazmierczak updateMetricsReq->emplace(pathAndUri, metricArgs); 13049e6c388aSLukasz Kazmierczak index++; 13059e6c388aSLukasz Kazmierczak } 13069e6c388aSLukasz Kazmierczak 13079e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 13089e6c388aSLukasz Kazmierczak { 13099e6c388aSLukasz Kazmierczak retrieveUriToDbusMap( 13109e6c388aSLukasz Kazmierczak chassis, sensorType, 13119e6c388aSLukasz Kazmierczak [asyncResp, updateMetricsReq]( 13129e6c388aSLukasz Kazmierczak const boost::beast::http::status status, 13139e6c388aSLukasz Kazmierczak const std::map<std::string, std::string>& uriToDbus) { 13149e6c388aSLukasz Kazmierczak if (status != boost::beast::http::status::ok) 13159e6c388aSLukasz Kazmierczak { 13169e6c388aSLukasz Kazmierczak BMCWEB_LOG_ERROR( 13179e6c388aSLukasz Kazmierczak "Failed to retrieve URI to dbus sensors map with err {}", 13189e6c388aSLukasz Kazmierczak static_cast<unsigned>(status)); 13199e6c388aSLukasz Kazmierczak return; 13209e6c388aSLukasz Kazmierczak } 13219e6c388aSLukasz Kazmierczak updateMetricsReq->insert(uriToDbus); 13229e6c388aSLukasz Kazmierczak }); 13239e6c388aSLukasz Kazmierczak } 13249e6c388aSLukasz Kazmierczak }); 13259e6c388aSLukasz Kazmierczak } 1326081ebf06SWludzik, Jozef 13274220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead( 13284220be3bSEd Tanous App& app, const crow::Request& req, 13294220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 13304220be3bSEd Tanous { 13314220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13324220be3bSEd Tanous { 13334220be3bSEd Tanous return; 13344220be3bSEd Tanous } 13354220be3bSEd Tanous asyncResp->res.addHeader( 13364220be3bSEd Tanous boost::beast::http::field::link, 13374220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby"); 13384220be3bSEd Tanous } 13394220be3bSEd Tanous 13404220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet( 1341fc0edbe3SEd Tanous App& app, const crow::Request& req, 1342fc0edbe3SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1343fc0edbe3SEd Tanous { 1344fc0edbe3SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1345fc0edbe3SEd Tanous { 1346fc0edbe3SEd Tanous return; 1347fc0edbe3SEd Tanous } 13489e6c388aSLukasz Kazmierczak asyncResp->res.addHeader( 13499e6c388aSLukasz Kazmierczak boost::beast::http::field::link, 13509e6c388aSLukasz Kazmierczak "</redfish/v1/JsonSchemas/MetricReportDefinition/MetricReportDefinition.json>; rel=describedby"); 1351fc0edbe3SEd Tanous 1352fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1353fc0edbe3SEd Tanous "#MetricReportDefinitionCollection." 1354fc0edbe3SEd Tanous "MetricReportDefinitionCollection"; 1355fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1356fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"; 1357fc0edbe3SEd Tanous asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; 1358fc0edbe3SEd Tanous constexpr std::array<std::string_view, 1> interfaces{ 1359fc0edbe3SEd Tanous telemetry::reportInterface}; 1360fc0edbe3SEd Tanous collection_util::getCollectionMembers( 1361fc0edbe3SEd Tanous asyncResp, 1362fc0edbe3SEd Tanous boost::urls::url( 1363fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"), 1364fc0edbe3SEd Tanous interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); 1365fc0edbe3SEd Tanous } 1366fc0edbe3SEd Tanous 1367bd79bce8SPatrick Williams inline void handleReportPatch( 1368bd79bce8SPatrick Williams App& app, const crow::Request& req, 1369bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id) 13709e6c388aSLukasz Kazmierczak { 13719e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13729e6c388aSLukasz Kazmierczak { 13739e6c388aSLukasz Kazmierczak return; 13749e6c388aSLukasz Kazmierczak } 13759e6c388aSLukasz Kazmierczak 13769e6c388aSLukasz Kazmierczak std::optional<std::string> reportingTypeStr; 13779e6c388aSLukasz Kazmierczak std::optional<std::string> reportUpdatesStr; 13789e6c388aSLukasz Kazmierczak std::optional<bool> metricReportDefinitionEnabled; 1379a64919e8SBoleslaw Ogonczyk Makowski std::optional< 1380a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 1381a64919e8SBoleslaw Ogonczyk Makowski metrics; 13829e6c388aSLukasz Kazmierczak std::optional<std::vector<std::string>> reportActionsStr; 1383b14f357fSEd Tanous std::optional<std::string> scheduleDurationStr; 13849e6c388aSLukasz Kazmierczak 1385afc474aeSMyung Bae if (!json_util::readJsonPatch( // 1386afc474aeSMyung Bae req, asyncResp->res, // 1387afc474aeSMyung Bae "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, // 1388afc474aeSMyung Bae "MetricReportDefinitionType", reportingTypeStr, // 1389afc474aeSMyung Bae "Metrics", metrics, // 1390afc474aeSMyung Bae "ReportActions", reportActionsStr, // 1391afc474aeSMyung Bae "ReportUpdates", reportUpdatesStr, // 1392afc474aeSMyung Bae "Schedule/RecurrenceInterval", scheduleDurationStr // 1393afc474aeSMyung Bae )) 13949e6c388aSLukasz Kazmierczak { 13959e6c388aSLukasz Kazmierczak return; 13969e6c388aSLukasz Kazmierczak } 13979e6c388aSLukasz Kazmierczak 13989e6c388aSLukasz Kazmierczak if (metricReportDefinitionEnabled) 13999e6c388aSLukasz Kazmierczak { 14009e6c388aSLukasz Kazmierczak setReportEnabled(asyncResp, id, *metricReportDefinitionEnabled); 14019e6c388aSLukasz Kazmierczak } 14029e6c388aSLukasz Kazmierczak 14039e6c388aSLukasz Kazmierczak if (reportUpdatesStr) 14049e6c388aSLukasz Kazmierczak { 1405b4361d63SEd Tanous setReportUpdates(asyncResp, id, *reportUpdatesStr); 14069e6c388aSLukasz Kazmierczak } 14079e6c388aSLukasz Kazmierczak 14089e6c388aSLukasz Kazmierczak if (reportActionsStr) 14099e6c388aSLukasz Kazmierczak { 1410b4361d63SEd Tanous setReportActions(asyncResp, id, *reportActionsStr); 14119e6c388aSLukasz Kazmierczak } 14129e6c388aSLukasz Kazmierczak 1413b14f357fSEd Tanous if (reportingTypeStr || scheduleDurationStr) 14149e6c388aSLukasz Kazmierczak { 1415b4361d63SEd Tanous setReportTypeAndInterval(asyncResp, id, reportingTypeStr, 1416b4361d63SEd Tanous scheduleDurationStr); 14179e6c388aSLukasz Kazmierczak } 14189e6c388aSLukasz Kazmierczak 14199e6c388aSLukasz Kazmierczak if (metrics) 14209e6c388aSLukasz Kazmierczak { 1421ba498310SKrzysztof Grobelny setReportMetrics(asyncResp, id, std::move(*metrics)); 14229e6c388aSLukasz Kazmierczak } 14239e6c388aSLukasz Kazmierczak } 14249e6c388aSLukasz Kazmierczak 1425bd79bce8SPatrick Williams inline void handleReportDelete( 1426bd79bce8SPatrick Williams App& app, const crow::Request& req, 1427bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id) 14289e6c388aSLukasz Kazmierczak { 14299e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14309e6c388aSLukasz Kazmierczak { 14319e6c388aSLukasz Kazmierczak return; 14329e6c388aSLukasz Kazmierczak } 14339e6c388aSLukasz Kazmierczak 14349e6c388aSLukasz Kazmierczak const std::string reportPath = getDbusReportPath(id); 14359e6c388aSLukasz Kazmierczak 1436*177612aaSEd Tanous dbus::utility::async_method_call( 1437*177612aaSEd Tanous asyncResp, 14389e6c388aSLukasz Kazmierczak [asyncResp, 14399e6c388aSLukasz Kazmierczak reportId = std::string(id)](const boost::system::error_code& ec) { 14409e6c388aSLukasz Kazmierczak if (!verifyCommonErrors(asyncResp->res, reportId, ec)) 14419e6c388aSLukasz Kazmierczak { 14429e6c388aSLukasz Kazmierczak return; 14439e6c388aSLukasz Kazmierczak } 14449e6c388aSLukasz Kazmierczak asyncResp->res.result(boost::beast::http::status::no_content); 14459e6c388aSLukasz Kazmierczak }, 14469e6c388aSLukasz Kazmierczak service, reportPath, "xyz.openbmc_project.Object.Delete", "Delete"); 14479e6c388aSLukasz Kazmierczak } 14489e6c388aSLukasz Kazmierczak } // namespace telemetry 14499e6c388aSLukasz Kazmierczak 145095bdb5f0SEd Tanous inline void afterRetrieveUriToDbusMap( 145195bdb5f0SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/, 145295bdb5f0SEd Tanous const std::shared_ptr<telemetry::AddReport>& addReportReq, 145395bdb5f0SEd Tanous const boost::beast::http::status status, 145495bdb5f0SEd Tanous const std::map<std::string, std::string>& uriToDbus) 145595bdb5f0SEd Tanous { 145695bdb5f0SEd Tanous if (status != boost::beast::http::status::ok) 145795bdb5f0SEd Tanous { 145895bdb5f0SEd Tanous BMCWEB_LOG_ERROR( 145995bdb5f0SEd Tanous "Failed to retrieve URI to dbus sensors map with err {}", 146095bdb5f0SEd Tanous static_cast<unsigned>(status)); 146195bdb5f0SEd Tanous return; 146295bdb5f0SEd Tanous } 146395bdb5f0SEd Tanous addReportReq->insert(uriToDbus); 146495bdb5f0SEd Tanous } 146595bdb5f0SEd Tanous 14669e6c388aSLukasz Kazmierczak inline void handleMetricReportDefinitionsPost( 14679e6c388aSLukasz Kazmierczak App& app, const crow::Request& req, 14689e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 14699e6c388aSLukasz Kazmierczak { 14709e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14719e6c388aSLukasz Kazmierczak { 14729e6c388aSLukasz Kazmierczak return; 14739e6c388aSLukasz Kazmierczak } 14749e6c388aSLukasz Kazmierczak 14759e6c388aSLukasz Kazmierczak telemetry::AddReportArgs args; 14769e6c388aSLukasz Kazmierczak if (!telemetry::getUserParameters(asyncResp->res, req, args)) 14779e6c388aSLukasz Kazmierczak { 14789e6c388aSLukasz Kazmierczak return; 14799e6c388aSLukasz Kazmierczak } 14809e6c388aSLukasz Kazmierczak 14819e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 14829e6c388aSLukasz Kazmierczak chassisSensors; 14839e6c388aSLukasz Kazmierczak if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, 14849e6c388aSLukasz Kazmierczak chassisSensors)) 14859e6c388aSLukasz Kazmierczak { 14869e6c388aSLukasz Kazmierczak return; 14879e6c388aSLukasz Kazmierczak } 14889e6c388aSLukasz Kazmierczak 1489bd79bce8SPatrick Williams auto addReportReq = 1490bd79bce8SPatrick Williams std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 14919e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 14929e6c388aSLukasz Kazmierczak { 149395bdb5f0SEd Tanous retrieveUriToDbusMap(chassis, sensorType, 149495bdb5f0SEd Tanous std::bind_front(afterRetrieveUriToDbusMap, 149595bdb5f0SEd Tanous asyncResp, addReportReq)); 14969e6c388aSLukasz Kazmierczak } 14979e6c388aSLukasz Kazmierczak } 14989e6c388aSLukasz Kazmierczak 1499504af5a0SPatrick Williams inline void handleMetricReportHead( 1500504af5a0SPatrick Williams App& app, const crow::Request& req, 15014220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 15024220be3bSEd Tanous const std::string& /*id*/) 15034220be3bSEd Tanous { 15044220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 15054220be3bSEd Tanous { 15064220be3bSEd Tanous return; 15074220be3bSEd Tanous } 15084220be3bSEd Tanous asyncResp->res.addHeader( 15094220be3bSEd Tanous boost::beast::http::field::link, 15104220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 15114220be3bSEd Tanous } 15124220be3bSEd Tanous 1513bd79bce8SPatrick Williams inline void handleMetricReportGet( 1514bd79bce8SPatrick Williams App& app, const crow::Request& req, 1515bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 151686a5ac98SEd Tanous { 151786a5ac98SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 151886a5ac98SEd Tanous { 151986a5ac98SEd Tanous return; 152086a5ac98SEd Tanous } 15214220be3bSEd Tanous asyncResp->res.addHeader( 15224220be3bSEd Tanous boost::beast::http::field::link, 15234220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 152486a5ac98SEd Tanous 1525deae6a78SEd Tanous dbus::utility::getAllProperties( 1526deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1527deae6a78SEd Tanous telemetry::reportInterface, 152886a5ac98SEd Tanous [asyncResp, id](const boost::system::error_code& ec, 152986a5ac98SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 15309e6c388aSLukasz Kazmierczak if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec)) 153186a5ac98SEd Tanous { 153286a5ac98SEd Tanous return; 153386a5ac98SEd Tanous } 153486a5ac98SEd Tanous 153586a5ac98SEd Tanous telemetry::fillReportDefinition(asyncResp, id, properties); 153686a5ac98SEd Tanous }); 153786a5ac98SEd Tanous } 153886a5ac98SEd Tanous 1539dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete( 1540dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 1541dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 1542dd1c4a9cSSzymon Dompke 1543dd1c4a9cSSzymon Dompke { 1544dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1545dd1c4a9cSSzymon Dompke { 1546dd1c4a9cSSzymon Dompke return; 1547dd1c4a9cSSzymon Dompke } 1548dd1c4a9cSSzymon Dompke 1549dd1c4a9cSSzymon Dompke const std::string reportPath = telemetry::getDbusReportPath(id); 1550dd1c4a9cSSzymon Dompke 1551*177612aaSEd Tanous dbus::utility::async_method_call( 1552*177612aaSEd Tanous asyncResp, 1553dd1c4a9cSSzymon Dompke [asyncResp, id](const boost::system::error_code& ec) { 1554dd1c4a9cSSzymon Dompke /* 1555dd1c4a9cSSzymon Dompke * boost::system::errc and std::errc are missing value 1556dd1c4a9cSSzymon Dompke * for EBADR error that is defined in Linux. 1557dd1c4a9cSSzymon Dompke */ 1558dd1c4a9cSSzymon Dompke if (ec.value() == EBADR) 1559dd1c4a9cSSzymon Dompke { 1560bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1561bd79bce8SPatrick Williams "MetricReportDefinition", id); 1562dd1c4a9cSSzymon Dompke return; 1563dd1c4a9cSSzymon Dompke } 1564dd1c4a9cSSzymon Dompke 1565dd1c4a9cSSzymon Dompke if (ec) 1566dd1c4a9cSSzymon Dompke { 156762598e31SEd Tanous BMCWEB_LOG_ERROR("respHandler DBus error {}", ec); 1568dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 1569dd1c4a9cSSzymon Dompke return; 1570dd1c4a9cSSzymon Dompke } 1571dd1c4a9cSSzymon Dompke 1572dd1c4a9cSSzymon Dompke asyncResp->res.result(boost::beast::http::status::no_content); 1573dd1c4a9cSSzymon Dompke }, 1574dd1c4a9cSSzymon Dompke telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 1575dd1c4a9cSSzymon Dompke "Delete"); 1576dd1c4a9cSSzymon Dompke } 1577dd1c4a9cSSzymon Dompke 15787e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app) 1579081ebf06SWludzik, Jozef { 15807e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 15814220be3bSEd Tanous .privileges(redfish::privileges::headMetricReportDefinitionCollection) 15824220be3bSEd Tanous .methods(boost::beast::http::verb::head)(std::bind_front( 15839e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionHead, 15849e6c388aSLukasz Kazmierczak std::ref(app))); 15854220be3bSEd Tanous 15864220be3bSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1587ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinitionCollection) 15884220be3bSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 15899e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionGet, 15909e6c388aSLukasz Kazmierczak std::ref(app))); 15914dbb8aeaSWludzik, Jozef 15927e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1593ed398213SEd Tanous .privileges(redfish::privileges::postMetricReportDefinitionCollection) 1594002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 15959e6c388aSLukasz Kazmierczak std::bind_front(handleMetricReportDefinitionsPost, std::ref(app))); 1596081ebf06SWludzik, Jozef } 1597081ebf06SWludzik, Jozef 15987e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app) 1599081ebf06SWludzik, Jozef { 16007e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 16017e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 1602ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 16034220be3bSEd Tanous .methods(boost::beast::http::verb::head)( 16044220be3bSEd Tanous std::bind_front(handleMetricReportHead, std::ref(app))); 16054220be3bSEd Tanous 16064220be3bSEd Tanous BMCWEB_ROUTE(app, 16074220be3bSEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 16084220be3bSEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 16097e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 161086a5ac98SEd Tanous std::bind_front(handleMetricReportGet, std::ref(app))); 1611479e899dSKrzysztof Grobelny 16127e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 16137e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 16149e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::deleteMetricReportDefinition) 16157e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 1616dd1c4a9cSSzymon Dompke std::bind_front(handleMetricReportDelete, std::ref(app))); 16179e6c388aSLukasz Kazmierczak 16189e6c388aSLukasz Kazmierczak BMCWEB_ROUTE(app, 16199e6c388aSLukasz Kazmierczak "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 16209e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::patchMetricReportDefinition) 16219e6c388aSLukasz Kazmierczak .methods(boost::beast::http::verb::patch)( 16229e6c388aSLukasz Kazmierczak std::bind_front(telemetry::handleReportPatch, std::ref(app))); 16234dbb8aeaSWludzik, Jozef } 1624081ebf06SWludzik, Jozef } // namespace redfish 1625