xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision ca1600c10f43648ce90f84a2a712c6ebd043dded)
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>
124dbb8aeaSWludzik, Jozef 
13081ebf06SWludzik, Jozef #include <tuple>
14081ebf06SWludzik, Jozef #include <variant>
15081ebf06SWludzik, Jozef 
16081ebf06SWludzik, Jozef namespace redfish
17081ebf06SWludzik, Jozef {
18081ebf06SWludzik, Jozef 
19081ebf06SWludzik, Jozef namespace telemetry
20081ebf06SWludzik, Jozef {
21081ebf06SWludzik, Jozef 
22456cd875SSzymon Dompke constexpr const char* metricReportDefinitionUri =
23456cd875SSzymon Dompke     "/redfish/v1/TelemetryService/MetricReportDefinitions";
24456cd875SSzymon Dompke 
25081ebf06SWludzik, Jozef using ReadingParameters =
26081ebf06SWludzik, Jozef     std::vector<std::tuple<sdbusplus::message::object_path, std::string,
27081ebf06SWludzik, Jozef                            std::string, std::string>>;
28081ebf06SWludzik, Jozef 
29b9d36b47SEd Tanous inline void
30b9d36b47SEd Tanous     fillReportDefinition(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
31b9d36b47SEd Tanous                          const std::string& id,
32b9d36b47SEd Tanous                          const dbus::utility::DBusPropertiesMap& ret)
33081ebf06SWludzik, Jozef {
34081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.type"] =
35081ebf06SWludzik, Jozef         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
36081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.id"] =
37456cd875SSzymon Dompke         crow::utility::urlFromPieces("redfish", "v1", "TelemetryService",
38456cd875SSzymon Dompke                                      "MetricReportDefinitions", id)
39456cd875SSzymon Dompke             .string();
40081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Id"] = id;
41081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Name"] = id;
42081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
43456cd875SSzymon Dompke         crow::utility::urlFromPieces("redfish", "v1", "TelemetryService",
44456cd875SSzymon Dompke                                      "MetricReports", id)
45456cd875SSzymon Dompke             .string();
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;
51081ebf06SWludzik, Jozef     const ReadingParameters* readingParams = nullptr;
52081ebf06SWludzik, Jozef     const std::string* reportingType = nullptr;
53081ebf06SWludzik, Jozef     const uint64_t* interval = nullptr;
54081ebf06SWludzik, Jozef     for (const auto& [key, var] : ret)
55081ebf06SWludzik, Jozef     {
56081ebf06SWludzik, Jozef         if (key == "EmitsReadingsUpdate")
57081ebf06SWludzik, Jozef         {
58081ebf06SWludzik, Jozef             emitsReadingsUpdate = std::get_if<bool>(&var);
59081ebf06SWludzik, Jozef         }
60081ebf06SWludzik, Jozef         else if (key == "LogToMetricReportsCollection")
61081ebf06SWludzik, Jozef         {
62081ebf06SWludzik, Jozef             logToMetricReportsCollection = std::get_if<bool>(&var);
63081ebf06SWludzik, Jozef         }
64081ebf06SWludzik, Jozef         else if (key == "ReadingParameters")
65081ebf06SWludzik, Jozef         {
66081ebf06SWludzik, Jozef             readingParams = std::get_if<ReadingParameters>(&var);
67081ebf06SWludzik, Jozef         }
68081ebf06SWludzik, Jozef         else if (key == "ReportingType")
69081ebf06SWludzik, Jozef         {
70081ebf06SWludzik, Jozef             reportingType = std::get_if<std::string>(&var);
71081ebf06SWludzik, Jozef         }
72081ebf06SWludzik, Jozef         else if (key == "Interval")
73081ebf06SWludzik, Jozef         {
74081ebf06SWludzik, Jozef             interval = std::get_if<uint64_t>(&var);
75081ebf06SWludzik, Jozef         }
76081ebf06SWludzik, Jozef     }
77e662eae8SEd Tanous     if (emitsReadingsUpdate == nullptr ||
78e662eae8SEd Tanous         logToMetricReportsCollection == nullptr || readingParams == nullptr ||
79e662eae8SEd Tanous         reportingType == nullptr || interval == nullptr)
80081ebf06SWludzik, Jozef     {
81081ebf06SWludzik, Jozef         BMCWEB_LOG_ERROR << "Property type mismatch or property is missing";
82081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
83081ebf06SWludzik, Jozef         return;
84081ebf06SWludzik, Jozef     }
85081ebf06SWludzik, Jozef 
86081ebf06SWludzik, Jozef     std::vector<std::string> redfishReportActions;
87081ebf06SWludzik, Jozef     redfishReportActions.reserve(2);
88081ebf06SWludzik, Jozef     if (*emitsReadingsUpdate)
89081ebf06SWludzik, Jozef     {
90081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("RedfishEvent");
91081ebf06SWludzik, Jozef     }
92081ebf06SWludzik, Jozef     if (*logToMetricReportsCollection)
93081ebf06SWludzik, Jozef     {
94081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("LogToMetricReportsCollection");
95081ebf06SWludzik, Jozef     }
96081ebf06SWludzik, Jozef 
97081ebf06SWludzik, Jozef     nlohmann::json metrics = nlohmann::json::array();
989eb808c1SEd Tanous     for (const auto& [sensorPath, operationType, id, metadata] : *readingParams)
99081ebf06SWludzik, Jozef     {
100081ebf06SWludzik, Jozef         metrics.push_back({
101081ebf06SWludzik, Jozef             {"MetricId", id},
102081ebf06SWludzik, Jozef             {"MetricProperties", {metadata}},
103081ebf06SWludzik, Jozef         });
104081ebf06SWludzik, Jozef     }
105081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Metrics"] = metrics;
106081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType;
107081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["ReportActions"] = redfishReportActions;
108081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
109081ebf06SWludzik, Jozef         time_utils::toDurationString(std::chrono::milliseconds(*interval));
110081ebf06SWludzik, Jozef }
1114dbb8aeaSWludzik, Jozef 
1124dbb8aeaSWludzik, Jozef struct AddReportArgs
1134dbb8aeaSWludzik, Jozef {
1144dbb8aeaSWludzik, Jozef     std::string name;
1154dbb8aeaSWludzik, Jozef     std::string reportingType;
1164dbb8aeaSWludzik, Jozef     bool emitsReadingsUpdate = false;
1174dbb8aeaSWludzik, Jozef     bool logToMetricReportsCollection = false;
1184dbb8aeaSWludzik, Jozef     uint64_t interval = 0;
1194dbb8aeaSWludzik, Jozef     std::vector<std::pair<std::string, std::vector<std::string>>> metrics;
1204dbb8aeaSWludzik, Jozef };
1214dbb8aeaSWludzik, Jozef 
1224dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res,
1234dbb8aeaSWludzik, Jozef                                 std::vector<std::string>& actions,
1244dbb8aeaSWludzik, Jozef                                 AddReportArgs& args)
1254dbb8aeaSWludzik, Jozef {
1264dbb8aeaSWludzik, Jozef     size_t index = 0;
1274dbb8aeaSWludzik, Jozef     for (auto& action : actions)
1284dbb8aeaSWludzik, Jozef     {
1294dbb8aeaSWludzik, Jozef         if (action == "RedfishEvent")
1304dbb8aeaSWludzik, Jozef         {
1314dbb8aeaSWludzik, Jozef             args.emitsReadingsUpdate = true;
1324dbb8aeaSWludzik, Jozef         }
1334dbb8aeaSWludzik, Jozef         else if (action == "LogToMetricReportsCollection")
1344dbb8aeaSWludzik, Jozef         {
1354dbb8aeaSWludzik, Jozef             args.logToMetricReportsCollection = true;
1364dbb8aeaSWludzik, Jozef         }
1374dbb8aeaSWludzik, Jozef         else
1384dbb8aeaSWludzik, Jozef         {
1394dbb8aeaSWludzik, Jozef             messages::propertyValueNotInList(
1404dbb8aeaSWludzik, Jozef                 res, action, "ReportActions/" + std::to_string(index));
1414dbb8aeaSWludzik, Jozef             return false;
1424dbb8aeaSWludzik, Jozef         }
1434dbb8aeaSWludzik, Jozef         index++;
1444dbb8aeaSWludzik, Jozef     }
1454dbb8aeaSWludzik, Jozef     return true;
1464dbb8aeaSWludzik, Jozef }
1474dbb8aeaSWludzik, Jozef 
1484dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req,
1494dbb8aeaSWludzik, Jozef                               AddReportArgs& args)
1504dbb8aeaSWludzik, Jozef {
1514dbb8aeaSWludzik, Jozef     std::vector<nlohmann::json> metrics;
1524dbb8aeaSWludzik, Jozef     std::vector<std::string> reportActions;
1534dbb8aeaSWludzik, Jozef     std::optional<nlohmann::json> schedule;
15415ed6780SWilly Tu     if (!json_util::readJsonPatch(req, res, "Id", args.name, "Metrics", metrics,
15515ed6780SWilly Tu                                   "MetricReportDefinitionType",
15615ed6780SWilly Tu                                   args.reportingType, "ReportActions",
15715ed6780SWilly Tu                                   reportActions, "Schedule", schedule))
1584dbb8aeaSWludzik, Jozef     {
1594dbb8aeaSWludzik, Jozef         return false;
1604dbb8aeaSWludzik, Jozef     }
1614dbb8aeaSWludzik, Jozef 
1624dbb8aeaSWludzik, Jozef     constexpr const char* allowedCharactersInName =
1634dbb8aeaSWludzik, Jozef         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
1644dbb8aeaSWludzik, Jozef     if (args.name.empty() || args.name.find_first_not_of(
1654dbb8aeaSWludzik, Jozef                                  allowedCharactersInName) != std::string::npos)
1664dbb8aeaSWludzik, Jozef     {
1674dbb8aeaSWludzik, Jozef         BMCWEB_LOG_ERROR << "Failed to match " << args.name
1684dbb8aeaSWludzik, Jozef                          << " with allowed character "
1694dbb8aeaSWludzik, Jozef                          << allowedCharactersInName;
1704dbb8aeaSWludzik, Jozef         messages::propertyValueIncorrect(res, "Id", args.name);
1714dbb8aeaSWludzik, Jozef         return false;
1724dbb8aeaSWludzik, Jozef     }
1734dbb8aeaSWludzik, Jozef 
1744dbb8aeaSWludzik, Jozef     if (args.reportingType != "Periodic" && args.reportingType != "OnRequest")
1754dbb8aeaSWludzik, Jozef     {
1764dbb8aeaSWludzik, Jozef         messages::propertyValueNotInList(res, args.reportingType,
1774dbb8aeaSWludzik, Jozef                                          "MetricReportDefinitionType");
1784dbb8aeaSWludzik, Jozef         return false;
1794dbb8aeaSWludzik, Jozef     }
1804dbb8aeaSWludzik, Jozef 
1814dbb8aeaSWludzik, Jozef     if (!toDbusReportActions(res, reportActions, args))
1824dbb8aeaSWludzik, Jozef     {
1834dbb8aeaSWludzik, Jozef         return false;
1844dbb8aeaSWludzik, Jozef     }
1854dbb8aeaSWludzik, Jozef 
1864dbb8aeaSWludzik, Jozef     if (args.reportingType == "Periodic")
1874dbb8aeaSWludzik, Jozef     {
1884dbb8aeaSWludzik, Jozef         if (!schedule)
1894dbb8aeaSWludzik, Jozef         {
1904dbb8aeaSWludzik, Jozef             messages::createFailedMissingReqProperties(res, "Schedule");
1914dbb8aeaSWludzik, Jozef             return false;
1924dbb8aeaSWludzik, Jozef         }
1934dbb8aeaSWludzik, Jozef 
1944dbb8aeaSWludzik, Jozef         std::string durationStr;
1954dbb8aeaSWludzik, Jozef         if (!json_util::readJson(*schedule, res, "RecurrenceInterval",
1964dbb8aeaSWludzik, Jozef                                  durationStr))
1974dbb8aeaSWludzik, Jozef         {
1984dbb8aeaSWludzik, Jozef             return false;
1994dbb8aeaSWludzik, Jozef         }
2004dbb8aeaSWludzik, Jozef 
2014dbb8aeaSWludzik, Jozef         std::optional<std::chrono::milliseconds> durationNum =
2024dbb8aeaSWludzik, Jozef             time_utils::fromDurationString(durationStr);
2034dbb8aeaSWludzik, Jozef         if (!durationNum)
2044dbb8aeaSWludzik, Jozef         {
2054dbb8aeaSWludzik, Jozef             messages::propertyValueIncorrect(res, "RecurrenceInterval",
2064dbb8aeaSWludzik, Jozef                                              durationStr);
2074dbb8aeaSWludzik, Jozef             return false;
2084dbb8aeaSWludzik, Jozef         }
2094dbb8aeaSWludzik, Jozef         args.interval = static_cast<uint64_t>(durationNum->count());
2104dbb8aeaSWludzik, Jozef     }
2114dbb8aeaSWludzik, Jozef 
2124dbb8aeaSWludzik, Jozef     args.metrics.reserve(metrics.size());
2134dbb8aeaSWludzik, Jozef     for (auto& m : metrics)
2144dbb8aeaSWludzik, Jozef     {
2154dbb8aeaSWludzik, Jozef         std::string id;
2164dbb8aeaSWludzik, Jozef         std::vector<std::string> uris;
2174dbb8aeaSWludzik, Jozef         if (!json_util::readJson(m, res, "MetricId", id, "MetricProperties",
2184dbb8aeaSWludzik, Jozef                                  uris))
2194dbb8aeaSWludzik, Jozef         {
2204dbb8aeaSWludzik, Jozef             return false;
2214dbb8aeaSWludzik, Jozef         }
2224dbb8aeaSWludzik, Jozef 
2234dbb8aeaSWludzik, Jozef         args.metrics.emplace_back(std::move(id), std::move(uris));
2244dbb8aeaSWludzik, Jozef     }
2254dbb8aeaSWludzik, Jozef 
2264dbb8aeaSWludzik, Jozef     return true;
2274dbb8aeaSWludzik, Jozef }
2284dbb8aeaSWludzik, Jozef 
229*ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics(
2308d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2314dbb8aeaSWludzik, Jozef     const std::vector<std::pair<std::string, std::vector<std::string>>>&
2324dbb8aeaSWludzik, Jozef         metrics,
2334dbb8aeaSWludzik, Jozef     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
2344dbb8aeaSWludzik, Jozef {
235*ca1600c1SSzymon Dompke     for (const auto& metric : metrics)
2364dbb8aeaSWludzik, Jozef     {
237*ca1600c1SSzymon Dompke         const std::vector<std::string>& uris = metric.second;
2384dbb8aeaSWludzik, Jozef 
239*ca1600c1SSzymon Dompke         std::optional<IncorrectMetricUri> error =
240*ca1600c1SSzymon Dompke             getChassisSensorNode(uris, matched);
241*ca1600c1SSzymon Dompke         if (error)
2424dbb8aeaSWludzik, Jozef         {
243*ca1600c1SSzymon Dompke             messages::propertyValueIncorrect(asyncResp->res, error->uri,
2444dbb8aeaSWludzik, Jozef                                              "MetricProperties/" +
245*ca1600c1SSzymon Dompke                                                  std::to_string(error->index));
2464dbb8aeaSWludzik, Jozef             return false;
2474dbb8aeaSWludzik, Jozef         }
2484dbb8aeaSWludzik, Jozef     }
2494dbb8aeaSWludzik, Jozef     return true;
2504dbb8aeaSWludzik, Jozef }
2514dbb8aeaSWludzik, Jozef 
2524dbb8aeaSWludzik, Jozef class AddReport
2534dbb8aeaSWludzik, Jozef {
2544dbb8aeaSWludzik, Jozef   public:
2558d1b46d7Szhanghch05     AddReport(AddReportArgs argsIn,
2568d1b46d7Szhanghch05               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) :
2578d1b46d7Szhanghch05         asyncResp(asyncResp),
2588d1b46d7Szhanghch05         args{std::move(argsIn)}
2594dbb8aeaSWludzik, Jozef     {}
2604dbb8aeaSWludzik, Jozef     ~AddReport()
2614dbb8aeaSWludzik, Jozef     {
2624dbb8aeaSWludzik, Jozef         if (asyncResp->res.result() != boost::beast::http::status::ok)
2634dbb8aeaSWludzik, Jozef         {
2644dbb8aeaSWludzik, Jozef             return;
2654dbb8aeaSWludzik, Jozef         }
2664dbb8aeaSWludzik, Jozef 
2674dbb8aeaSWludzik, Jozef         telemetry::ReadingParameters readingParams;
2684dbb8aeaSWludzik, Jozef         readingParams.reserve(args.metrics.size());
2694dbb8aeaSWludzik, Jozef 
2704dbb8aeaSWludzik, Jozef         for (const auto& [id, uris] : args.metrics)
2714dbb8aeaSWludzik, Jozef         {
2724dbb8aeaSWludzik, Jozef             for (size_t i = 0; i < uris.size(); i++)
2734dbb8aeaSWludzik, Jozef             {
2744dbb8aeaSWludzik, Jozef                 const std::string& uri = uris[i];
2754dbb8aeaSWludzik, Jozef                 auto el = uriToDbus.find(uri);
2764dbb8aeaSWludzik, Jozef                 if (el == uriToDbus.end())
2774dbb8aeaSWludzik, Jozef                 {
2780fda0f12SGeorge Liu                     BMCWEB_LOG_ERROR
2790fda0f12SGeorge Liu                         << "Failed to find DBus sensor corresponding to URI "
2804dbb8aeaSWludzik, Jozef                         << uri;
2814dbb8aeaSWludzik, Jozef                     messages::propertyValueNotInList(asyncResp->res, uri,
2824dbb8aeaSWludzik, Jozef                                                      "MetricProperties/" +
2834dbb8aeaSWludzik, Jozef                                                          std::to_string(i));
2844dbb8aeaSWludzik, Jozef                     return;
2854dbb8aeaSWludzik, Jozef                 }
2864dbb8aeaSWludzik, Jozef 
2874dbb8aeaSWludzik, Jozef                 const std::string& dbusPath = el->second;
2884dbb8aeaSWludzik, Jozef                 readingParams.emplace_back(dbusPath, "SINGLE", id, uri);
2894dbb8aeaSWludzik, Jozef             }
2904dbb8aeaSWludzik, Jozef         }
2918d1b46d7Szhanghch05         const std::shared_ptr<bmcweb::AsyncResp> aResp = asyncResp;
2924dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
2938d1b46d7Szhanghch05             [aResp, name = args.name, uriToDbus = std::move(uriToDbus)](
2944dbb8aeaSWludzik, Jozef                 const boost::system::error_code ec, const std::string&) {
2954dbb8aeaSWludzik, Jozef                 if (ec == boost::system::errc::file_exists)
2964dbb8aeaSWludzik, Jozef                 {
2974dbb8aeaSWludzik, Jozef                     messages::resourceAlreadyExists(
2988d1b46d7Szhanghch05                         aResp->res, "MetricReportDefinition", "Id", name);
2994dbb8aeaSWludzik, Jozef                     return;
3004dbb8aeaSWludzik, Jozef                 }
3014dbb8aeaSWludzik, Jozef                 if (ec == boost::system::errc::too_many_files_open)
3024dbb8aeaSWludzik, Jozef                 {
3038d1b46d7Szhanghch05                     messages::createLimitReachedForResource(aResp->res);
3044dbb8aeaSWludzik, Jozef                     return;
3054dbb8aeaSWludzik, Jozef                 }
3064dbb8aeaSWludzik, Jozef                 if (ec == boost::system::errc::argument_list_too_long)
3074dbb8aeaSWludzik, Jozef                 {
3084dbb8aeaSWludzik, Jozef                     nlohmann::json metricProperties = nlohmann::json::array();
3094dbb8aeaSWludzik, Jozef                     for (const auto& [uri, _] : uriToDbus)
3104dbb8aeaSWludzik, Jozef                     {
3114dbb8aeaSWludzik, Jozef                         metricProperties.emplace_back(uri);
3124dbb8aeaSWludzik, Jozef                     }
3131668ce6dSEd Tanous                     messages::propertyValueIncorrect(aResp->res,
3141668ce6dSEd Tanous                                                      metricProperties.dump(),
3151668ce6dSEd Tanous                                                      "MetricProperties");
3164dbb8aeaSWludzik, Jozef                     return;
3174dbb8aeaSWludzik, Jozef                 }
3184dbb8aeaSWludzik, Jozef                 if (ec)
3194dbb8aeaSWludzik, Jozef                 {
3208d1b46d7Szhanghch05                     messages::internalError(aResp->res);
3214dbb8aeaSWludzik, Jozef                     BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
3224dbb8aeaSWludzik, Jozef                     return;
3234dbb8aeaSWludzik, Jozef                 }
3244dbb8aeaSWludzik, Jozef 
3258d1b46d7Szhanghch05                 messages::created(aResp->res);
3264dbb8aeaSWludzik, Jozef             },
3274dbb8aeaSWludzik, Jozef             telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
3284dbb8aeaSWludzik, Jozef             "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
3294dbb8aeaSWludzik, Jozef             "TelemetryService/" + args.name, args.reportingType,
3304dbb8aeaSWludzik, Jozef             args.emitsReadingsUpdate, args.logToMetricReportsCollection,
3314dbb8aeaSWludzik, Jozef             args.interval, readingParams);
3324dbb8aeaSWludzik, Jozef     }
3334dbb8aeaSWludzik, Jozef 
334ecd6a3a2SEd Tanous     AddReport(const AddReport&) = delete;
335ecd6a3a2SEd Tanous     AddReport(AddReport&&) = delete;
336ecd6a3a2SEd Tanous     AddReport& operator=(const AddReport&) = delete;
337ecd6a3a2SEd Tanous     AddReport& operator=(AddReport&&) = delete;
338ecd6a3a2SEd Tanous 
3394dbb8aeaSWludzik, Jozef     void insert(const boost::container::flat_map<std::string, std::string>& el)
3404dbb8aeaSWludzik, Jozef     {
3414dbb8aeaSWludzik, Jozef         uriToDbus.insert(el.begin(), el.end());
3424dbb8aeaSWludzik, Jozef     }
3434dbb8aeaSWludzik, Jozef 
3444dbb8aeaSWludzik, Jozef   private:
3458d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
3464dbb8aeaSWludzik, Jozef     AddReportArgs args;
3474dbb8aeaSWludzik, Jozef     boost::container::flat_map<std::string, std::string> uriToDbus{};
3484dbb8aeaSWludzik, Jozef };
349081ebf06SWludzik, Jozef } // namespace telemetry
350081ebf06SWludzik, Jozef 
3517e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app)
352081ebf06SWludzik, Jozef {
3537e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
354ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinitionCollection)
3557e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
35645ca1b86SEd Tanous             [&app](const crow::Request& req,
3577e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
35845ca1b86SEd Tanous                 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
35945ca1b86SEd Tanous                 {
36045ca1b86SEd Tanous                     return;
36145ca1b86SEd Tanous                 }
36245ca1b86SEd Tanous 
3638d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
3648d1b46d7Szhanghch05                     "#MetricReportDefinitionCollection."
365081ebf06SWludzik, Jozef                     "MetricReportDefinitionCollection";
3668d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
367456cd875SSzymon Dompke                     telemetry::metricReportDefinitionUri;
3687e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Name"] =
3697e860f15SJohn Edward Broadbent                     "Metric Definition Collection";
3704028ff77SEd Tanous                 const std::vector<const char*> interfaces{
3714028ff77SEd Tanous                     telemetry::reportInterface};
3724028ff77SEd Tanous                 collection_util::getCollectionMembers(
3734028ff77SEd Tanous                     asyncResp, telemetry::metricReportDefinitionUri, interfaces,
3744028ff77SEd Tanous                     "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
3757e860f15SJohn Edward Broadbent             });
3764dbb8aeaSWludzik, Jozef 
3777e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
378ed398213SEd Tanous         .privileges(redfish::privileges::postMetricReportDefinitionCollection)
3790fda0f12SGeorge Liu         .methods(
3800fda0f12SGeorge Liu             boost::beast::http::verb::
38145ca1b86SEd Tanous                 post)([&app](
38245ca1b86SEd Tanous                           const crow::Request& req,
3837e860f15SJohn Edward Broadbent                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
38445ca1b86SEd Tanous             if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
38545ca1b86SEd Tanous             {
38645ca1b86SEd Tanous                 return;
38745ca1b86SEd Tanous             }
38845ca1b86SEd Tanous 
3894dbb8aeaSWludzik, Jozef             telemetry::AddReportArgs args;
3908d1b46d7Szhanghch05             if (!telemetry::getUserParameters(asyncResp->res, req, args))
3914dbb8aeaSWludzik, Jozef             {
3924dbb8aeaSWludzik, Jozef                 return;
3934dbb8aeaSWludzik, Jozef             }
3944dbb8aeaSWludzik, Jozef 
3954dbb8aeaSWludzik, Jozef             boost::container::flat_set<std::pair<std::string, std::string>>
3964dbb8aeaSWludzik, Jozef                 chassisSensors;
397*ca1600c1SSzymon Dompke             if (!telemetry::getChassisSensorNodeFromMetrics(
398*ca1600c1SSzymon Dompke                     asyncResp, args.metrics, chassisSensors))
3994dbb8aeaSWludzik, Jozef             {
4004dbb8aeaSWludzik, Jozef                 return;
4014dbb8aeaSWludzik, Jozef             }
4024dbb8aeaSWludzik, Jozef 
4037e860f15SJohn Edward Broadbent             auto addReportReq = std::make_shared<telemetry::AddReport>(
4047e860f15SJohn Edward Broadbent                 std::move(args), asyncResp);
4054dbb8aeaSWludzik, Jozef             for (const auto& [chassis, sensorType] : chassisSensors)
4064dbb8aeaSWludzik, Jozef             {
4074dbb8aeaSWludzik, Jozef                 retrieveUriToDbusMap(
408021d32cfSKrzysztof Grobelny                     chassis, sensorType,
4090fda0f12SGeorge Liu                     [asyncResp,
4100fda0f12SGeorge Liu                      addReportReq](const boost::beast::http::status status,
4117e860f15SJohn Edward Broadbent                                    const boost::container::flat_map<
4127e860f15SJohn Edward Broadbent                                        std::string, std::string>& uriToDbus) {
4134dbb8aeaSWludzik, Jozef                         if (status != boost::beast::http::status::ok)
4144dbb8aeaSWludzik, Jozef                         {
4157e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR
4160fda0f12SGeorge Liu                                 << "Failed to retrieve URI to dbus sensors map with err "
4174dbb8aeaSWludzik, Jozef                                 << static_cast<unsigned>(status);
4184dbb8aeaSWludzik, Jozef                             return;
4194dbb8aeaSWludzik, Jozef                         }
4204dbb8aeaSWludzik, Jozef                         addReportReq->insert(uriToDbus);
4214dbb8aeaSWludzik, Jozef                     });
4224dbb8aeaSWludzik, Jozef             }
4237e860f15SJohn Edward Broadbent         });
424081ebf06SWludzik, Jozef }
425081ebf06SWludzik, Jozef 
4267e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app)
427081ebf06SWludzik, Jozef {
4287e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
4297e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
430ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
4317e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
43245ca1b86SEd Tanous             [&app](const crow::Request& req,
4337e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4347e860f15SJohn Edward Broadbent                    const std::string& id) {
43545ca1b86SEd Tanous                 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
43645ca1b86SEd Tanous                 {
43745ca1b86SEd Tanous                     return;
43845ca1b86SEd Tanous                 }
43945ca1b86SEd Tanous 
440081ebf06SWludzik, Jozef                 crow::connections::systemBus->async_method_call(
441168e20c1SEd Tanous                     [asyncResp,
442168e20c1SEd Tanous                      id](const boost::system::error_code ec,
443081ebf06SWludzik, Jozef                          const std::vector<std::pair<
444168e20c1SEd Tanous                              std::string, dbus::utility::DbusVariantType>>&
445168e20c1SEd Tanous                              ret) {
446081ebf06SWludzik, Jozef                         if (ec.value() == EBADR ||
447081ebf06SWludzik, Jozef                             ec == boost::system::errc::host_unreachable)
448081ebf06SWludzik, Jozef                         {
4497e860f15SJohn Edward Broadbent                             messages::resourceNotFound(
4507e860f15SJohn Edward Broadbent                                 asyncResp->res, "MetricReportDefinition", id);
451081ebf06SWludzik, Jozef                             return;
452081ebf06SWludzik, Jozef                         }
453081ebf06SWludzik, Jozef                         if (ec)
454081ebf06SWludzik, Jozef                         {
455081ebf06SWludzik, Jozef                             BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
456081ebf06SWludzik, Jozef                             messages::internalError(asyncResp->res);
457081ebf06SWludzik, Jozef                             return;
458081ebf06SWludzik, Jozef                         }
459081ebf06SWludzik, Jozef 
460081ebf06SWludzik, Jozef                         telemetry::fillReportDefinition(asyncResp, id, ret);
461081ebf06SWludzik, Jozef                     },
462081ebf06SWludzik, Jozef                     telemetry::service, telemetry::getDbusReportPath(id),
463081ebf06SWludzik, Jozef                     "org.freedesktop.DBus.Properties", "GetAll",
464081ebf06SWludzik, Jozef                     telemetry::reportInterface);
4657e860f15SJohn Edward Broadbent             });
4667e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
4677e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
468ed398213SEd Tanous         .privileges(redfish::privileges::deleteMetricReportDefinitionCollection)
4697e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
47045ca1b86SEd Tanous             [&app](const crow::Request& req,
4717e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4727e860f15SJohn Edward Broadbent                    const std::string& id)
4734dbb8aeaSWludzik, Jozef 
4744dbb8aeaSWludzik, Jozef             {
47545ca1b86SEd Tanous                 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
47645ca1b86SEd Tanous                 {
47745ca1b86SEd Tanous                     return;
47845ca1b86SEd Tanous                 }
47945ca1b86SEd Tanous 
4804dbb8aeaSWludzik, Jozef                 const std::string reportPath = telemetry::getDbusReportPath(id);
4814dbb8aeaSWludzik, Jozef 
4824dbb8aeaSWludzik, Jozef                 crow::connections::systemBus->async_method_call(
4834dbb8aeaSWludzik, Jozef                     [asyncResp, id](const boost::system::error_code ec) {
4844dbb8aeaSWludzik, Jozef                         /*
4857e860f15SJohn Edward Broadbent                          * boost::system::errc and std::errc are missing value
4867e860f15SJohn Edward Broadbent                          * for EBADR error that is defined in Linux.
4874dbb8aeaSWludzik, Jozef                          */
4884dbb8aeaSWludzik, Jozef                         if (ec.value() == EBADR)
4894dbb8aeaSWludzik, Jozef                         {
4907e860f15SJohn Edward Broadbent                             messages::resourceNotFound(
4917e860f15SJohn Edward Broadbent                                 asyncResp->res, "MetricReportDefinition", id);
4924dbb8aeaSWludzik, Jozef                             return;
4934dbb8aeaSWludzik, Jozef                         }
4944dbb8aeaSWludzik, Jozef 
4954dbb8aeaSWludzik, Jozef                         if (ec)
4964dbb8aeaSWludzik, Jozef                         {
4974dbb8aeaSWludzik, Jozef                             BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
4984dbb8aeaSWludzik, Jozef                             messages::internalError(asyncResp->res);
4994dbb8aeaSWludzik, Jozef                             return;
5004dbb8aeaSWludzik, Jozef                         }
5014dbb8aeaSWludzik, Jozef 
5027e860f15SJohn Edward Broadbent                         asyncResp->res.result(
5037e860f15SJohn Edward Broadbent                             boost::beast::http::status::no_content);
5044dbb8aeaSWludzik, Jozef                     },
5057e860f15SJohn Edward Broadbent                     telemetry::service, reportPath,
5067e860f15SJohn Edward Broadbent                     "xyz.openbmc_project.Object.Delete", "Delete");
5077e860f15SJohn Edward Broadbent             });
5084dbb8aeaSWludzik, Jozef }
509081ebf06SWludzik, Jozef } // namespace redfish
510