xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3081ebf06SWludzik, Jozef #pragma once
4081ebf06SWludzik, Jozef 
53ccb3adbSEd Tanous #include "app.hpp"
63ccb3adbSEd Tanous #include "dbus_utility.hpp"
7479e899dSKrzysztof Grobelny #include "generated/enums/metric_report_definition.hpp"
8539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
93ccb3adbSEd Tanous #include "query.hpp"
103ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
114dbb8aeaSWludzik, Jozef #include "sensors.hpp"
123ccb3adbSEd Tanous #include "utils/collection.hpp"
133ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
145b90429aSEd Tanous #include "utils/json_utils.hpp"
15081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp"
16081ebf06SWludzik, Jozef #include "utils/time_utils.hpp"
17081ebf06SWludzik, Jozef 
184dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp>
19ef4c65b7SEd Tanous #include <boost/url/format.hpp>
2089474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
2189474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
224dbb8aeaSWludzik, Jozef 
237a1dbc48SGeorge Liu #include <array>
24fe04d49cSNan Zhou #include <map>
25f19ab44aSSzymon Dompke #include <optional>
26f19ab44aSSzymon Dompke #include <span>
27f19ab44aSSzymon Dompke #include <string>
287a1dbc48SGeorge Liu #include <string_view>
29081ebf06SWludzik, Jozef #include <tuple>
30f19ab44aSSzymon Dompke #include <utility>
31081ebf06SWludzik, Jozef #include <variant>
32f19ab44aSSzymon Dompke #include <vector>
33081ebf06SWludzik, Jozef 
34081ebf06SWludzik, Jozef namespace redfish
35081ebf06SWludzik, Jozef {
36081ebf06SWludzik, Jozef 
37081ebf06SWludzik, Jozef namespace telemetry
38081ebf06SWludzik, Jozef {
39081ebf06SWludzik, Jozef 
40479e899dSKrzysztof Grobelny using ReadingParameters = std::vector<std::tuple<
41479e899dSKrzysztof Grobelny     std::vector<std::tuple<sdbusplus::message::object_path, std::string>>,
42479e899dSKrzysztof Grobelny     std::string, std::string, uint64_t>>;
43479e899dSKrzysztof Grobelny 
449e6c388aSLukasz Kazmierczak inline bool verifyCommonErrors(crow::Response& res, const std::string& id,
459e6c388aSLukasz Kazmierczak                                const boost::system::error_code& ec)
469e6c388aSLukasz Kazmierczak {
479e6c388aSLukasz Kazmierczak     if (ec.value() == EBADR || ec == boost::system::errc::host_unreachable)
489e6c388aSLukasz Kazmierczak     {
499e6c388aSLukasz Kazmierczak         messages::resourceNotFound(res, "MetricReportDefinition", id);
509e6c388aSLukasz Kazmierczak         return false;
519e6c388aSLukasz Kazmierczak     }
529e6c388aSLukasz Kazmierczak 
539e6c388aSLukasz Kazmierczak     if (ec == boost::system::errc::file_exists)
549e6c388aSLukasz Kazmierczak     {
559e6c388aSLukasz Kazmierczak         messages::resourceAlreadyExists(res, "MetricReportDefinition", "Id",
569e6c388aSLukasz Kazmierczak                                         id);
579e6c388aSLukasz Kazmierczak         return false;
589e6c388aSLukasz Kazmierczak     }
599e6c388aSLukasz Kazmierczak 
609e6c388aSLukasz Kazmierczak     if (ec == boost::system::errc::too_many_files_open)
619e6c388aSLukasz Kazmierczak     {
629e6c388aSLukasz Kazmierczak         messages::createLimitReachedForResource(res);
639e6c388aSLukasz Kazmierczak         return false;
649e6c388aSLukasz Kazmierczak     }
659e6c388aSLukasz Kazmierczak 
669e6c388aSLukasz Kazmierczak     if (ec)
679e6c388aSLukasz Kazmierczak     {
689e6c388aSLukasz Kazmierczak         BMCWEB_LOG_ERROR("DBUS response error {}", ec);
699e6c388aSLukasz Kazmierczak         messages::internalError(res);
709e6c388aSLukasz Kazmierczak         return false;
719e6c388aSLukasz Kazmierczak     }
729e6c388aSLukasz Kazmierczak 
739e6c388aSLukasz Kazmierczak     return true;
749e6c388aSLukasz Kazmierczak }
759e6c388aSLukasz Kazmierczak 
76479e899dSKrzysztof Grobelny inline metric_report_definition::ReportActionsEnum
77479e899dSKrzysztof Grobelny     toRedfishReportAction(std::string_view dbusValue)
78479e899dSKrzysztof Grobelny {
79479e899dSKrzysztof Grobelny     if (dbusValue ==
80479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate")
81479e899dSKrzysztof Grobelny     {
82479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::RedfishEvent;
83479e899dSKrzysztof Grobelny     }
84479e899dSKrzysztof Grobelny     if (dbusValue ==
85479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection")
86479e899dSKrzysztof Grobelny     {
87479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::
88479e899dSKrzysztof Grobelny             LogToMetricReportsCollection;
89479e899dSKrzysztof Grobelny     }
90479e899dSKrzysztof Grobelny     return metric_report_definition::ReportActionsEnum::Invalid;
91479e899dSKrzysztof Grobelny }
92479e899dSKrzysztof Grobelny 
93479e899dSKrzysztof Grobelny inline std::string toDbusReportAction(std::string_view redfishValue)
94479e899dSKrzysztof Grobelny {
95479e899dSKrzysztof Grobelny     if (redfishValue == "RedfishEvent")
96479e899dSKrzysztof Grobelny     {
97479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate";
98479e899dSKrzysztof Grobelny     }
99479e899dSKrzysztof Grobelny     if (redfishValue == "LogToMetricReportsCollection")
100479e899dSKrzysztof Grobelny     {
101479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection";
102479e899dSKrzysztof Grobelny     }
103479e899dSKrzysztof Grobelny     return "";
104479e899dSKrzysztof Grobelny }
105479e899dSKrzysztof Grobelny 
106479e899dSKrzysztof Grobelny inline metric_report_definition::MetricReportDefinitionType
107479e899dSKrzysztof Grobelny     toRedfishReportingType(std::string_view dbusValue)
108479e899dSKrzysztof Grobelny {
109479e899dSKrzysztof Grobelny     if (dbusValue ==
110479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange")
111479e899dSKrzysztof Grobelny     {
112479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnChange;
113479e899dSKrzysztof Grobelny     }
114479e899dSKrzysztof Grobelny     if (dbusValue ==
115479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest")
116479e899dSKrzysztof Grobelny     {
117479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnRequest;
118479e899dSKrzysztof Grobelny     }
119479e899dSKrzysztof Grobelny     if (dbusValue ==
120479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic")
121479e899dSKrzysztof Grobelny     {
122479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::Periodic;
123479e899dSKrzysztof Grobelny     }
124479e899dSKrzysztof Grobelny     return metric_report_definition::MetricReportDefinitionType::Invalid;
125479e899dSKrzysztof Grobelny }
126479e899dSKrzysztof Grobelny 
127479e899dSKrzysztof Grobelny inline std::string toDbusReportingType(std::string_view redfishValue)
128479e899dSKrzysztof Grobelny {
129479e899dSKrzysztof Grobelny     if (redfishValue == "OnChange")
130479e899dSKrzysztof Grobelny     {
131479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange";
132479e899dSKrzysztof Grobelny     }
133479e899dSKrzysztof Grobelny     if (redfishValue == "OnRequest")
134479e899dSKrzysztof Grobelny     {
135479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest";
136479e899dSKrzysztof Grobelny     }
137479e899dSKrzysztof Grobelny     if (redfishValue == "Periodic")
138479e899dSKrzysztof Grobelny     {
139479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic";
140479e899dSKrzysztof Grobelny     }
141479e899dSKrzysztof Grobelny     return "";
142479e899dSKrzysztof Grobelny }
143479e899dSKrzysztof Grobelny 
144479e899dSKrzysztof Grobelny inline metric_report_definition::CollectionTimeScope
145479e899dSKrzysztof Grobelny     toRedfishCollectionTimeScope(std::string_view dbusValue)
146479e899dSKrzysztof Grobelny {
147479e899dSKrzysztof Grobelny     if (dbusValue ==
148479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point")
149479e899dSKrzysztof Grobelny     {
150479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Point;
151479e899dSKrzysztof Grobelny     }
152479e899dSKrzysztof Grobelny     if (dbusValue ==
153479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval")
154479e899dSKrzysztof Grobelny     {
155479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Interval;
156479e899dSKrzysztof Grobelny     }
157479e899dSKrzysztof Grobelny     if (dbusValue ==
158479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval")
159479e899dSKrzysztof Grobelny     {
160479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::StartupInterval;
161479e899dSKrzysztof Grobelny     }
162479e899dSKrzysztof Grobelny     return metric_report_definition::CollectionTimeScope::Invalid;
163479e899dSKrzysztof Grobelny }
164479e899dSKrzysztof Grobelny 
165479e899dSKrzysztof Grobelny inline std::string toDbusCollectionTimeScope(std::string_view redfishValue)
166479e899dSKrzysztof Grobelny {
167479e899dSKrzysztof Grobelny     if (redfishValue == "Point")
168479e899dSKrzysztof Grobelny     {
169479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point";
170479e899dSKrzysztof Grobelny     }
171479e899dSKrzysztof Grobelny     if (redfishValue == "Interval")
172479e899dSKrzysztof Grobelny     {
173479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval";
174479e899dSKrzysztof Grobelny     }
175479e899dSKrzysztof Grobelny     if (redfishValue == "StartupInterval")
176479e899dSKrzysztof Grobelny     {
177479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval";
178479e899dSKrzysztof Grobelny     }
179479e899dSKrzysztof Grobelny     return "";
180479e899dSKrzysztof Grobelny }
181479e899dSKrzysztof Grobelny 
182479e899dSKrzysztof Grobelny inline metric_report_definition::ReportUpdatesEnum
183479e899dSKrzysztof Grobelny     toRedfishReportUpdates(std::string_view dbusValue)
184479e899dSKrzysztof Grobelny {
185479e899dSKrzysztof Grobelny     if (dbusValue ==
186479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite")
187479e899dSKrzysztof Grobelny     {
188479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::Overwrite;
189479e899dSKrzysztof Grobelny     }
190479e899dSKrzysztof Grobelny     if (dbusValue ==
191479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull")
192479e899dSKrzysztof Grobelny     {
193479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendWrapsWhenFull;
194479e899dSKrzysztof Grobelny     }
195479e899dSKrzysztof Grobelny     if (dbusValue ==
196479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull")
197479e899dSKrzysztof Grobelny     {
198479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendStopsWhenFull;
199479e899dSKrzysztof Grobelny     }
200479e899dSKrzysztof Grobelny     return metric_report_definition::ReportUpdatesEnum::Invalid;
201479e899dSKrzysztof Grobelny }
202479e899dSKrzysztof Grobelny 
203479e899dSKrzysztof Grobelny inline std::string toDbusReportUpdates(std::string_view redfishValue)
204479e899dSKrzysztof Grobelny {
205479e899dSKrzysztof Grobelny     if (redfishValue == "Overwrite")
206479e899dSKrzysztof Grobelny     {
207479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite";
208479e899dSKrzysztof Grobelny     }
209479e899dSKrzysztof Grobelny     if (redfishValue == "AppendWrapsWhenFull")
210479e899dSKrzysztof Grobelny     {
211479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull";
212479e899dSKrzysztof Grobelny     }
213479e899dSKrzysztof Grobelny     if (redfishValue == "AppendStopsWhenFull")
214479e899dSKrzysztof Grobelny     {
215479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull";
216479e899dSKrzysztof Grobelny     }
217479e899dSKrzysztof Grobelny     return "";
218479e899dSKrzysztof Grobelny }
219081ebf06SWludzik, Jozef 
220f19ab44aSSzymon Dompke inline std::optional<nlohmann::json::array_t> getLinkedTriggers(
221f19ab44aSSzymon Dompke     std::span<const sdbusplus::message::object_path> triggerPaths)
222f19ab44aSSzymon Dompke {
223f19ab44aSSzymon Dompke     nlohmann::json::array_t triggers;
224f19ab44aSSzymon Dompke 
225f19ab44aSSzymon Dompke     for (const sdbusplus::message::object_path& path : triggerPaths)
226f19ab44aSSzymon Dompke     {
227f19ab44aSSzymon Dompke         if (path.parent_path() !=
228f19ab44aSSzymon Dompke             "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService")
229f19ab44aSSzymon Dompke         {
23062598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}",
23162598e31SEd Tanous                              path.str);
232f19ab44aSSzymon Dompke             return std::nullopt;
233f19ab44aSSzymon Dompke         }
234f19ab44aSSzymon Dompke 
235f19ab44aSSzymon Dompke         std::string id = path.filename();
236f19ab44aSSzymon Dompke         if (id.empty())
237f19ab44aSSzymon Dompke         {
23862598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Triggers contains invalid value: {}",
23962598e31SEd Tanous                              path.str);
240f19ab44aSSzymon Dompke             return std::nullopt;
241f19ab44aSSzymon Dompke         }
242f19ab44aSSzymon Dompke         nlohmann::json::object_t trigger;
243f19ab44aSSzymon Dompke         trigger["@odata.id"] =
244f19ab44aSSzymon Dompke             boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
245f19ab44aSSzymon Dompke         triggers.emplace_back(std::move(trigger));
246f19ab44aSSzymon Dompke     }
247f19ab44aSSzymon Dompke 
248f19ab44aSSzymon Dompke     return triggers;
249f19ab44aSSzymon Dompke }
250f19ab44aSSzymon Dompke 
251bd79bce8SPatrick Williams inline void fillReportDefinition(
252bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
253479e899dSKrzysztof Grobelny     const dbus::utility::DBusPropertiesMap& properties)
254081ebf06SWludzik, Jozef {
255479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
256479e899dSKrzysztof Grobelny     ReadingParameters readingParams;
257479e899dSKrzysztof Grobelny     std::string reportingType;
258479e899dSKrzysztof Grobelny     std::string reportUpdates;
259479e899dSKrzysztof Grobelny     std::string name;
260479e899dSKrzysztof Grobelny     uint64_t appendLimit = 0;
261479e899dSKrzysztof Grobelny     uint64_t interval = 0;
262479e899dSKrzysztof Grobelny     bool enabled = false;
263f19ab44aSSzymon Dompke     std::vector<sdbusplus::message::object_path> triggers;
26489474494SKrzysztof Grobelny 
26589474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
266479e899dSKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "ReportingType",
267479e899dSKrzysztof Grobelny         reportingType, "Interval", interval, "ReportActions", reportActions,
268479e899dSKrzysztof Grobelny         "ReportUpdates", reportUpdates, "AppendLimit", appendLimit,
269f19ab44aSSzymon Dompke         "ReadingParameters", readingParams, "Name", name, "Enabled", enabled,
270f19ab44aSSzymon Dompke         "Triggers", triggers);
27189474494SKrzysztof Grobelny 
27289474494SKrzysztof Grobelny     if (!success)
273081ebf06SWludzik, Jozef     {
274081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
275081ebf06SWludzik, Jozef         return;
276081ebf06SWludzik, Jozef     }
277081ebf06SWludzik, Jozef 
278479e899dSKrzysztof Grobelny     metric_report_definition::MetricReportDefinitionType redfishReportingType =
279479e899dSKrzysztof Grobelny         toRedfishReportingType(reportingType);
280479e899dSKrzysztof Grobelny     if (redfishReportingType ==
281479e899dSKrzysztof Grobelny         metric_report_definition::MetricReportDefinitionType::Invalid)
282081ebf06SWludzik, Jozef     {
283479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
284479e899dSKrzysztof Grobelny         return;
285081ebf06SWludzik, Jozef     }
28689474494SKrzysztof Grobelny 
287479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionType"] =
288479e899dSKrzysztof Grobelny         redfishReportingType;
289479e899dSKrzysztof Grobelny 
290f19ab44aSSzymon Dompke     std::optional<nlohmann::json::array_t> linkedTriggers =
291f19ab44aSSzymon Dompke         getLinkedTriggers(triggers);
292f19ab44aSSzymon Dompke     if (!linkedTriggers)
293f19ab44aSSzymon Dompke     {
294f19ab44aSSzymon Dompke         messages::internalError(asyncResp->res);
295f19ab44aSSzymon Dompke         return;
296f19ab44aSSzymon Dompke     }
297f19ab44aSSzymon Dompke 
298f19ab44aSSzymon Dompke     asyncResp->res.jsonValue["Links"]["Triggers"] = std::move(*linkedTriggers);
299f19ab44aSSzymon Dompke 
300479e899dSKrzysztof Grobelny     nlohmann::json::array_t redfishReportActions;
301479e899dSKrzysztof Grobelny     for (const std::string& action : reportActions)
302081ebf06SWludzik, Jozef     {
303479e899dSKrzysztof Grobelny         metric_report_definition::ReportActionsEnum redfishAction =
304479e899dSKrzysztof Grobelny             toRedfishReportAction(action);
305479e899dSKrzysztof Grobelny         if (redfishAction ==
306479e899dSKrzysztof Grobelny             metric_report_definition::ReportActionsEnum::Invalid)
307479e899dSKrzysztof Grobelny         {
308479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
309479e899dSKrzysztof Grobelny             return;
310081ebf06SWludzik, Jozef         }
311081ebf06SWludzik, Jozef 
312479e899dSKrzysztof Grobelny         redfishReportActions.emplace_back(redfishAction);
313479e899dSKrzysztof Grobelny     }
314479e899dSKrzysztof Grobelny 
315479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions);
316479e899dSKrzysztof Grobelny 
317479e899dSKrzysztof Grobelny     nlohmann::json::array_t metrics = nlohmann::json::array();
318479e899dSKrzysztof Grobelny     for (const auto& [sensorData, collectionFunction, collectionTimeScope,
319479e899dSKrzysztof Grobelny                       collectionDuration] : readingParams)
32089474494SKrzysztof Grobelny     {
321479e899dSKrzysztof Grobelny         nlohmann::json::array_t metricProperties;
322479e899dSKrzysztof Grobelny 
323479e899dSKrzysztof Grobelny         for (const auto& [sensorPath, sensorMetadata] : sensorData)
324081ebf06SWludzik, Jozef         {
325479e899dSKrzysztof Grobelny             metricProperties.emplace_back(sensorMetadata);
326479e899dSKrzysztof Grobelny         }
327479e899dSKrzysztof Grobelny 
328613dabeaSEd Tanous         nlohmann::json::object_t metric;
329479e899dSKrzysztof Grobelny 
330479e899dSKrzysztof Grobelny         metric_report_definition::CalculationAlgorithmEnum
331479e899dSKrzysztof Grobelny             redfishCollectionFunction =
332479e899dSKrzysztof Grobelny                 telemetry::toRedfishCollectionFunction(collectionFunction);
333479e899dSKrzysztof Grobelny         if (redfishCollectionFunction ==
334479e899dSKrzysztof Grobelny             metric_report_definition::CalculationAlgorithmEnum::Invalid)
335479e899dSKrzysztof Grobelny         {
336479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
337479e899dSKrzysztof Grobelny             return;
338479e899dSKrzysztof Grobelny         }
339479e899dSKrzysztof Grobelny         metric["CollectionFunction"] = redfishCollectionFunction;
340479e899dSKrzysztof Grobelny 
341479e899dSKrzysztof Grobelny         metric_report_definition::CollectionTimeScope
342479e899dSKrzysztof Grobelny             redfishCollectionTimeScope =
343479e899dSKrzysztof Grobelny                 toRedfishCollectionTimeScope(collectionTimeScope);
344479e899dSKrzysztof Grobelny         if (redfishCollectionTimeScope ==
345479e899dSKrzysztof Grobelny             metric_report_definition::CollectionTimeScope::Invalid)
346479e899dSKrzysztof Grobelny         {
347479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
348479e899dSKrzysztof Grobelny             return;
349479e899dSKrzysztof Grobelny         }
350479e899dSKrzysztof Grobelny         metric["CollectionTimeScope"] = redfishCollectionTimeScope;
351479e899dSKrzysztof Grobelny 
352479e899dSKrzysztof Grobelny         metric["MetricProperties"] = std::move(metricProperties);
353479e899dSKrzysztof Grobelny         metric["CollectionDuration"] = time_utils::toDurationString(
354479e899dSKrzysztof Grobelny             std::chrono::milliseconds(collectionDuration));
355b2ba3072SPatrick Williams         metrics.emplace_back(std::move(metric));
356081ebf06SWludzik, Jozef     }
357479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Metrics"] = std::move(metrics);
358479e899dSKrzysztof Grobelny 
359479e899dSKrzysztof Grobelny     if (enabled)
360479e899dSKrzysztof Grobelny     {
361539d8c6bSEd Tanous         asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
362479e899dSKrzysztof Grobelny     }
363479e899dSKrzysztof Grobelny     else
364479e899dSKrzysztof Grobelny     {
365539d8c6bSEd Tanous         asyncResp->res.jsonValue["Status"]["State"] = resource::State::Disabled;
36689474494SKrzysztof Grobelny     }
36789474494SKrzysztof Grobelny 
368479e899dSKrzysztof Grobelny     metric_report_definition::ReportUpdatesEnum redfishReportUpdates =
369479e899dSKrzysztof Grobelny         toRedfishReportUpdates(reportUpdates);
370479e899dSKrzysztof Grobelny     if (redfishReportUpdates ==
371479e899dSKrzysztof Grobelny         metric_report_definition::ReportUpdatesEnum::Invalid)
37289474494SKrzysztof Grobelny     {
373479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
374479e899dSKrzysztof Grobelny         return;
37589474494SKrzysztof Grobelny     }
376479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportUpdates"] = redfishReportUpdates;
37789474494SKrzysztof Grobelny 
378479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionEnabled"] = enabled;
379479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["AppendLimit"] = appendLimit;
380479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Name"] = name;
381081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
382479e899dSKrzysztof Grobelny         time_utils::toDurationString(std::chrono::milliseconds(interval));
383479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.type"] =
384479e899dSKrzysztof Grobelny         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
385479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
386479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id);
387479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Id"] = id;
388479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format(
389479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReports/{}", id);
39089474494SKrzysztof Grobelny }
39189474494SKrzysztof Grobelny 
3924dbb8aeaSWludzik, Jozef struct AddReportArgs
3934dbb8aeaSWludzik, Jozef {
394479e899dSKrzysztof Grobelny     struct MetricArgs
395479e899dSKrzysztof Grobelny     {
396479e899dSKrzysztof Grobelny         std::vector<std::string> uris;
397479e899dSKrzysztof Grobelny         std::string collectionFunction;
398479e899dSKrzysztof Grobelny         std::string collectionTimeScope;
399479e899dSKrzysztof Grobelny         uint64_t collectionDuration = 0;
400479e899dSKrzysztof Grobelny     };
401479e899dSKrzysztof Grobelny 
402479e899dSKrzysztof Grobelny     std::string id;
4034dbb8aeaSWludzik, Jozef     std::string name;
4044dbb8aeaSWludzik, Jozef     std::string reportingType;
405479e899dSKrzysztof Grobelny     std::string reportUpdates;
406479e899dSKrzysztof Grobelny     uint64_t appendLimit = std::numeric_limits<uint64_t>::max();
407479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
408479e899dSKrzysztof Grobelny     uint64_t interval = std::numeric_limits<uint64_t>::max();
409479e899dSKrzysztof Grobelny     std::vector<MetricArgs> metrics;
410479e899dSKrzysztof Grobelny     bool metricReportDefinitionEnabled = true;
4114dbb8aeaSWludzik, Jozef };
4124dbb8aeaSWludzik, Jozef 
4134dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res,
414479e899dSKrzysztof Grobelny                                 const std::vector<std::string>& actions,
4159e6c388aSLukasz Kazmierczak                                 std::vector<std::string>& outReportActions)
4164dbb8aeaSWludzik, Jozef {
4174dbb8aeaSWludzik, Jozef     size_t index = 0;
418479e899dSKrzysztof Grobelny     for (const std::string& action : actions)
4194dbb8aeaSWludzik, Jozef     {
420479e899dSKrzysztof Grobelny         std::string dbusReportAction = toDbusReportAction(action);
421479e899dSKrzysztof Grobelny         if (dbusReportAction.empty())
4224dbb8aeaSWludzik, Jozef         {
4239e6c388aSLukasz Kazmierczak             messages::propertyValueNotInList(
4249e6c388aSLukasz Kazmierczak                 res, action, "ReportActions/" + std::to_string(index));
4254dbb8aeaSWludzik, Jozef             return false;
4264dbb8aeaSWludzik, Jozef         }
427479e899dSKrzysztof Grobelny 
4289e6c388aSLukasz Kazmierczak         outReportActions.emplace_back(std::move(dbusReportAction));
4294dbb8aeaSWludzik, Jozef         index++;
4304dbb8aeaSWludzik, Jozef     }
4314dbb8aeaSWludzik, Jozef     return true;
4324dbb8aeaSWludzik, Jozef }
4334dbb8aeaSWludzik, Jozef 
434b14f357fSEd Tanous inline bool getUserMetric(crow::Response& res, nlohmann::json::object_t& metric,
435479e899dSKrzysztof Grobelny                           AddReportArgs::MetricArgs& metricArgs)
436479e899dSKrzysztof Grobelny {
437479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> uris;
438479e899dSKrzysztof Grobelny     std::optional<std::string> collectionDurationStr;
439479e899dSKrzysztof Grobelny     std::optional<std::string> collectionFunction;
440479e899dSKrzysztof Grobelny     std::optional<std::string> collectionTimeScopeStr;
441479e899dSKrzysztof Grobelny 
442afc474aeSMyung Bae     if (!json_util::readJsonObject( //
443afc474aeSMyung Bae             metric, res, //
444afc474aeSMyung Bae             "CollectionDuration", collectionDurationStr, //
445afc474aeSMyung Bae             "CollectionFunction", collectionFunction, //
446afc474aeSMyung Bae             "CollectionTimeScope", collectionTimeScopeStr, //
447afc474aeSMyung Bae             "MetricProperties", uris //
448afc474aeSMyung Bae             ))
449479e899dSKrzysztof Grobelny     {
450479e899dSKrzysztof Grobelny         return false;
451479e899dSKrzysztof Grobelny     }
452479e899dSKrzysztof Grobelny 
453479e899dSKrzysztof Grobelny     if (uris)
454479e899dSKrzysztof Grobelny     {
455479e899dSKrzysztof Grobelny         metricArgs.uris = std::move(*uris);
456479e899dSKrzysztof Grobelny     }
457479e899dSKrzysztof Grobelny 
458479e899dSKrzysztof Grobelny     if (collectionFunction)
459479e899dSKrzysztof Grobelny     {
460479e899dSKrzysztof Grobelny         std::string dbusCollectionFunction =
461479e899dSKrzysztof Grobelny             telemetry::toDbusCollectionFunction(*collectionFunction);
462479e899dSKrzysztof Grobelny         if (dbusCollectionFunction.empty())
463479e899dSKrzysztof Grobelny         {
464479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionFunction",
465479e899dSKrzysztof Grobelny                                              *collectionFunction);
466479e899dSKrzysztof Grobelny             return false;
467479e899dSKrzysztof Grobelny         }
468479e899dSKrzysztof Grobelny         metricArgs.collectionFunction = std::move(dbusCollectionFunction);
469479e899dSKrzysztof Grobelny     }
470479e899dSKrzysztof Grobelny 
471479e899dSKrzysztof Grobelny     if (collectionTimeScopeStr)
472479e899dSKrzysztof Grobelny     {
473479e899dSKrzysztof Grobelny         std::string dbusCollectionTimeScope =
474479e899dSKrzysztof Grobelny             toDbusCollectionTimeScope(*collectionTimeScopeStr);
475479e899dSKrzysztof Grobelny         if (dbusCollectionTimeScope.empty())
476479e899dSKrzysztof Grobelny         {
477479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionTimeScope",
478479e899dSKrzysztof Grobelny                                              *collectionTimeScopeStr);
479479e899dSKrzysztof Grobelny             return false;
480479e899dSKrzysztof Grobelny         }
481479e899dSKrzysztof Grobelny         metricArgs.collectionTimeScope = std::move(dbusCollectionTimeScope);
482479e899dSKrzysztof Grobelny     }
483479e899dSKrzysztof Grobelny 
484479e899dSKrzysztof Grobelny     if (collectionDurationStr)
485479e899dSKrzysztof Grobelny     {
486479e899dSKrzysztof Grobelny         std::optional<std::chrono::milliseconds> duration =
487479e899dSKrzysztof Grobelny             time_utils::fromDurationString(*collectionDurationStr);
488479e899dSKrzysztof Grobelny 
489479e899dSKrzysztof Grobelny         if (!duration || duration->count() < 0)
490479e899dSKrzysztof Grobelny         {
491479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionDuration",
492479e899dSKrzysztof Grobelny                                              *collectionDurationStr);
493479e899dSKrzysztof Grobelny             return false;
494479e899dSKrzysztof Grobelny         }
495479e899dSKrzysztof Grobelny 
496479e899dSKrzysztof Grobelny         metricArgs.collectionDuration =
497479e899dSKrzysztof Grobelny             static_cast<uint64_t>(duration->count());
498479e899dSKrzysztof Grobelny     }
499479e899dSKrzysztof Grobelny 
500479e899dSKrzysztof Grobelny     return true;
501479e899dSKrzysztof Grobelny }
502479e899dSKrzysztof Grobelny 
503479e899dSKrzysztof Grobelny inline bool getUserMetrics(crow::Response& res,
504b14f357fSEd Tanous                            std::span<nlohmann::json::object_t> metrics,
505479e899dSKrzysztof Grobelny                            std::vector<AddReportArgs::MetricArgs>& result)
506479e899dSKrzysztof Grobelny {
507479e899dSKrzysztof Grobelny     result.reserve(metrics.size());
508479e899dSKrzysztof Grobelny 
509b14f357fSEd Tanous     for (nlohmann::json::object_t& m : metrics)
510479e899dSKrzysztof Grobelny     {
511479e899dSKrzysztof Grobelny         AddReportArgs::MetricArgs metricArgs;
512479e899dSKrzysztof Grobelny 
513479e899dSKrzysztof Grobelny         if (!getUserMetric(res, m, metricArgs))
514479e899dSKrzysztof Grobelny         {
515479e899dSKrzysztof Grobelny             return false;
516479e899dSKrzysztof Grobelny         }
517479e899dSKrzysztof Grobelny 
518479e899dSKrzysztof Grobelny         result.emplace_back(std::move(metricArgs));
519479e899dSKrzysztof Grobelny     }
520479e899dSKrzysztof Grobelny 
521479e899dSKrzysztof Grobelny     return true;
522479e899dSKrzysztof Grobelny }
523479e899dSKrzysztof Grobelny 
5244dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req,
5254dbb8aeaSWludzik, Jozef                               AddReportArgs& args)
5264dbb8aeaSWludzik, Jozef {
527479e899dSKrzysztof Grobelny     std::optional<std::string> id;
528479e899dSKrzysztof Grobelny     std::optional<std::string> name;
529479e899dSKrzysztof Grobelny     std::optional<std::string> reportingTypeStr;
530479e899dSKrzysztof Grobelny     std::optional<std::string> reportUpdatesStr;
531479e899dSKrzysztof Grobelny     std::optional<uint64_t> appendLimit;
532479e899dSKrzysztof Grobelny     std::optional<bool> metricReportDefinitionEnabled;
533b14f357fSEd Tanous     std::optional<std::vector<nlohmann::json::object_t>> metrics;
534479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> reportActionsStr;
535b14f357fSEd Tanous     std::optional<std::string> scheduleDurationStr;
536479e899dSKrzysztof Grobelny 
537afc474aeSMyung Bae     if (!json_util::readJsonPatch( //
538afc474aeSMyung Bae             req, res, //
539afc474aeSMyung Bae             "AppendLimit", appendLimit, //
540afc474aeSMyung Bae             "Id", id, //
541afc474aeSMyung Bae             "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, //
542afc474aeSMyung Bae             "MetricReportDefinitionType", reportingTypeStr, //
543afc474aeSMyung Bae             "Metrics", metrics, //
544afc474aeSMyung Bae             "Name", name, //
545afc474aeSMyung Bae             "ReportActions", reportActionsStr, //
546afc474aeSMyung Bae             "ReportUpdates", reportUpdatesStr, //
547afc474aeSMyung Bae             "Schedule/RecurrenceInterval", scheduleDurationStr //
548afc474aeSMyung Bae             ))
5494dbb8aeaSWludzik, Jozef     {
5504dbb8aeaSWludzik, Jozef         return false;
5514dbb8aeaSWludzik, Jozef     }
5524dbb8aeaSWludzik, Jozef 
553479e899dSKrzysztof Grobelny     if (id)
554479e899dSKrzysztof Grobelny     {
555479e899dSKrzysztof Grobelny         constexpr const char* allowedCharactersInId =
5564dbb8aeaSWludzik, Jozef             "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
557479e899dSKrzysztof Grobelny         if (id->empty() ||
558479e899dSKrzysztof Grobelny             id->find_first_not_of(allowedCharactersInId) != std::string::npos)
5594dbb8aeaSWludzik, Jozef         {
560479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "Id", *id);
5614dbb8aeaSWludzik, Jozef             return false;
5624dbb8aeaSWludzik, Jozef         }
563479e899dSKrzysztof Grobelny         args.id = *id;
564479e899dSKrzysztof Grobelny     }
5654dbb8aeaSWludzik, Jozef 
566479e899dSKrzysztof Grobelny     if (name)
5674dbb8aeaSWludzik, Jozef     {
568479e899dSKrzysztof Grobelny         args.name = *name;
569479e899dSKrzysztof Grobelny     }
570479e899dSKrzysztof Grobelny 
571479e899dSKrzysztof Grobelny     if (reportingTypeStr)
572479e899dSKrzysztof Grobelny     {
573479e899dSKrzysztof Grobelny         std::string dbusReportingType = toDbusReportingType(*reportingTypeStr);
574479e899dSKrzysztof Grobelny         if (dbusReportingType.empty())
575479e899dSKrzysztof Grobelny         {
576479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportingTypeStr,
5774dbb8aeaSWludzik, Jozef                                              "MetricReportDefinitionType");
5784dbb8aeaSWludzik, Jozef             return false;
5794dbb8aeaSWludzik, Jozef         }
580479e899dSKrzysztof Grobelny         args.reportingType = dbusReportingType;
581479e899dSKrzysztof Grobelny     }
5824dbb8aeaSWludzik, Jozef 
583479e899dSKrzysztof Grobelny     if (reportUpdatesStr)
584479e899dSKrzysztof Grobelny     {
585479e899dSKrzysztof Grobelny         std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr);
586479e899dSKrzysztof Grobelny         if (dbusReportUpdates.empty())
587479e899dSKrzysztof Grobelny         {
588479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportUpdatesStr,
589479e899dSKrzysztof Grobelny                                              "ReportUpdates");
590479e899dSKrzysztof Grobelny             return false;
591479e899dSKrzysztof Grobelny         }
592479e899dSKrzysztof Grobelny         args.reportUpdates = dbusReportUpdates;
593479e899dSKrzysztof Grobelny     }
594479e899dSKrzysztof Grobelny 
595479e899dSKrzysztof Grobelny     if (appendLimit)
596479e899dSKrzysztof Grobelny     {
597479e899dSKrzysztof Grobelny         args.appendLimit = *appendLimit;
598479e899dSKrzysztof Grobelny     }
599479e899dSKrzysztof Grobelny 
600479e899dSKrzysztof Grobelny     if (metricReportDefinitionEnabled)
601479e899dSKrzysztof Grobelny     {
602479e899dSKrzysztof Grobelny         args.metricReportDefinitionEnabled = *metricReportDefinitionEnabled;
603479e899dSKrzysztof Grobelny     }
604479e899dSKrzysztof Grobelny 
605479e899dSKrzysztof Grobelny     if (reportActionsStr)
606479e899dSKrzysztof Grobelny     {
6079e6c388aSLukasz Kazmierczak         if (!toDbusReportActions(res, *reportActionsStr, args.reportActions))
6084dbb8aeaSWludzik, Jozef         {
6094dbb8aeaSWludzik, Jozef             return false;
6104dbb8aeaSWludzik, Jozef         }
611479e899dSKrzysztof Grobelny     }
6124dbb8aeaSWludzik, Jozef 
613479e899dSKrzysztof Grobelny     if (reportingTypeStr == "Periodic")
6144dbb8aeaSWludzik, Jozef     {
615b14f357fSEd Tanous         if (!scheduleDurationStr)
6164dbb8aeaSWludzik, Jozef         {
6174dbb8aeaSWludzik, Jozef             messages::createFailedMissingReqProperties(res, "Schedule");
6184dbb8aeaSWludzik, Jozef             return false;
6194dbb8aeaSWludzik, Jozef         }
6204dbb8aeaSWludzik, Jozef 
6214dbb8aeaSWludzik, Jozef         std::optional<std::chrono::milliseconds> durationNum =
622b14f357fSEd Tanous             time_utils::fromDurationString(*scheduleDurationStr);
623479e899dSKrzysztof Grobelny         if (!durationNum || durationNum->count() < 0)
6244dbb8aeaSWludzik, Jozef         {
6254dbb8aeaSWludzik, Jozef             messages::propertyValueIncorrect(res, "RecurrenceInterval",
626b14f357fSEd Tanous                                              *scheduleDurationStr);
6274dbb8aeaSWludzik, Jozef             return false;
6284dbb8aeaSWludzik, Jozef         }
6294dbb8aeaSWludzik, Jozef         args.interval = static_cast<uint64_t>(durationNum->count());
6304dbb8aeaSWludzik, Jozef     }
6314dbb8aeaSWludzik, Jozef 
632479e899dSKrzysztof Grobelny     if (metrics)
6334dbb8aeaSWludzik, Jozef     {
634479e899dSKrzysztof Grobelny         if (!getUserMetrics(res, *metrics, args.metrics))
6354dbb8aeaSWludzik, Jozef         {
6364dbb8aeaSWludzik, Jozef             return false;
6374dbb8aeaSWludzik, Jozef         }
6384dbb8aeaSWludzik, Jozef     }
6394dbb8aeaSWludzik, Jozef 
6404dbb8aeaSWludzik, Jozef     return true;
6414dbb8aeaSWludzik, Jozef }
6424dbb8aeaSWludzik, Jozef 
643ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics(
6448d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
645479e899dSKrzysztof Grobelny     std::span<const AddReportArgs::MetricArgs> metrics,
6464dbb8aeaSWludzik, Jozef     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
6474dbb8aeaSWludzik, Jozef {
648ca1600c1SSzymon Dompke     for (const auto& metric : metrics)
6494dbb8aeaSWludzik, Jozef     {
650479e899dSKrzysztof Grobelny         std::optional<IncorrectMetricUri> error =
651479e899dSKrzysztof Grobelny             getChassisSensorNode(metric.uris, matched);
652ca1600c1SSzymon Dompke         if (error)
6534dbb8aeaSWludzik, Jozef         {
654bd79bce8SPatrick Williams             messages::propertyValueIncorrect(
655bd79bce8SPatrick Williams                 asyncResp->res, error->uri,
656bd79bce8SPatrick Williams                 "MetricProperties/" + std::to_string(error->index));
6574dbb8aeaSWludzik, Jozef             return false;
6584dbb8aeaSWludzik, Jozef         }
6594dbb8aeaSWludzik, Jozef     }
6604dbb8aeaSWludzik, Jozef     return true;
6614dbb8aeaSWludzik, Jozef }
6624dbb8aeaSWludzik, Jozef 
663ba498310SKrzysztof Grobelny inline std::string toRedfishProperty(std::string_view dbusMessage)
664ba498310SKrzysztof Grobelny {
665ba498310SKrzysztof Grobelny     if (dbusMessage == "Id")
666ba498310SKrzysztof Grobelny     {
667ba498310SKrzysztof Grobelny         return "Id";
668ba498310SKrzysztof Grobelny     }
669ba498310SKrzysztof Grobelny     if (dbusMessage == "Name")
670ba498310SKrzysztof Grobelny     {
671ba498310SKrzysztof Grobelny         return "Name";
672ba498310SKrzysztof Grobelny     }
673ba498310SKrzysztof Grobelny     if (dbusMessage == "ReportingType")
674ba498310SKrzysztof Grobelny     {
675ba498310SKrzysztof Grobelny         return "MetricReportDefinitionType";
676ba498310SKrzysztof Grobelny     }
677ba498310SKrzysztof Grobelny     if (dbusMessage == "AppendLimit")
678ba498310SKrzysztof Grobelny     {
679ba498310SKrzysztof Grobelny         return "AppendLimit";
680ba498310SKrzysztof Grobelny     }
681ba498310SKrzysztof Grobelny     if (dbusMessage == "ReportActions")
682ba498310SKrzysztof Grobelny     {
683ba498310SKrzysztof Grobelny         return "ReportActions";
684ba498310SKrzysztof Grobelny     }
685ba498310SKrzysztof Grobelny     if (dbusMessage == "Interval")
686ba498310SKrzysztof Grobelny     {
687ba498310SKrzysztof Grobelny         return "RecurrenceInterval";
688ba498310SKrzysztof Grobelny     }
689ba498310SKrzysztof Grobelny     if (dbusMessage == "ReportUpdates")
690ba498310SKrzysztof Grobelny     {
691ba498310SKrzysztof Grobelny         return "ReportUpdates";
692ba498310SKrzysztof Grobelny     }
693ba498310SKrzysztof Grobelny     if (dbusMessage == "ReadingParameters")
694ba498310SKrzysztof Grobelny     {
695ba498310SKrzysztof Grobelny         return "Metrics";
696ba498310SKrzysztof Grobelny     }
697ba498310SKrzysztof Grobelny     return "";
698ba498310SKrzysztof Grobelny }
699ba498310SKrzysztof Grobelny 
700ba498310SKrzysztof Grobelny inline bool handleParamError(crow::Response& res, const char* errorMessage,
701ba498310SKrzysztof Grobelny                              std::string_view key)
702ba498310SKrzysztof Grobelny {
703ba498310SKrzysztof Grobelny     if (errorMessage == nullptr)
704ba498310SKrzysztof Grobelny     {
705ba498310SKrzysztof Grobelny         BMCWEB_LOG_ERROR("errorMessage was null");
706ba498310SKrzysztof Grobelny         return true;
707ba498310SKrzysztof Grobelny     }
708ba498310SKrzysztof Grobelny     std::string_view errorMessageSv(errorMessage);
709ba498310SKrzysztof Grobelny     if (errorMessageSv.starts_with(key))
710ba498310SKrzysztof Grobelny     {
711ba498310SKrzysztof Grobelny         std::string redfishProperty = toRedfishProperty(key);
712ba498310SKrzysztof Grobelny         if (redfishProperty.empty())
713ba498310SKrzysztof Grobelny         {
714ba498310SKrzysztof Grobelny             // Getting here means most possibly that toRedfishProperty has
715ba498310SKrzysztof Grobelny             // incomplete implementation. Return internal error for now.
716ba498310SKrzysztof Grobelny             BMCWEB_LOG_ERROR("{} has no corresponding Redfish property", key);
717ba498310SKrzysztof Grobelny             messages::internalError(res);
718ba498310SKrzysztof Grobelny             return false;
719ba498310SKrzysztof Grobelny         }
720ba498310SKrzysztof Grobelny         messages::propertyValueError(res, redfishProperty);
721ba498310SKrzysztof Grobelny         return false;
722ba498310SKrzysztof Grobelny     }
723ba498310SKrzysztof Grobelny 
724ba498310SKrzysztof Grobelny     return true;
725ba498310SKrzysztof Grobelny }
726ba498310SKrzysztof Grobelny 
727ba498310SKrzysztof Grobelny inline void afterAddReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
728ba498310SKrzysztof Grobelny                            const AddReportArgs& args,
729ba498310SKrzysztof Grobelny                            const boost::system::error_code& ec,
730ba498310SKrzysztof Grobelny                            const sdbusplus::message_t& msg)
731ba498310SKrzysztof Grobelny {
732ba498310SKrzysztof Grobelny     if (!ec)
733ba498310SKrzysztof Grobelny     {
734ba498310SKrzysztof Grobelny         messages::created(asyncResp->res);
735ba498310SKrzysztof Grobelny         return;
736ba498310SKrzysztof Grobelny     }
737ba498310SKrzysztof Grobelny 
738ba498310SKrzysztof Grobelny     if (ec == boost::system::errc::invalid_argument)
739ba498310SKrzysztof Grobelny     {
740ba498310SKrzysztof Grobelny         const sd_bus_error* errorMessage = msg.get_error();
741ba498310SKrzysztof Grobelny         if (errorMessage != nullptr)
742ba498310SKrzysztof Grobelny         {
743ba498310SKrzysztof Grobelny             for (const auto& arg :
744ba498310SKrzysztof Grobelny                  {"Id", "Name", "ReportingType", "AppendLimit", "ReportActions",
745ba498310SKrzysztof Grobelny                   "Interval", "ReportUpdates", "ReadingParameters"})
746ba498310SKrzysztof Grobelny             {
747ba498310SKrzysztof Grobelny                 if (!handleParamError(asyncResp->res, errorMessage->message,
748ba498310SKrzysztof Grobelny                                       arg))
749ba498310SKrzysztof Grobelny                 {
750ba498310SKrzysztof Grobelny                     return;
751ba498310SKrzysztof Grobelny                 }
752ba498310SKrzysztof Grobelny             }
753ba498310SKrzysztof Grobelny         }
754ba498310SKrzysztof Grobelny     }
755ba498310SKrzysztof Grobelny     if (!verifyCommonErrors(asyncResp->res, args.id, ec))
756ba498310SKrzysztof Grobelny     {
757ba498310SKrzysztof Grobelny         return;
758ba498310SKrzysztof Grobelny     }
759ba498310SKrzysztof Grobelny     messages::internalError(asyncResp->res);
760ba498310SKrzysztof Grobelny }
761ba498310SKrzysztof Grobelny 
7624dbb8aeaSWludzik, Jozef class AddReport
7634dbb8aeaSWludzik, Jozef {
7644dbb8aeaSWludzik, Jozef   public:
765891eaa7cSEd Tanous     AddReport(AddReportArgs&& argsIn,
7668a592810SEd Tanous               const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
767bd79bce8SPatrick Williams         asyncResp(asyncRespIn), args(std::move(argsIn))
7684dbb8aeaSWludzik, Jozef     {}
769479e899dSKrzysztof Grobelny 
7704dbb8aeaSWludzik, Jozef     ~AddReport()
7714dbb8aeaSWludzik, Jozef     {
772479e899dSKrzysztof Grobelny         boost::asio::post(crow::connections::systemBus->get_io_context(),
773479e899dSKrzysztof Grobelny                           std::bind_front(&performAddReport, asyncResp, args,
774479e899dSKrzysztof Grobelny                                           std::move(uriToDbus)));
775479e899dSKrzysztof Grobelny     }
776479e899dSKrzysztof Grobelny 
777479e899dSKrzysztof Grobelny     static void performAddReport(
778479e899dSKrzysztof Grobelny         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
779479e899dSKrzysztof Grobelny         const AddReportArgs& args,
780479e899dSKrzysztof Grobelny         const boost::container::flat_map<std::string, std::string>& uriToDbus)
781479e899dSKrzysztof Grobelny     {
7824dbb8aeaSWludzik, Jozef         if (asyncResp->res.result() != boost::beast::http::status::ok)
7834dbb8aeaSWludzik, Jozef         {
7844dbb8aeaSWludzik, Jozef             return;
7854dbb8aeaSWludzik, Jozef         }
7864dbb8aeaSWludzik, Jozef 
7874dbb8aeaSWludzik, Jozef         telemetry::ReadingParameters readingParams;
7884dbb8aeaSWludzik, Jozef         readingParams.reserve(args.metrics.size());
7894dbb8aeaSWludzik, Jozef 
790479e899dSKrzysztof Grobelny         for (const auto& metric : args.metrics)
7914dbb8aeaSWludzik, Jozef         {
792479e899dSKrzysztof Grobelny             std::vector<
793479e899dSKrzysztof Grobelny                 std::tuple<sdbusplus::message::object_path, std::string>>
794479e899dSKrzysztof Grobelny                 sensorParams;
795479e899dSKrzysztof Grobelny             sensorParams.reserve(metric.uris.size());
796479e899dSKrzysztof Grobelny 
797479e899dSKrzysztof Grobelny             for (size_t i = 0; i < metric.uris.size(); i++)
7984dbb8aeaSWludzik, Jozef             {
799479e899dSKrzysztof Grobelny                 const std::string& uri = metric.uris[i];
8004dbb8aeaSWludzik, Jozef                 auto el = uriToDbus.find(uri);
8014dbb8aeaSWludzik, Jozef                 if (el == uriToDbus.end())
8024dbb8aeaSWludzik, Jozef                 {
80362598e31SEd Tanous                     BMCWEB_LOG_ERROR(
80462598e31SEd Tanous                         "Failed to find DBus sensor corresponding to URI {}",
80562598e31SEd Tanous                         uri);
806bd79bce8SPatrick Williams                     messages::propertyValueNotInList(
807bd79bce8SPatrick Williams                         asyncResp->res, uri,
808bd79bce8SPatrick Williams                         "MetricProperties/" + std::to_string(i));
8094dbb8aeaSWludzik, Jozef                     return;
8104dbb8aeaSWludzik, Jozef                 }
8114dbb8aeaSWludzik, Jozef 
8124dbb8aeaSWludzik, Jozef                 const std::string& dbusPath = el->second;
813479e899dSKrzysztof Grobelny                 sensorParams.emplace_back(dbusPath, uri);
8144dbb8aeaSWludzik, Jozef             }
815479e899dSKrzysztof Grobelny 
816479e899dSKrzysztof Grobelny             readingParams.emplace_back(
817479e899dSKrzysztof Grobelny                 std::move(sensorParams), metric.collectionFunction,
818479e899dSKrzysztof Grobelny                 metric.collectionTimeScope, metric.collectionDuration);
8194dbb8aeaSWludzik, Jozef         }
8204dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
821ba498310SKrzysztof Grobelny             [asyncResp, args](const boost::system::error_code& ec,
822ba498310SKrzysztof Grobelny                               const sdbusplus::message_t& msg,
823ba498310SKrzysztof Grobelny                               const std::string& /*arg1*/) {
824ba498310SKrzysztof Grobelny                 afterAddReport(asyncResp, args, ec, msg);
8254dbb8aeaSWludzik, Jozef             },
8264dbb8aeaSWludzik, Jozef             telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
8274dbb8aeaSWludzik, Jozef             "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
828479e899dSKrzysztof Grobelny             "TelemetryService/" + args.id, args.name, args.reportingType,
829479e899dSKrzysztof Grobelny             args.reportUpdates, args.appendLimit, args.reportActions,
830479e899dSKrzysztof Grobelny             args.interval, readingParams, args.metricReportDefinitionEnabled);
8314dbb8aeaSWludzik, Jozef     }
8324dbb8aeaSWludzik, Jozef 
833ecd6a3a2SEd Tanous     AddReport(const AddReport&) = delete;
834ecd6a3a2SEd Tanous     AddReport(AddReport&&) = delete;
835ecd6a3a2SEd Tanous     AddReport& operator=(const AddReport&) = delete;
836ecd6a3a2SEd Tanous     AddReport& operator=(AddReport&&) = delete;
837ecd6a3a2SEd Tanous 
838fe04d49cSNan Zhou     void insert(const std::map<std::string, std::string>& el)
8394dbb8aeaSWludzik, Jozef     {
8404dbb8aeaSWludzik, Jozef         uriToDbus.insert(el.begin(), el.end());
8414dbb8aeaSWludzik, Jozef     }
8424dbb8aeaSWludzik, Jozef 
8434dbb8aeaSWludzik, Jozef   private:
844ba498310SKrzysztof Grobelny     const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
8454dbb8aeaSWludzik, Jozef     AddReportArgs args;
84647f2934cSEd Tanous     boost::container::flat_map<std::string, std::string> uriToDbus;
8474dbb8aeaSWludzik, Jozef };
8489e6c388aSLukasz Kazmierczak 
849ba498310SKrzysztof Grobelny inline std::optional<
850ba498310SKrzysztof Grobelny     std::vector<std::tuple<sdbusplus::message::object_path, std::string>>>
851ba498310SKrzysztof Grobelny     sensorPathToUri(
852ba498310SKrzysztof Grobelny         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
853ba498310SKrzysztof Grobelny         std::span<const std::string> uris,
854ba498310SKrzysztof Grobelny         const std::map<std::string, std::string>& metricPropertyToDbusPaths)
855ba498310SKrzysztof Grobelny {
856ba498310SKrzysztof Grobelny     std::vector<std::tuple<sdbusplus::message::object_path, std::string>>
857ba498310SKrzysztof Grobelny         result;
858ba498310SKrzysztof Grobelny 
859ba498310SKrzysztof Grobelny     for (const std::string& uri : uris)
860ba498310SKrzysztof Grobelny     {
861ba498310SKrzysztof Grobelny         auto it = metricPropertyToDbusPaths.find(uri);
862ba498310SKrzysztof Grobelny         if (it == metricPropertyToDbusPaths.end())
863ba498310SKrzysztof Grobelny         {
864ba498310SKrzysztof Grobelny             messages::propertyValueNotInList(asyncResp->res, uri,
865ba498310SKrzysztof Grobelny                                              "MetricProperties");
866ba498310SKrzysztof Grobelny             return {};
867ba498310SKrzysztof Grobelny         }
868ba498310SKrzysztof Grobelny         result.emplace_back(it->second, uri);
869ba498310SKrzysztof Grobelny     }
870ba498310SKrzysztof Grobelny 
871ba498310SKrzysztof Grobelny     return result;
872ba498310SKrzysztof Grobelny }
873ba498310SKrzysztof Grobelny 
874ba498310SKrzysztof Grobelny inline void afterSetReadingParams(
875ba498310SKrzysztof Grobelny     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
876ba498310SKrzysztof Grobelny     const std::string& reportId, const boost::system::error_code& ec,
877ba498310SKrzysztof Grobelny     const sdbusplus::message_t& msg)
878ba498310SKrzysztof Grobelny {
879ba498310SKrzysztof Grobelny     if (!ec)
880ba498310SKrzysztof Grobelny     {
881ba498310SKrzysztof Grobelny         messages::success(asyncResp->res);
882ba498310SKrzysztof Grobelny         return;
883ba498310SKrzysztof Grobelny     }
884ba498310SKrzysztof Grobelny     if (ec == boost::system::errc::invalid_argument)
885ba498310SKrzysztof Grobelny     {
886ba498310SKrzysztof Grobelny         const sd_bus_error* errorMessage = msg.get_error();
887ba498310SKrzysztof Grobelny         if (errorMessage != nullptr)
888ba498310SKrzysztof Grobelny         {
889ba498310SKrzysztof Grobelny             for (const auto& arg : {"Id", "ReadingParameters"})
890ba498310SKrzysztof Grobelny             {
891ba498310SKrzysztof Grobelny                 if (!handleParamError(asyncResp->res, errorMessage->message,
892ba498310SKrzysztof Grobelny                                       arg))
893ba498310SKrzysztof Grobelny                 {
894ba498310SKrzysztof Grobelny                     return;
895ba498310SKrzysztof Grobelny                 }
896ba498310SKrzysztof Grobelny             }
897ba498310SKrzysztof Grobelny         }
898ba498310SKrzysztof Grobelny     }
899ba498310SKrzysztof Grobelny     if (!verifyCommonErrors(asyncResp->res, reportId, ec))
900ba498310SKrzysztof Grobelny     {
901ba498310SKrzysztof Grobelny         return;
902ba498310SKrzysztof Grobelny     }
903ba498310SKrzysztof Grobelny     messages::internalError(asyncResp->res);
904ba498310SKrzysztof Grobelny }
905ba498310SKrzysztof Grobelny 
906ba498310SKrzysztof Grobelny inline void setReadingParams(
907ba498310SKrzysztof Grobelny     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
908ba498310SKrzysztof Grobelny     const std::string& reportId, ReadingParameters readingParams,
909ba498310SKrzysztof Grobelny     const std::vector<std::vector<std::string>>& readingParamsUris,
910ba498310SKrzysztof Grobelny     const std::map<std::string, std::string>& metricPropertyToDbusPaths)
911ba498310SKrzysztof Grobelny {
912ba498310SKrzysztof Grobelny     if (asyncResp->res.result() != boost::beast::http::status::ok)
913ba498310SKrzysztof Grobelny     {
914ba498310SKrzysztof Grobelny         return;
915ba498310SKrzysztof Grobelny     }
916ba498310SKrzysztof Grobelny 
917ba498310SKrzysztof Grobelny     for (size_t index = 0; index < readingParamsUris.size(); ++index)
918ba498310SKrzysztof Grobelny     {
919ba498310SKrzysztof Grobelny         std::span<const std::string> newUris = readingParamsUris[index];
920ba498310SKrzysztof Grobelny 
921ba498310SKrzysztof Grobelny         const std::optional<std::vector<
922ba498310SKrzysztof Grobelny             std::tuple<sdbusplus::message::object_path, std::string>>>
923ba498310SKrzysztof Grobelny             readingParam =
924ba498310SKrzysztof Grobelny                 sensorPathToUri(asyncResp, newUris, metricPropertyToDbusPaths);
925ba498310SKrzysztof Grobelny 
926ba498310SKrzysztof Grobelny         if (!readingParam)
927ba498310SKrzysztof Grobelny         {
928ba498310SKrzysztof Grobelny             return;
929ba498310SKrzysztof Grobelny         }
930ba498310SKrzysztof Grobelny 
931ba498310SKrzysztof Grobelny         for (const std::tuple<sdbusplus::message::object_path, std::string>&
932ba498310SKrzysztof Grobelny                  value : *readingParam)
933ba498310SKrzysztof Grobelny         {
934ba498310SKrzysztof Grobelny             std::get<0>(readingParams[index]).emplace_back(value);
935ba498310SKrzysztof Grobelny         }
936ba498310SKrzysztof Grobelny     }
937ba498310SKrzysztof Grobelny 
938ba498310SKrzysztof Grobelny     crow::connections::systemBus->async_method_call(
939ba498310SKrzysztof Grobelny         [asyncResp, reportId](const boost::system::error_code& ec,
940ba498310SKrzysztof Grobelny                               const sdbusplus::message_t& msg) {
941ba498310SKrzysztof Grobelny             afterSetReadingParams(asyncResp, reportId, ec, msg);
942ba498310SKrzysztof Grobelny         },
943ba498310SKrzysztof Grobelny         "xyz.openbmc_project.Telemetry", getDbusReportPath(reportId),
944ba498310SKrzysztof Grobelny         "org.freedesktop.DBus.Properties", "Set",
945ba498310SKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report", "ReadingParameters",
946ba498310SKrzysztof Grobelny         dbus::utility::DbusVariantType{readingParams});
947ba498310SKrzysztof Grobelny }
948ba498310SKrzysztof Grobelny 
9499e6c388aSLukasz Kazmierczak class UpdateMetrics
9509e6c388aSLukasz Kazmierczak {
9519e6c388aSLukasz Kazmierczak   public:
9529e6c388aSLukasz Kazmierczak     UpdateMetrics(std::string_view idIn,
9539e6c388aSLukasz Kazmierczak                   const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
954bd79bce8SPatrick Williams         id(idIn), asyncResp(asyncRespIn)
9559e6c388aSLukasz Kazmierczak     {}
9569e6c388aSLukasz Kazmierczak 
9579e6c388aSLukasz Kazmierczak     ~UpdateMetrics()
9589e6c388aSLukasz Kazmierczak     {
959ba498310SKrzysztof Grobelny         boost::asio::post(
960ba498310SKrzysztof Grobelny             crow::connections::systemBus->get_io_context(),
961ba498310SKrzysztof Grobelny             std::bind_front(&setReadingParams, asyncResp, id,
962ba498310SKrzysztof Grobelny                             std::move(readingParams), readingParamsUris,
963ba498310SKrzysztof Grobelny                             metricPropertyToDbusPaths));
9649e6c388aSLukasz Kazmierczak     }
9659e6c388aSLukasz Kazmierczak 
9669e6c388aSLukasz Kazmierczak     UpdateMetrics(const UpdateMetrics&) = delete;
9679e6c388aSLukasz Kazmierczak     UpdateMetrics(UpdateMetrics&&) = delete;
9689e6c388aSLukasz Kazmierczak     UpdateMetrics& operator=(const UpdateMetrics&) = delete;
9699e6c388aSLukasz Kazmierczak     UpdateMetrics& operator=(UpdateMetrics&&) = delete;
9709e6c388aSLukasz Kazmierczak 
9719e6c388aSLukasz Kazmierczak     std::string id;
9729e6c388aSLukasz Kazmierczak     std::map<std::string, std::string> metricPropertyToDbusPaths;
9739e6c388aSLukasz Kazmierczak 
9749e6c388aSLukasz Kazmierczak     void insert(const std::map<std::string, std::string>&
9759e6c388aSLukasz Kazmierczak                     additionalMetricPropertyToDbusPaths)
9769e6c388aSLukasz Kazmierczak     {
9779e6c388aSLukasz Kazmierczak         metricPropertyToDbusPaths.insert(
9789e6c388aSLukasz Kazmierczak             additionalMetricPropertyToDbusPaths.begin(),
9799e6c388aSLukasz Kazmierczak             additionalMetricPropertyToDbusPaths.end());
9809e6c388aSLukasz Kazmierczak     }
9819e6c388aSLukasz Kazmierczak 
982bd79bce8SPatrick Williams     void emplace(
983bd79bce8SPatrick Williams         std::span<
984bd79bce8SPatrick Williams             const std::tuple<sdbusplus::message::object_path, std::string>>
9859e6c388aSLukasz Kazmierczak             pathAndUri,
9869e6c388aSLukasz Kazmierczak         const AddReportArgs::MetricArgs& metricArgs)
9879e6c388aSLukasz Kazmierczak     {
9889e6c388aSLukasz Kazmierczak         readingParamsUris.emplace_back(metricArgs.uris);
9899e6c388aSLukasz Kazmierczak         readingParams.emplace_back(
9909e6c388aSLukasz Kazmierczak             std::vector(pathAndUri.begin(), pathAndUri.end()),
9919e6c388aSLukasz Kazmierczak             metricArgs.collectionFunction, metricArgs.collectionTimeScope,
9929e6c388aSLukasz Kazmierczak             metricArgs.collectionDuration);
9939e6c388aSLukasz Kazmierczak     }
9949e6c388aSLukasz Kazmierczak 
9959e6c388aSLukasz Kazmierczak   private:
9969e6c388aSLukasz Kazmierczak     const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
9979e6c388aSLukasz Kazmierczak     std::vector<std::vector<std::string>> readingParamsUris;
99847f2934cSEd Tanous     ReadingParameters readingParams;
9999e6c388aSLukasz Kazmierczak };
10009e6c388aSLukasz Kazmierczak 
10019e6c388aSLukasz Kazmierczak inline void
10029e6c388aSLukasz Kazmierczak     setReportEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10039e6c388aSLukasz Kazmierczak                      std::string_view id, bool enabled)
10049e6c388aSLukasz Kazmierczak {
10059e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
10069e6c388aSLukasz Kazmierczak         [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
10079e6c388aSLukasz Kazmierczak             if (!verifyCommonErrors(asyncResp->res, id, ec))
10089e6c388aSLukasz Kazmierczak             {
10099e6c388aSLukasz Kazmierczak                 return;
10109e6c388aSLukasz Kazmierczak             }
10119e6c388aSLukasz Kazmierczak         },
10129e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
10139e6c388aSLukasz Kazmierczak         "org.freedesktop.DBus.Properties", "Set",
10149e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "Enabled",
10159e6c388aSLukasz Kazmierczak         dbus::utility::DbusVariantType{enabled});
10169e6c388aSLukasz Kazmierczak }
10179e6c388aSLukasz Kazmierczak 
1018ba498310SKrzysztof Grobelny inline void afterSetReportingProperties(
1019ba498310SKrzysztof Grobelny     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
1020ba498310SKrzysztof Grobelny     const boost::system::error_code& ec, const sdbusplus::message_t& msg)
1021ba498310SKrzysztof Grobelny {
1022ba498310SKrzysztof Grobelny     if (!ec)
1023ba498310SKrzysztof Grobelny     {
1024ba498310SKrzysztof Grobelny         asyncResp->res.result(boost::beast::http::status::no_content);
1025ba498310SKrzysztof Grobelny         return;
1026ba498310SKrzysztof Grobelny     }
1027ba498310SKrzysztof Grobelny 
1028ba498310SKrzysztof Grobelny     if (ec == boost::system::errc::invalid_argument)
1029ba498310SKrzysztof Grobelny     {
1030ba498310SKrzysztof Grobelny         const sd_bus_error* errorMessage = msg.get_error();
1031ba498310SKrzysztof Grobelny         if (errorMessage != nullptr)
1032ba498310SKrzysztof Grobelny         {
1033ba498310SKrzysztof Grobelny             for (const auto& arg : {"Id", "ReportingType", "Interval"})
1034ba498310SKrzysztof Grobelny             {
1035ba498310SKrzysztof Grobelny                 if (!handleParamError(asyncResp->res, errorMessage->message,
1036ba498310SKrzysztof Grobelny                                       arg))
1037ba498310SKrzysztof Grobelny                 {
1038ba498310SKrzysztof Grobelny                     return;
1039ba498310SKrzysztof Grobelny                 }
1040ba498310SKrzysztof Grobelny             }
1041ba498310SKrzysztof Grobelny         }
1042ba498310SKrzysztof Grobelny     }
1043ba498310SKrzysztof Grobelny     if (!verifyCommonErrors(asyncResp->res, id, ec))
1044ba498310SKrzysztof Grobelny     {
1045ba498310SKrzysztof Grobelny         return;
1046ba498310SKrzysztof Grobelny     }
1047ba498310SKrzysztof Grobelny     messages::internalError(asyncResp->res);
1048ba498310SKrzysztof Grobelny }
1049ba498310SKrzysztof Grobelny 
10509e6c388aSLukasz Kazmierczak inline void setReportTypeAndInterval(
10519e6c388aSLukasz Kazmierczak     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id,
1052b4361d63SEd Tanous     const std::optional<std::string>& reportingType,
1053b4361d63SEd Tanous     const std::optional<std::string>& recurrenceIntervalStr)
10549e6c388aSLukasz Kazmierczak {
1055b4361d63SEd Tanous     std::string dbusReportingType;
1056b4361d63SEd Tanous     if (reportingType)
1057b4361d63SEd Tanous     {
1058b4361d63SEd Tanous         dbusReportingType = toDbusReportingType(*reportingType);
1059b4361d63SEd Tanous         if (dbusReportingType.empty())
1060b4361d63SEd Tanous         {
1061b4361d63SEd Tanous             messages::propertyValueNotInList(asyncResp->res, *reportingType,
1062b4361d63SEd Tanous                                              "MetricReportDefinitionType");
1063b4361d63SEd Tanous             return;
1064b4361d63SEd Tanous         }
1065b4361d63SEd Tanous     }
1066b4361d63SEd Tanous 
1067b4361d63SEd Tanous     uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max();
1068b4361d63SEd Tanous     if (recurrenceIntervalStr)
1069b4361d63SEd Tanous     {
1070b4361d63SEd Tanous         std::optional<std::chrono::milliseconds> durationNum =
1071b4361d63SEd Tanous             time_utils::fromDurationString(*recurrenceIntervalStr);
1072b4361d63SEd Tanous         if (!durationNum || durationNum->count() < 0)
1073b4361d63SEd Tanous         {
1074b4361d63SEd Tanous             messages::propertyValueIncorrect(
1075b4361d63SEd Tanous                 asyncResp->res, "RecurrenceInterval", *recurrenceIntervalStr);
1076b4361d63SEd Tanous             return;
1077b4361d63SEd Tanous         }
1078b4361d63SEd Tanous 
1079b4361d63SEd Tanous         recurrenceInterval = static_cast<uint64_t>(durationNum->count());
1080b4361d63SEd Tanous     }
1081b4361d63SEd Tanous 
10829e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
1083ba498310SKrzysztof Grobelny         [asyncResp, id = std::string(id)](const boost::system::error_code& ec,
1084ba498310SKrzysztof Grobelny                                           const sdbusplus::message_t& msg) {
1085ba498310SKrzysztof Grobelny             afterSetReportingProperties(asyncResp, id, ec, msg);
10869e6c388aSLukasz Kazmierczak         },
10879e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
10889e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "SetReportingProperties",
1089b4361d63SEd Tanous         dbusReportingType, recurrenceInterval);
10909e6c388aSLukasz Kazmierczak }
10919e6c388aSLukasz Kazmierczak 
1092ba498310SKrzysztof Grobelny inline void afterSetReportUpdates(
1093ba498310SKrzysztof Grobelny     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
1094ba498310SKrzysztof Grobelny     const boost::system::error_code& ec, const sdbusplus::message_t& msg)
1095ba498310SKrzysztof Grobelny {
1096ba498310SKrzysztof Grobelny     if (!ec)
1097ba498310SKrzysztof Grobelny     {
1098ba498310SKrzysztof Grobelny         asyncResp->res.result(boost::beast::http::status::no_content);
1099ba498310SKrzysztof Grobelny         return;
1100ba498310SKrzysztof Grobelny     }
1101ba498310SKrzysztof Grobelny     if (ec == boost::system::errc::invalid_argument)
1102ba498310SKrzysztof Grobelny     {
1103ba498310SKrzysztof Grobelny         const sd_bus_error* errorMessage = msg.get_error();
1104ba498310SKrzysztof Grobelny         if (errorMessage != nullptr)
1105ba498310SKrzysztof Grobelny         {
1106ba498310SKrzysztof Grobelny             for (const auto& arg : {"Id", "ReportUpdates"})
1107ba498310SKrzysztof Grobelny             {
1108ba498310SKrzysztof Grobelny                 if (!handleParamError(asyncResp->res, errorMessage->message,
1109ba498310SKrzysztof Grobelny                                       arg))
1110ba498310SKrzysztof Grobelny                 {
1111ba498310SKrzysztof Grobelny                     return;
1112ba498310SKrzysztof Grobelny                 }
1113ba498310SKrzysztof Grobelny             }
1114ba498310SKrzysztof Grobelny         }
1115ba498310SKrzysztof Grobelny     }
1116ba498310SKrzysztof Grobelny     if (!verifyCommonErrors(asyncResp->res, id, ec))
1117ba498310SKrzysztof Grobelny     {
1118ba498310SKrzysztof Grobelny         return;
1119ba498310SKrzysztof Grobelny     }
1120ba498310SKrzysztof Grobelny }
1121ba498310SKrzysztof Grobelny 
11229e6c388aSLukasz Kazmierczak inline void
11239e6c388aSLukasz Kazmierczak     setReportUpdates(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11249e6c388aSLukasz Kazmierczak                      std::string_view id, const std::string& reportUpdates)
11259e6c388aSLukasz Kazmierczak {
1126b4361d63SEd Tanous     std::string dbusReportUpdates = toDbusReportUpdates(reportUpdates);
1127b4361d63SEd Tanous     if (dbusReportUpdates.empty())
1128b4361d63SEd Tanous     {
1129b4361d63SEd Tanous         messages::propertyValueNotInList(asyncResp->res, reportUpdates,
1130b4361d63SEd Tanous                                          "ReportUpdates");
1131b4361d63SEd Tanous         return;
1132b4361d63SEd Tanous     }
11339e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
1134ba498310SKrzysztof Grobelny         [asyncResp, id = std::string(id)](const boost::system::error_code& ec,
1135ba498310SKrzysztof Grobelny                                           const sdbusplus::message_t& msg) {
1136ba498310SKrzysztof Grobelny             afterSetReportUpdates(asyncResp, id, ec, msg);
11379e6c388aSLukasz Kazmierczak         },
11389e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
11399e6c388aSLukasz Kazmierczak         "org.freedesktop.DBus.Properties", "Set",
11409e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "ReportUpdates",
1141ba498310SKrzysztof Grobelny         dbus::utility::DbusVariantType{dbusReportUpdates});
1142ba498310SKrzysztof Grobelny }
1143ba498310SKrzysztof Grobelny 
1144ba498310SKrzysztof Grobelny inline void afterSetReportActions(
1145ba498310SKrzysztof Grobelny     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
1146ba498310SKrzysztof Grobelny     const boost::system::error_code& ec, const sdbusplus::message_t& msg)
1147ba498310SKrzysztof Grobelny {
1148ba498310SKrzysztof Grobelny     if (ec == boost::system::errc::invalid_argument)
1149ba498310SKrzysztof Grobelny     {
1150ba498310SKrzysztof Grobelny         const sd_bus_error* errorMessage = msg.get_error();
1151ba498310SKrzysztof Grobelny         if (errorMessage != nullptr)
1152ba498310SKrzysztof Grobelny         {
1153ba498310SKrzysztof Grobelny             for (const auto& arg : {"Id", "ReportActions"})
1154ba498310SKrzysztof Grobelny             {
1155ba498310SKrzysztof Grobelny                 if (!handleParamError(asyncResp->res, errorMessage->message,
1156ba498310SKrzysztof Grobelny                                       arg))
1157ba498310SKrzysztof Grobelny                 {
1158ba498310SKrzysztof Grobelny                     return;
1159ba498310SKrzysztof Grobelny                 }
1160ba498310SKrzysztof Grobelny             }
1161ba498310SKrzysztof Grobelny         }
1162ba498310SKrzysztof Grobelny     }
1163ba498310SKrzysztof Grobelny 
1164ba498310SKrzysztof Grobelny     if (!verifyCommonErrors(asyncResp->res, id, ec))
1165ba498310SKrzysztof Grobelny     {
1166ba498310SKrzysztof Grobelny         return;
1167ba498310SKrzysztof Grobelny     }
1168ba498310SKrzysztof Grobelny 
1169ba498310SKrzysztof Grobelny     messages::internalError(asyncResp->res);
11709e6c388aSLukasz Kazmierczak }
11719e6c388aSLukasz Kazmierczak 
1172bd79bce8SPatrick Williams inline void setReportActions(
1173bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id,
1174b4361d63SEd Tanous     const std::vector<std::string>& reportActions)
11759e6c388aSLukasz Kazmierczak {
1176b4361d63SEd Tanous     std::vector<std::string> dbusReportActions;
1177b4361d63SEd Tanous     if (!toDbusReportActions(asyncResp->res, reportActions, dbusReportActions))
1178b4361d63SEd Tanous     {
1179b4361d63SEd Tanous         return;
1180b4361d63SEd Tanous     }
1181b4361d63SEd Tanous 
11829e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
1183ba498310SKrzysztof Grobelny         [asyncResp, id = std::string(id)](const boost::system::error_code& ec,
1184ba498310SKrzysztof Grobelny                                           const sdbusplus::message_t& msg) {
1185ba498310SKrzysztof Grobelny             afterSetReportActions(asyncResp, id, ec, msg);
11869e6c388aSLukasz Kazmierczak         },
11879e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
11889e6c388aSLukasz Kazmierczak         "org.freedesktop.DBus.Properties", "Set",
11899e6c388aSLukasz Kazmierczak         "xyz.openbmc_project.Telemetry.Report", "ReportActions",
11909e6c388aSLukasz Kazmierczak         dbus::utility::DbusVariantType{dbusReportActions});
11919e6c388aSLukasz Kazmierczak }
11929e6c388aSLukasz Kazmierczak 
1193bd79bce8SPatrick Williams inline void setReportMetrics(
1194bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id,
1195a64919e8SBoleslaw Ogonczyk Makowski     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>&&
1196a64919e8SBoleslaw Ogonczyk Makowski         metrics)
11979e6c388aSLukasz Kazmierczak {
1198deae6a78SEd Tanous     dbus::utility::getAllProperties(
1199deae6a78SEd Tanous         telemetry::service, telemetry::getDbusReportPath(id),
1200deae6a78SEd Tanous         telemetry::reportInterface,
1201ba498310SKrzysztof Grobelny         [asyncResp, id = std::string(id), redfishMetrics = std::move(metrics)](
12029e6c388aSLukasz Kazmierczak             boost::system::error_code ec,
12039e6c388aSLukasz Kazmierczak             const dbus::utility::DBusPropertiesMap& properties) mutable {
1204ba498310SKrzysztof Grobelny             if (!verifyCommonErrors(asyncResp->res, id, ec))
12059e6c388aSLukasz Kazmierczak             {
12069e6c388aSLukasz Kazmierczak                 return;
12079e6c388aSLukasz Kazmierczak             }
12089e6c388aSLukasz Kazmierczak 
12099e6c388aSLukasz Kazmierczak             ReadingParameters readingParams;
12109e6c388aSLukasz Kazmierczak 
12119e6c388aSLukasz Kazmierczak             const bool success = sdbusplus::unpackPropertiesNoThrow(
1212bd79bce8SPatrick Williams                 dbus_utils::UnpackErrorPrinter(), properties,
1213bd79bce8SPatrick Williams                 "ReadingParameters", readingParams);
12149e6c388aSLukasz Kazmierczak 
12159e6c388aSLukasz Kazmierczak             if (!success)
12169e6c388aSLukasz Kazmierczak             {
12179e6c388aSLukasz Kazmierczak                 messages::internalError(asyncResp->res);
12189e6c388aSLukasz Kazmierczak                 return;
12199e6c388aSLukasz Kazmierczak             }
12209e6c388aSLukasz Kazmierczak 
1221bd79bce8SPatrick Williams             auto updateMetricsReq =
1222bd79bce8SPatrick Williams                 std::make_shared<UpdateMetrics>(id, asyncResp);
12239e6c388aSLukasz Kazmierczak 
12249e6c388aSLukasz Kazmierczak             boost::container::flat_set<std::pair<std::string, std::string>>
12259e6c388aSLukasz Kazmierczak                 chassisSensors;
12269e6c388aSLukasz Kazmierczak 
12279e6c388aSLukasz Kazmierczak             size_t index = 0;
1228a64919e8SBoleslaw Ogonczyk Makowski             for (std::variant<nlohmann::json::object_t, std::nullptr_t>&
1229a64919e8SBoleslaw Ogonczyk Makowski                      metricVariant : redfishMetrics)
12309e6c388aSLukasz Kazmierczak             {
1231a64919e8SBoleslaw Ogonczyk Makowski                 nlohmann::json::object_t* metric =
1232a64919e8SBoleslaw Ogonczyk Makowski                     std::get_if<nlohmann::json::object_t>(&metricVariant);
1233a64919e8SBoleslaw Ogonczyk Makowski                 if (metric == nullptr)
1234a64919e8SBoleslaw Ogonczyk Makowski                 {
1235a64919e8SBoleslaw Ogonczyk Makowski                     index++;
1236a64919e8SBoleslaw Ogonczyk Makowski                     continue;
1237a64919e8SBoleslaw Ogonczyk Makowski                 }
1238a64919e8SBoleslaw Ogonczyk Makowski 
12399e6c388aSLukasz Kazmierczak                 AddReportArgs::MetricArgs metricArgs;
12409e6c388aSLukasz Kazmierczak                 std::vector<
12419e6c388aSLukasz Kazmierczak                     std::tuple<sdbusplus::message::object_path, std::string>>
12429e6c388aSLukasz Kazmierczak                     pathAndUri;
12439e6c388aSLukasz Kazmierczak 
12449e6c388aSLukasz Kazmierczak                 if (index < readingParams.size())
12459e6c388aSLukasz Kazmierczak                 {
12469e6c388aSLukasz Kazmierczak                     const ReadingParameters::value_type& existing =
12479e6c388aSLukasz Kazmierczak                         readingParams[index];
12489e6c388aSLukasz Kazmierczak 
1249dac07cadSBoleslaw Ogonczyk Makowski                     if (metric->empty())
1250dac07cadSBoleslaw Ogonczyk Makowski                     {
12519e6c388aSLukasz Kazmierczak                         pathAndUri = std::get<0>(existing);
1252dac07cadSBoleslaw Ogonczyk Makowski                     }
12539e6c388aSLukasz Kazmierczak                     metricArgs.collectionFunction = std::get<1>(existing);
12549e6c388aSLukasz Kazmierczak                     metricArgs.collectionTimeScope = std::get<2>(existing);
12559e6c388aSLukasz Kazmierczak                     metricArgs.collectionDuration = std::get<3>(existing);
12569e6c388aSLukasz Kazmierczak                 }
12579e6c388aSLukasz Kazmierczak 
1258a64919e8SBoleslaw Ogonczyk Makowski                 if (!getUserMetric(asyncResp->res, *metric, metricArgs))
12599e6c388aSLukasz Kazmierczak                 {
12609e6c388aSLukasz Kazmierczak                     return;
12619e6c388aSLukasz Kazmierczak                 }
12629e6c388aSLukasz Kazmierczak 
12639e6c388aSLukasz Kazmierczak                 std::optional<IncorrectMetricUri> error =
12649e6c388aSLukasz Kazmierczak                     getChassisSensorNode(metricArgs.uris, chassisSensors);
12659e6c388aSLukasz Kazmierczak 
12669e6c388aSLukasz Kazmierczak                 if (error)
12679e6c388aSLukasz Kazmierczak                 {
12689e6c388aSLukasz Kazmierczak                     messages::propertyValueIncorrect(
12699e6c388aSLukasz Kazmierczak                         asyncResp->res, error->uri,
12709e6c388aSLukasz Kazmierczak                         "MetricProperties/" + std::to_string(error->index));
12719e6c388aSLukasz Kazmierczak                     return;
12729e6c388aSLukasz Kazmierczak                 }
12739e6c388aSLukasz Kazmierczak 
12749e6c388aSLukasz Kazmierczak                 updateMetricsReq->emplace(pathAndUri, metricArgs);
12759e6c388aSLukasz Kazmierczak                 index++;
12769e6c388aSLukasz Kazmierczak             }
12779e6c388aSLukasz Kazmierczak 
12789e6c388aSLukasz Kazmierczak             for (const auto& [chassis, sensorType] : chassisSensors)
12799e6c388aSLukasz Kazmierczak             {
12809e6c388aSLukasz Kazmierczak                 retrieveUriToDbusMap(
12819e6c388aSLukasz Kazmierczak                     chassis, sensorType,
12829e6c388aSLukasz Kazmierczak                     [asyncResp, updateMetricsReq](
12839e6c388aSLukasz Kazmierczak                         const boost::beast::http::status status,
12849e6c388aSLukasz Kazmierczak                         const std::map<std::string, std::string>& uriToDbus) {
12859e6c388aSLukasz Kazmierczak                         if (status != boost::beast::http::status::ok)
12869e6c388aSLukasz Kazmierczak                         {
12879e6c388aSLukasz Kazmierczak                             BMCWEB_LOG_ERROR(
12889e6c388aSLukasz Kazmierczak                                 "Failed to retrieve URI to dbus sensors map with err {}",
12899e6c388aSLukasz Kazmierczak                                 static_cast<unsigned>(status));
12909e6c388aSLukasz Kazmierczak                             return;
12919e6c388aSLukasz Kazmierczak                         }
12929e6c388aSLukasz Kazmierczak                         updateMetricsReq->insert(uriToDbus);
12939e6c388aSLukasz Kazmierczak                     });
12949e6c388aSLukasz Kazmierczak             }
12959e6c388aSLukasz Kazmierczak         });
12969e6c388aSLukasz Kazmierczak }
1297081ebf06SWludzik, Jozef 
12984220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionHead(
12994220be3bSEd Tanous     App& app, const crow::Request& req,
13004220be3bSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
13014220be3bSEd Tanous {
13024220be3bSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
13034220be3bSEd Tanous     {
13044220be3bSEd Tanous         return;
13054220be3bSEd Tanous     }
13064220be3bSEd Tanous     asyncResp->res.addHeader(
13074220be3bSEd Tanous         boost::beast::http::field::link,
13084220be3bSEd Tanous         "</redfish/v1/JsonSchemas/MetricReportDefinitionCollection/MetricReportDefinitionCollection.json>; rel=describedby");
13094220be3bSEd Tanous }
13104220be3bSEd Tanous 
13114220be3bSEd Tanous inline void handleMetricReportDefinitionCollectionGet(
1312fc0edbe3SEd Tanous     App& app, const crow::Request& req,
1313fc0edbe3SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1314fc0edbe3SEd Tanous {
1315fc0edbe3SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1316fc0edbe3SEd Tanous     {
1317fc0edbe3SEd Tanous         return;
1318fc0edbe3SEd Tanous     }
13199e6c388aSLukasz Kazmierczak     asyncResp->res.addHeader(
13209e6c388aSLukasz Kazmierczak         boost::beast::http::field::link,
13219e6c388aSLukasz Kazmierczak         "</redfish/v1/JsonSchemas/MetricReportDefinition/MetricReportDefinition.json>; rel=describedby");
1322fc0edbe3SEd Tanous 
1323fc0edbe3SEd Tanous     asyncResp->res.jsonValue["@odata.type"] =
1324fc0edbe3SEd Tanous         "#MetricReportDefinitionCollection."
1325fc0edbe3SEd Tanous         "MetricReportDefinitionCollection";
1326fc0edbe3SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
1327fc0edbe3SEd Tanous         "/redfish/v1/TelemetryService/MetricReportDefinitions";
1328fc0edbe3SEd Tanous     asyncResp->res.jsonValue["Name"] = "Metric Definition Collection";
1329fc0edbe3SEd Tanous     constexpr std::array<std::string_view, 1> interfaces{
1330fc0edbe3SEd Tanous         telemetry::reportInterface};
1331fc0edbe3SEd Tanous     collection_util::getCollectionMembers(
1332fc0edbe3SEd Tanous         asyncResp,
1333fc0edbe3SEd Tanous         boost::urls::url(
1334fc0edbe3SEd Tanous             "/redfish/v1/TelemetryService/MetricReportDefinitions"),
1335fc0edbe3SEd Tanous         interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
1336fc0edbe3SEd Tanous }
1337fc0edbe3SEd Tanous 
1338bd79bce8SPatrick Williams inline void handleReportPatch(
1339bd79bce8SPatrick Williams     App& app, const crow::Request& req,
1340bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id)
13419e6c388aSLukasz Kazmierczak {
13429e6c388aSLukasz Kazmierczak     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
13439e6c388aSLukasz Kazmierczak     {
13449e6c388aSLukasz Kazmierczak         return;
13459e6c388aSLukasz Kazmierczak     }
13469e6c388aSLukasz Kazmierczak 
13479e6c388aSLukasz Kazmierczak     std::optional<std::string> reportingTypeStr;
13489e6c388aSLukasz Kazmierczak     std::optional<std::string> reportUpdatesStr;
13499e6c388aSLukasz Kazmierczak     std::optional<bool> metricReportDefinitionEnabled;
1350a64919e8SBoleslaw Ogonczyk Makowski     std::optional<
1351a64919e8SBoleslaw Ogonczyk Makowski         std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
1352a64919e8SBoleslaw Ogonczyk Makowski         metrics;
13539e6c388aSLukasz Kazmierczak     std::optional<std::vector<std::string>> reportActionsStr;
1354b14f357fSEd Tanous     std::optional<std::string> scheduleDurationStr;
13559e6c388aSLukasz Kazmierczak 
1356afc474aeSMyung Bae     if (!json_util::readJsonPatch( //
1357afc474aeSMyung Bae             req, asyncResp->res, //
1358afc474aeSMyung Bae             "MetricReportDefinitionEnabled", metricReportDefinitionEnabled, //
1359afc474aeSMyung Bae             "MetricReportDefinitionType", reportingTypeStr, //
1360afc474aeSMyung Bae             "Metrics", metrics, //
1361afc474aeSMyung Bae             "ReportActions", reportActionsStr, //
1362afc474aeSMyung Bae             "ReportUpdates", reportUpdatesStr, //
1363afc474aeSMyung Bae             "Schedule/RecurrenceInterval", scheduleDurationStr //
1364afc474aeSMyung Bae             ))
13659e6c388aSLukasz Kazmierczak     {
13669e6c388aSLukasz Kazmierczak         return;
13679e6c388aSLukasz Kazmierczak     }
13689e6c388aSLukasz Kazmierczak 
13699e6c388aSLukasz Kazmierczak     if (metricReportDefinitionEnabled)
13709e6c388aSLukasz Kazmierczak     {
13719e6c388aSLukasz Kazmierczak         setReportEnabled(asyncResp, id, *metricReportDefinitionEnabled);
13729e6c388aSLukasz Kazmierczak     }
13739e6c388aSLukasz Kazmierczak 
13749e6c388aSLukasz Kazmierczak     if (reportUpdatesStr)
13759e6c388aSLukasz Kazmierczak     {
1376b4361d63SEd Tanous         setReportUpdates(asyncResp, id, *reportUpdatesStr);
13779e6c388aSLukasz Kazmierczak     }
13789e6c388aSLukasz Kazmierczak 
13799e6c388aSLukasz Kazmierczak     if (reportActionsStr)
13809e6c388aSLukasz Kazmierczak     {
1381b4361d63SEd Tanous         setReportActions(asyncResp, id, *reportActionsStr);
13829e6c388aSLukasz Kazmierczak     }
13839e6c388aSLukasz Kazmierczak 
1384b14f357fSEd Tanous     if (reportingTypeStr || scheduleDurationStr)
13859e6c388aSLukasz Kazmierczak     {
1386b4361d63SEd Tanous         setReportTypeAndInterval(asyncResp, id, reportingTypeStr,
1387b4361d63SEd Tanous                                  scheduleDurationStr);
13889e6c388aSLukasz Kazmierczak     }
13899e6c388aSLukasz Kazmierczak 
13909e6c388aSLukasz Kazmierczak     if (metrics)
13919e6c388aSLukasz Kazmierczak     {
1392ba498310SKrzysztof Grobelny         setReportMetrics(asyncResp, id, std::move(*metrics));
13939e6c388aSLukasz Kazmierczak     }
13949e6c388aSLukasz Kazmierczak }
13959e6c388aSLukasz Kazmierczak 
1396bd79bce8SPatrick Williams inline void handleReportDelete(
1397bd79bce8SPatrick Williams     App& app, const crow::Request& req,
1398bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id)
13999e6c388aSLukasz Kazmierczak {
14009e6c388aSLukasz Kazmierczak     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
14019e6c388aSLukasz Kazmierczak     {
14029e6c388aSLukasz Kazmierczak         return;
14039e6c388aSLukasz Kazmierczak     }
14049e6c388aSLukasz Kazmierczak 
14059e6c388aSLukasz Kazmierczak     const std::string reportPath = getDbusReportPath(id);
14069e6c388aSLukasz Kazmierczak 
14079e6c388aSLukasz Kazmierczak     crow::connections::systemBus->async_method_call(
14089e6c388aSLukasz Kazmierczak         [asyncResp,
14099e6c388aSLukasz Kazmierczak          reportId = std::string(id)](const boost::system::error_code& ec) {
14109e6c388aSLukasz Kazmierczak             if (!verifyCommonErrors(asyncResp->res, reportId, ec))
14119e6c388aSLukasz Kazmierczak             {
14129e6c388aSLukasz Kazmierczak                 return;
14139e6c388aSLukasz Kazmierczak             }
14149e6c388aSLukasz Kazmierczak             asyncResp->res.result(boost::beast::http::status::no_content);
14159e6c388aSLukasz Kazmierczak         },
14169e6c388aSLukasz Kazmierczak         service, reportPath, "xyz.openbmc_project.Object.Delete", "Delete");
14179e6c388aSLukasz Kazmierczak }
14189e6c388aSLukasz Kazmierczak } // namespace telemetry
14199e6c388aSLukasz Kazmierczak 
142095bdb5f0SEd Tanous inline void afterRetrieveUriToDbusMap(
142195bdb5f0SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/,
142295bdb5f0SEd Tanous     const std::shared_ptr<telemetry::AddReport>& addReportReq,
142395bdb5f0SEd Tanous     const boost::beast::http::status status,
142495bdb5f0SEd Tanous     const std::map<std::string, std::string>& uriToDbus)
142595bdb5f0SEd Tanous {
142695bdb5f0SEd Tanous     if (status != boost::beast::http::status::ok)
142795bdb5f0SEd Tanous     {
142895bdb5f0SEd Tanous         BMCWEB_LOG_ERROR(
142995bdb5f0SEd Tanous             "Failed to retrieve URI to dbus sensors map with err {}",
143095bdb5f0SEd Tanous             static_cast<unsigned>(status));
143195bdb5f0SEd Tanous         return;
143295bdb5f0SEd Tanous     }
143395bdb5f0SEd Tanous     addReportReq->insert(uriToDbus);
143495bdb5f0SEd Tanous }
143595bdb5f0SEd Tanous 
14369e6c388aSLukasz Kazmierczak inline void handleMetricReportDefinitionsPost(
14379e6c388aSLukasz Kazmierczak     App& app, const crow::Request& req,
14389e6c388aSLukasz Kazmierczak     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
14399e6c388aSLukasz Kazmierczak {
14409e6c388aSLukasz Kazmierczak     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
14419e6c388aSLukasz Kazmierczak     {
14429e6c388aSLukasz Kazmierczak         return;
14439e6c388aSLukasz Kazmierczak     }
14449e6c388aSLukasz Kazmierczak 
14459e6c388aSLukasz Kazmierczak     telemetry::AddReportArgs args;
14469e6c388aSLukasz Kazmierczak     if (!telemetry::getUserParameters(asyncResp->res, req, args))
14479e6c388aSLukasz Kazmierczak     {
14489e6c388aSLukasz Kazmierczak         return;
14499e6c388aSLukasz Kazmierczak     }
14509e6c388aSLukasz Kazmierczak 
14519e6c388aSLukasz Kazmierczak     boost::container::flat_set<std::pair<std::string, std::string>>
14529e6c388aSLukasz Kazmierczak         chassisSensors;
14539e6c388aSLukasz Kazmierczak     if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics,
14549e6c388aSLukasz Kazmierczak                                                     chassisSensors))
14559e6c388aSLukasz Kazmierczak     {
14569e6c388aSLukasz Kazmierczak         return;
14579e6c388aSLukasz Kazmierczak     }
14589e6c388aSLukasz Kazmierczak 
1459bd79bce8SPatrick Williams     auto addReportReq =
1460bd79bce8SPatrick Williams         std::make_shared<telemetry::AddReport>(std::move(args), asyncResp);
14619e6c388aSLukasz Kazmierczak     for (const auto& [chassis, sensorType] : chassisSensors)
14629e6c388aSLukasz Kazmierczak     {
146395bdb5f0SEd Tanous         retrieveUriToDbusMap(chassis, sensorType,
146495bdb5f0SEd Tanous                              std::bind_front(afterRetrieveUriToDbusMap,
146595bdb5f0SEd Tanous                                              asyncResp, addReportReq));
14669e6c388aSLukasz Kazmierczak     }
14679e6c388aSLukasz Kazmierczak }
14689e6c388aSLukasz Kazmierczak 
14699e6c388aSLukasz Kazmierczak inline void
14704220be3bSEd Tanous     handleMetricReportHead(App& app, const crow::Request& req,
14714220be3bSEd Tanous                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
14724220be3bSEd Tanous                            const std::string& /*id*/)
14734220be3bSEd Tanous {
14744220be3bSEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
14754220be3bSEd Tanous     {
14764220be3bSEd Tanous         return;
14774220be3bSEd Tanous     }
14784220be3bSEd Tanous     asyncResp->res.addHeader(
14794220be3bSEd Tanous         boost::beast::http::field::link,
14804220be3bSEd Tanous         "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby");
14814220be3bSEd Tanous }
14824220be3bSEd Tanous 
1483bd79bce8SPatrick Williams inline void handleMetricReportGet(
1484bd79bce8SPatrick Williams     App& app, const crow::Request& req,
1485bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
148686a5ac98SEd Tanous {
148786a5ac98SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
148886a5ac98SEd Tanous     {
148986a5ac98SEd Tanous         return;
149086a5ac98SEd Tanous     }
14914220be3bSEd Tanous     asyncResp->res.addHeader(
14924220be3bSEd Tanous         boost::beast::http::field::link,
14934220be3bSEd Tanous         "</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby");
149486a5ac98SEd Tanous 
1495deae6a78SEd Tanous     dbus::utility::getAllProperties(
1496deae6a78SEd Tanous         telemetry::service, telemetry::getDbusReportPath(id),
1497deae6a78SEd Tanous         telemetry::reportInterface,
149886a5ac98SEd Tanous         [asyncResp, id](const boost::system::error_code& ec,
149986a5ac98SEd Tanous                         const dbus::utility::DBusPropertiesMap& properties) {
15009e6c388aSLukasz Kazmierczak             if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec))
150186a5ac98SEd Tanous             {
150286a5ac98SEd Tanous                 return;
150386a5ac98SEd Tanous             }
150486a5ac98SEd Tanous 
150586a5ac98SEd Tanous             telemetry::fillReportDefinition(asyncResp, id, properties);
150686a5ac98SEd Tanous         });
150786a5ac98SEd Tanous }
150886a5ac98SEd Tanous 
1509dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete(
1510dd1c4a9cSSzymon Dompke     App& app, const crow::Request& req,
1511dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
1512dd1c4a9cSSzymon Dompke 
1513dd1c4a9cSSzymon Dompke {
1514dd1c4a9cSSzymon Dompke     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1515dd1c4a9cSSzymon Dompke     {
1516dd1c4a9cSSzymon Dompke         return;
1517dd1c4a9cSSzymon Dompke     }
1518dd1c4a9cSSzymon Dompke 
1519dd1c4a9cSSzymon Dompke     const std::string reportPath = telemetry::getDbusReportPath(id);
1520dd1c4a9cSSzymon Dompke 
1521dd1c4a9cSSzymon Dompke     crow::connections::systemBus->async_method_call(
1522dd1c4a9cSSzymon Dompke         [asyncResp, id](const boost::system::error_code& ec) {
1523dd1c4a9cSSzymon Dompke             /*
1524dd1c4a9cSSzymon Dompke              * boost::system::errc and std::errc are missing value
1525dd1c4a9cSSzymon Dompke              * for EBADR error that is defined in Linux.
1526dd1c4a9cSSzymon Dompke              */
1527dd1c4a9cSSzymon Dompke             if (ec.value() == EBADR)
1528dd1c4a9cSSzymon Dompke             {
1529bd79bce8SPatrick Williams                 messages::resourceNotFound(asyncResp->res,
1530bd79bce8SPatrick Williams                                            "MetricReportDefinition", id);
1531dd1c4a9cSSzymon Dompke                 return;
1532dd1c4a9cSSzymon Dompke             }
1533dd1c4a9cSSzymon Dompke 
1534dd1c4a9cSSzymon Dompke             if (ec)
1535dd1c4a9cSSzymon Dompke             {
153662598e31SEd Tanous                 BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
1537dd1c4a9cSSzymon Dompke                 messages::internalError(asyncResp->res);
1538dd1c4a9cSSzymon Dompke                 return;
1539dd1c4a9cSSzymon Dompke             }
1540dd1c4a9cSSzymon Dompke 
1541dd1c4a9cSSzymon Dompke             asyncResp->res.result(boost::beast::http::status::no_content);
1542dd1c4a9cSSzymon Dompke         },
1543dd1c4a9cSSzymon Dompke         telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete",
1544dd1c4a9cSSzymon Dompke         "Delete");
1545dd1c4a9cSSzymon Dompke }
1546dd1c4a9cSSzymon Dompke 
15477e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app)
1548081ebf06SWludzik, Jozef {
15497e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
15504220be3bSEd Tanous         .privileges(redfish::privileges::headMetricReportDefinitionCollection)
15514220be3bSEd Tanous         .methods(boost::beast::http::verb::head)(std::bind_front(
15529e6c388aSLukasz Kazmierczak             telemetry::handleMetricReportDefinitionCollectionHead,
15539e6c388aSLukasz Kazmierczak             std::ref(app)));
15544220be3bSEd Tanous 
15554220be3bSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
1556ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinitionCollection)
15574220be3bSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
15589e6c388aSLukasz Kazmierczak             telemetry::handleMetricReportDefinitionCollectionGet,
15599e6c388aSLukasz Kazmierczak             std::ref(app)));
15604dbb8aeaSWludzik, Jozef 
15617e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
1562ed398213SEd Tanous         .privileges(redfish::privileges::postMetricReportDefinitionCollection)
1563002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
15649e6c388aSLukasz Kazmierczak             std::bind_front(handleMetricReportDefinitionsPost, std::ref(app)));
1565081ebf06SWludzik, Jozef }
1566081ebf06SWludzik, Jozef 
15677e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app)
1568081ebf06SWludzik, Jozef {
15697e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
15707e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
1571ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
15724220be3bSEd Tanous         .methods(boost::beast::http::verb::head)(
15734220be3bSEd Tanous             std::bind_front(handleMetricReportHead, std::ref(app)));
15744220be3bSEd Tanous 
15754220be3bSEd Tanous     BMCWEB_ROUTE(app,
15764220be3bSEd Tanous                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
15774220be3bSEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
15787e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
157986a5ac98SEd Tanous             std::bind_front(handleMetricReportGet, std::ref(app)));
1580479e899dSKrzysztof Grobelny 
15817e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
15827e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
15839e6c388aSLukasz Kazmierczak         .privileges(redfish::privileges::deleteMetricReportDefinition)
15847e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
1585dd1c4a9cSSzymon Dompke             std::bind_front(handleMetricReportDelete, std::ref(app)));
15869e6c388aSLukasz Kazmierczak 
15879e6c388aSLukasz Kazmierczak     BMCWEB_ROUTE(app,
15889e6c388aSLukasz Kazmierczak                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
15899e6c388aSLukasz Kazmierczak         .privileges(redfish::privileges::patchMetricReportDefinition)
15909e6c388aSLukasz Kazmierczak         .methods(boost::beast::http::verb::patch)(
15919e6c388aSLukasz Kazmierczak             std::bind_front(telemetry::handleReportPatch, std::ref(app)));
15924dbb8aeaSWludzik, Jozef }
1593081ebf06SWludzik, Jozef } // namespace redfish
1594