xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision 9e6c388a003d707136e26523dae84ba434695028)
1081ebf06SWludzik, Jozef #pragma once
2081ebf06SWludzik, Jozef 
33ccb3adbSEd Tanous #include "app.hpp"
43ccb3adbSEd Tanous #include "dbus_utility.hpp"
5479e899dSKrzysztof Grobelny #include "generated/enums/metric_report_definition.hpp"
63ccb3adbSEd Tanous #include "query.hpp"
73ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
84dbb8aeaSWludzik, Jozef #include "sensors.hpp"
93ccb3adbSEd Tanous #include "utils/collection.hpp"
103ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
11081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp"
12081ebf06SWludzik, Jozef #include "utils/time_utils.hpp"
13081ebf06SWludzik, Jozef 
144dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp>
15ef4c65b7SEd Tanous #include <boost/url/format.hpp>
1689474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
1789474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
184dbb8aeaSWludzik, Jozef 
197a1dbc48SGeorge Liu #include <array>
20fe04d49cSNan Zhou #include <map>
21f19ab44aSSzymon Dompke #include <optional>
22f19ab44aSSzymon Dompke #include <span>
23f19ab44aSSzymon Dompke #include <string>
247a1dbc48SGeorge Liu #include <string_view>
25081ebf06SWludzik, Jozef #include <tuple>
26f19ab44aSSzymon Dompke #include <utility>
27081ebf06SWludzik, Jozef #include <variant>
28f19ab44aSSzymon Dompke #include <vector>
29081ebf06SWludzik, Jozef 
30081ebf06SWludzik, Jozef namespace redfish
31081ebf06SWludzik, Jozef {
32081ebf06SWludzik, Jozef 
33081ebf06SWludzik, Jozef namespace telemetry
34081ebf06SWludzik, Jozef {
35081ebf06SWludzik, Jozef 
36479e899dSKrzysztof Grobelny using ReadingParameters = std::vector<std::tuple<
37479e899dSKrzysztof Grobelny     std::vector<std::tuple<sdbusplus::message::object_path, std::string>>,
38479e899dSKrzysztof Grobelny     std::string, std::string, uint64_t>>;
39479e899dSKrzysztof Grobelny 
40*9e6c388aSLukasz Kazmierczak inline bool verifyCommonErrors(crow::Response& res, const std::string& id,
41*9e6c388aSLukasz Kazmierczak                                const boost::system::error_code& ec)
42*9e6c388aSLukasz Kazmierczak {
43*9e6c388aSLukasz Kazmierczak     if (ec.value() == EBADR || ec == boost::system::errc::host_unreachable)
44*9e6c388aSLukasz Kazmierczak     {
45*9e6c388aSLukasz Kazmierczak         messages::resourceNotFound(res, "MetricReportDefinition", id);
46*9e6c388aSLukasz Kazmierczak         return false;
47*9e6c388aSLukasz Kazmierczak     }
48*9e6c388aSLukasz Kazmierczak 
49*9e6c388aSLukasz Kazmierczak     if (ec == boost::system::errc::file_exists)
50*9e6c388aSLukasz Kazmierczak     {
51*9e6c388aSLukasz Kazmierczak         messages::resourceAlreadyExists(res, "MetricReportDefinition", "Id",
52*9e6c388aSLukasz Kazmierczak                                         id);
53*9e6c388aSLukasz Kazmierczak         return false;
54*9e6c388aSLukasz Kazmierczak     }
55*9e6c388aSLukasz Kazmierczak 
56*9e6c388aSLukasz Kazmierczak     if (ec == boost::system::errc::too_many_files_open)
57*9e6c388aSLukasz Kazmierczak     {
58*9e6c388aSLukasz Kazmierczak         messages::createLimitReachedForResource(res);
59*9e6c388aSLukasz Kazmierczak         return false;
60*9e6c388aSLukasz Kazmierczak     }
61*9e6c388aSLukasz Kazmierczak 
62*9e6c388aSLukasz Kazmierczak     if (ec)
63*9e6c388aSLukasz Kazmierczak     {
64*9e6c388aSLukasz Kazmierczak         BMCWEB_LOG_ERROR("DBUS response error {}", ec);
65*9e6c388aSLukasz Kazmierczak         messages::internalError(res);
66*9e6c388aSLukasz Kazmierczak         return false;
67*9e6c388aSLukasz Kazmierczak     }
68*9e6c388aSLukasz Kazmierczak 
69*9e6c388aSLukasz Kazmierczak     return true;
70*9e6c388aSLukasz Kazmierczak }
71*9e6c388aSLukasz Kazmierczak 
72479e899dSKrzysztof Grobelny inline metric_report_definition::ReportActionsEnum
73479e899dSKrzysztof Grobelny     toRedfishReportAction(std::string_view dbusValue)
74479e899dSKrzysztof Grobelny {
75479e899dSKrzysztof Grobelny     if (dbusValue ==
76479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate")
77479e899dSKrzysztof Grobelny     {
78479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::RedfishEvent;
79479e899dSKrzysztof Grobelny     }
80479e899dSKrzysztof Grobelny     if (dbusValue ==
81479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection")
82479e899dSKrzysztof Grobelny     {
83479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::
84479e899dSKrzysztof Grobelny             LogToMetricReportsCollection;
85479e899dSKrzysztof Grobelny     }
86479e899dSKrzysztof Grobelny     return metric_report_definition::ReportActionsEnum::Invalid;
87479e899dSKrzysztof Grobelny }
88479e899dSKrzysztof Grobelny 
89479e899dSKrzysztof Grobelny inline std::string toDbusReportAction(std::string_view redfishValue)
90479e899dSKrzysztof Grobelny {
91479e899dSKrzysztof Grobelny     if (redfishValue == "RedfishEvent")
92479e899dSKrzysztof Grobelny     {
93479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate";
94479e899dSKrzysztof Grobelny     }
95479e899dSKrzysztof Grobelny     if (redfishValue == "LogToMetricReportsCollection")
96479e899dSKrzysztof Grobelny     {
97479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection";
98479e899dSKrzysztof Grobelny     }
99479e899dSKrzysztof Grobelny     return "";
100479e899dSKrzysztof Grobelny }
101479e899dSKrzysztof Grobelny 
102479e899dSKrzysztof Grobelny inline metric_report_definition::MetricReportDefinitionType
103479e899dSKrzysztof Grobelny     toRedfishReportingType(std::string_view dbusValue)
104479e899dSKrzysztof Grobelny {
105479e899dSKrzysztof Grobelny     if (dbusValue ==
106479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange")
107479e899dSKrzysztof Grobelny     {
108479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnChange;
109479e899dSKrzysztof Grobelny     }
110479e899dSKrzysztof Grobelny     if (dbusValue ==
111479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest")
112479e899dSKrzysztof Grobelny     {
113479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnRequest;
114479e899dSKrzysztof Grobelny     }
115479e899dSKrzysztof Grobelny     if (dbusValue ==
116479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic")
117479e899dSKrzysztof Grobelny     {
118479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::Periodic;
119479e899dSKrzysztof Grobelny     }
120479e899dSKrzysztof Grobelny     return metric_report_definition::MetricReportDefinitionType::Invalid;
121479e899dSKrzysztof Grobelny }
122479e899dSKrzysztof Grobelny 
123479e899dSKrzysztof Grobelny inline std::string toDbusReportingType(std::string_view redfishValue)
124479e899dSKrzysztof Grobelny {
125479e899dSKrzysztof Grobelny     if (redfishValue == "OnChange")
126479e899dSKrzysztof Grobelny     {
127479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange";
128479e899dSKrzysztof Grobelny     }
129479e899dSKrzysztof Grobelny     if (redfishValue == "OnRequest")
130479e899dSKrzysztof Grobelny     {
131479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest";
132479e899dSKrzysztof Grobelny     }
133479e899dSKrzysztof Grobelny     if (redfishValue == "Periodic")
134479e899dSKrzysztof Grobelny     {
135479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic";
136479e899dSKrzysztof Grobelny     }
137479e899dSKrzysztof Grobelny     return "";
138479e899dSKrzysztof Grobelny }
139479e899dSKrzysztof Grobelny 
140479e899dSKrzysztof Grobelny inline metric_report_definition::CollectionTimeScope
141479e899dSKrzysztof Grobelny     toRedfishCollectionTimeScope(std::string_view dbusValue)
142479e899dSKrzysztof Grobelny {
143479e899dSKrzysztof Grobelny     if (dbusValue ==
144479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point")
145479e899dSKrzysztof Grobelny     {
146479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Point;
147479e899dSKrzysztof Grobelny     }
148479e899dSKrzysztof Grobelny     if (dbusValue ==
149479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval")
150479e899dSKrzysztof Grobelny     {
151479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Interval;
152479e899dSKrzysztof Grobelny     }
153479e899dSKrzysztof Grobelny     if (dbusValue ==
154479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval")
155479e899dSKrzysztof Grobelny     {
156479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::StartupInterval;
157479e899dSKrzysztof Grobelny     }
158479e899dSKrzysztof Grobelny     return metric_report_definition::CollectionTimeScope::Invalid;
159479e899dSKrzysztof Grobelny }
160479e899dSKrzysztof Grobelny 
161479e899dSKrzysztof Grobelny inline std::string toDbusCollectionTimeScope(std::string_view redfishValue)
162479e899dSKrzysztof Grobelny {
163479e899dSKrzysztof Grobelny     if (redfishValue == "Point")
164479e899dSKrzysztof Grobelny     {
165479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point";
166479e899dSKrzysztof Grobelny     }
167479e899dSKrzysztof Grobelny     if (redfishValue == "Interval")
168479e899dSKrzysztof Grobelny     {
169479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval";
170479e899dSKrzysztof Grobelny     }
171479e899dSKrzysztof Grobelny     if (redfishValue == "StartupInterval")
172479e899dSKrzysztof Grobelny     {
173479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval";
174479e899dSKrzysztof Grobelny     }
175479e899dSKrzysztof Grobelny     return "";
176479e899dSKrzysztof Grobelny }
177479e899dSKrzysztof Grobelny 
178479e899dSKrzysztof Grobelny inline metric_report_definition::ReportUpdatesEnum
179479e899dSKrzysztof Grobelny     toRedfishReportUpdates(std::string_view dbusValue)
180479e899dSKrzysztof Grobelny {
181479e899dSKrzysztof Grobelny     if (dbusValue ==
182479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite")
183479e899dSKrzysztof Grobelny     {
184479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::Overwrite;
185479e899dSKrzysztof Grobelny     }
186479e899dSKrzysztof Grobelny     if (dbusValue ==
187479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull")
188479e899dSKrzysztof Grobelny     {
189479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendWrapsWhenFull;
190479e899dSKrzysztof Grobelny     }
191479e899dSKrzysztof Grobelny     if (dbusValue ==
192479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull")
193479e899dSKrzysztof Grobelny     {
194479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendStopsWhenFull;
195479e899dSKrzysztof Grobelny     }
196479e899dSKrzysztof Grobelny     return metric_report_definition::ReportUpdatesEnum::Invalid;
197479e899dSKrzysztof Grobelny }
198479e899dSKrzysztof Grobelny 
199479e899dSKrzysztof Grobelny inline std::string toDbusReportUpdates(std::string_view redfishValue)
200479e899dSKrzysztof Grobelny {
201479e899dSKrzysztof Grobelny     if (redfishValue == "Overwrite")
202479e899dSKrzysztof Grobelny     {
203479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite";
204479e899dSKrzysztof Grobelny     }
205479e899dSKrzysztof Grobelny     if (redfishValue == "AppendWrapsWhenFull")
206479e899dSKrzysztof Grobelny     {
207479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull";
208479e899dSKrzysztof Grobelny     }
209479e899dSKrzysztof Grobelny     if (redfishValue == "AppendStopsWhenFull")
210479e899dSKrzysztof Grobelny     {
211479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull";
212479e899dSKrzysztof Grobelny     }
213479e899dSKrzysztof Grobelny     return "";
214479e899dSKrzysztof Grobelny }
215081ebf06SWludzik, Jozef 
216f19ab44aSSzymon Dompke inline std::optional<nlohmann::json::array_t> getLinkedTriggers(
217f19ab44aSSzymon Dompke     std::span<const sdbusplus::message::object_path> triggerPaths)
218f19ab44aSSzymon Dompke {
219f19ab44aSSzymon Dompke     nlohmann::json::array_t triggers;
220f19ab44aSSzymon Dompke 
221f19ab44aSSzymon Dompke     for (const sdbusplus::message::object_path& path : triggerPaths)
222f19ab44aSSzymon Dompke     {
223f19ab44aSSzymon Dompke         if (path.parent_path() !=
224f19ab44aSSzymon Dompke             "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService")
225f19ab44aSSzymon Dompke         {
22662598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}",
22762598e31SEd Tanous                              path.str);
228f19ab44aSSzymon Dompke             return std::nullopt;
229f19ab44aSSzymon Dompke         }
230f19ab44aSSzymon Dompke 
231f19ab44aSSzymon Dompke         std::string id = path.filename();
232f19ab44aSSzymon Dompke         if (id.empty())
233f19ab44aSSzymon Dompke         {
23462598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}",
23562598e31SEd Tanous                              path.str);
236f19ab44aSSzymon Dompke             return std::nullopt;
237f19ab44aSSzymon Dompke         }
238f19ab44aSSzymon Dompke         nlohmann::json::object_t trigger;
239f19ab44aSSzymon Dompke         trigger["@odata.id"] =
240f19ab44aSSzymon Dompke             boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
241f19ab44aSSzymon Dompke         triggers.emplace_back(std::move(trigger));
242f19ab44aSSzymon Dompke     }
243f19ab44aSSzymon Dompke 
244f19ab44aSSzymon Dompke     return triggers;
245f19ab44aSSzymon Dompke }
246f19ab44aSSzymon Dompke 
247b9d36b47SEd Tanous inline void
248b9d36b47SEd Tanous     fillReportDefinition(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
249b9d36b47SEd Tanous                          const std::string& id,
250479e899dSKrzysztof Grobelny                          const dbus::utility::DBusPropertiesMap& properties)
251081ebf06SWludzik, Jozef {
252479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
253479e899dSKrzysztof Grobelny     ReadingParameters readingParams;
254479e899dSKrzysztof Grobelny     std::string reportingType;
255479e899dSKrzysztof Grobelny     std::string reportUpdates;
256479e899dSKrzysztof Grobelny     std::string name;
257479e899dSKrzysztof Grobelny     uint64_t appendLimit = 0;
258479e899dSKrzysztof Grobelny     uint64_t interval = 0;
259479e899dSKrzysztof Grobelny     bool enabled = false;
260f19ab44aSSzymon Dompke     std::vector<sdbusplus::message::object_path> triggers;
26189474494SKrzysztof Grobelny 
26289474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
263479e899dSKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "ReportingType",
264479e899dSKrzysztof Grobelny         reportingType, "Interval", interval, "ReportActions", reportActions,
265479e899dSKrzysztof Grobelny         "ReportUpdates", reportUpdates, "AppendLimit", appendLimit,
266f19ab44aSSzymon Dompke         "ReadingParameters", readingParams, "Name", name, "Enabled", enabled,
267f19ab44aSSzymon Dompke         "Triggers", triggers);
26889474494SKrzysztof Grobelny 
26989474494SKrzysztof Grobelny     if (!success)
270081ebf06SWludzik, Jozef     {
271081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
272081ebf06SWludzik, Jozef         return;
273081ebf06SWludzik, Jozef     }
274081ebf06SWludzik, Jozef 
275479e899dSKrzysztof Grobelny     metric_report_definition::MetricReportDefinitionType redfishReportingType =
276479e899dSKrzysztof Grobelny         toRedfishReportingType(reportingType);
277479e899dSKrzysztof Grobelny     if (redfishReportingType ==
278479e899dSKrzysztof Grobelny         metric_report_definition::MetricReportDefinitionType::Invalid)
279081ebf06SWludzik, Jozef     {
280479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
281479e899dSKrzysztof Grobelny         return;
282081ebf06SWludzik, Jozef     }
28389474494SKrzysztof Grobelny 
284479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionType"] =
285479e899dSKrzysztof Grobelny         redfishReportingType;
286479e899dSKrzysztof Grobelny 
287f19ab44aSSzymon Dompke     std::optional<nlohmann::json::array_t> linkedTriggers =
288f19ab44aSSzymon Dompke         getLinkedTriggers(triggers);
289f19ab44aSSzymon Dompke     if (!linkedTriggers)
290f19ab44aSSzymon Dompke     {
291f19ab44aSSzymon Dompke         messages::internalError(asyncResp->res);
292f19ab44aSSzymon Dompke         return;
293f19ab44aSSzymon Dompke     }
294f19ab44aSSzymon Dompke 
295f19ab44aSSzymon Dompke     asyncResp->res.jsonValue["Links"]["Triggers"] = std::move(*linkedTriggers);
296f19ab44aSSzymon Dompke 
297479e899dSKrzysztof Grobelny     nlohmann::json::array_t redfishReportActions;
298479e899dSKrzysztof Grobelny     for (const std::string& action : reportActions)
299081ebf06SWludzik, Jozef     {
300479e899dSKrzysztof Grobelny         metric_report_definition::ReportActionsEnum redfishAction =
301479e899dSKrzysztof Grobelny             toRedfishReportAction(action);
302479e899dSKrzysztof Grobelny         if (redfishAction ==
303479e899dSKrzysztof Grobelny             metric_report_definition::ReportActionsEnum::Invalid)
304479e899dSKrzysztof Grobelny         {
305479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
306479e899dSKrzysztof Grobelny             return;
307081ebf06SWludzik, Jozef         }
308081ebf06SWludzik, Jozef 
309479e899dSKrzysztof Grobelny         redfishReportActions.emplace_back(redfishAction);
310479e899dSKrzysztof Grobelny     }
311479e899dSKrzysztof Grobelny 
312479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions);
313479e899dSKrzysztof Grobelny 
314479e899dSKrzysztof Grobelny     nlohmann::json::array_t metrics = nlohmann::json::array();
315479e899dSKrzysztof Grobelny     for (const auto& [sensorData, collectionFunction, collectionTimeScope,
316479e899dSKrzysztof Grobelny                       collectionDuration] : readingParams)
31789474494SKrzysztof Grobelny     {
318479e899dSKrzysztof Grobelny         nlohmann::json::array_t metricProperties;
319479e899dSKrzysztof Grobelny 
320479e899dSKrzysztof Grobelny         for (const auto& [sensorPath, sensorMetadata] : sensorData)
321081ebf06SWludzik, Jozef         {
322479e899dSKrzysztof Grobelny             metricProperties.emplace_back(sensorMetadata);
323479e899dSKrzysztof Grobelny         }
324479e899dSKrzysztof Grobelny 
325613dabeaSEd Tanous         nlohmann::json::object_t metric;
326479e899dSKrzysztof Grobelny 
327479e899dSKrzysztof Grobelny         metric_report_definition::CalculationAlgorithmEnum
328479e899dSKrzysztof Grobelny             redfishCollectionFunction =
329479e899dSKrzysztof Grobelny                 telemetry::toRedfishCollectionFunction(collectionFunction);
330479e899dSKrzysztof Grobelny         if (redfishCollectionFunction ==
331479e899dSKrzysztof Grobelny             metric_report_definition::CalculationAlgorithmEnum::Invalid)
332479e899dSKrzysztof Grobelny         {
333479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
334479e899dSKrzysztof Grobelny             return;
335479e899dSKrzysztof Grobelny         }
336479e899dSKrzysztof Grobelny         metric["CollectionFunction"] = redfishCollectionFunction;
337479e899dSKrzysztof Grobelny 
338479e899dSKrzysztof Grobelny         metric_report_definition::CollectionTimeScope
339479e899dSKrzysztof Grobelny             redfishCollectionTimeScope =
340479e899dSKrzysztof Grobelny                 toRedfishCollectionTimeScope(collectionTimeScope);
341479e899dSKrzysztof Grobelny         if (redfishCollectionTimeScope ==
342479e899dSKrzysztof Grobelny             metric_report_definition::CollectionTimeScope::Invalid)
343479e899dSKrzysztof Grobelny         {
344479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
345479e899dSKrzysztof Grobelny             return;
346479e899dSKrzysztof Grobelny         }
347479e899dSKrzysztof Grobelny         metric["CollectionTimeScope"] = redfishCollectionTimeScope;
348479e899dSKrzysztof Grobelny 
349479e899dSKrzysztof Grobelny         metric["MetricProperties"] = std::move(metricProperties);
350479e899dSKrzysztof Grobelny         metric["CollectionDuration"] = time_utils::toDurationString(
351479e899dSKrzysztof Grobelny             std::chrono::milliseconds(collectionDuration));
352b2ba3072SPatrick Williams         metrics.emplace_back(std::move(metric));
353081ebf06SWludzik, Jozef     }
354479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Metrics"] = std::move(metrics);
355479e899dSKrzysztof Grobelny 
356479e899dSKrzysztof Grobelny     if (enabled)
357479e899dSKrzysztof Grobelny     {
358479e899dSKrzysztof Grobelny         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
359479e899dSKrzysztof Grobelny     }
360479e899dSKrzysztof Grobelny     else
361479e899dSKrzysztof Grobelny     {
362479e899dSKrzysztof Grobelny         asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
36389474494SKrzysztof Grobelny     }
36489474494SKrzysztof Grobelny 
365479e899dSKrzysztof Grobelny     metric_report_definition::ReportUpdatesEnum redfishReportUpdates =
366479e899dSKrzysztof Grobelny         toRedfishReportUpdates(reportUpdates);
367479e899dSKrzysztof Grobelny     if (redfishReportUpdates ==
368479e899dSKrzysztof Grobelny         metric_report_definition::ReportUpdatesEnum::Invalid)
36989474494SKrzysztof Grobelny     {
370479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
371479e899dSKrzysztof Grobelny         return;
37289474494SKrzysztof Grobelny     }
373479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportUpdates"] = redfishReportUpdates;
37489474494SKrzysztof Grobelny 
375479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionEnabled"] = enabled;
376479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["AppendLimit"] = appendLimit;
377479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Name"] = name;
378081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
379479e899dSKrzysztof Grobelny         time_utils::toDurationString(std::chrono::milliseconds(interval));
380479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.type"] =
381479e899dSKrzysztof Grobelny         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
382479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
383479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id);
384479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Id"] = id;
385479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format(
386479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReports/{}", id);
38789474494SKrzysztof Grobelny }
38889474494SKrzysztof Grobelny 
3894dbb8aeaSWludzik, Jozef struct AddReportArgs
3904dbb8aeaSWludzik, Jozef {
391479e899dSKrzysztof Grobelny     struct MetricArgs
392479e899dSKrzysztof Grobelny     {
393479e899dSKrzysztof Grobelny         std::vector<std::string> uris;
394479e899dSKrzysztof Grobelny         std::string collectionFunction;
395479e899dSKrzysztof Grobelny         std::string collectionTimeScope;
396479e899dSKrzysztof Grobelny         uint64_t collectionDuration = 0;
397479e899dSKrzysztof Grobelny     };
398479e899dSKrzysztof Grobelny 
399479e899dSKrzysztof Grobelny     std::string id;
4004dbb8aeaSWludzik, Jozef     std::string name;
4014dbb8aeaSWludzik, Jozef     std::string reportingType;
402479e899dSKrzysztof Grobelny     std::string reportUpdates;
403479e899dSKrzysztof Grobelny     uint64_t appendLimit = std::numeric_limits<uint64_t>::max();
404479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
405479e899dSKrzysztof Grobelny     uint64_t interval = std::numeric_limits<uint64_t>::max();
406479e899dSKrzysztof Grobelny     std::vector<MetricArgs> metrics;
407479e899dSKrzysztof Grobelny     bool metricReportDefinitionEnabled = true;
4084dbb8aeaSWludzik, Jozef };
4094dbb8aeaSWludzik, Jozef 
4104dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res,
411479e899dSKrzysztof Grobelny                                 const std::vector<std::string>& actions,
412*9e6c388aSLukasz Kazmierczak                                 std::vector<std::string>& outReportActions)
4134dbb8aeaSWludzik, Jozef {
4144dbb8aeaSWludzik, Jozef     size_t index = 0;
415479e899dSKrzysztof Grobelny     for (const std::string& action : actions)
4164dbb8aeaSWludzik, Jozef     {
417479e899dSKrzysztof Grobelny         std::string dbusReportAction = toDbusReportAction(action);
418479e899dSKrzysztof Grobelny         if (dbusReportAction.empty())
4194dbb8aeaSWludzik, Jozef         {
420*9e6c388aSLukasz Kazmierczak             messages::propertyValueNotInList(
421*9e6c388aSLukasz Kazmierczak                 res, action, "ReportActions/" + std::to_string(index));
4224dbb8aeaSWludzik, Jozef             return false;
4234dbb8aeaSWludzik, Jozef         }
424479e899dSKrzysztof Grobelny 
425*9e6c388aSLukasz Kazmierczak         outReportActions.emplace_back(std::move(dbusReportAction));
4264dbb8aeaSWludzik, Jozef         index++;
4274dbb8aeaSWludzik, Jozef     }
4284dbb8aeaSWludzik, Jozef     return true;
4294dbb8aeaSWludzik, Jozef }
4304dbb8aeaSWludzik, Jozef 
431479e899dSKrzysztof Grobelny inline bool getUserMetric(crow::Response& res, nlohmann::json& metric,
432479e899dSKrzysztof Grobelny                           AddReportArgs::MetricArgs& metricArgs)
433479e899dSKrzysztof Grobelny {
434479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> uris;
435479e899dSKrzysztof Grobelny     std::optional<std::string> collectionDurationStr;
436479e899dSKrzysztof Grobelny     std::optional<std::string> collectionFunction;
437479e899dSKrzysztof Grobelny     std::optional<std::string> collectionTimeScopeStr;
438479e899dSKrzysztof Grobelny 
439479e899dSKrzysztof Grobelny     if (!json_util::readJson(metric, res, "MetricProperties", uris,
440479e899dSKrzysztof Grobelny                              "CollectionFunction", collectionFunction,
441479e899dSKrzysztof Grobelny                              "CollectionTimeScope", collectionTimeScopeStr,
442479e899dSKrzysztof Grobelny                              "CollectionDuration", collectionDurationStr))
443479e899dSKrzysztof Grobelny     {
444479e899dSKrzysztof Grobelny         return false;
445479e899dSKrzysztof Grobelny     }
446479e899dSKrzysztof Grobelny 
447479e899dSKrzysztof Grobelny     if (uris)
448479e899dSKrzysztof Grobelny     {
449479e899dSKrzysztof Grobelny         metricArgs.uris = std::move(*uris);
450479e899dSKrzysztof Grobelny     }
451479e899dSKrzysztof Grobelny 
452479e899dSKrzysztof Grobelny     if (collectionFunction)
453479e899dSKrzysztof Grobelny     {
454479e899dSKrzysztof Grobelny         std::string dbusCollectionFunction =
455479e899dSKrzysztof Grobelny             telemetry::toDbusCollectionFunction(*collectionFunction);
456479e899dSKrzysztof Grobelny         if (dbusCollectionFunction.empty())
457479e899dSKrzysztof Grobelny         {
458479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionFunction",
459479e899dSKrzysztof Grobelny                                              *collectionFunction);
460479e899dSKrzysztof Grobelny             return false;
461479e899dSKrzysztof Grobelny         }
462479e899dSKrzysztof Grobelny         metricArgs.collectionFunction = std::move(dbusCollectionFunction);
463479e899dSKrzysztof Grobelny     }
464479e899dSKrzysztof Grobelny 
465479e899dSKrzysztof Grobelny     if (collectionTimeScopeStr)
466479e899dSKrzysztof Grobelny     {
467479e899dSKrzysztof Grobelny         std::string dbusCollectionTimeScope =
468479e899dSKrzysztof Grobelny             toDbusCollectionTimeScope(*collectionTimeScopeStr);
469479e899dSKrzysztof Grobelny         if (dbusCollectionTimeScope.empty())
470479e899dSKrzysztof Grobelny         {
471479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionTimeScope",
472479e899dSKrzysztof Grobelny                                              *collectionTimeScopeStr);
473479e899dSKrzysztof Grobelny             return false;
474479e899dSKrzysztof Grobelny         }
475479e899dSKrzysztof Grobelny         metricArgs.collectionTimeScope = std::move(dbusCollectionTimeScope);
476479e899dSKrzysztof Grobelny     }
477479e899dSKrzysztof Grobelny 
478479e899dSKrzysztof Grobelny     if (collectionDurationStr)
479479e899dSKrzysztof Grobelny     {
480479e899dSKrzysztof Grobelny         std::optional<std::chrono::milliseconds> duration =
481479e899dSKrzysztof Grobelny             time_utils::fromDurationString(*collectionDurationStr);
482479e899dSKrzysztof Grobelny 
483479e899dSKrzysztof Grobelny         if (!duration || duration->count() < 0)
484479e899dSKrzysztof Grobelny         {
485479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionDuration",
486479e899dSKrzysztof Grobelny                                              *collectionDurationStr);
487479e899dSKrzysztof Grobelny             return false;
488479e899dSKrzysztof Grobelny         }
489479e899dSKrzysztof Grobelny 
490479e899dSKrzysztof Grobelny         metricArgs.collectionDuration =
491479e899dSKrzysztof Grobelny             static_cast<uint64_t>(duration->count());
492479e899dSKrzysztof Grobelny     }
493479e899dSKrzysztof Grobelny 
494479e899dSKrzysztof Grobelny     return true;
495479e899dSKrzysztof Grobelny }
496479e899dSKrzysztof Grobelny 
497479e899dSKrzysztof Grobelny inline bool getUserMetrics(crow::Response& res,
498479e899dSKrzysztof Grobelny                            std::span<nlohmann::json> metrics,
499479e899dSKrzysztof Grobelny                            std::vector<AddReportArgs::MetricArgs>& result)
500479e899dSKrzysztof Grobelny {
501479e899dSKrzysztof Grobelny     result.reserve(metrics.size());
502479e899dSKrzysztof Grobelny 
503479e899dSKrzysztof Grobelny     for (nlohmann::json& m : metrics)
504479e899dSKrzysztof Grobelny     {
505479e899dSKrzysztof Grobelny         AddReportArgs::MetricArgs metricArgs;
506479e899dSKrzysztof Grobelny 
507479e899dSKrzysztof Grobelny         if (!getUserMetric(res, m, metricArgs))
508479e899dSKrzysztof Grobelny         {
509479e899dSKrzysztof Grobelny             return false;
510479e899dSKrzysztof Grobelny         }
511479e899dSKrzysztof Grobelny 
512479e899dSKrzysztof Grobelny         result.emplace_back(std::move(metricArgs));
513479e899dSKrzysztof Grobelny     }
514479e899dSKrzysztof Grobelny 
515479e899dSKrzysztof Grobelny     return true;
516479e899dSKrzysztof Grobelny }
517479e899dSKrzysztof Grobelny 
5184dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req,
5194dbb8aeaSWludzik, Jozef                               AddReportArgs& args)
5204dbb8aeaSWludzik, Jozef {
521479e899dSKrzysztof Grobelny     std::optional<std::string> id;
522479e899dSKrzysztof Grobelny     std::optional<std::string> name;
523479e899dSKrzysztof Grobelny     std::optional<std::string> reportingTypeStr;
524479e899dSKrzysztof Grobelny     std::optional<std::string> reportUpdatesStr;
525479e899dSKrzysztof Grobelny     std::optional<uint64_t> appendLimit;
526479e899dSKrzysztof Grobelny     std::optional<bool> metricReportDefinitionEnabled;
527479e899dSKrzysztof Grobelny     std::optional<std::vector<nlohmann::json>> metrics;
528479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> reportActionsStr;
5294dbb8aeaSWludzik, Jozef     std::optional<nlohmann::json> schedule;
530479e899dSKrzysztof Grobelny 
531479e899dSKrzysztof Grobelny     if (!json_util::readJsonPatch(
532479e899dSKrzysztof Grobelny             req, res, "Id", id, "Name", name, "Metrics", metrics,
533479e899dSKrzysztof Grobelny             "MetricReportDefinitionType", reportingTypeStr, "ReportUpdates",
534479e899dSKrzysztof Grobelny             reportUpdatesStr, "AppendLimit", appendLimit, "ReportActions",
535479e899dSKrzysztof Grobelny             reportActionsStr, "Schedule", schedule,
536479e899dSKrzysztof Grobelny             "MetricReportDefinitionEnabled", metricReportDefinitionEnabled))
5374dbb8aeaSWludzik, Jozef     {
5384dbb8aeaSWludzik, Jozef         return false;
5394dbb8aeaSWludzik, Jozef     }
5404dbb8aeaSWludzik, Jozef 
541479e899dSKrzysztof Grobelny     if (id)
542479e899dSKrzysztof Grobelny     {
543479e899dSKrzysztof Grobelny         constexpr const char* allowedCharactersInId =
5444dbb8aeaSWludzik, Jozef             "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
545479e899dSKrzysztof Grobelny         if (id->empty() ||
546479e899dSKrzysztof Grobelny             id->find_first_not_of(allowedCharactersInId) != std::string::npos)
5474dbb8aeaSWludzik, Jozef         {
548479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "Id", *id);
5494dbb8aeaSWludzik, Jozef             return false;
5504dbb8aeaSWludzik, Jozef         }
551479e899dSKrzysztof Grobelny         args.id = *id;
552479e899dSKrzysztof Grobelny     }
5534dbb8aeaSWludzik, Jozef 
554479e899dSKrzysztof Grobelny     if (name)
5554dbb8aeaSWludzik, Jozef     {
556479e899dSKrzysztof Grobelny         args.name = *name;
557479e899dSKrzysztof Grobelny     }
558479e899dSKrzysztof Grobelny 
559479e899dSKrzysztof Grobelny     if (reportingTypeStr)
560479e899dSKrzysztof Grobelny     {
561479e899dSKrzysztof Grobelny         std::string dbusReportingType = toDbusReportingType(*reportingTypeStr);
562479e899dSKrzysztof Grobelny         if (dbusReportingType.empty())
563479e899dSKrzysztof Grobelny         {
564479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportingTypeStr,
5654dbb8aeaSWludzik, Jozef                                              "MetricReportDefinitionType");
5664dbb8aeaSWludzik, Jozef             return false;
5674dbb8aeaSWludzik, Jozef         }
568479e899dSKrzysztof Grobelny         args.reportingType = dbusReportingType;
569479e899dSKrzysztof Grobelny     }
5704dbb8aeaSWludzik, Jozef 
571479e899dSKrzysztof Grobelny     if (reportUpdatesStr)
572479e899dSKrzysztof Grobelny     {
573479e899dSKrzysztof Grobelny         std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr);
574479e899dSKrzysztof Grobelny         if (dbusReportUpdates.empty())
575479e899dSKrzysztof Grobelny         {
576479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportUpdatesStr,
577479e899dSKrzysztof Grobelny                                              "ReportUpdates");
578479e899dSKrzysztof Grobelny             return false;
579479e899dSKrzysztof Grobelny         }
580479e899dSKrzysztof Grobelny         args.reportUpdates = dbusReportUpdates;
581479e899dSKrzysztof Grobelny     }
582479e899dSKrzysztof Grobelny 
583479e899dSKrzysztof Grobelny     if (appendLimit)
584479e899dSKrzysztof Grobelny     {
585479e899dSKrzysztof Grobelny         args.appendLimit = *appendLimit;
586479e899dSKrzysztof Grobelny     }
587479e899dSKrzysztof Grobelny 
588479e899dSKrzysztof Grobelny     if (metricReportDefinitionEnabled)
589479e899dSKrzysztof Grobelny     {
590479e899dSKrzysztof Grobelny         args.metricReportDefinitionEnabled = *metricReportDefinitionEnabled;
591479e899dSKrzysztof Grobelny     }
592479e899dSKrzysztof Grobelny 
593479e899dSKrzysztof Grobelny     if (reportActionsStr)
594479e899dSKrzysztof Grobelny     {
595*9e6c388aSLukasz Kazmierczak         if (!toDbusReportActions(res, *reportActionsStr, args.reportActions))
5964dbb8aeaSWludzik, Jozef         {
5974dbb8aeaSWludzik, Jozef             return false;
5984dbb8aeaSWludzik, Jozef         }
599479e899dSKrzysztof Grobelny     }
6004dbb8aeaSWludzik, Jozef 
601479e899dSKrzysztof Grobelny     if (reportingTypeStr == "Periodic")
6024dbb8aeaSWludzik, Jozef     {
6034dbb8aeaSWludzik, Jozef         if (!schedule)
6044dbb8aeaSWludzik, Jozef         {
6054dbb8aeaSWludzik, Jozef             messages::createFailedMissingReqProperties(res, "Schedule");
6064dbb8aeaSWludzik, Jozef             return false;
6074dbb8aeaSWludzik, Jozef         }
6084dbb8aeaSWludzik, Jozef 
6094dbb8aeaSWludzik, Jozef         std::string durationStr;
6104dbb8aeaSWludzik, Jozef         if (!json_util::readJson(*schedule, res, "RecurrenceInterval",
6114dbb8aeaSWludzik, Jozef                                  durationStr))
6124dbb8aeaSWludzik, Jozef         {
6134dbb8aeaSWludzik, Jozef             return false;
6144dbb8aeaSWludzik, Jozef         }
6154dbb8aeaSWludzik, Jozef 
6164dbb8aeaSWludzik, Jozef         std::optional<std::chrono::milliseconds> durationNum =
6174dbb8aeaSWludzik, Jozef             time_utils::fromDurationString(durationStr);
618479e899dSKrzysztof Grobelny         if (!durationNum || durationNum->count() < 0)
6194dbb8aeaSWludzik, Jozef         {
6204dbb8aeaSWludzik, Jozef             messages::propertyValueIncorrect(res, "RecurrenceInterval",
6214dbb8aeaSWludzik, Jozef                                              durationStr);
6224dbb8aeaSWludzik, Jozef             return false;
6234dbb8aeaSWludzik, Jozef         }
6244dbb8aeaSWludzik, Jozef         args.interval = static_cast<uint64_t>(durationNum->count());
6254dbb8aeaSWludzik, Jozef     }
6264dbb8aeaSWludzik, Jozef 
627479e899dSKrzysztof Grobelny     if (metrics)
6284dbb8aeaSWludzik, Jozef     {
629479e899dSKrzysztof Grobelny         if (!getUserMetrics(res, *metrics, args.metrics))
6304dbb8aeaSWludzik, Jozef         {
6314dbb8aeaSWludzik, Jozef             return false;
6324dbb8aeaSWludzik, Jozef         }
6334dbb8aeaSWludzik, Jozef     }
6344dbb8aeaSWludzik, Jozef 
6354dbb8aeaSWludzik, Jozef     return true;
6364dbb8aeaSWludzik, Jozef }
6374dbb8aeaSWludzik, Jozef 
638ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics(
6398d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
640479e899dSKrzysztof Grobelny     std::span<const AddReportArgs::MetricArgs> metrics,
6414dbb8aeaSWludzik, Jozef     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
6424dbb8aeaSWludzik, Jozef {
643ca1600c1SSzymon Dompke     for (const auto& metric : metrics)
6444dbb8aeaSWludzik, Jozef     {
645479e899dSKrzysztof Grobelny         std::optional<IncorrectMetricUri> error =
646479e899dSKrzysztof Grobelny             getChassisSensorNode(metric.uris, matched);
647ca1600c1SSzymon Dompke         if (error)
6484dbb8aeaSWludzik, Jozef         {
649ca1600c1SSzymon Dompke             messages::propertyValueIncorrect(asyncResp->res, error->uri,
6504dbb8aeaSWludzik, Jozef                                              "MetricProperties/" +
651ca1600c1SSzymon Dompke                                                  std::to_string(error->index));
6524dbb8aeaSWludzik, Jozef             return false;
6534dbb8aeaSWludzik, Jozef         }
6544dbb8aeaSWludzik, Jozef     }
6554dbb8aeaSWludzik, Jozef     return true;
6564dbb8aeaSWludzik, Jozef }
6574dbb8aeaSWludzik, Jozef 
6584dbb8aeaSWludzik, Jozef class AddReport
6594dbb8aeaSWludzik, Jozef {
6604dbb8aeaSWludzik, Jozef   public:
6618d1b46d7Szhanghch05     AddReport(AddReportArgs argsIn,
6628a592810SEd Tanous               const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
6638a592810SEd Tanous         asyncResp(asyncRespIn),
664*9e6c388aSLukasz Kazmierczak         args(std::move(argsIn))
6654dbb8aeaSWludzik, Jozef     {}
666479e899dSKrzysztof Grobelny 
6674dbb8aeaSWludzik, Jozef     ~AddReport()
6684dbb8aeaSWludzik, Jozef     {
669479e899dSKrzysztof Grobelny         boost::asio::post(crow::connections::systemBus->get_io_context(),
670479e899dSKrzysztof Grobelny                           std::bind_front(&performAddReport, asyncResp, args,
671479e899dSKrzysztof Grobelny                                           std::move(uriToDbus)));
672479e899dSKrzysztof Grobelny     }
673479e899dSKrzysztof Grobelny 
674479e899dSKrzysztof Grobelny     static void performAddReport(
675479e899dSKrzysztof Grobelny         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
676479e899dSKrzysztof Grobelny         const AddReportArgs& args,
677479e899dSKrzysztof Grobelny         const boost::container::flat_map<std::string, std::string>& uriToDbus)
678479e899dSKrzysztof Grobelny     {
6794dbb8aeaSWludzik, Jozef         if (asyncResp->res.result() != boost::beast::http::status::ok)
6804dbb8aeaSWludzik, Jozef         {
6814dbb8aeaSWludzik, Jozef             return;
6824dbb8aeaSWludzik, Jozef         }
6834dbb8aeaSWludzik, Jozef 
6844dbb8aeaSWludzik, Jozef         telemetry::ReadingParameters readingParams;
6854dbb8aeaSWludzik, Jozef         readingParams.reserve(args.metrics.size());
6864dbb8aeaSWludzik, Jozef 
687479e899dSKrzysztof Grobelny         for (const auto& metric : args.metrics)
6884dbb8aeaSWludzik, Jozef         {
689479e899dSKrzysztof Grobelny             std::vector<
690479e899dSKrzysztof Grobelny                 std::tuple<sdbusplus::message::object_path, std::string>>
691479e899dSKrzysztof Grobelny                 sensorParams;
692479e899dSKrzysztof Grobelny             sensorParams.reserve(metric.uris.size());
693479e899dSKrzysztof Grobelny 
694479e899dSKrzysztof Grobelny             for (size_t i = 0; i < metric.uris.size(); i++)
6954dbb8aeaSWludzik, Jozef             {
696479e899dSKrzysztof Grobelny                 const std::string& uri = metric.uris[i];
6974dbb8aeaSWludzik, Jozef                 auto el = uriToDbus.find(uri);
6984dbb8aeaSWludzik, Jozef                 if (el == uriToDbus.end())
6994dbb8aeaSWludzik, Jozef                 {
70062598e31SEd Tanous                     BMCWEB_LOG_ERROR(
70162598e31SEd Tanous                         "Failed to find DBus sensor corresponding to URI {}",
70262598e31SEd Tanous                         uri);
7034dbb8aeaSWludzik, Jozef                     messages::propertyValueNotInList(asyncResp->res, uri,
7044dbb8aeaSWludzik, Jozef                                                      "MetricProperties/" +
7054dbb8aeaSWludzik, Jozef                                                          std::to_string(i));
7064dbb8aeaSWludzik, Jozef                     return;
7074dbb8aeaSWludzik, Jozef                 }
7084dbb8aeaSWludzik, Jozef 
7094dbb8aeaSWludzik, Jozef                 const std::string& dbusPath = el->second;
710479e899dSKrzysztof Grobelny                 sensorParams.emplace_back(dbusPath, uri);
7114dbb8aeaSWludzik, Jozef             }
712479e899dSKrzysztof Grobelny 
713479e899dSKrzysztof Grobelny             readingParams.emplace_back(
714479e899dSKrzysztof Grobelny                 std::move(sensorParams), metric.collectionFunction,
715479e899dSKrzysztof Grobelny                 metric.collectionTimeScope, metric.collectionDuration);
7164dbb8aeaSWludzik, Jozef         }
717479e899dSKrzysztof Grobelny 
7184dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
719479e899dSKrzysztof Grobelny             [asyncResp, id = args.id, uriToDbus](
7205e7e2dc5SEd Tanous                 const boost::system::error_code& ec, const std::string&) {
7214dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::file_exists)
7224dbb8aeaSWludzik, Jozef             {
7234dbb8aeaSWludzik, Jozef                 messages::resourceAlreadyExists(
724479e899dSKrzysztof Grobelny                     asyncResp->res, "MetricReportDefinition", "Id", id);
7254dbb8aeaSWludzik, Jozef                 return;
7264dbb8aeaSWludzik, Jozef             }
7274dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::too_many_files_open)
7284dbb8aeaSWludzik, Jozef             {
729479e899dSKrzysztof Grobelny                 messages::createLimitReachedForResource(asyncResp->res);
7304dbb8aeaSWludzik, Jozef                 return;
7314dbb8aeaSWludzik, Jozef             }
7324dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::argument_list_too_long)
7334dbb8aeaSWludzik, Jozef             {
7344dbb8aeaSWludzik, Jozef                 nlohmann::json metricProperties = nlohmann::json::array();
7354dbb8aeaSWludzik, Jozef                 for (const auto& [uri, _] : uriToDbus)
7364dbb8aeaSWludzik, Jozef                 {
7374dbb8aeaSWludzik, Jozef                     metricProperties.emplace_back(uri);
7384dbb8aeaSWludzik, Jozef                 }
73914fbced6SEd Tanous                 messages::propertyValueIncorrect(
74014fbced6SEd Tanous                     asyncResp->res, metricProperties, "MetricProperties");
7414dbb8aeaSWludzik, Jozef                 return;
7424dbb8aeaSWludzik, Jozef             }
7434dbb8aeaSWludzik, Jozef             if (ec)
7444dbb8aeaSWludzik, Jozef             {
745479e899dSKrzysztof Grobelny                 messages::internalError(asyncResp->res);
74662598e31SEd Tanous                 BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
7474dbb8aeaSWludzik, Jozef                 return;
7484dbb8aeaSWludzik, Jozef             }
7494dbb8aeaSWludzik, Jozef 
750479e899dSKrzysztof Grobelny             messages::created(asyncResp->res);
7514dbb8aeaSWludzik, Jozef             },
7524dbb8aeaSWludzik, Jozef             telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
7534dbb8aeaSWludzik, Jozef             "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
754479e899dSKrzysztof Grobelny             "TelemetryService/" + args.id, args.name, args.reportingType,
755479e899dSKrzysztof Grobelny             args.reportUpdates, args.appendLimit, args.reportActions,
756479e899dSKrzysztof Grobelny             args.interval, readingParams, args.metricReportDefinitionEnabled);
7574dbb8aeaSWludzik, Jozef     }
7584dbb8aeaSWludzik, Jozef 
759ecd6a3a2SEd Tanous     AddReport(const AddReport&) = delete;
760ecd6a3a2SEd Tanous     AddReport(AddReport&&) = delete;
761ecd6a3a2SEd Tanous     AddReport& operator=(const AddReport&) = delete;
762ecd6a3a2SEd Tanous     AddReport& operator=(AddReport&&) = delete;
763ecd6a3a2SEd Tanous 
764fe04d49cSNan Zhou     void insert(const std::map<std::string, std::string>& el)
7654dbb8aeaSWludzik, Jozef     {
7664dbb8aeaSWludzik, Jozef         uriToDbus.insert(el.begin(), el.end());
7674dbb8aeaSWludzik, Jozef     }
7684dbb8aeaSWludzik, Jozef 
7694dbb8aeaSWludzik, Jozef   private:
770479e899dSKrzysztof Grobelny     std::shared_ptr<bmcweb::AsyncResp> asyncResp;
7714dbb8aeaSWludzik, Jozef     AddReportArgs args;
7724dbb8aeaSWludzik, Jozef     boost::container::flat_map<std::string, std::string> uriToDbus{};
7734dbb8aeaSWludzik, Jozef };
774*9e6c388aSLukasz Kazmierczak 
775*9e6c388aSLukasz Kazmierczak class UpdateMetrics
776*9e6c388aSLukasz Kazmierczak {
777*9e6c388aSLukasz Kazmierczak   public:
778*9e6c388aSLukasz Kazmierczak     UpdateMetrics(std::string_view idIn,
779*9e6c388aSLukasz Kazmierczak                   const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
780*9e6c388aSLukasz Kazmierczak         id(idIn),
781*9e6c388aSLukasz Kazmierczak         asyncResp(asyncRespIn)
782*9e6c388aSLukasz Kazmierczak     {}
783*9e6c388aSLukasz Kazmierczak 
784*9e6c388aSLukasz Kazmierczak     ~UpdateMetrics()
785*9e6c388aSLukasz Kazmierczak     {
786*9e6c388aSLukasz Kazmierczak         try
787*9e6c388aSLukasz Kazmierczak         {
788*9e6c388aSLukasz Kazmierczak             setReadingParams();
789*9e6c388aSLukasz Kazmierczak         }
790*9e6c388aSLukasz Kazmierczak         catch (const std::exception& e)
791*9e6c388aSLukasz Kazmierczak         {
792*9e6c388aSLukasz Kazmierczak             BMCWEB_LOG_ERROR("{}", e.what());
793*9e6c388aSLukasz Kazmierczak         }
794*9e6c388aSLukasz Kazmierczak         catch (...)
795*9e6c388aSLukasz Kazmierczak         {
796*9e6c388aSLukasz Kazmierczak             BMCWEB_LOG_ERROR("Unknown error");
797*9e6c388aSLukasz Kazmierczak         }
798*9e6c388aSLukasz Kazmierczak     }
799*9e6c388aSLukasz Kazmierczak 
800*9e6c388aSLukasz Kazmierczak     UpdateMetrics(const UpdateMetrics&) = delete;
801*9e6c388aSLukasz Kazmierczak     UpdateMetrics(UpdateMetrics&&) = delete;
802*9e6c388aSLukasz Kazmierczak     UpdateMetrics& operator=(const UpdateMetrics&) = delete;
803*9e6c388aSLukasz Kazmierczak     UpdateMetrics& operator=(UpdateMetrics&&) = delete;
804*9e6c388aSLukasz Kazmierczak 
805*9e6c388aSLukasz Kazmierczak     std::string id;
806*9e6c388aSLukasz Kazmierczak     std::map<std::string, std::string> metricPropertyToDbusPaths;
807*9e6c388aSLukasz Kazmierczak 
808*9e6c388aSLukasz Kazmierczak     void insert(const std::map<std::string, std::string>&
809*9e6c388aSLukasz Kazmierczak                     additionalMetricPropertyToDbusPaths)
810*9e6c388aSLukasz Kazmierczak     {
811*9e6c388aSLukasz Kazmierczak         metricPropertyToDbusPaths.insert(
812*9e6c388aSLukasz Kazmierczak             additionalMetricPropertyToDbusPaths.begin(),
813*9e6c388aSLukasz Kazmierczak             additionalMetricPropertyToDbusPaths.end());
814*9e6c388aSLukasz Kazmierczak     }
815*9e6c388aSLukasz Kazmierczak 
816*9e6c388aSLukasz Kazmierczak     void emplace(std::span<const std::tuple<sdbusplus::message::object_path,
817*9e6c388aSLukasz Kazmierczak                                             std::string>>
818*9e6c388aSLukasz Kazmierczak                      pathAndUri,
819*9e6c388aSLukasz Kazmierczak                  const AddReportArgs::MetricArgs& metricArgs)
820*9e6c388aSLukasz Kazmierczak     {
821*9e6c388aSLukasz Kazmierczak         readingParamsUris.emplace_back(metricArgs.uris);
822*9e6c388aSLukasz Kazmierczak         readingParams.emplace_back(
823*9e6c388aSLukasz Kazmierczak             std::vector(pathAndUri.begin(), pathAndUri.end()),
824*9e6c388aSLukasz Kazmierczak             metricArgs.collectionFunction, metricArgs.collectionTimeScope,
825*9e6c388aSLukasz Kazmierczak             metricArgs.collectionDuration);
826*9e6c388aSLukasz Kazmierczak     }
827*9e6c388aSLukasz Kazmierczak 
828*9e6c388aSLukasz Kazmierczak     void setReadingParams()
829*9e6c388aSLukasz Kazmierczak     {
830*9e6c388aSLukasz Kazmierczak         if (asyncResp->res.result() != boost::beast::http::status::ok)
831*9e6c388aSLukasz Kazmierczak         {
832*9e6c388aSLukasz Kazmierczak             return;
833*9e6c388aSLukasz Kazmierczak         }
834*9e6c388aSLukasz Kazmierczak 
835*9e6c388aSLukasz Kazmierczak         for (size_t index = 0; index < readingParamsUris.size(); ++index)
836*9e6c388aSLukasz Kazmierczak         {
837*9e6c388aSLukasz Kazmierczak             std::span<const std::string> newUris = readingParamsUris[index];
838*9e6c388aSLukasz Kazmierczak 
839*9e6c388aSLukasz Kazmierczak             const std::optional<std::vector<
840*9e6c388aSLukasz Kazmierczak                 std::tuple<sdbusplus::message::object_path, std::string>>>
841*9e6c388aSLukasz Kazmierczak                 readingParam = sensorPathToUri(newUris);
842*9e6c388aSLukasz Kazmierczak 
843*9e6c388aSLukasz Kazmierczak             if (!readingParam)
844*9e6c388aSLukasz Kazmierczak             {
845*9e6c388aSLukasz Kazmierczak                 return;
846*9e6c388aSLukasz Kazmierczak             }
847*9e6c388aSLukasz Kazmierczak 
848*9e6c388aSLukasz Kazmierczak             std::get<0>(readingParams[index]) = *readingParam;
849*9e6c388aSLukasz Kazmierczak         }
850*9e6c388aSLukasz Kazmierczak 
851*9e6c388aSLukasz Kazmierczak         crow::connections::systemBus->async_method_call(
852*9e6c388aSLukasz Kazmierczak             [asyncResp(this->asyncResp),
853*9e6c388aSLukasz Kazmierczak              reportId = id](const boost::system::error_code& ec) {
854*9e6c388aSLukasz Kazmierczak             if (!verifyCommonErrors(asyncResp->res, reportId, ec))
855*9e6c388aSLukasz Kazmierczak             {
856*9e6c388aSLukasz Kazmierczak                 return;
857*9e6c388aSLukasz Kazmierczak             }
858*9e6c388aSLukasz Kazmierczak             },
859*9e6c388aSLukasz Kazmierczak             "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
860*9e6c388aSLukasz Kazmierczak             "org.freedesktop.DBus.Properties", "Set",
861*9e6c388aSLukasz Kazmierczak             "xyz.openbmc_project.Telemetry.Report", "ReadingParameters",
862*9e6c388aSLukasz Kazmierczak             dbus::utility::DbusVariantType{readingParams});
863*9e6c388aSLukasz Kazmierczak     }
864*9e6c388aSLukasz Kazmierczak 
865*9e6c388aSLukasz Kazmierczak   private:
866*9e6c388aSLukasz Kazmierczak     std::optional<
867*9e6c388aSLukasz Kazmierczak         std::vector<std::tuple<sdbusplus::message::object_path, std::string>>>
868*9e6c388aSLukasz Kazmierczak         sensorPathToUri(std::span<const std::string> uris) const
869*9e6c388aSLukasz Kazmierczak     {
870*9e6c388aSLukasz Kazmierczak         std::vector<std::tuple<sdbusplus::message::object_path, std::string>>
871*9e6c388aSLukasz Kazmierczak             result;
872*9e6c388aSLukasz Kazmierczak 
873*9e6c388aSLukasz Kazmierczak         for (const std::string& uri : uris)
874*9e6c388aSLukasz Kazmierczak         {
875*9e6c388aSLukasz Kazmierczak             auto it = metricPropertyToDbusPaths.find(uri);
876*9e6c388aSLukasz Kazmierczak             if (it == metricPropertyToDbusPaths.end())
877*9e6c388aSLukasz Kazmierczak             {
878*9e6c388aSLukasz Kazmierczak                 messages::propertyValueNotInList(asyncResp->res, uri,
879*9e6c388aSLukasz Kazmierczak                                                  "MetricProperties");
880*9e6c388aSLukasz Kazmierczak                 return {};
881*9e6c388aSLukasz Kazmierczak             }
882*9e6c388aSLukasz Kazmierczak             result.emplace_back(it->second, uri);
883*9e6c388aSLukasz Kazmierczak         }
884*9e6c388aSLukasz Kazmierczak 
885*9e6c388aSLukasz Kazmierczak         return result;
886*9e6c388aSLukasz Kazmierczak     }
887*9e6c388aSLukasz Kazmierczak 
888*9e6c388aSLukasz Kazmierczak     const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
889*9e6c388aSLukasz Kazmierczak     std::vector<std::vector<std::string>> readingParamsUris;
890*9e6c388aSLukasz Kazmierczak     ReadingParameters readingParams{};
891*9e6c388aSLukasz Kazmierczak };
892*9e6c388aSLukasz Kazmierczak 
893*9e6c388aSLukasz Kazmierczak inline void
894*9e6c388aSLukasz Kazmierczak     setReportEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
895*9e6c388aSLukasz Kazmierczak                      std::string_view id, bool enabled)
896*9e6c388aSLukasz Kazmierczak {
897*9e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
898*9e6c388aSLukasz Kazmierczak         [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
899*9e6c388aSLukasz Kazmierczak         if (!verifyCommonErrors(asyncResp->res, id, ec))
900*9e6c388aSLukasz Kazmierczak         {
901*9e6c388aSLukasz Kazmierczak             return;
902*9e6c388aSLukasz Kazmierczak         }
903*9e6c388aSLukasz Kazmierczak         },
904*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
905*9e6c388aSLukasz Kazmierczak         "org.freedesktop.DBus.Properties", "Set",
906*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "Enabled",
907*9e6c388aSLukasz Kazmierczak         dbus::utility::DbusVariantType{enabled});
908*9e6c388aSLukasz Kazmierczak }
909*9e6c388aSLukasz Kazmierczak 
910*9e6c388aSLukasz Kazmierczak inline void setReportTypeAndInterval(
911*9e6c388aSLukasz Kazmierczak     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id,
912*9e6c388aSLukasz Kazmierczak     const std::string& reportingType, uint64_t recurrenceInterval)
913*9e6c388aSLukasz Kazmierczak {
914*9e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
915*9e6c388aSLukasz Kazmierczak         [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
916*9e6c388aSLukasz Kazmierczak         if (!verifyCommonErrors(asyncResp->res, id, ec))
917*9e6c388aSLukasz Kazmierczak         {
918*9e6c388aSLukasz Kazmierczak             return;
919*9e6c388aSLukasz Kazmierczak         }
920*9e6c388aSLukasz Kazmierczak         },
921*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
922*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "SetReportingProperties",
923*9e6c388aSLukasz Kazmierczak         reportingType, recurrenceInterval);
924*9e6c388aSLukasz Kazmierczak }
925*9e6c388aSLukasz Kazmierczak 
926*9e6c388aSLukasz Kazmierczak inline void
927*9e6c388aSLukasz Kazmierczak     setReportUpdates(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
928*9e6c388aSLukasz Kazmierczak                      std::string_view id, const std::string& reportUpdates)
929*9e6c388aSLukasz Kazmierczak {
930*9e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
931*9e6c388aSLukasz Kazmierczak         [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
932*9e6c388aSLukasz Kazmierczak         if (!verifyCommonErrors(asyncResp->res, id, ec))
933*9e6c388aSLukasz Kazmierczak         {
934*9e6c388aSLukasz Kazmierczak             return;
935*9e6c388aSLukasz Kazmierczak         }
936*9e6c388aSLukasz Kazmierczak         },
937*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
938*9e6c388aSLukasz Kazmierczak         "org.freedesktop.DBus.Properties", "Set",
939*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "ReportUpdates",
940*9e6c388aSLukasz Kazmierczak         dbus::utility::DbusVariantType{reportUpdates});
941*9e6c388aSLukasz Kazmierczak }
942*9e6c388aSLukasz Kazmierczak 
943*9e6c388aSLukasz Kazmierczak inline void
944*9e6c388aSLukasz Kazmierczak     setReportActions(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
945*9e6c388aSLukasz Kazmierczak                      std::string_view id,
946*9e6c388aSLukasz Kazmierczak                      const std::vector<std::string>& dbusReportActions)
947*9e6c388aSLukasz Kazmierczak {
948*9e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
949*9e6c388aSLukasz Kazmierczak         [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
950*9e6c388aSLukasz Kazmierczak         if (!verifyCommonErrors(asyncResp->res, id, ec))
951*9e6c388aSLukasz Kazmierczak         {
952*9e6c388aSLukasz Kazmierczak             return;
953*9e6c388aSLukasz Kazmierczak         }
954*9e6c388aSLukasz Kazmierczak         },
955*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
956*9e6c388aSLukasz Kazmierczak         "org.freedesktop.DBus.Properties", "Set",
957*9e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "ReportActions",
958*9e6c388aSLukasz Kazmierczak         dbus::utility::DbusVariantType{dbusReportActions});
959*9e6c388aSLukasz Kazmierczak }
960*9e6c388aSLukasz Kazmierczak 
961*9e6c388aSLukasz Kazmierczak inline void
962*9e6c388aSLukasz Kazmierczak     setReportMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
963*9e6c388aSLukasz Kazmierczak                      std::string_view id, std::span<nlohmann::json> metrics)
964*9e6c388aSLukasz Kazmierczak {
965*9e6c388aSLukasz Kazmierczak     sdbusplus::asio::getAllProperties(
966*9e6c388aSLukasz Kazmierczak         *crow::connections::systemBus, telemetry::service,
967*9e6c388aSLukasz Kazmierczak         telemetry::getDbusReportPath(id), telemetry::reportInterface,
968*9e6c388aSLukasz Kazmierczak         [asyncResp, id = std::string(id),
969*9e6c388aSLukasz Kazmierczak          redfishMetrics = std::vector<nlohmann::json>(metrics.begin(),
970*9e6c388aSLukasz Kazmierczak                                                       metrics.end())](
971*9e6c388aSLukasz Kazmierczak             boost::system::error_code ec,
972*9e6c388aSLukasz Kazmierczak             const dbus::utility::DBusPropertiesMap& properties) mutable {
973*9e6c388aSLukasz Kazmierczak         if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec))
974*9e6c388aSLukasz Kazmierczak         {
975*9e6c388aSLukasz Kazmierczak             return;
976*9e6c388aSLukasz Kazmierczak         }
977*9e6c388aSLukasz Kazmierczak 
978*9e6c388aSLukasz Kazmierczak         ReadingParameters readingParams;
979*9e6c388aSLukasz Kazmierczak 
980*9e6c388aSLukasz Kazmierczak         const bool success = sdbusplus::unpackPropertiesNoThrow(
981*9e6c388aSLukasz Kazmierczak             dbus_utils::UnpackErrorPrinter(), properties, "ReadingParameters",
982*9e6c388aSLukasz Kazmierczak             readingParams);
983*9e6c388aSLukasz Kazmierczak 
984*9e6c388aSLukasz Kazmierczak         if (!success)
985*9e6c388aSLukasz Kazmierczak         {
986*9e6c388aSLukasz Kazmierczak             messages::internalError(asyncResp->res);
987*9e6c388aSLukasz Kazmierczak             return;
988*9e6c388aSLukasz Kazmierczak         }
989*9e6c388aSLukasz Kazmierczak 
990*9e6c388aSLukasz Kazmierczak         auto updateMetricsReq = std::make_shared<UpdateMetrics>(id, asyncResp);
991*9e6c388aSLukasz Kazmierczak 
992*9e6c388aSLukasz Kazmierczak         boost::container::flat_set<std::pair<std::string, std::string>>
993*9e6c388aSLukasz Kazmierczak             chassisSensors;
994*9e6c388aSLukasz Kazmierczak 
995*9e6c388aSLukasz Kazmierczak         size_t index = 0;
996*9e6c388aSLukasz Kazmierczak         for (nlohmann::json& metric : redfishMetrics)
997*9e6c388aSLukasz Kazmierczak         {
998*9e6c388aSLukasz Kazmierczak             if (metric.is_null())
999*9e6c388aSLukasz Kazmierczak             {
1000*9e6c388aSLukasz Kazmierczak                 continue;
1001*9e6c388aSLukasz Kazmierczak             }
1002*9e6c388aSLukasz Kazmierczak 
1003*9e6c388aSLukasz Kazmierczak             AddReportArgs::MetricArgs metricArgs;
1004*9e6c388aSLukasz Kazmierczak             std::vector<
1005*9e6c388aSLukasz Kazmierczak                 std::tuple<sdbusplus::message::object_path, std::string>>
1006*9e6c388aSLukasz Kazmierczak                 pathAndUri;
1007*9e6c388aSLukasz Kazmierczak 
1008*9e6c388aSLukasz Kazmierczak             if (index < readingParams.size())
1009*9e6c388aSLukasz Kazmierczak             {
1010*9e6c388aSLukasz Kazmierczak                 const ReadingParameters::value_type& existing =
1011*9e6c388aSLukasz Kazmierczak                     readingParams[index];
1012*9e6c388aSLukasz Kazmierczak 
1013*9e6c388aSLukasz Kazmierczak                 pathAndUri = std::get<0>(existing);
1014*9e6c388aSLukasz Kazmierczak                 metricArgs.collectionFunction = std::get<1>(existing);
1015*9e6c388aSLukasz Kazmierczak                 metricArgs.collectionTimeScope = std::get<2>(existing);
1016*9e6c388aSLukasz Kazmierczak                 metricArgs.collectionDuration = std::get<3>(existing);
1017*9e6c388aSLukasz Kazmierczak             }
1018*9e6c388aSLukasz Kazmierczak 
1019*9e6c388aSLukasz Kazmierczak             if (!getUserMetric(asyncResp->res, metric, metricArgs))
1020*9e6c388aSLukasz Kazmierczak             {
1021*9e6c388aSLukasz Kazmierczak                 return;
1022*9e6c388aSLukasz Kazmierczak             }
1023*9e6c388aSLukasz Kazmierczak 
1024*9e6c388aSLukasz Kazmierczak             std::optional<IncorrectMetricUri> error =
1025*9e6c388aSLukasz Kazmierczak                 getChassisSensorNode(metricArgs.uris, chassisSensors);
1026*9e6c388aSLukasz Kazmierczak 
1027*9e6c388aSLukasz Kazmierczak             if (error)
1028*9e6c388aSLukasz Kazmierczak             {
1029*9e6c388aSLukasz Kazmierczak                 messages::propertyValueIncorrect(
1030*9e6c388aSLukasz Kazmierczak                     asyncResp->res, error->uri,
1031*9e6c388aSLukasz Kazmierczak                     "MetricProperties/" + std::to_string(error->index));
1032*9e6c388aSLukasz Kazmierczak                 return;
1033*9e6c388aSLukasz Kazmierczak             }
1034*9e6c388aSLukasz Kazmierczak 
1035*9e6c388aSLukasz Kazmierczak             updateMetricsReq->emplace(pathAndUri, metricArgs);
1036*9e6c388aSLukasz Kazmierczak             index++;
1037*9e6c388aSLukasz Kazmierczak         }
1038*9e6c388aSLukasz Kazmierczak 
1039*9e6c388aSLukasz Kazmierczak         for (const auto& [chassis, sensorType] : chassisSensors)
1040*9e6c388aSLukasz Kazmierczak         {
1041*9e6c388aSLukasz Kazmierczak             retrieveUriToDbusMap(
1042*9e6c388aSLukasz Kazmierczak                 chassis, sensorType,
1043*9e6c388aSLukasz Kazmierczak                 [asyncResp, updateMetricsReq](
1044*9e6c388aSLukasz Kazmierczak                     const boost::beast::http::status status,
1045*9e6c388aSLukasz Kazmierczak                     const std::map<std::string, std::string>& uriToDbus) {
1046*9e6c388aSLukasz Kazmierczak                 if (status != boost::beast::http::status::ok)
1047*9e6c388aSLukasz Kazmierczak                 {
1048*9e6c388aSLukasz Kazmierczak                     BMCWEB_LOG_ERROR(
1049*9e6c388aSLukasz Kazmierczak                         "Failed to retrieve URI to dbus sensors map with err {}",
1050*9e6c388aSLukasz Kazmierczak                         static_cast<unsigned>(status));
1051*9e6c388aSLukasz Kazmierczak                     return;
1052*9e6c388aSLukasz Kazmierczak                 }
1053*9e6c388aSLukasz Kazmierczak                 updateMetricsReq->insert(uriToDbus);
1054*9e6c388aSLukasz Kazmierczak                 });
1055*9e6c388aSLukasz Kazmierczak         }
1056*9e6c388aSLukasz Kazmierczak         });
1057*9e6c388aSLukasz Kazmierczak }
1058081ebf06SWludzik, Jozef 
10594220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead(
10604220be3bSEd Tanous     App& app, const crow::Request& req,
10614220be3bSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
10624220be3bSEd Tanous {
10634220be3bSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
10644220be3bSEd Tanous     {
10654220be3bSEd Tanous         return;
10664220be3bSEd Tanous     }
10674220be3bSEd Tanous     asyncResp->res.addHeader(
10684220be3bSEd Tanous         boost::beast::http::field::link,
10694220be3bSEd Tanous         "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby");
10704220be3bSEd Tanous }
10714220be3bSEd Tanous 
10724220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet(
1073fc0edbe3SEd Tanous     App& app, const crow::Request& req,
1074fc0edbe3SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1075fc0edbe3SEd Tanous {
1076fc0edbe3SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1077fc0edbe3SEd Tanous     {
1078fc0edbe3SEd Tanous         return;
1079fc0edbe3SEd Tanous     }
1080*9e6c388aSLukasz Kazmierczak     asyncResp->res.addHeader(
1081*9e6c388aSLukasz Kazmierczak         boost::beast::http::field::link,
1082*9e6c388aSLukasz Kazmierczak         "</redfish/v1/JsonSchemas/MetricReportDefinition/MetricReportDefinition.json>; rel=describedby");
1083fc0edbe3SEd Tanous 
1084fc0edbe3SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
1085fc0edbe3SEd Tanous         "#MetricReportDefinitionCollection."
1086fc0edbe3SEd Tanous         "MetricReportDefinitionCollection";
1087fc0edbe3SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
1088fc0edbe3SEd Tanous         "/redfish/v1/TelemetryService/MetricReportDefinitions";
1089fc0edbe3SEd Tanous     asyncResp->res.jsonValue["Name"] = "Metric Definition Collection";
1090fc0edbe3SEd Tanous     constexpr std::array<std::string_view, 1> interfaces{
1091fc0edbe3SEd Tanous         telemetry::reportInterface};
1092fc0edbe3SEd Tanous     collection_util::getCollectionMembers(
1093fc0edbe3SEd Tanous         asyncResp,
1094fc0edbe3SEd Tanous         boost::urls::url(
1095fc0edbe3SEd Tanous             "/redfish/v1/TelemetryService/MetricReportDefinitions"),
1096fc0edbe3SEd Tanous         interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
1097fc0edbe3SEd Tanous }
1098fc0edbe3SEd Tanous 
109986a5ac98SEd Tanous inline void
1100*9e6c388aSLukasz Kazmierczak     handleReportPatch(App& app, const crow::Request& req,
1101*9e6c388aSLukasz Kazmierczak                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1102*9e6c388aSLukasz Kazmierczak                       std::string_view id)
1103*9e6c388aSLukasz Kazmierczak {
1104*9e6c388aSLukasz Kazmierczak     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1105*9e6c388aSLukasz Kazmierczak     {
1106*9e6c388aSLukasz Kazmierczak         return;
1107*9e6c388aSLukasz Kazmierczak     }
1108*9e6c388aSLukasz Kazmierczak 
1109*9e6c388aSLukasz Kazmierczak     std::optional<std::string> reportingTypeStr;
1110*9e6c388aSLukasz Kazmierczak     std::optional<std::string> reportUpdatesStr;
1111*9e6c388aSLukasz Kazmierczak     std::optional<bool> metricReportDefinitionEnabled;
1112*9e6c388aSLukasz Kazmierczak     std::optional<std::vector<nlohmann::json>> metrics;
1113*9e6c388aSLukasz Kazmierczak     std::optional<std::vector<std::string>> reportActionsStr;
1114*9e6c388aSLukasz Kazmierczak     std::optional<nlohmann::json> schedule;
1115*9e6c388aSLukasz Kazmierczak 
1116*9e6c388aSLukasz Kazmierczak     if (!json_util::readJsonPatch(
1117*9e6c388aSLukasz Kazmierczak             req, asyncResp->res, "Metrics", metrics,
1118*9e6c388aSLukasz Kazmierczak             "MetricReportDefinitionType", reportingTypeStr, "ReportUpdates",
1119*9e6c388aSLukasz Kazmierczak             reportUpdatesStr, "ReportActions", reportActionsStr, "Schedule",
1120*9e6c388aSLukasz Kazmierczak             schedule, "MetricReportDefinitionEnabled",
1121*9e6c388aSLukasz Kazmierczak             metricReportDefinitionEnabled))
1122*9e6c388aSLukasz Kazmierczak     {
1123*9e6c388aSLukasz Kazmierczak         return;
1124*9e6c388aSLukasz Kazmierczak     }
1125*9e6c388aSLukasz Kazmierczak 
1126*9e6c388aSLukasz Kazmierczak     if (metricReportDefinitionEnabled)
1127*9e6c388aSLukasz Kazmierczak     {
1128*9e6c388aSLukasz Kazmierczak         setReportEnabled(asyncResp, id, *metricReportDefinitionEnabled);
1129*9e6c388aSLukasz Kazmierczak     }
1130*9e6c388aSLukasz Kazmierczak 
1131*9e6c388aSLukasz Kazmierczak     if (reportUpdatesStr)
1132*9e6c388aSLukasz Kazmierczak     {
1133*9e6c388aSLukasz Kazmierczak         std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr);
1134*9e6c388aSLukasz Kazmierczak         if (dbusReportUpdates.empty())
1135*9e6c388aSLukasz Kazmierczak         {
1136*9e6c388aSLukasz Kazmierczak             messages::propertyValueNotInList(asyncResp->res, *reportUpdatesStr,
1137*9e6c388aSLukasz Kazmierczak                                              "ReportUpdates");
1138*9e6c388aSLukasz Kazmierczak             return;
1139*9e6c388aSLukasz Kazmierczak         }
1140*9e6c388aSLukasz Kazmierczak         setReportUpdates(asyncResp, id, dbusReportUpdates);
1141*9e6c388aSLukasz Kazmierczak     }
1142*9e6c388aSLukasz Kazmierczak 
1143*9e6c388aSLukasz Kazmierczak     if (reportActionsStr)
1144*9e6c388aSLukasz Kazmierczak     {
1145*9e6c388aSLukasz Kazmierczak         std::vector<std::string> dbusReportActions;
1146*9e6c388aSLukasz Kazmierczak         if (!toDbusReportActions(asyncResp->res, *reportActionsStr,
1147*9e6c388aSLukasz Kazmierczak                                  dbusReportActions))
1148*9e6c388aSLukasz Kazmierczak         {
1149*9e6c388aSLukasz Kazmierczak             return;
1150*9e6c388aSLukasz Kazmierczak         }
1151*9e6c388aSLukasz Kazmierczak         setReportActions(asyncResp, id, dbusReportActions);
1152*9e6c388aSLukasz Kazmierczak     }
1153*9e6c388aSLukasz Kazmierczak 
1154*9e6c388aSLukasz Kazmierczak     if (reportingTypeStr || schedule)
1155*9e6c388aSLukasz Kazmierczak     {
1156*9e6c388aSLukasz Kazmierczak         std::string dbusReportingType;
1157*9e6c388aSLukasz Kazmierczak         if (reportingTypeStr)
1158*9e6c388aSLukasz Kazmierczak         {
1159*9e6c388aSLukasz Kazmierczak             dbusReportingType = toDbusReportingType(*reportingTypeStr);
1160*9e6c388aSLukasz Kazmierczak             if (dbusReportingType.empty())
1161*9e6c388aSLukasz Kazmierczak             {
1162*9e6c388aSLukasz Kazmierczak                 messages::propertyValueNotInList(asyncResp->res,
1163*9e6c388aSLukasz Kazmierczak                                                  *reportingTypeStr,
1164*9e6c388aSLukasz Kazmierczak                                                  "MetricReportDefinitionType");
1165*9e6c388aSLukasz Kazmierczak                 return;
1166*9e6c388aSLukasz Kazmierczak             }
1167*9e6c388aSLukasz Kazmierczak         }
1168*9e6c388aSLukasz Kazmierczak 
1169*9e6c388aSLukasz Kazmierczak         uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max();
1170*9e6c388aSLukasz Kazmierczak         if (schedule)
1171*9e6c388aSLukasz Kazmierczak         {
1172*9e6c388aSLukasz Kazmierczak             std::string durationStr;
1173*9e6c388aSLukasz Kazmierczak             if (!json_util::readJson(*schedule, asyncResp->res,
1174*9e6c388aSLukasz Kazmierczak                                      "RecurrenceInterval", durationStr))
1175*9e6c388aSLukasz Kazmierczak             {
1176*9e6c388aSLukasz Kazmierczak                 return;
1177*9e6c388aSLukasz Kazmierczak             }
1178*9e6c388aSLukasz Kazmierczak 
1179*9e6c388aSLukasz Kazmierczak             std::optional<std::chrono::milliseconds> durationNum =
1180*9e6c388aSLukasz Kazmierczak                 time_utils::fromDurationString(durationStr);
1181*9e6c388aSLukasz Kazmierczak             if (!durationNum || durationNum->count() < 0)
1182*9e6c388aSLukasz Kazmierczak             {
1183*9e6c388aSLukasz Kazmierczak                 messages::propertyValueIncorrect(
1184*9e6c388aSLukasz Kazmierczak                     asyncResp->res, "RecurrenceInterval", durationStr);
1185*9e6c388aSLukasz Kazmierczak                 return;
1186*9e6c388aSLukasz Kazmierczak             }
1187*9e6c388aSLukasz Kazmierczak 
1188*9e6c388aSLukasz Kazmierczak             recurrenceInterval = static_cast<uint64_t>(durationNum->count());
1189*9e6c388aSLukasz Kazmierczak         }
1190*9e6c388aSLukasz Kazmierczak 
1191*9e6c388aSLukasz Kazmierczak         setReportTypeAndInterval(asyncResp, id, dbusReportingType,
1192*9e6c388aSLukasz Kazmierczak                                  recurrenceInterval);
1193*9e6c388aSLukasz Kazmierczak     }
1194*9e6c388aSLukasz Kazmierczak 
1195*9e6c388aSLukasz Kazmierczak     if (metrics)
1196*9e6c388aSLukasz Kazmierczak     {
1197*9e6c388aSLukasz Kazmierczak         setReportMetrics(asyncResp, id, *metrics);
1198*9e6c388aSLukasz Kazmierczak     }
1199*9e6c388aSLukasz Kazmierczak }
1200*9e6c388aSLukasz Kazmierczak 
1201*9e6c388aSLukasz Kazmierczak inline void
1202*9e6c388aSLukasz Kazmierczak     handleReportDelete(App& app, const crow::Request& req,
1203*9e6c388aSLukasz Kazmierczak                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1204*9e6c388aSLukasz Kazmierczak                        std::string_view id)
1205*9e6c388aSLukasz Kazmierczak {
1206*9e6c388aSLukasz Kazmierczak     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1207*9e6c388aSLukasz Kazmierczak     {
1208*9e6c388aSLukasz Kazmierczak         return;
1209*9e6c388aSLukasz Kazmierczak     }
1210*9e6c388aSLukasz Kazmierczak 
1211*9e6c388aSLukasz Kazmierczak     const std::string reportPath = getDbusReportPath(id);
1212*9e6c388aSLukasz Kazmierczak 
1213*9e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
1214*9e6c388aSLukasz Kazmierczak         [asyncResp,
1215*9e6c388aSLukasz Kazmierczak          reportId = std::string(id)](const boost::system::error_code& ec) {
1216*9e6c388aSLukasz Kazmierczak         if (!verifyCommonErrors(asyncResp->res, reportId, ec))
1217*9e6c388aSLukasz Kazmierczak         {
1218*9e6c388aSLukasz Kazmierczak             return;
1219*9e6c388aSLukasz Kazmierczak         }
1220*9e6c388aSLukasz Kazmierczak         asyncResp->res.result(boost::beast::http::status::no_content);
1221*9e6c388aSLukasz Kazmierczak         },
1222*9e6c388aSLukasz Kazmierczak         service, reportPath, "xyz.openbmc_project.Object.Delete", "Delete");
1223*9e6c388aSLukasz Kazmierczak }
1224*9e6c388aSLukasz Kazmierczak } // namespace telemetry
1225*9e6c388aSLukasz Kazmierczak 
1226*9e6c388aSLukasz Kazmierczak inline void handleMetricReportDefinitionsPost(
1227*9e6c388aSLukasz Kazmierczak     App& app, const crow::Request& req,
1228*9e6c388aSLukasz Kazmierczak     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1229*9e6c388aSLukasz Kazmierczak {
1230*9e6c388aSLukasz Kazmierczak     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1231*9e6c388aSLukasz Kazmierczak     {
1232*9e6c388aSLukasz Kazmierczak         return;
1233*9e6c388aSLukasz Kazmierczak     }
1234*9e6c388aSLukasz Kazmierczak 
1235*9e6c388aSLukasz Kazmierczak     telemetry::AddReportArgs args;
1236*9e6c388aSLukasz Kazmierczak     if (!telemetry::getUserParameters(asyncResp->res, req, args))
1237*9e6c388aSLukasz Kazmierczak     {
1238*9e6c388aSLukasz Kazmierczak         return;
1239*9e6c388aSLukasz Kazmierczak     }
1240*9e6c388aSLukasz Kazmierczak 
1241*9e6c388aSLukasz Kazmierczak     boost::container::flat_set<std::pair<std::string, std::string>>
1242*9e6c388aSLukasz Kazmierczak         chassisSensors;
1243*9e6c388aSLukasz Kazmierczak     if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics,
1244*9e6c388aSLukasz Kazmierczak                                                     chassisSensors))
1245*9e6c388aSLukasz Kazmierczak     {
1246*9e6c388aSLukasz Kazmierczak         return;
1247*9e6c388aSLukasz Kazmierczak     }
1248*9e6c388aSLukasz Kazmierczak 
1249*9e6c388aSLukasz Kazmierczak     auto addReportReq = std::make_shared<telemetry::AddReport>(std::move(args),
1250*9e6c388aSLukasz Kazmierczak                                                                asyncResp);
1251*9e6c388aSLukasz Kazmierczak     for (const auto& [chassis, sensorType] : chassisSensors)
1252*9e6c388aSLukasz Kazmierczak     {
1253*9e6c388aSLukasz Kazmierczak         retrieveUriToDbusMap(
1254*9e6c388aSLukasz Kazmierczak             chassis, sensorType,
1255*9e6c388aSLukasz Kazmierczak             [asyncResp, addReportReq](
1256*9e6c388aSLukasz Kazmierczak                 const boost::beast::http::status status,
1257*9e6c388aSLukasz Kazmierczak                 const std::map<std::string, std::string>& uriToDbus) {
1258*9e6c388aSLukasz Kazmierczak             if (status != boost::beast::http::status::ok)
1259*9e6c388aSLukasz Kazmierczak             {
1260*9e6c388aSLukasz Kazmierczak                 BMCWEB_LOG_ERROR(
1261*9e6c388aSLukasz Kazmierczak                     "Failed to retrieve URI to dbus sensors map with err {}",
1262*9e6c388aSLukasz Kazmierczak                     static_cast<unsigned>(status));
1263*9e6c388aSLukasz Kazmierczak                 return;
1264*9e6c388aSLukasz Kazmierczak             }
1265*9e6c388aSLukasz Kazmierczak             addReportReq->insert(uriToDbus);
1266*9e6c388aSLukasz Kazmierczak             });
1267*9e6c388aSLukasz Kazmierczak     }
1268*9e6c388aSLukasz Kazmierczak }
1269*9e6c388aSLukasz Kazmierczak 
1270*9e6c388aSLukasz Kazmierczak inline void
12714220be3bSEd Tanous     handleMetricReportHead(App& app, const crow::Request& req,
12724220be3bSEd Tanous                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12734220be3bSEd Tanous                            const std::string& /*id*/)
12744220be3bSEd Tanous {
12754220be3bSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
12764220be3bSEd Tanous     {
12774220be3bSEd Tanous         return;
12784220be3bSEd Tanous     }
12794220be3bSEd Tanous     asyncResp->res.addHeader(
12804220be3bSEd Tanous         boost::beast::http::field::link,
12814220be3bSEd Tanous         "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby");
12824220be3bSEd Tanous }
12834220be3bSEd Tanous 
12844220be3bSEd Tanous inline void
128586a5ac98SEd Tanous     handleMetricReportGet(App& app, const crow::Request& req,
128686a5ac98SEd Tanous                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
128786a5ac98SEd Tanous                           const std::string& id)
128886a5ac98SEd Tanous {
128986a5ac98SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
129086a5ac98SEd Tanous     {
129186a5ac98SEd Tanous         return;
129286a5ac98SEd Tanous     }
12934220be3bSEd Tanous     asyncResp->res.addHeader(
12944220be3bSEd Tanous         boost::beast::http::field::link,
12954220be3bSEd Tanous         "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby");
129686a5ac98SEd Tanous 
129786a5ac98SEd Tanous     sdbusplus::asio::getAllProperties(
129886a5ac98SEd Tanous         *crow::connections::systemBus, telemetry::service,
129986a5ac98SEd Tanous         telemetry::getDbusReportPath(id), telemetry::reportInterface,
130086a5ac98SEd Tanous         [asyncResp, id](const boost::system::error_code& ec,
130186a5ac98SEd Tanous                         const dbus::utility::DBusPropertiesMap& properties) {
1302*9e6c388aSLukasz Kazmierczak         if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec))
130386a5ac98SEd Tanous         {
130486a5ac98SEd Tanous             return;
130586a5ac98SEd Tanous         }
130686a5ac98SEd Tanous 
130786a5ac98SEd Tanous         telemetry::fillReportDefinition(asyncResp, id, properties);
130886a5ac98SEd Tanous         });
130986a5ac98SEd Tanous }
131086a5ac98SEd Tanous 
1311dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete(
1312dd1c4a9cSSzymon Dompke     App& app, const crow::Request& req,
1313dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1314dd1c4a9cSSzymon Dompke 
1315dd1c4a9cSSzymon Dompke {
1316dd1c4a9cSSzymon Dompke     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1317dd1c4a9cSSzymon Dompke     {
1318dd1c4a9cSSzymon Dompke         return;
1319dd1c4a9cSSzymon Dompke     }
1320dd1c4a9cSSzymon Dompke 
1321dd1c4a9cSSzymon Dompke     const std::string reportPath = telemetry::getDbusReportPath(id);
1322dd1c4a9cSSzymon Dompke 
1323dd1c4a9cSSzymon Dompke     crow::connections::systemBus->async_method_call(
1324dd1c4a9cSSzymon Dompke         [asyncResp, id](const boost::system::error_code& ec) {
1325dd1c4a9cSSzymon Dompke         /*
1326dd1c4a9cSSzymon Dompke          * boost::system::errc and std::errc are missing value
1327dd1c4a9cSSzymon Dompke          * for EBADR error that is defined in Linux.
1328dd1c4a9cSSzymon Dompke          */
1329dd1c4a9cSSzymon Dompke         if (ec.value() == EBADR)
1330dd1c4a9cSSzymon Dompke         {
1331dd1c4a9cSSzymon Dompke             messages::resourceNotFound(asyncResp->res, "MetricReportDefinition",
1332dd1c4a9cSSzymon Dompke                                        id);
1333dd1c4a9cSSzymon Dompke             return;
1334dd1c4a9cSSzymon Dompke         }
1335dd1c4a9cSSzymon Dompke 
1336dd1c4a9cSSzymon Dompke         if (ec)
1337dd1c4a9cSSzymon Dompke         {
133862598e31SEd Tanous             BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
1339dd1c4a9cSSzymon Dompke             messages::internalError(asyncResp->res);
1340dd1c4a9cSSzymon Dompke             return;
1341dd1c4a9cSSzymon Dompke         }
1342dd1c4a9cSSzymon Dompke 
1343dd1c4a9cSSzymon Dompke         asyncResp->res.result(boost::beast::http::status::no_content);
1344dd1c4a9cSSzymon Dompke         },
1345dd1c4a9cSSzymon Dompke         telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete",
1346dd1c4a9cSSzymon Dompke         "Delete");
1347dd1c4a9cSSzymon Dompke }
1348dd1c4a9cSSzymon Dompke 
13497e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app)
1350081ebf06SWludzik, Jozef {
13517e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
13524220be3bSEd Tanous         .privileges(redfish::privileges::headMetricReportDefinitionCollection)
13534220be3bSEd Tanous         .methods(boost::beast::http::verb::head)(std::bind_front(
1354*9e6c388aSLukasz Kazmierczak             telemetry::handleMetricReportDefinitionCollectionHead,
1355*9e6c388aSLukasz Kazmierczak             std::ref(app)));
13564220be3bSEd Tanous 
13574220be3bSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
1358ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinitionCollection)
13594220be3bSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
1360*9e6c388aSLukasz Kazmierczak             telemetry::handleMetricReportDefinitionCollectionGet,
1361*9e6c388aSLukasz Kazmierczak             std::ref(app)));
13624dbb8aeaSWludzik, Jozef 
13637e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
1364ed398213SEd Tanous         .privileges(redfish::privileges::postMetricReportDefinitionCollection)
1365002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
1366*9e6c388aSLukasz Kazmierczak             std::bind_front(handleMetricReportDefinitionsPost, std::ref(app)));
1367081ebf06SWludzik, Jozef }
1368081ebf06SWludzik, Jozef 
13697e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app)
1370081ebf06SWludzik, Jozef {
13717e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
13727e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
1373ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
13744220be3bSEd Tanous         .methods(boost::beast::http::verb::head)(
13754220be3bSEd Tanous             std::bind_front(handleMetricReportHead, std::ref(app)));
13764220be3bSEd Tanous 
13774220be3bSEd Tanous     BMCWEB_ROUTE(app,
13784220be3bSEd Tanous                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
13794220be3bSEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
13807e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
138186a5ac98SEd Tanous             std::bind_front(handleMetricReportGet, std::ref(app)));
1382479e899dSKrzysztof Grobelny 
13837e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
13847e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
1385*9e6c388aSLukasz Kazmierczak         .privileges(redfish::privileges::deleteMetricReportDefinition)
13867e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
1387dd1c4a9cSSzymon Dompke             std::bind_front(handleMetricReportDelete, std::ref(app)));
1388*9e6c388aSLukasz Kazmierczak 
1389*9e6c388aSLukasz Kazmierczak     BMCWEB_ROUTE(app,
1390*9e6c388aSLukasz Kazmierczak                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
1391*9e6c388aSLukasz Kazmierczak         .privileges(redfish::privileges::patchMetricReportDefinition)
1392*9e6c388aSLukasz Kazmierczak         .methods(boost::beast::http::verb::patch)(
1393*9e6c388aSLukasz Kazmierczak             std::bind_front(telemetry::handleReportPatch, std::ref(app)));
13944dbb8aeaSWludzik, Jozef }
1395081ebf06SWludzik, Jozef } // namespace redfish
1396