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" 6*d7857201SEd Tanous #include "async_resp.hpp" 7*d7857201SEd Tanous #include "dbus_singleton.hpp" 83ccb3adbSEd Tanous #include "dbus_utility.hpp" 9*d7857201SEd Tanous #include "error_messages.hpp" 10479e899dSKrzysztof Grobelny #include "generated/enums/metric_report_definition.hpp" 11539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 12*d7857201SEd Tanous #include "http_request.hpp" 13*d7857201SEd Tanous #include "http_response.hpp" 14*d7857201SEd 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 24*d7857201SEd Tanous #include <asm-generic/errno.h> 25*d7857201SEd Tanous #include <systemd/sd-bus.h> 26*d7857201SEd Tanous 27*d7857201SEd Tanous #include <boost/asio/post.hpp> 28*d7857201SEd Tanous #include <boost/beast/http/field.hpp> 29*d7857201SEd Tanous #include <boost/beast/http/status.hpp> 30*d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 314dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp> 32*d7857201SEd Tanous #include <boost/container/flat_set.hpp> 33ef4c65b7SEd Tanous #include <boost/url/format.hpp> 34*d7857201SEd Tanous #include <boost/url/url.hpp> 35*d7857201SEd Tanous #include <nlohmann/json.hpp> 36*d7857201SEd Tanous #include <sdbusplus/message.hpp> 37*d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 3889474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 394dbb8aeaSWludzik, Jozef 407a1dbc48SGeorge Liu #include <array> 41*d7857201SEd Tanous #include <chrono> 42*d7857201SEd Tanous #include <cstddef> 43*d7857201SEd Tanous #include <cstdint> 44*d7857201SEd Tanous #include <functional> 45*d7857201SEd Tanous #include <limits> 46fe04d49cSNan Zhou #include <map> 47*d7857201SEd 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 99479e899dSKrzysztof Grobelny inline metric_report_definition::ReportActionsEnum 100479e899dSKrzysztof Grobelny toRedfishReportAction(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 205479e899dSKrzysztof Grobelny inline metric_report_definition::ReportUpdatesEnum 206479e899dSKrzysztof Grobelny toRedfishReportUpdates(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 } 8434dbb8aeaSWludzik, Jozef crow::connections::systemBus->async_method_call( 844ba498310SKrzysztof Grobelny [asyncResp, args](const boost::system::error_code& ec, 845ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg, 846ba498310SKrzysztof Grobelny const std::string& /*arg1*/) { 847ba498310SKrzysztof Grobelny afterAddReport(asyncResp, args, ec, msg); 8484dbb8aeaSWludzik, Jozef }, 8494dbb8aeaSWludzik, Jozef telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", 8504dbb8aeaSWludzik, Jozef "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", 851479e899dSKrzysztof Grobelny "TelemetryService/" + args.id, args.name, args.reportingType, 852479e899dSKrzysztof Grobelny args.reportUpdates, args.appendLimit, args.reportActions, 853479e899dSKrzysztof Grobelny args.interval, readingParams, args.metricReportDefinitionEnabled); 8544dbb8aeaSWludzik, Jozef } 8554dbb8aeaSWludzik, Jozef 856ecd6a3a2SEd Tanous AddReport(const AddReport&) = delete; 857ecd6a3a2SEd Tanous AddReport(AddReport&&) = delete; 858ecd6a3a2SEd Tanous AddReport& operator=(const AddReport&) = delete; 859ecd6a3a2SEd Tanous AddReport& operator=(AddReport&&) = delete; 860ecd6a3a2SEd Tanous 861fe04d49cSNan Zhou void insert(const std::map<std::string, std::string>& el) 8624dbb8aeaSWludzik, Jozef { 8634dbb8aeaSWludzik, Jozef uriToDbus.insert(el.begin(), el.end()); 8644dbb8aeaSWludzik, Jozef } 8654dbb8aeaSWludzik, Jozef 8664dbb8aeaSWludzik, Jozef private: 867ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 8684dbb8aeaSWludzik, Jozef AddReportArgs args; 86947f2934cSEd Tanous boost::container::flat_map<std::string, std::string> uriToDbus; 8704dbb8aeaSWludzik, Jozef }; 8719e6c388aSLukasz Kazmierczak 872ba498310SKrzysztof Grobelny inline std::optional< 873ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>>> 874ba498310SKrzysztof Grobelny sensorPathToUri( 875ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 876ba498310SKrzysztof Grobelny std::span<const std::string> uris, 877ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 878ba498310SKrzysztof Grobelny { 879ba498310SKrzysztof Grobelny std::vector<std::tuple<sdbusplus::message::object_path, std::string>> 880ba498310SKrzysztof Grobelny result; 881ba498310SKrzysztof Grobelny 882ba498310SKrzysztof Grobelny for (const std::string& uri : uris) 883ba498310SKrzysztof Grobelny { 884ba498310SKrzysztof Grobelny auto it = metricPropertyToDbusPaths.find(uri); 885ba498310SKrzysztof Grobelny if (it == metricPropertyToDbusPaths.end()) 886ba498310SKrzysztof Grobelny { 887ba498310SKrzysztof Grobelny messages::propertyValueNotInList(asyncResp->res, uri, 888ba498310SKrzysztof Grobelny "MetricProperties"); 889ba498310SKrzysztof Grobelny return {}; 890ba498310SKrzysztof Grobelny } 891ba498310SKrzysztof Grobelny result.emplace_back(it->second, uri); 892ba498310SKrzysztof Grobelny } 893ba498310SKrzysztof Grobelny 894ba498310SKrzysztof Grobelny return result; 895ba498310SKrzysztof Grobelny } 896ba498310SKrzysztof Grobelny 897ba498310SKrzysztof Grobelny inline void afterSetReadingParams( 898ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 899ba498310SKrzysztof Grobelny const std::string& reportId, const boost::system::error_code& ec, 900ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) 901ba498310SKrzysztof Grobelny { 902ba498310SKrzysztof Grobelny if (!ec) 903ba498310SKrzysztof Grobelny { 904ba498310SKrzysztof Grobelny messages::success(asyncResp->res); 905ba498310SKrzysztof Grobelny return; 906ba498310SKrzysztof Grobelny } 907ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 908ba498310SKrzysztof Grobelny { 909ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 910ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 911ba498310SKrzysztof Grobelny { 912ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReadingParameters"}) 913ba498310SKrzysztof Grobelny { 914ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 915ba498310SKrzysztof Grobelny arg)) 916ba498310SKrzysztof Grobelny { 917ba498310SKrzysztof Grobelny return; 918ba498310SKrzysztof Grobelny } 919ba498310SKrzysztof Grobelny } 920ba498310SKrzysztof Grobelny } 921ba498310SKrzysztof Grobelny } 922ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, reportId, ec)) 923ba498310SKrzysztof Grobelny { 924ba498310SKrzysztof Grobelny return; 925ba498310SKrzysztof Grobelny } 926ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 927ba498310SKrzysztof Grobelny } 928ba498310SKrzysztof Grobelny 929ba498310SKrzysztof Grobelny inline void setReadingParams( 930ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 931ba498310SKrzysztof Grobelny const std::string& reportId, ReadingParameters readingParams, 932ba498310SKrzysztof Grobelny const std::vector<std::vector<std::string>>& readingParamsUris, 933ba498310SKrzysztof Grobelny const std::map<std::string, std::string>& metricPropertyToDbusPaths) 934ba498310SKrzysztof Grobelny { 935ba498310SKrzysztof Grobelny if (asyncResp->res.result() != boost::beast::http::status::ok) 936ba498310SKrzysztof Grobelny { 937ba498310SKrzysztof Grobelny return; 938ba498310SKrzysztof Grobelny } 939ba498310SKrzysztof Grobelny 940ba498310SKrzysztof Grobelny for (size_t index = 0; index < readingParamsUris.size(); ++index) 941ba498310SKrzysztof Grobelny { 942ba498310SKrzysztof Grobelny std::span<const std::string> newUris = readingParamsUris[index]; 943ba498310SKrzysztof Grobelny 944ba498310SKrzysztof Grobelny const std::optional<std::vector< 945ba498310SKrzysztof Grobelny std::tuple<sdbusplus::message::object_path, std::string>>> 946ba498310SKrzysztof Grobelny readingParam = 947ba498310SKrzysztof Grobelny sensorPathToUri(asyncResp, newUris, metricPropertyToDbusPaths); 948ba498310SKrzysztof Grobelny 949ba498310SKrzysztof Grobelny if (!readingParam) 950ba498310SKrzysztof Grobelny { 951ba498310SKrzysztof Grobelny return; 952ba498310SKrzysztof Grobelny } 953ba498310SKrzysztof Grobelny 954ba498310SKrzysztof Grobelny for (const std::tuple<sdbusplus::message::object_path, std::string>& 955ba498310SKrzysztof Grobelny value : *readingParam) 956ba498310SKrzysztof Grobelny { 957ba498310SKrzysztof Grobelny std::get<0>(readingParams[index]).emplace_back(value); 958ba498310SKrzysztof Grobelny } 959ba498310SKrzysztof Grobelny } 960ba498310SKrzysztof Grobelny 961ba498310SKrzysztof Grobelny crow::connections::systemBus->async_method_call( 962ba498310SKrzysztof Grobelny [asyncResp, reportId](const boost::system::error_code& ec, 963ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 964ba498310SKrzysztof Grobelny afterSetReadingParams(asyncResp, reportId, ec, msg); 965ba498310SKrzysztof Grobelny }, 966ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry", getDbusReportPath(reportId), 967ba498310SKrzysztof Grobelny "org.freedesktop.DBus.Properties", "Set", 968ba498310SKrzysztof Grobelny "xyz.openbmc_project.Telemetry.Report", "ReadingParameters", 969ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{readingParams}); 970ba498310SKrzysztof Grobelny } 971ba498310SKrzysztof Grobelny 9729e6c388aSLukasz Kazmierczak class UpdateMetrics 9739e6c388aSLukasz Kazmierczak { 9749e6c388aSLukasz Kazmierczak public: 9759e6c388aSLukasz Kazmierczak UpdateMetrics(std::string_view idIn, 9769e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) : 977bd79bce8SPatrick Williams id(idIn), asyncResp(asyncRespIn) 9789e6c388aSLukasz Kazmierczak {} 9799e6c388aSLukasz Kazmierczak 9809e6c388aSLukasz Kazmierczak ~UpdateMetrics() 9819e6c388aSLukasz Kazmierczak { 982ba498310SKrzysztof Grobelny boost::asio::post( 983ba498310SKrzysztof Grobelny crow::connections::systemBus->get_io_context(), 984ba498310SKrzysztof Grobelny std::bind_front(&setReadingParams, asyncResp, id, 985ba498310SKrzysztof Grobelny std::move(readingParams), readingParamsUris, 986ba498310SKrzysztof Grobelny metricPropertyToDbusPaths)); 9879e6c388aSLukasz Kazmierczak } 9889e6c388aSLukasz Kazmierczak 9899e6c388aSLukasz Kazmierczak UpdateMetrics(const UpdateMetrics&) = delete; 9909e6c388aSLukasz Kazmierczak UpdateMetrics(UpdateMetrics&&) = delete; 9919e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(const UpdateMetrics&) = delete; 9929e6c388aSLukasz Kazmierczak UpdateMetrics& operator=(UpdateMetrics&&) = delete; 9939e6c388aSLukasz Kazmierczak 9949e6c388aSLukasz Kazmierczak std::string id; 9959e6c388aSLukasz Kazmierczak std::map<std::string, std::string> metricPropertyToDbusPaths; 9969e6c388aSLukasz Kazmierczak 9979e6c388aSLukasz Kazmierczak void insert(const std::map<std::string, std::string>& 9989e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths) 9999e6c388aSLukasz Kazmierczak { 10009e6c388aSLukasz Kazmierczak metricPropertyToDbusPaths.insert( 10019e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.begin(), 10029e6c388aSLukasz Kazmierczak additionalMetricPropertyToDbusPaths.end()); 10039e6c388aSLukasz Kazmierczak } 10049e6c388aSLukasz Kazmierczak 1005bd79bce8SPatrick Williams void emplace( 1006bd79bce8SPatrick Williams std::span< 1007bd79bce8SPatrick Williams const std::tuple<sdbusplus::message::object_path, std::string>> 10089e6c388aSLukasz Kazmierczak pathAndUri, 10099e6c388aSLukasz Kazmierczak const AddReportArgs::MetricArgs& metricArgs) 10109e6c388aSLukasz Kazmierczak { 10119e6c388aSLukasz Kazmierczak readingParamsUris.emplace_back(metricArgs.uris); 10129e6c388aSLukasz Kazmierczak readingParams.emplace_back( 10139e6c388aSLukasz Kazmierczak std::vector(pathAndUri.begin(), pathAndUri.end()), 10149e6c388aSLukasz Kazmierczak metricArgs.collectionFunction, metricArgs.collectionTimeScope, 10159e6c388aSLukasz Kazmierczak metricArgs.collectionDuration); 10169e6c388aSLukasz Kazmierczak } 10179e6c388aSLukasz Kazmierczak 10189e6c388aSLukasz Kazmierczak private: 10199e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp> asyncResp; 10209e6c388aSLukasz Kazmierczak std::vector<std::vector<std::string>> readingParamsUris; 102147f2934cSEd Tanous ReadingParameters readingParams; 10229e6c388aSLukasz Kazmierczak }; 10239e6c388aSLukasz Kazmierczak 10249e6c388aSLukasz Kazmierczak inline void 10259e6c388aSLukasz Kazmierczak setReportEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10269e6c388aSLukasz Kazmierczak std::string_view id, bool enabled) 10279e6c388aSLukasz Kazmierczak { 10289e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 10299e6c388aSLukasz Kazmierczak [asyncResp, id = std::string(id)](const boost::system::error_code& ec) { 10309e6c388aSLukasz Kazmierczak if (!verifyCommonErrors(asyncResp->res, id, ec)) 10319e6c388aSLukasz Kazmierczak { 10329e6c388aSLukasz Kazmierczak return; 10339e6c388aSLukasz Kazmierczak } 10349e6c388aSLukasz Kazmierczak }, 10359e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 10369e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 10379e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "Enabled", 10389e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{enabled}); 10399e6c388aSLukasz Kazmierczak } 10409e6c388aSLukasz Kazmierczak 1041ba498310SKrzysztof Grobelny inline void afterSetReportingProperties( 1042ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1043ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1044ba498310SKrzysztof Grobelny { 1045ba498310SKrzysztof Grobelny if (!ec) 1046ba498310SKrzysztof Grobelny { 1047ba498310SKrzysztof Grobelny asyncResp->res.result(boost::beast::http::status::no_content); 1048ba498310SKrzysztof Grobelny return; 1049ba498310SKrzysztof Grobelny } 1050ba498310SKrzysztof Grobelny 1051ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1052ba498310SKrzysztof Grobelny { 1053ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1054ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1055ba498310SKrzysztof Grobelny { 1056ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportingType", "Interval"}) 1057ba498310SKrzysztof Grobelny { 1058ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1059ba498310SKrzysztof Grobelny arg)) 1060ba498310SKrzysztof Grobelny { 1061ba498310SKrzysztof Grobelny return; 1062ba498310SKrzysztof Grobelny } 1063ba498310SKrzysztof Grobelny } 1064ba498310SKrzysztof Grobelny } 1065ba498310SKrzysztof Grobelny } 1066ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1067ba498310SKrzysztof Grobelny { 1068ba498310SKrzysztof Grobelny return; 1069ba498310SKrzysztof Grobelny } 1070ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 1071ba498310SKrzysztof Grobelny } 1072ba498310SKrzysztof Grobelny 10739e6c388aSLukasz Kazmierczak inline void setReportTypeAndInterval( 10749e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1075b4361d63SEd Tanous const std::optional<std::string>& reportingType, 1076b4361d63SEd Tanous const std::optional<std::string>& recurrenceIntervalStr) 10779e6c388aSLukasz Kazmierczak { 1078b4361d63SEd Tanous std::string dbusReportingType; 1079b4361d63SEd Tanous if (reportingType) 1080b4361d63SEd Tanous { 1081b4361d63SEd Tanous dbusReportingType = toDbusReportingType(*reportingType); 1082b4361d63SEd Tanous if (dbusReportingType.empty()) 1083b4361d63SEd Tanous { 1084b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, *reportingType, 1085b4361d63SEd Tanous "MetricReportDefinitionType"); 1086b4361d63SEd Tanous return; 1087b4361d63SEd Tanous } 1088b4361d63SEd Tanous } 1089b4361d63SEd Tanous 1090b4361d63SEd Tanous uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max(); 1091b4361d63SEd Tanous if (recurrenceIntervalStr) 1092b4361d63SEd Tanous { 1093b4361d63SEd Tanous std::optional<std::chrono::milliseconds> durationNum = 1094b4361d63SEd Tanous time_utils::fromDurationString(*recurrenceIntervalStr); 1095b4361d63SEd Tanous if (!durationNum || durationNum->count() < 0) 1096b4361d63SEd Tanous { 1097b4361d63SEd Tanous messages::propertyValueIncorrect( 1098b4361d63SEd Tanous asyncResp->res, "RecurrenceInterval", *recurrenceIntervalStr); 1099b4361d63SEd Tanous return; 1100b4361d63SEd Tanous } 1101b4361d63SEd Tanous 1102b4361d63SEd Tanous recurrenceInterval = static_cast<uint64_t>(durationNum->count()); 1103b4361d63SEd Tanous } 1104b4361d63SEd Tanous 11059e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 1106ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1107ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1108ba498310SKrzysztof Grobelny afterSetReportingProperties(asyncResp, id, ec, msg); 11099e6c388aSLukasz Kazmierczak }, 11109e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11119e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "SetReportingProperties", 1112b4361d63SEd Tanous dbusReportingType, recurrenceInterval); 11139e6c388aSLukasz Kazmierczak } 11149e6c388aSLukasz Kazmierczak 1115ba498310SKrzysztof Grobelny inline void afterSetReportUpdates( 1116ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1117ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1118ba498310SKrzysztof Grobelny { 1119ba498310SKrzysztof Grobelny if (!ec) 1120ba498310SKrzysztof Grobelny { 1121ba498310SKrzysztof Grobelny asyncResp->res.result(boost::beast::http::status::no_content); 1122ba498310SKrzysztof Grobelny return; 1123ba498310SKrzysztof Grobelny } 1124ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1125ba498310SKrzysztof Grobelny { 1126ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1127ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1128ba498310SKrzysztof Grobelny { 1129ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportUpdates"}) 1130ba498310SKrzysztof Grobelny { 1131ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1132ba498310SKrzysztof Grobelny arg)) 1133ba498310SKrzysztof Grobelny { 1134ba498310SKrzysztof Grobelny return; 1135ba498310SKrzysztof Grobelny } 1136ba498310SKrzysztof Grobelny } 1137ba498310SKrzysztof Grobelny } 1138ba498310SKrzysztof Grobelny } 1139ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1140ba498310SKrzysztof Grobelny { 1141ba498310SKrzysztof Grobelny return; 1142ba498310SKrzysztof Grobelny } 1143ba498310SKrzysztof Grobelny } 1144ba498310SKrzysztof Grobelny 11459e6c388aSLukasz Kazmierczak inline void 11469e6c388aSLukasz Kazmierczak setReportUpdates(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11479e6c388aSLukasz Kazmierczak std::string_view id, const std::string& reportUpdates) 11489e6c388aSLukasz Kazmierczak { 1149b4361d63SEd Tanous std::string dbusReportUpdates = toDbusReportUpdates(reportUpdates); 1150b4361d63SEd Tanous if (dbusReportUpdates.empty()) 1151b4361d63SEd Tanous { 1152b4361d63SEd Tanous messages::propertyValueNotInList(asyncResp->res, reportUpdates, 1153b4361d63SEd Tanous "ReportUpdates"); 1154b4361d63SEd Tanous return; 1155b4361d63SEd Tanous } 11569e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 1157ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1158ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1159ba498310SKrzysztof Grobelny afterSetReportUpdates(asyncResp, id, ec, msg); 11609e6c388aSLukasz Kazmierczak }, 11619e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 11629e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 11639e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportUpdates", 1164ba498310SKrzysztof Grobelny dbus::utility::DbusVariantType{dbusReportUpdates}); 1165ba498310SKrzysztof Grobelny } 1166ba498310SKrzysztof Grobelny 1167ba498310SKrzysztof Grobelny inline void afterSetReportActions( 1168ba498310SKrzysztof Grobelny const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, 1169ba498310SKrzysztof Grobelny const boost::system::error_code& ec, const sdbusplus::message_t& msg) 1170ba498310SKrzysztof Grobelny { 1171ba498310SKrzysztof Grobelny if (ec == boost::system::errc::invalid_argument) 1172ba498310SKrzysztof Grobelny { 1173ba498310SKrzysztof Grobelny const sd_bus_error* errorMessage = msg.get_error(); 1174ba498310SKrzysztof Grobelny if (errorMessage != nullptr) 1175ba498310SKrzysztof Grobelny { 1176ba498310SKrzysztof Grobelny for (const auto& arg : {"Id", "ReportActions"}) 1177ba498310SKrzysztof Grobelny { 1178ba498310SKrzysztof Grobelny if (!handleParamError(asyncResp->res, errorMessage->message, 1179ba498310SKrzysztof Grobelny arg)) 1180ba498310SKrzysztof Grobelny { 1181ba498310SKrzysztof Grobelny return; 1182ba498310SKrzysztof Grobelny } 1183ba498310SKrzysztof Grobelny } 1184ba498310SKrzysztof Grobelny } 1185ba498310SKrzysztof Grobelny } 1186ba498310SKrzysztof Grobelny 1187ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 1188ba498310SKrzysztof Grobelny { 1189ba498310SKrzysztof Grobelny return; 1190ba498310SKrzysztof Grobelny } 1191ba498310SKrzysztof Grobelny 1192ba498310SKrzysztof Grobelny messages::internalError(asyncResp->res); 11939e6c388aSLukasz Kazmierczak } 11949e6c388aSLukasz Kazmierczak 1195bd79bce8SPatrick Williams inline void setReportActions( 1196bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1197b4361d63SEd Tanous const std::vector<std::string>& reportActions) 11989e6c388aSLukasz Kazmierczak { 1199b4361d63SEd Tanous std::vector<std::string> dbusReportActions; 1200b4361d63SEd Tanous if (!toDbusReportActions(asyncResp->res, reportActions, dbusReportActions)) 1201b4361d63SEd Tanous { 1202b4361d63SEd Tanous return; 1203b4361d63SEd Tanous } 1204b4361d63SEd Tanous 12059e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 1206ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id)](const boost::system::error_code& ec, 1207ba498310SKrzysztof Grobelny const sdbusplus::message_t& msg) { 1208ba498310SKrzysztof Grobelny afterSetReportActions(asyncResp, id, ec, msg); 12099e6c388aSLukasz Kazmierczak }, 12109e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry", getDbusReportPath(id), 12119e6c388aSLukasz Kazmierczak "org.freedesktop.DBus.Properties", "Set", 12129e6c388aSLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Report", "ReportActions", 12139e6c388aSLukasz Kazmierczak dbus::utility::DbusVariantType{dbusReportActions}); 12149e6c388aSLukasz Kazmierczak } 12159e6c388aSLukasz Kazmierczak 1216bd79bce8SPatrick Williams inline void setReportMetrics( 1217bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id, 1218a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>&& 1219a64919e8SBoleslaw Ogonczyk Makowski metrics) 12209e6c388aSLukasz Kazmierczak { 1221deae6a78SEd Tanous dbus::utility::getAllProperties( 1222deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1223deae6a78SEd Tanous telemetry::reportInterface, 1224ba498310SKrzysztof Grobelny [asyncResp, id = std::string(id), redfishMetrics = std::move(metrics)]( 12259e6c388aSLukasz Kazmierczak boost::system::error_code ec, 12269e6c388aSLukasz Kazmierczak const dbus::utility::DBusPropertiesMap& properties) mutable { 1227ba498310SKrzysztof Grobelny if (!verifyCommonErrors(asyncResp->res, id, ec)) 12289e6c388aSLukasz Kazmierczak { 12299e6c388aSLukasz Kazmierczak return; 12309e6c388aSLukasz Kazmierczak } 12319e6c388aSLukasz Kazmierczak 12329e6c388aSLukasz Kazmierczak ReadingParameters readingParams; 12339e6c388aSLukasz Kazmierczak 12349e6c388aSLukasz Kazmierczak const bool success = sdbusplus::unpackPropertiesNoThrow( 1235bd79bce8SPatrick Williams dbus_utils::UnpackErrorPrinter(), properties, 1236bd79bce8SPatrick Williams "ReadingParameters", readingParams); 12379e6c388aSLukasz Kazmierczak 12389e6c388aSLukasz Kazmierczak if (!success) 12399e6c388aSLukasz Kazmierczak { 12409e6c388aSLukasz Kazmierczak messages::internalError(asyncResp->res); 12419e6c388aSLukasz Kazmierczak return; 12429e6c388aSLukasz Kazmierczak } 12439e6c388aSLukasz Kazmierczak 1244bd79bce8SPatrick Williams auto updateMetricsReq = 1245bd79bce8SPatrick Williams std::make_shared<UpdateMetrics>(id, asyncResp); 12469e6c388aSLukasz Kazmierczak 12479e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 12489e6c388aSLukasz Kazmierczak chassisSensors; 12499e6c388aSLukasz Kazmierczak 12509e6c388aSLukasz Kazmierczak size_t index = 0; 1251a64919e8SBoleslaw Ogonczyk Makowski for (std::variant<nlohmann::json::object_t, std::nullptr_t>& 1252a64919e8SBoleslaw Ogonczyk Makowski metricVariant : redfishMetrics) 12539e6c388aSLukasz Kazmierczak { 1254a64919e8SBoleslaw Ogonczyk Makowski nlohmann::json::object_t* metric = 1255a64919e8SBoleslaw Ogonczyk Makowski std::get_if<nlohmann::json::object_t>(&metricVariant); 1256a64919e8SBoleslaw Ogonczyk Makowski if (metric == nullptr) 1257a64919e8SBoleslaw Ogonczyk Makowski { 1258a64919e8SBoleslaw Ogonczyk Makowski index++; 1259a64919e8SBoleslaw Ogonczyk Makowski continue; 1260a64919e8SBoleslaw Ogonczyk Makowski } 1261a64919e8SBoleslaw Ogonczyk Makowski 12629e6c388aSLukasz Kazmierczak AddReportArgs::MetricArgs metricArgs; 12639e6c388aSLukasz Kazmierczak std::vector< 12649e6c388aSLukasz Kazmierczak std::tuple<sdbusplus::message::object_path, std::string>> 12659e6c388aSLukasz Kazmierczak pathAndUri; 12669e6c388aSLukasz Kazmierczak 12679e6c388aSLukasz Kazmierczak if (index < readingParams.size()) 12689e6c388aSLukasz Kazmierczak { 12699e6c388aSLukasz Kazmierczak const ReadingParameters::value_type& existing = 12709e6c388aSLukasz Kazmierczak readingParams[index]; 12719e6c388aSLukasz Kazmierczak 1272dac07cadSBoleslaw Ogonczyk Makowski if (metric->empty()) 1273dac07cadSBoleslaw Ogonczyk Makowski { 12749e6c388aSLukasz Kazmierczak pathAndUri = std::get<0>(existing); 1275dac07cadSBoleslaw Ogonczyk Makowski } 12769e6c388aSLukasz Kazmierczak metricArgs.collectionFunction = std::get<1>(existing); 12779e6c388aSLukasz Kazmierczak metricArgs.collectionTimeScope = std::get<2>(existing); 12789e6c388aSLukasz Kazmierczak metricArgs.collectionDuration = std::get<3>(existing); 12799e6c388aSLukasz Kazmierczak } 12809e6c388aSLukasz Kazmierczak 1281a64919e8SBoleslaw Ogonczyk Makowski if (!getUserMetric(asyncResp->res, *metric, metricArgs)) 12829e6c388aSLukasz Kazmierczak { 12839e6c388aSLukasz Kazmierczak return; 12849e6c388aSLukasz Kazmierczak } 12859e6c388aSLukasz Kazmierczak 12869e6c388aSLukasz Kazmierczak std::optional<IncorrectMetricUri> error = 12879e6c388aSLukasz Kazmierczak getChassisSensorNode(metricArgs.uris, chassisSensors); 12889e6c388aSLukasz Kazmierczak 12899e6c388aSLukasz Kazmierczak if (error) 12909e6c388aSLukasz Kazmierczak { 12919e6c388aSLukasz Kazmierczak messages::propertyValueIncorrect( 12929e6c388aSLukasz Kazmierczak asyncResp->res, error->uri, 12939e6c388aSLukasz Kazmierczak "MetricProperties/" + std::to_string(error->index)); 12949e6c388aSLukasz Kazmierczak return; 12959e6c388aSLukasz Kazmierczak } 12969e6c388aSLukasz Kazmierczak 12979e6c388aSLukasz Kazmierczak updateMetricsReq->emplace(pathAndUri, metricArgs); 12989e6c388aSLukasz Kazmierczak index++; 12999e6c388aSLukasz Kazmierczak } 13009e6c388aSLukasz Kazmierczak 13019e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 13029e6c388aSLukasz Kazmierczak { 13039e6c388aSLukasz Kazmierczak retrieveUriToDbusMap( 13049e6c388aSLukasz Kazmierczak chassis, sensorType, 13059e6c388aSLukasz Kazmierczak [asyncResp, updateMetricsReq]( 13069e6c388aSLukasz Kazmierczak const boost::beast::http::status status, 13079e6c388aSLukasz Kazmierczak const std::map<std::string, std::string>& uriToDbus) { 13089e6c388aSLukasz Kazmierczak if (status != boost::beast::http::status::ok) 13099e6c388aSLukasz Kazmierczak { 13109e6c388aSLukasz Kazmierczak BMCWEB_LOG_ERROR( 13119e6c388aSLukasz Kazmierczak "Failed to retrieve URI to dbus sensors map with err {}", 13129e6c388aSLukasz Kazmierczak static_cast<unsigned>(status)); 13139e6c388aSLukasz Kazmierczak return; 13149e6c388aSLukasz Kazmierczak } 13159e6c388aSLukasz Kazmierczak updateMetricsReq->insert(uriToDbus); 13169e6c388aSLukasz Kazmierczak }); 13179e6c388aSLukasz Kazmierczak } 13189e6c388aSLukasz Kazmierczak }); 13199e6c388aSLukasz Kazmierczak } 1320081ebf06SWludzik, Jozef 13214220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead( 13224220be3bSEd Tanous App& app, const crow::Request& req, 13234220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 13244220be3bSEd Tanous { 13254220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13264220be3bSEd Tanous { 13274220be3bSEd Tanous return; 13284220be3bSEd Tanous } 13294220be3bSEd Tanous asyncResp->res.addHeader( 13304220be3bSEd Tanous boost::beast::http::field::link, 13314220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby"); 13324220be3bSEd Tanous } 13334220be3bSEd Tanous 13344220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet( 1335fc0edbe3SEd Tanous App& app, const crow::Request& req, 1336fc0edbe3SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1337fc0edbe3SEd Tanous { 1338fc0edbe3SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1339fc0edbe3SEd Tanous { 1340fc0edbe3SEd Tanous return; 1341fc0edbe3SEd Tanous } 13429e6c388aSLukasz Kazmierczak asyncResp->res.addHeader( 13439e6c388aSLukasz Kazmierczak boost::beast::http::field::link, 13449e6c388aSLukasz Kazmierczak "</redfish/v1/JsonSchemas/MetricReportDefinition/MetricReportDefinition.json>; rel=describedby"); 1345fc0edbe3SEd Tanous 1346fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1347fc0edbe3SEd Tanous "#MetricReportDefinitionCollection." 1348fc0edbe3SEd Tanous "MetricReportDefinitionCollection"; 1349fc0edbe3SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1350fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"; 1351fc0edbe3SEd Tanous asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; 1352fc0edbe3SEd Tanous constexpr std::array<std::string_view, 1> interfaces{ 1353fc0edbe3SEd Tanous telemetry::reportInterface}; 1354fc0edbe3SEd Tanous collection_util::getCollectionMembers( 1355fc0edbe3SEd Tanous asyncResp, 1356fc0edbe3SEd Tanous boost::urls::url( 1357fc0edbe3SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions"), 1358fc0edbe3SEd Tanous interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); 1359fc0edbe3SEd Tanous } 1360fc0edbe3SEd Tanous 1361bd79bce8SPatrick Williams inline void handleReportPatch( 1362bd79bce8SPatrick Williams App& app, const crow::Request& req, 1363bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id) 13649e6c388aSLukasz Kazmierczak { 13659e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 13669e6c388aSLukasz Kazmierczak { 13679e6c388aSLukasz Kazmierczak return; 13689e6c388aSLukasz Kazmierczak } 13699e6c388aSLukasz Kazmierczak 13709e6c388aSLukasz Kazmierczak std::optional<std::string> reportingTypeStr; 13719e6c388aSLukasz Kazmierczak std::optional<std::string> reportUpdatesStr; 13729e6c388aSLukasz Kazmierczak std::optional<bool> metricReportDefinitionEnabled; 1373a64919e8SBoleslaw Ogonczyk Makowski std::optional< 1374a64919e8SBoleslaw Ogonczyk Makowski std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 1375a64919e8SBoleslaw Ogonczyk Makowski metrics; 13769e6c388aSLukasz Kazmierczak std::optional<std::vector<std::string>> reportActionsStr; 1377b14f357fSEd Tanous std::optional<std::string> scheduleDurationStr; 13789e6c388aSLukasz Kazmierczak 1379afc474aeSMyung Bae if (!json_util::readJsonPatch( // 1380afc474aeSMyung Bae req, asyncResp->res, // 1381afc474aeSMyung Bae "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, // 1382afc474aeSMyung Bae "MetricReportDefinitionType", reportingTypeStr, // 1383afc474aeSMyung Bae "Metrics", metrics, // 1384afc474aeSMyung Bae "ReportActions", reportActionsStr, // 1385afc474aeSMyung Bae "ReportUpdates", reportUpdatesStr, // 1386afc474aeSMyung Bae "Schedule/RecurrenceInterval", scheduleDurationStr // 1387afc474aeSMyung Bae )) 13889e6c388aSLukasz Kazmierczak { 13899e6c388aSLukasz Kazmierczak return; 13909e6c388aSLukasz Kazmierczak } 13919e6c388aSLukasz Kazmierczak 13929e6c388aSLukasz Kazmierczak if (metricReportDefinitionEnabled) 13939e6c388aSLukasz Kazmierczak { 13949e6c388aSLukasz Kazmierczak setReportEnabled(asyncResp, id, *metricReportDefinitionEnabled); 13959e6c388aSLukasz Kazmierczak } 13969e6c388aSLukasz Kazmierczak 13979e6c388aSLukasz Kazmierczak if (reportUpdatesStr) 13989e6c388aSLukasz Kazmierczak { 1399b4361d63SEd Tanous setReportUpdates(asyncResp, id, *reportUpdatesStr); 14009e6c388aSLukasz Kazmierczak } 14019e6c388aSLukasz Kazmierczak 14029e6c388aSLukasz Kazmierczak if (reportActionsStr) 14039e6c388aSLukasz Kazmierczak { 1404b4361d63SEd Tanous setReportActions(asyncResp, id, *reportActionsStr); 14059e6c388aSLukasz Kazmierczak } 14069e6c388aSLukasz Kazmierczak 1407b14f357fSEd Tanous if (reportingTypeStr || scheduleDurationStr) 14089e6c388aSLukasz Kazmierczak { 1409b4361d63SEd Tanous setReportTypeAndInterval(asyncResp, id, reportingTypeStr, 1410b4361d63SEd Tanous scheduleDurationStr); 14119e6c388aSLukasz Kazmierczak } 14129e6c388aSLukasz Kazmierczak 14139e6c388aSLukasz Kazmierczak if (metrics) 14149e6c388aSLukasz Kazmierczak { 1415ba498310SKrzysztof Grobelny setReportMetrics(asyncResp, id, std::move(*metrics)); 14169e6c388aSLukasz Kazmierczak } 14179e6c388aSLukasz Kazmierczak } 14189e6c388aSLukasz Kazmierczak 1419bd79bce8SPatrick Williams inline void handleReportDelete( 1420bd79bce8SPatrick Williams App& app, const crow::Request& req, 1421bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id) 14229e6c388aSLukasz Kazmierczak { 14239e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14249e6c388aSLukasz Kazmierczak { 14259e6c388aSLukasz Kazmierczak return; 14269e6c388aSLukasz Kazmierczak } 14279e6c388aSLukasz Kazmierczak 14289e6c388aSLukasz Kazmierczak const std::string reportPath = getDbusReportPath(id); 14299e6c388aSLukasz Kazmierczak 14309e6c388aSLukasz Kazmierczak crow::connections::systemBus->async_method_call( 14319e6c388aSLukasz Kazmierczak [asyncResp, 14329e6c388aSLukasz Kazmierczak reportId = std::string(id)](const boost::system::error_code& ec) { 14339e6c388aSLukasz Kazmierczak if (!verifyCommonErrors(asyncResp->res, reportId, ec)) 14349e6c388aSLukasz Kazmierczak { 14359e6c388aSLukasz Kazmierczak return; 14369e6c388aSLukasz Kazmierczak } 14379e6c388aSLukasz Kazmierczak asyncResp->res.result(boost::beast::http::status::no_content); 14389e6c388aSLukasz Kazmierczak }, 14399e6c388aSLukasz Kazmierczak service, reportPath, "xyz.openbmc_project.Object.Delete", "Delete"); 14409e6c388aSLukasz Kazmierczak } 14419e6c388aSLukasz Kazmierczak } // namespace telemetry 14429e6c388aSLukasz Kazmierczak 144395bdb5f0SEd Tanous inline void afterRetrieveUriToDbusMap( 144495bdb5f0SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/, 144595bdb5f0SEd Tanous const std::shared_ptr<telemetry::AddReport>& addReportReq, 144695bdb5f0SEd Tanous const boost::beast::http::status status, 144795bdb5f0SEd Tanous const std::map<std::string, std::string>& uriToDbus) 144895bdb5f0SEd Tanous { 144995bdb5f0SEd Tanous if (status != boost::beast::http::status::ok) 145095bdb5f0SEd Tanous { 145195bdb5f0SEd Tanous BMCWEB_LOG_ERROR( 145295bdb5f0SEd Tanous "Failed to retrieve URI to dbus sensors map with err {}", 145395bdb5f0SEd Tanous static_cast<unsigned>(status)); 145495bdb5f0SEd Tanous return; 145595bdb5f0SEd Tanous } 145695bdb5f0SEd Tanous addReportReq->insert(uriToDbus); 145795bdb5f0SEd Tanous } 145895bdb5f0SEd Tanous 14599e6c388aSLukasz Kazmierczak inline void handleMetricReportDefinitionsPost( 14609e6c388aSLukasz Kazmierczak App& app, const crow::Request& req, 14619e6c388aSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 14629e6c388aSLukasz Kazmierczak { 14639e6c388aSLukasz Kazmierczak if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14649e6c388aSLukasz Kazmierczak { 14659e6c388aSLukasz Kazmierczak return; 14669e6c388aSLukasz Kazmierczak } 14679e6c388aSLukasz Kazmierczak 14689e6c388aSLukasz Kazmierczak telemetry::AddReportArgs args; 14699e6c388aSLukasz Kazmierczak if (!telemetry::getUserParameters(asyncResp->res, req, args)) 14709e6c388aSLukasz Kazmierczak { 14719e6c388aSLukasz Kazmierczak return; 14729e6c388aSLukasz Kazmierczak } 14739e6c388aSLukasz Kazmierczak 14749e6c388aSLukasz Kazmierczak boost::container::flat_set<std::pair<std::string, std::string>> 14759e6c388aSLukasz Kazmierczak chassisSensors; 14769e6c388aSLukasz Kazmierczak if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, 14779e6c388aSLukasz Kazmierczak chassisSensors)) 14789e6c388aSLukasz Kazmierczak { 14799e6c388aSLukasz Kazmierczak return; 14809e6c388aSLukasz Kazmierczak } 14819e6c388aSLukasz Kazmierczak 1482bd79bce8SPatrick Williams auto addReportReq = 1483bd79bce8SPatrick Williams std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 14849e6c388aSLukasz Kazmierczak for (const auto& [chassis, sensorType] : chassisSensors) 14859e6c388aSLukasz Kazmierczak { 148695bdb5f0SEd Tanous retrieveUriToDbusMap(chassis, sensorType, 148795bdb5f0SEd Tanous std::bind_front(afterRetrieveUriToDbusMap, 148895bdb5f0SEd Tanous asyncResp, addReportReq)); 14899e6c388aSLukasz Kazmierczak } 14909e6c388aSLukasz Kazmierczak } 14919e6c388aSLukasz Kazmierczak 14929e6c388aSLukasz Kazmierczak inline void 14934220be3bSEd Tanous handleMetricReportHead(App& app, const crow::Request& req, 14944220be3bSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 14954220be3bSEd Tanous const std::string& /*id*/) 14964220be3bSEd Tanous { 14974220be3bSEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14984220be3bSEd Tanous { 14994220be3bSEd Tanous return; 15004220be3bSEd Tanous } 15014220be3bSEd Tanous asyncResp->res.addHeader( 15024220be3bSEd Tanous boost::beast::http::field::link, 15034220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 15044220be3bSEd Tanous } 15054220be3bSEd Tanous 1506bd79bce8SPatrick Williams inline void handleMetricReportGet( 1507bd79bce8SPatrick Williams App& app, const crow::Request& req, 1508bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 150986a5ac98SEd Tanous { 151086a5ac98SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 151186a5ac98SEd Tanous { 151286a5ac98SEd Tanous return; 151386a5ac98SEd Tanous } 15144220be3bSEd Tanous asyncResp->res.addHeader( 15154220be3bSEd Tanous boost::beast::http::field::link, 15164220be3bSEd Tanous "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby"); 151786a5ac98SEd Tanous 1518deae6a78SEd Tanous dbus::utility::getAllProperties( 1519deae6a78SEd Tanous telemetry::service, telemetry::getDbusReportPath(id), 1520deae6a78SEd Tanous telemetry::reportInterface, 152186a5ac98SEd Tanous [asyncResp, id](const boost::system::error_code& ec, 152286a5ac98SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 15239e6c388aSLukasz Kazmierczak if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec)) 152486a5ac98SEd Tanous { 152586a5ac98SEd Tanous return; 152686a5ac98SEd Tanous } 152786a5ac98SEd Tanous 152886a5ac98SEd Tanous telemetry::fillReportDefinition(asyncResp, id, properties); 152986a5ac98SEd Tanous }); 153086a5ac98SEd Tanous } 153186a5ac98SEd Tanous 1532dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete( 1533dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 1534dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 1535dd1c4a9cSSzymon Dompke 1536dd1c4a9cSSzymon Dompke { 1537dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1538dd1c4a9cSSzymon Dompke { 1539dd1c4a9cSSzymon Dompke return; 1540dd1c4a9cSSzymon Dompke } 1541dd1c4a9cSSzymon Dompke 1542dd1c4a9cSSzymon Dompke const std::string reportPath = telemetry::getDbusReportPath(id); 1543dd1c4a9cSSzymon Dompke 1544dd1c4a9cSSzymon Dompke crow::connections::systemBus->async_method_call( 1545dd1c4a9cSSzymon Dompke [asyncResp, id](const boost::system::error_code& ec) { 1546dd1c4a9cSSzymon Dompke /* 1547dd1c4a9cSSzymon Dompke * boost::system::errc and std::errc are missing value 1548dd1c4a9cSSzymon Dompke * for EBADR error that is defined in Linux. 1549dd1c4a9cSSzymon Dompke */ 1550dd1c4a9cSSzymon Dompke if (ec.value() == EBADR) 1551dd1c4a9cSSzymon Dompke { 1552bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, 1553bd79bce8SPatrick Williams "MetricReportDefinition", id); 1554dd1c4a9cSSzymon Dompke return; 1555dd1c4a9cSSzymon Dompke } 1556dd1c4a9cSSzymon Dompke 1557dd1c4a9cSSzymon Dompke if (ec) 1558dd1c4a9cSSzymon Dompke { 155962598e31SEd Tanous BMCWEB_LOG_ERROR("respHandler DBus error {}", ec); 1560dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 1561dd1c4a9cSSzymon Dompke return; 1562dd1c4a9cSSzymon Dompke } 1563dd1c4a9cSSzymon Dompke 1564dd1c4a9cSSzymon Dompke asyncResp->res.result(boost::beast::http::status::no_content); 1565dd1c4a9cSSzymon Dompke }, 1566dd1c4a9cSSzymon Dompke telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 1567dd1c4a9cSSzymon Dompke "Delete"); 1568dd1c4a9cSSzymon Dompke } 1569dd1c4a9cSSzymon Dompke 15707e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app) 1571081ebf06SWludzik, Jozef { 15727e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 15734220be3bSEd Tanous .privileges(redfish::privileges::headMetricReportDefinitionCollection) 15744220be3bSEd Tanous .methods(boost::beast::http::verb::head)(std::bind_front( 15759e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionHead, 15769e6c388aSLukasz Kazmierczak std::ref(app))); 15774220be3bSEd Tanous 15784220be3bSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1579ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinitionCollection) 15804220be3bSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 15819e6c388aSLukasz Kazmierczak telemetry::handleMetricReportDefinitionCollectionGet, 15829e6c388aSLukasz Kazmierczak std::ref(app))); 15834dbb8aeaSWludzik, Jozef 15847e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 1585ed398213SEd Tanous .privileges(redfish::privileges::postMetricReportDefinitionCollection) 1586002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 15879e6c388aSLukasz Kazmierczak std::bind_front(handleMetricReportDefinitionsPost, std::ref(app))); 1588081ebf06SWludzik, Jozef } 1589081ebf06SWludzik, Jozef 15907e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app) 1591081ebf06SWludzik, Jozef { 15927e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 15937e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 1594ed398213SEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 15954220be3bSEd Tanous .methods(boost::beast::http::verb::head)( 15964220be3bSEd Tanous std::bind_front(handleMetricReportHead, std::ref(app))); 15974220be3bSEd Tanous 15984220be3bSEd Tanous BMCWEB_ROUTE(app, 15994220be3bSEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 16004220be3bSEd Tanous .privileges(redfish::privileges::getMetricReportDefinition) 16017e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 160286a5ac98SEd Tanous std::bind_front(handleMetricReportGet, std::ref(app))); 1603479e899dSKrzysztof Grobelny 16047e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 16057e860f15SJohn Edward Broadbent "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 16069e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::deleteMetricReportDefinition) 16077e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 1608dd1c4a9cSSzymon Dompke std::bind_front(handleMetricReportDelete, std::ref(app))); 16099e6c388aSLukasz Kazmierczak 16109e6c388aSLukasz Kazmierczak BMCWEB_ROUTE(app, 16119e6c388aSLukasz Kazmierczak "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") 16129e6c388aSLukasz Kazmierczak .privileges(redfish::privileges::patchMetricReportDefinition) 16139e6c388aSLukasz Kazmierczak .methods(boost::beast::http::verb::patch)( 16149e6c388aSLukasz Kazmierczak std::bind_front(telemetry::handleReportPatch, std::ref(app))); 16154dbb8aeaSWludzik, Jozef } 1616081ebf06SWludzik, Jozef } // namespace redfish 1617