xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision 7a1dbc4803bf78bfc0c574e6676b3c5def4cdae3)
1081ebf06SWludzik, Jozef #pragma once
2081ebf06SWludzik, Jozef 
34dbb8aeaSWludzik, Jozef #include "sensors.hpp"
4081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp"
5081ebf06SWludzik, Jozef #include "utils/time_utils.hpp"
6081ebf06SWludzik, Jozef 
77e860f15SJohn Edward Broadbent #include <app.hpp>
84dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp>
9168e20c1SEd Tanous #include <dbus_utility.hpp>
1045ca1b86SEd Tanous #include <query.hpp>
11ed398213SEd Tanous #include <registries/privilege_registry.hpp>
1289474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
1389474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
1489474494SKrzysztof Grobelny #include <utils/dbus_utils.hpp>
154dbb8aeaSWludzik, Jozef 
16*7a1dbc48SGeorge Liu #include <array>
17fe04d49cSNan Zhou #include <map>
18*7a1dbc48SGeorge Liu #include <string_view>
19081ebf06SWludzik, Jozef #include <tuple>
20081ebf06SWludzik, Jozef #include <variant>
21081ebf06SWludzik, Jozef 
22081ebf06SWludzik, Jozef namespace redfish
23081ebf06SWludzik, Jozef {
24081ebf06SWludzik, Jozef 
25081ebf06SWludzik, Jozef namespace telemetry
26081ebf06SWludzik, Jozef {
27081ebf06SWludzik, Jozef 
28081ebf06SWludzik, Jozef using ReadingParameters =
29081ebf06SWludzik, Jozef     std::vector<std::tuple<sdbusplus::message::object_path, std::string,
30081ebf06SWludzik, Jozef                            std::string, std::string>>;
31081ebf06SWludzik, Jozef 
32b9d36b47SEd Tanous inline void
33b9d36b47SEd Tanous     fillReportDefinition(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
34b9d36b47SEd Tanous                          const std::string& id,
35b9d36b47SEd Tanous                          const dbus::utility::DBusPropertiesMap& ret)
36081ebf06SWludzik, Jozef {
37081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.type"] =
38081ebf06SWludzik, Jozef         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
39079360aeSEd Tanous     asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
40079360aeSEd Tanous         "redfish", "v1", "TelemetryService", "MetricReportDefinitions", id);
41081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Id"] = id;
42081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Name"] = id;
43081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
44456cd875SSzymon Dompke         crow::utility::urlFromPieces("redfish", "v1", "TelemetryService",
45079360aeSEd Tanous                                      "MetricReports", id);
46081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
47081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite";
48081ebf06SWludzik, Jozef 
49081ebf06SWludzik, Jozef     const bool* emitsReadingsUpdate = nullptr;
50081ebf06SWludzik, Jozef     const bool* logToMetricReportsCollection = nullptr;
5189474494SKrzysztof Grobelny     const ReadingParameters* readingParameters = nullptr;
52081ebf06SWludzik, Jozef     const std::string* reportingType = nullptr;
53081ebf06SWludzik, Jozef     const uint64_t* interval = nullptr;
5489474494SKrzysztof Grobelny 
5589474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
5689474494SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), ret, "EmitsReadingsUpdate",
5789474494SKrzysztof Grobelny         emitsReadingsUpdate, "LogToMetricReportsCollection",
5889474494SKrzysztof Grobelny         logToMetricReportsCollection, "ReadingParameters", readingParameters,
5989474494SKrzysztof Grobelny         "ReportingType", reportingType, "Interval", interval);
6089474494SKrzysztof Grobelny 
6189474494SKrzysztof Grobelny     if (!success)
62081ebf06SWludzik, Jozef     {
63081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
64081ebf06SWludzik, Jozef         return;
65081ebf06SWludzik, Jozef     }
66081ebf06SWludzik, Jozef 
67081ebf06SWludzik, Jozef     std::vector<std::string> redfishReportActions;
68081ebf06SWludzik, Jozef     redfishReportActions.reserve(2);
6989474494SKrzysztof Grobelny     if (emitsReadingsUpdate != nullptr && *emitsReadingsUpdate)
70081ebf06SWludzik, Jozef     {
71081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("RedfishEvent");
72081ebf06SWludzik, Jozef     }
7389474494SKrzysztof Grobelny 
7489474494SKrzysztof Grobelny     if (logToMetricReportsCollection != nullptr &&
7589474494SKrzysztof Grobelny         *logToMetricReportsCollection)
76081ebf06SWludzik, Jozef     {
77081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("LogToMetricReportsCollection");
78081ebf06SWludzik, Jozef     }
79081ebf06SWludzik, Jozef 
80081ebf06SWludzik, Jozef     nlohmann::json metrics = nlohmann::json::array();
8189474494SKrzysztof Grobelny     if (readingParameters != nullptr)
8289474494SKrzysztof Grobelny     {
838a592810SEd Tanous         for (const auto& [sensorPath, operationType, metricId, metadata] :
8489474494SKrzysztof Grobelny              *readingParameters)
85081ebf06SWludzik, Jozef         {
86613dabeaSEd Tanous             nlohmann::json::object_t metric;
87613dabeaSEd Tanous             metric["MetricId"] = metricId;
88613dabeaSEd Tanous             metric["MetricProperties"] = nlohmann::json::array_t({metadata});
89613dabeaSEd Tanous             metrics.push_back(std::move(metric));
90081ebf06SWludzik, Jozef         }
9189474494SKrzysztof Grobelny     }
9289474494SKrzysztof Grobelny 
9389474494SKrzysztof Grobelny     if (reportingType != nullptr)
9489474494SKrzysztof Grobelny     {
95081ebf06SWludzik, Jozef         asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType;
9689474494SKrzysztof Grobelny     }
9789474494SKrzysztof Grobelny 
9889474494SKrzysztof Grobelny     if (interval != nullptr)
9989474494SKrzysztof Grobelny     {
100081ebf06SWludzik, Jozef         asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
101081ebf06SWludzik, Jozef             time_utils::toDurationString(std::chrono::milliseconds(*interval));
102081ebf06SWludzik, Jozef     }
1034dbb8aeaSWludzik, Jozef 
10489474494SKrzysztof Grobelny     asyncResp->res.jsonValue["Metrics"] = metrics;
10589474494SKrzysztof Grobelny     asyncResp->res.jsonValue["ReportActions"] = redfishReportActions;
10689474494SKrzysztof Grobelny }
10789474494SKrzysztof Grobelny 
1084dbb8aeaSWludzik, Jozef struct AddReportArgs
1094dbb8aeaSWludzik, Jozef {
1104dbb8aeaSWludzik, Jozef     std::string name;
1114dbb8aeaSWludzik, Jozef     std::string reportingType;
1124dbb8aeaSWludzik, Jozef     bool emitsReadingsUpdate = false;
1134dbb8aeaSWludzik, Jozef     bool logToMetricReportsCollection = false;
1144dbb8aeaSWludzik, Jozef     uint64_t interval = 0;
1154dbb8aeaSWludzik, Jozef     std::vector<std::pair<std::string, std::vector<std::string>>> metrics;
1164dbb8aeaSWludzik, Jozef };
1174dbb8aeaSWludzik, Jozef 
1184dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res,
1194dbb8aeaSWludzik, Jozef                                 std::vector<std::string>& actions,
1204dbb8aeaSWludzik, Jozef                                 AddReportArgs& args)
1214dbb8aeaSWludzik, Jozef {
1224dbb8aeaSWludzik, Jozef     size_t index = 0;
1234dbb8aeaSWludzik, Jozef     for (auto& action : actions)
1244dbb8aeaSWludzik, Jozef     {
1254dbb8aeaSWludzik, Jozef         if (action == "RedfishEvent")
1264dbb8aeaSWludzik, Jozef         {
1274dbb8aeaSWludzik, Jozef             args.emitsReadingsUpdate = true;
1284dbb8aeaSWludzik, Jozef         }
1294dbb8aeaSWludzik, Jozef         else if (action == "LogToMetricReportsCollection")
1304dbb8aeaSWludzik, Jozef         {
1314dbb8aeaSWludzik, Jozef             args.logToMetricReportsCollection = true;
1324dbb8aeaSWludzik, Jozef         }
1334dbb8aeaSWludzik, Jozef         else
1344dbb8aeaSWludzik, Jozef         {
1354dbb8aeaSWludzik, Jozef             messages::propertyValueNotInList(
1364dbb8aeaSWludzik, Jozef                 res, action, "ReportActions/" + std::to_string(index));
1374dbb8aeaSWludzik, Jozef             return false;
1384dbb8aeaSWludzik, Jozef         }
1394dbb8aeaSWludzik, Jozef         index++;
1404dbb8aeaSWludzik, Jozef     }
1414dbb8aeaSWludzik, Jozef     return true;
1424dbb8aeaSWludzik, Jozef }
1434dbb8aeaSWludzik, Jozef 
1444dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req,
1454dbb8aeaSWludzik, Jozef                               AddReportArgs& args)
1464dbb8aeaSWludzik, Jozef {
1474dbb8aeaSWludzik, Jozef     std::vector<nlohmann::json> metrics;
1484dbb8aeaSWludzik, Jozef     std::vector<std::string> reportActions;
1494dbb8aeaSWludzik, Jozef     std::optional<nlohmann::json> schedule;
15015ed6780SWilly Tu     if (!json_util::readJsonPatch(req, res, "Id", args.name, "Metrics", metrics,
15115ed6780SWilly Tu                                   "MetricReportDefinitionType",
15215ed6780SWilly Tu                                   args.reportingType, "ReportActions",
15315ed6780SWilly Tu                                   reportActions, "Schedule", schedule))
1544dbb8aeaSWludzik, Jozef     {
1554dbb8aeaSWludzik, Jozef         return false;
1564dbb8aeaSWludzik, Jozef     }
1574dbb8aeaSWludzik, Jozef 
1584dbb8aeaSWludzik, Jozef     constexpr const char* allowedCharactersInName =
1594dbb8aeaSWludzik, Jozef         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
1604dbb8aeaSWludzik, Jozef     if (args.name.empty() || args.name.find_first_not_of(
1614dbb8aeaSWludzik, Jozef                                  allowedCharactersInName) != std::string::npos)
1624dbb8aeaSWludzik, Jozef     {
1634dbb8aeaSWludzik, Jozef         BMCWEB_LOG_ERROR << "Failed to match " << args.name
1644dbb8aeaSWludzik, Jozef                          << " with allowed character "
1654dbb8aeaSWludzik, Jozef                          << allowedCharactersInName;
1664dbb8aeaSWludzik, Jozef         messages::propertyValueIncorrect(res, "Id", args.name);
1674dbb8aeaSWludzik, Jozef         return false;
1684dbb8aeaSWludzik, Jozef     }
1694dbb8aeaSWludzik, Jozef 
1704dbb8aeaSWludzik, Jozef     if (args.reportingType != "Periodic" && args.reportingType != "OnRequest")
1714dbb8aeaSWludzik, Jozef     {
1724dbb8aeaSWludzik, Jozef         messages::propertyValueNotInList(res, args.reportingType,
1734dbb8aeaSWludzik, Jozef                                          "MetricReportDefinitionType");
1744dbb8aeaSWludzik, Jozef         return false;
1754dbb8aeaSWludzik, Jozef     }
1764dbb8aeaSWludzik, Jozef 
1774dbb8aeaSWludzik, Jozef     if (!toDbusReportActions(res, reportActions, args))
1784dbb8aeaSWludzik, Jozef     {
1794dbb8aeaSWludzik, Jozef         return false;
1804dbb8aeaSWludzik, Jozef     }
1814dbb8aeaSWludzik, Jozef 
1824dbb8aeaSWludzik, Jozef     if (args.reportingType == "Periodic")
1834dbb8aeaSWludzik, Jozef     {
1844dbb8aeaSWludzik, Jozef         if (!schedule)
1854dbb8aeaSWludzik, Jozef         {
1864dbb8aeaSWludzik, Jozef             messages::createFailedMissingReqProperties(res, "Schedule");
1874dbb8aeaSWludzik, Jozef             return false;
1884dbb8aeaSWludzik, Jozef         }
1894dbb8aeaSWludzik, Jozef 
1904dbb8aeaSWludzik, Jozef         std::string durationStr;
1914dbb8aeaSWludzik, Jozef         if (!json_util::readJson(*schedule, res, "RecurrenceInterval",
1924dbb8aeaSWludzik, Jozef                                  durationStr))
1934dbb8aeaSWludzik, Jozef         {
1944dbb8aeaSWludzik, Jozef             return false;
1954dbb8aeaSWludzik, Jozef         }
1964dbb8aeaSWludzik, Jozef 
1974dbb8aeaSWludzik, Jozef         std::optional<std::chrono::milliseconds> durationNum =
1984dbb8aeaSWludzik, Jozef             time_utils::fromDurationString(durationStr);
1994dbb8aeaSWludzik, Jozef         if (!durationNum)
2004dbb8aeaSWludzik, Jozef         {
2014dbb8aeaSWludzik, Jozef             messages::propertyValueIncorrect(res, "RecurrenceInterval",
2024dbb8aeaSWludzik, Jozef                                              durationStr);
2034dbb8aeaSWludzik, Jozef             return false;
2044dbb8aeaSWludzik, Jozef         }
2054dbb8aeaSWludzik, Jozef         args.interval = static_cast<uint64_t>(durationNum->count());
2064dbb8aeaSWludzik, Jozef     }
2074dbb8aeaSWludzik, Jozef 
2084dbb8aeaSWludzik, Jozef     args.metrics.reserve(metrics.size());
2094dbb8aeaSWludzik, Jozef     for (auto& m : metrics)
2104dbb8aeaSWludzik, Jozef     {
2114dbb8aeaSWludzik, Jozef         std::string id;
2124dbb8aeaSWludzik, Jozef         std::vector<std::string> uris;
2134dbb8aeaSWludzik, Jozef         if (!json_util::readJson(m, res, "MetricId", id, "MetricProperties",
2144dbb8aeaSWludzik, Jozef                                  uris))
2154dbb8aeaSWludzik, Jozef         {
2164dbb8aeaSWludzik, Jozef             return false;
2174dbb8aeaSWludzik, Jozef         }
2184dbb8aeaSWludzik, Jozef 
2194dbb8aeaSWludzik, Jozef         args.metrics.emplace_back(std::move(id), std::move(uris));
2204dbb8aeaSWludzik, Jozef     }
2214dbb8aeaSWludzik, Jozef 
2224dbb8aeaSWludzik, Jozef     return true;
2234dbb8aeaSWludzik, Jozef }
2244dbb8aeaSWludzik, Jozef 
225ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics(
2268d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2274dbb8aeaSWludzik, Jozef     const std::vector<std::pair<std::string, std::vector<std::string>>>&
2284dbb8aeaSWludzik, Jozef         metrics,
2294dbb8aeaSWludzik, Jozef     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
2304dbb8aeaSWludzik, Jozef {
231ca1600c1SSzymon Dompke     for (const auto& metric : metrics)
2324dbb8aeaSWludzik, Jozef     {
233ca1600c1SSzymon Dompke         const std::vector<std::string>& uris = metric.second;
2344dbb8aeaSWludzik, Jozef 
235ca1600c1SSzymon Dompke         std::optional<IncorrectMetricUri> error =
236ca1600c1SSzymon Dompke             getChassisSensorNode(uris, matched);
237ca1600c1SSzymon Dompke         if (error)
2384dbb8aeaSWludzik, Jozef         {
239ca1600c1SSzymon Dompke             messages::propertyValueIncorrect(asyncResp->res, error->uri,
2404dbb8aeaSWludzik, Jozef                                              "MetricProperties/" +
241ca1600c1SSzymon Dompke                                                  std::to_string(error->index));
2424dbb8aeaSWludzik, Jozef             return false;
2434dbb8aeaSWludzik, Jozef         }
2444dbb8aeaSWludzik, Jozef     }
2454dbb8aeaSWludzik, Jozef     return true;
2464dbb8aeaSWludzik, Jozef }
2474dbb8aeaSWludzik, Jozef 
2484dbb8aeaSWludzik, Jozef class AddReport
2494dbb8aeaSWludzik, Jozef {
2504dbb8aeaSWludzik, Jozef   public:
2518d1b46d7Szhanghch05     AddReport(AddReportArgs argsIn,
2528a592810SEd Tanous               const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
2538a592810SEd Tanous         asyncResp(asyncRespIn),
2548d1b46d7Szhanghch05         args{std::move(argsIn)}
2554dbb8aeaSWludzik, Jozef     {}
2564dbb8aeaSWludzik, Jozef     ~AddReport()
2574dbb8aeaSWludzik, Jozef     {
2584dbb8aeaSWludzik, Jozef         if (asyncResp->res.result() != boost::beast::http::status::ok)
2594dbb8aeaSWludzik, Jozef         {
2604dbb8aeaSWludzik, Jozef             return;
2614dbb8aeaSWludzik, Jozef         }
2624dbb8aeaSWludzik, Jozef 
2634dbb8aeaSWludzik, Jozef         telemetry::ReadingParameters readingParams;
2644dbb8aeaSWludzik, Jozef         readingParams.reserve(args.metrics.size());
2654dbb8aeaSWludzik, Jozef 
2664dbb8aeaSWludzik, Jozef         for (const auto& [id, uris] : args.metrics)
2674dbb8aeaSWludzik, Jozef         {
2684dbb8aeaSWludzik, Jozef             for (size_t i = 0; i < uris.size(); i++)
2694dbb8aeaSWludzik, Jozef             {
2704dbb8aeaSWludzik, Jozef                 const std::string& uri = uris[i];
2714dbb8aeaSWludzik, Jozef                 auto el = uriToDbus.find(uri);
2724dbb8aeaSWludzik, Jozef                 if (el == uriToDbus.end())
2734dbb8aeaSWludzik, Jozef                 {
2740fda0f12SGeorge Liu                     BMCWEB_LOG_ERROR
2750fda0f12SGeorge Liu                         << "Failed to find DBus sensor corresponding to URI "
2764dbb8aeaSWludzik, Jozef                         << uri;
2774dbb8aeaSWludzik, Jozef                     messages::propertyValueNotInList(asyncResp->res, uri,
2784dbb8aeaSWludzik, Jozef                                                      "MetricProperties/" +
2794dbb8aeaSWludzik, Jozef                                                          std::to_string(i));
2804dbb8aeaSWludzik, Jozef                     return;
2814dbb8aeaSWludzik, Jozef                 }
2824dbb8aeaSWludzik, Jozef 
2834dbb8aeaSWludzik, Jozef                 const std::string& dbusPath = el->second;
2844dbb8aeaSWludzik, Jozef                 readingParams.emplace_back(dbusPath, "SINGLE", id, uri);
2854dbb8aeaSWludzik, Jozef             }
2864dbb8aeaSWludzik, Jozef         }
2878d1b46d7Szhanghch05         const std::shared_ptr<bmcweb::AsyncResp> aResp = asyncResp;
2884dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
2898d1b46d7Szhanghch05             [aResp, name = args.name, uriToDbus = std::move(uriToDbus)](
2904dbb8aeaSWludzik, Jozef                 const boost::system::error_code ec, const std::string&) {
2914dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::file_exists)
2924dbb8aeaSWludzik, Jozef             {
2934dbb8aeaSWludzik, Jozef                 messages::resourceAlreadyExists(
2948d1b46d7Szhanghch05                     aResp->res, "MetricReportDefinition", "Id", name);
2954dbb8aeaSWludzik, Jozef                 return;
2964dbb8aeaSWludzik, Jozef             }
2974dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::too_many_files_open)
2984dbb8aeaSWludzik, Jozef             {
2998d1b46d7Szhanghch05                 messages::createLimitReachedForResource(aResp->res);
3004dbb8aeaSWludzik, Jozef                 return;
3014dbb8aeaSWludzik, Jozef             }
3024dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::argument_list_too_long)
3034dbb8aeaSWludzik, Jozef             {
3044dbb8aeaSWludzik, Jozef                 nlohmann::json metricProperties = nlohmann::json::array();
3054dbb8aeaSWludzik, Jozef                 for (const auto& [uri, _] : uriToDbus)
3064dbb8aeaSWludzik, Jozef                 {
3074dbb8aeaSWludzik, Jozef                     metricProperties.emplace_back(uri);
3084dbb8aeaSWludzik, Jozef                 }
309002d39b4SEd Tanous                 messages::propertyValueIncorrect(
310002d39b4SEd Tanous                     aResp->res, metricProperties.dump(), "MetricProperties");
3114dbb8aeaSWludzik, Jozef                 return;
3124dbb8aeaSWludzik, Jozef             }
3134dbb8aeaSWludzik, Jozef             if (ec)
3144dbb8aeaSWludzik, Jozef             {
3158d1b46d7Szhanghch05                 messages::internalError(aResp->res);
3164dbb8aeaSWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
3174dbb8aeaSWludzik, Jozef                 return;
3184dbb8aeaSWludzik, Jozef             }
3194dbb8aeaSWludzik, Jozef 
3208d1b46d7Szhanghch05             messages::created(aResp->res);
3214dbb8aeaSWludzik, Jozef             },
3224dbb8aeaSWludzik, Jozef             telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
3234dbb8aeaSWludzik, Jozef             "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
3244dbb8aeaSWludzik, Jozef             "TelemetryService/" + args.name, args.reportingType,
3254dbb8aeaSWludzik, Jozef             args.emitsReadingsUpdate, args.logToMetricReportsCollection,
3264dbb8aeaSWludzik, Jozef             args.interval, readingParams);
3274dbb8aeaSWludzik, Jozef     }
3284dbb8aeaSWludzik, Jozef 
329ecd6a3a2SEd Tanous     AddReport(const AddReport&) = delete;
330ecd6a3a2SEd Tanous     AddReport(AddReport&&) = delete;
331ecd6a3a2SEd Tanous     AddReport& operator=(const AddReport&) = delete;
332ecd6a3a2SEd Tanous     AddReport& operator=(AddReport&&) = delete;
333ecd6a3a2SEd Tanous 
334fe04d49cSNan Zhou     void insert(const std::map<std::string, std::string>& el)
3354dbb8aeaSWludzik, Jozef     {
3364dbb8aeaSWludzik, Jozef         uriToDbus.insert(el.begin(), el.end());
3374dbb8aeaSWludzik, Jozef     }
3384dbb8aeaSWludzik, Jozef 
3394dbb8aeaSWludzik, Jozef   private:
3408d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
3414dbb8aeaSWludzik, Jozef     AddReportArgs args;
3424dbb8aeaSWludzik, Jozef     boost::container::flat_map<std::string, std::string> uriToDbus{};
3434dbb8aeaSWludzik, Jozef };
344081ebf06SWludzik, Jozef } // namespace telemetry
345081ebf06SWludzik, Jozef 
3467e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app)
347081ebf06SWludzik, Jozef {
3487e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
349ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinitionCollection)
3507e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
35145ca1b86SEd Tanous             [&app](const crow::Request& req,
3527e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3533ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
35445ca1b86SEd Tanous         {
35545ca1b86SEd Tanous             return;
35645ca1b86SEd Tanous         }
35745ca1b86SEd Tanous 
3588d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.type"] =
3598d1b46d7Szhanghch05             "#MetricReportDefinitionCollection."
360081ebf06SWludzik, Jozef             "MetricReportDefinitionCollection";
3618d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.id"] =
362ae9031f0SWilly Tu             "/redfish/v1/TelemetryService/MetricReportDefinitions";
363002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "Metric Definition Collection";
364*7a1dbc48SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces{
365*7a1dbc48SGeorge Liu             telemetry::reportInterface};
3664028ff77SEd Tanous         collection_util::getCollectionMembers(
367ae9031f0SWilly Tu             asyncResp,
368ae9031f0SWilly Tu             boost::urls::url(
369ae9031f0SWilly Tu                 "/redfish/v1/TelemetryService/MetricReportDefinitions"),
370ae9031f0SWilly Tu             interfaces,
3714028ff77SEd Tanous             "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
3727e860f15SJohn Edward Broadbent         });
3734dbb8aeaSWludzik, Jozef 
3747e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
375ed398213SEd Tanous         .privileges(redfish::privileges::postMetricReportDefinitionCollection)
376002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
377002d39b4SEd Tanous             [&app](const crow::Request& req,
3787e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3793ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
38045ca1b86SEd Tanous         {
38145ca1b86SEd Tanous             return;
38245ca1b86SEd Tanous         }
38345ca1b86SEd Tanous 
3844dbb8aeaSWludzik, Jozef         telemetry::AddReportArgs args;
3858d1b46d7Szhanghch05         if (!telemetry::getUserParameters(asyncResp->res, req, args))
3864dbb8aeaSWludzik, Jozef         {
3874dbb8aeaSWludzik, Jozef             return;
3884dbb8aeaSWludzik, Jozef         }
3894dbb8aeaSWludzik, Jozef 
3904dbb8aeaSWludzik, Jozef         boost::container::flat_set<std::pair<std::string, std::string>>
3914dbb8aeaSWludzik, Jozef             chassisSensors;
392002d39b4SEd Tanous         if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics,
393002d39b4SEd Tanous                                                         chassisSensors))
3944dbb8aeaSWludzik, Jozef         {
3954dbb8aeaSWludzik, Jozef             return;
3964dbb8aeaSWludzik, Jozef         }
3974dbb8aeaSWludzik, Jozef 
398002d39b4SEd Tanous         auto addReportReq =
399002d39b4SEd Tanous             std::make_shared<telemetry::AddReport>(std::move(args), asyncResp);
4004dbb8aeaSWludzik, Jozef         for (const auto& [chassis, sensorType] : chassisSensors)
4014dbb8aeaSWludzik, Jozef         {
4024dbb8aeaSWludzik, Jozef             retrieveUriToDbusMap(
403021d32cfSKrzysztof Grobelny                 chassis, sensorType,
404002d39b4SEd Tanous                 [asyncResp, addReportReq](
405002d39b4SEd Tanous                     const boost::beast::http::status status,
406fe04d49cSNan Zhou                     const std::map<std::string, std::string>& uriToDbus) {
4074dbb8aeaSWludzik, Jozef                 if (status != boost::beast::http::status::ok)
4084dbb8aeaSWludzik, Jozef                 {
4097e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
4100fda0f12SGeorge Liu                         << "Failed to retrieve URI to dbus sensors map with err "
4114dbb8aeaSWludzik, Jozef                         << static_cast<unsigned>(status);
4124dbb8aeaSWludzik, Jozef                     return;
4134dbb8aeaSWludzik, Jozef                 }
4144dbb8aeaSWludzik, Jozef                 addReportReq->insert(uriToDbus);
4154dbb8aeaSWludzik, Jozef                 });
4164dbb8aeaSWludzik, Jozef         }
4177e860f15SJohn Edward Broadbent         });
418081ebf06SWludzik, Jozef }
419081ebf06SWludzik, Jozef 
4207e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app)
421081ebf06SWludzik, Jozef {
4227e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
4237e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
424ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
4257e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
42645ca1b86SEd Tanous             [&app](const crow::Request& req,
4277e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4287e860f15SJohn Edward Broadbent                    const std::string& id) {
4293ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
43045ca1b86SEd Tanous         {
43145ca1b86SEd Tanous             return;
43245ca1b86SEd Tanous         }
43345ca1b86SEd Tanous 
43489474494SKrzysztof Grobelny         sdbusplus::asio::getAllProperties(
43589474494SKrzysztof Grobelny             *crow::connections::systemBus, telemetry::service,
43689474494SKrzysztof Grobelny             telemetry::getDbusReportPath(id), telemetry::reportInterface,
437168e20c1SEd Tanous             [asyncResp,
438168e20c1SEd Tanous              id](const boost::system::error_code ec,
439081ebf06SWludzik, Jozef                  const std::vector<std::pair<
440002d39b4SEd Tanous                      std::string, dbus::utility::DbusVariantType>>& ret) {
441081ebf06SWludzik, Jozef             if (ec.value() == EBADR ||
442081ebf06SWludzik, Jozef                 ec == boost::system::errc::host_unreachable)
443081ebf06SWludzik, Jozef             {
444002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res,
445002d39b4SEd Tanous                                            "MetricReportDefinition", id);
446081ebf06SWludzik, Jozef                 return;
447081ebf06SWludzik, Jozef             }
448081ebf06SWludzik, Jozef             if (ec)
449081ebf06SWludzik, Jozef             {
450081ebf06SWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
451081ebf06SWludzik, Jozef                 messages::internalError(asyncResp->res);
452081ebf06SWludzik, Jozef                 return;
453081ebf06SWludzik, Jozef             }
454081ebf06SWludzik, Jozef 
455081ebf06SWludzik, Jozef             telemetry::fillReportDefinition(asyncResp, id, ret);
45689474494SKrzysztof Grobelny             });
4577e860f15SJohn Edward Broadbent         });
4587e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
4597e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
460ed398213SEd Tanous         .privileges(redfish::privileges::deleteMetricReportDefinitionCollection)
4617e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
46245ca1b86SEd Tanous             [&app](const crow::Request& req,
4637e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4647e860f15SJohn Edward Broadbent                    const std::string& id)
4654dbb8aeaSWludzik, Jozef 
4664dbb8aeaSWludzik, Jozef             {
4673ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
46845ca1b86SEd Tanous         {
46945ca1b86SEd Tanous             return;
47045ca1b86SEd Tanous         }
47145ca1b86SEd Tanous 
4724dbb8aeaSWludzik, Jozef         const std::string reportPath = telemetry::getDbusReportPath(id);
4734dbb8aeaSWludzik, Jozef 
4744dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
4754dbb8aeaSWludzik, Jozef             [asyncResp, id](const boost::system::error_code ec) {
4764dbb8aeaSWludzik, Jozef             /*
4777e860f15SJohn Edward Broadbent              * boost::system::errc and std::errc are missing value
4787e860f15SJohn Edward Broadbent              * for EBADR error that is defined in Linux.
4794dbb8aeaSWludzik, Jozef              */
4804dbb8aeaSWludzik, Jozef             if (ec.value() == EBADR)
4814dbb8aeaSWludzik, Jozef             {
482002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res,
483002d39b4SEd Tanous                                            "MetricReportDefinition", id);
4844dbb8aeaSWludzik, Jozef                 return;
4854dbb8aeaSWludzik, Jozef             }
4864dbb8aeaSWludzik, Jozef 
4874dbb8aeaSWludzik, Jozef             if (ec)
4884dbb8aeaSWludzik, Jozef             {
4894dbb8aeaSWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
4904dbb8aeaSWludzik, Jozef                 messages::internalError(asyncResp->res);
4914dbb8aeaSWludzik, Jozef                 return;
4924dbb8aeaSWludzik, Jozef             }
4934dbb8aeaSWludzik, Jozef 
494002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
4954dbb8aeaSWludzik, Jozef             },
496002d39b4SEd Tanous             telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete",
497002d39b4SEd Tanous             "Delete");
4987e860f15SJohn Edward Broadbent         });
4994dbb8aeaSWludzik, Jozef }
500081ebf06SWludzik, Jozef } // namespace redfish
501