xref: /openbmc/bmcweb/features/redfish/lib/trigger.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
307148cf2SLukasz Kazmierczak #pragma once
407148cf2SLukasz Kazmierczak 
53ccb3adbSEd Tanous #include "app.hpp"
6539d8c6bSEd Tanous #include "generated/enums/metric_definition.hpp"
7dd1c4a9cSSzymon Dompke #include "generated/enums/resource.hpp"
8dd1c4a9cSSzymon Dompke #include "generated/enums/triggers.hpp"
93ccb3adbSEd Tanous #include "query.hpp"
103ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
11dd1c4a9cSSzymon Dompke #include "utility.hpp"
1207148cf2SLukasz Kazmierczak #include "utils/collection.hpp"
133ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
145b90429aSEd Tanous #include "utils/json_utils.hpp"
151516c21bSJanet Adkins #include "utils/sensor_utils.hpp"
1607148cf2SLukasz Kazmierczak #include "utils/telemetry_utils.hpp"
173ccb3adbSEd Tanous #include "utils/time_utils.hpp"
1807148cf2SLukasz Kazmierczak 
19ef4c65b7SEd Tanous #include <boost/url/format.hpp>
2089474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
2189474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
2207148cf2SLukasz Kazmierczak 
237a1dbc48SGeorge Liu #include <array>
247a1dbc48SGeorge Liu #include <string_view>
251b7e696bSLukasz Kazmierczak #include <tuple>
261b7e696bSLukasz Kazmierczak #include <variant>
271b7e696bSLukasz Kazmierczak #include <vector>
281b7e696bSLukasz Kazmierczak 
2907148cf2SLukasz Kazmierczak namespace redfish
3007148cf2SLukasz Kazmierczak {
3107148cf2SLukasz Kazmierczak namespace telemetry
3207148cf2SLukasz Kazmierczak {
3307148cf2SLukasz Kazmierczak constexpr const char* triggerInterface =
3407148cf2SLukasz Kazmierczak     "xyz.openbmc_project.Telemetry.Trigger";
3507148cf2SLukasz Kazmierczak 
361b7e696bSLukasz Kazmierczak using NumericThresholdParams =
371b7e696bSLukasz Kazmierczak     std::tuple<std::string, uint64_t, std::string, double>;
381b7e696bSLukasz Kazmierczak 
391b7e696bSLukasz Kazmierczak using DiscreteThresholdParams =
401b7e696bSLukasz Kazmierczak     std::tuple<std::string, std::string, uint64_t, std::string>;
411b7e696bSLukasz Kazmierczak 
421b7e696bSLukasz Kazmierczak using TriggerSensorsParams =
431b7e696bSLukasz Kazmierczak     std::vector<std::pair<sdbusplus::message::object_path, std::string>>;
441b7e696bSLukasz Kazmierczak 
45dd1c4a9cSSzymon Dompke inline triggers::TriggerActionEnum
46dd1c4a9cSSzymon Dompke     toRedfishTriggerAction(std::string_view dbusValue)
471b7e696bSLukasz Kazmierczak {
48dd1c4a9cSSzymon Dompke     if (dbusValue ==
49dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport")
501b7e696bSLukasz Kazmierczak     {
51dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishMetricReport;
521b7e696bSLukasz Kazmierczak     }
53dd1c4a9cSSzymon Dompke     if (dbusValue ==
54dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog")
551b7e696bSLukasz Kazmierczak     {
56dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishEvent;
571b7e696bSLukasz Kazmierczak     }
58dd1c4a9cSSzymon Dompke     if (dbusValue ==
59dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal")
601b7e696bSLukasz Kazmierczak     {
61dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::LogToLogService;
621b7e696bSLukasz Kazmierczak     }
63dd1c4a9cSSzymon Dompke     return triggers::TriggerActionEnum::Invalid;
641b7e696bSLukasz Kazmierczak }
651b7e696bSLukasz Kazmierczak 
66dd1c4a9cSSzymon Dompke inline std::string toDbusTriggerAction(std::string_view redfishValue)
671b7e696bSLukasz Kazmierczak {
68dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishMetricReport")
691b7e696bSLukasz Kazmierczak     {
70dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport";
71dd1c4a9cSSzymon Dompke     }
72dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishEvent")
73dd1c4a9cSSzymon Dompke     {
74dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog";
75dd1c4a9cSSzymon Dompke     }
76dd1c4a9cSSzymon Dompke     if (redfishValue == "LogToLogService")
77dd1c4a9cSSzymon Dompke     {
78dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal";
79dd1c4a9cSSzymon Dompke     }
80dd1c4a9cSSzymon Dompke     return "";
81dd1c4a9cSSzymon Dompke }
821b7e696bSLukasz Kazmierczak 
83dd1c4a9cSSzymon Dompke inline std::string toDbusSeverity(std::string_view redfishValue)
84dd1c4a9cSSzymon Dompke {
85dd1c4a9cSSzymon Dompke     if (redfishValue == "OK")
86dd1c4a9cSSzymon Dompke     {
87dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.OK";
88dd1c4a9cSSzymon Dompke     }
89dd1c4a9cSSzymon Dompke     if (redfishValue == "Warning")
90dd1c4a9cSSzymon Dompke     {
91dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning";
92dd1c4a9cSSzymon Dompke     }
93dd1c4a9cSSzymon Dompke     if (redfishValue == "Critical")
94dd1c4a9cSSzymon Dompke     {
95dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical";
96dd1c4a9cSSzymon Dompke     }
97dd1c4a9cSSzymon Dompke     return "";
98dd1c4a9cSSzymon Dompke }
99dd1c4a9cSSzymon Dompke 
100dd1c4a9cSSzymon Dompke inline resource::Health toRedfishSeverity(std::string_view dbusValue)
101dd1c4a9cSSzymon Dompke {
102dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.OK")
103dd1c4a9cSSzymon Dompke     {
104dd1c4a9cSSzymon Dompke         return resource::Health::OK;
105dd1c4a9cSSzymon Dompke     }
106dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning")
107dd1c4a9cSSzymon Dompke     {
108dd1c4a9cSSzymon Dompke         return resource::Health::Warning;
109dd1c4a9cSSzymon Dompke     }
110dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical")
111dd1c4a9cSSzymon Dompke     {
112dd1c4a9cSSzymon Dompke         return resource::Health::Critical;
113dd1c4a9cSSzymon Dompke     }
114dd1c4a9cSSzymon Dompke     return resource::Health::Invalid;
115dd1c4a9cSSzymon Dompke }
116dd1c4a9cSSzymon Dompke 
117dd1c4a9cSSzymon Dompke inline std::string toRedfishThresholdName(std::string_view dbusValue)
118dd1c4a9cSSzymon Dompke {
119dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical")
120dd1c4a9cSSzymon Dompke     {
121dd1c4a9cSSzymon Dompke         return "UpperCritical";
122dd1c4a9cSSzymon Dompke     }
123dd1c4a9cSSzymon Dompke 
124dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical")
125dd1c4a9cSSzymon Dompke     {
126dd1c4a9cSSzymon Dompke         return "LowerCritical";
127dd1c4a9cSSzymon Dompke     }
128dd1c4a9cSSzymon Dompke 
129dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning")
130dd1c4a9cSSzymon Dompke     {
131dd1c4a9cSSzymon Dompke         return "UpperWarning";
132dd1c4a9cSSzymon Dompke     }
133dd1c4a9cSSzymon Dompke 
134dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning")
135dd1c4a9cSSzymon Dompke     {
136dd1c4a9cSSzymon Dompke         return "LowerWarning";
137dd1c4a9cSSzymon Dompke     }
138dd1c4a9cSSzymon Dompke 
139dd1c4a9cSSzymon Dompke     return "";
140dd1c4a9cSSzymon Dompke }
141dd1c4a9cSSzymon Dompke 
142dd1c4a9cSSzymon Dompke inline std::string toDbusActivation(std::string_view redfishValue)
143dd1c4a9cSSzymon Dompke {
144dd1c4a9cSSzymon Dompke     if (redfishValue == "Either")
145dd1c4a9cSSzymon Dompke     {
146dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Either";
147dd1c4a9cSSzymon Dompke     }
148dd1c4a9cSSzymon Dompke 
149dd1c4a9cSSzymon Dompke     if (redfishValue == "Decreasing")
150dd1c4a9cSSzymon Dompke     {
151dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing";
152dd1c4a9cSSzymon Dompke     }
153dd1c4a9cSSzymon Dompke 
154dd1c4a9cSSzymon Dompke     if (redfishValue == "Increasing")
155dd1c4a9cSSzymon Dompke     {
156dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing";
157dd1c4a9cSSzymon Dompke     }
158dd1c4a9cSSzymon Dompke 
159dd1c4a9cSSzymon Dompke     return "";
160dd1c4a9cSSzymon Dompke }
161dd1c4a9cSSzymon Dompke 
162dd1c4a9cSSzymon Dompke inline triggers::ThresholdActivation
163dd1c4a9cSSzymon Dompke     toRedfishActivation(std::string_view dbusValue)
164dd1c4a9cSSzymon Dompke {
165dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Direction.Either")
166dd1c4a9cSSzymon Dompke     {
167dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Either;
168dd1c4a9cSSzymon Dompke     }
169dd1c4a9cSSzymon Dompke 
170dd1c4a9cSSzymon Dompke     if (dbusValue ==
171dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing")
172dd1c4a9cSSzymon Dompke     {
173dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Decreasing;
174dd1c4a9cSSzymon Dompke     }
175dd1c4a9cSSzymon Dompke 
176dd1c4a9cSSzymon Dompke     if (dbusValue ==
177dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing")
178dd1c4a9cSSzymon Dompke     {
179dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Increasing;
180dd1c4a9cSSzymon Dompke     }
181dd1c4a9cSSzymon Dompke 
182dd1c4a9cSSzymon Dompke     return triggers::ThresholdActivation::Invalid;
183dd1c4a9cSSzymon Dompke }
184dd1c4a9cSSzymon Dompke 
185dd1c4a9cSSzymon Dompke enum class MetricType
186dd1c4a9cSSzymon Dompke {
187dd1c4a9cSSzymon Dompke     Discrete,
188dd1c4a9cSSzymon Dompke     Numeric
189dd1c4a9cSSzymon Dompke };
190dd1c4a9cSSzymon Dompke 
191dd1c4a9cSSzymon Dompke enum class DiscreteCondition
192dd1c4a9cSSzymon Dompke {
193dd1c4a9cSSzymon Dompke     Specified,
194dd1c4a9cSSzymon Dompke     Changed
195dd1c4a9cSSzymon Dompke };
196dd1c4a9cSSzymon Dompke 
197dd1c4a9cSSzymon Dompke struct Context
198dd1c4a9cSSzymon Dompke {
199dd1c4a9cSSzymon Dompke     std::string id;
200dd1c4a9cSSzymon Dompke     std::string name;
201dd1c4a9cSSzymon Dompke     std::vector<std::string> actions;
202dd1c4a9cSSzymon Dompke     std::vector<std::pair<sdbusplus::message::object_path, std::string>>
203dd1c4a9cSSzymon Dompke         sensors;
204dd1c4a9cSSzymon Dompke     std::vector<sdbusplus::message::object_path> reports;
20558c71488SEd Tanous     std::vector<NumericThresholdParams> numericThresholds;
20658c71488SEd Tanous     std::vector<DiscreteThresholdParams> discreteThresholds;
207dd1c4a9cSSzymon Dompke     std::optional<DiscreteCondition> discreteCondition;
208dd1c4a9cSSzymon Dompke     std::optional<MetricType> metricType;
209dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> metricProperties;
210dd1c4a9cSSzymon Dompke };
211dd1c4a9cSSzymon Dompke 
212dd1c4a9cSSzymon Dompke inline std::optional<sdbusplus::message::object_path>
213dd1c4a9cSSzymon Dompke     getReportPathFromReportDefinitionUri(const std::string& uri)
214dd1c4a9cSSzymon Dompke {
2156fd29553SEd Tanous     boost::system::result<boost::urls::url_view> parsed =
216dd1c4a9cSSzymon Dompke         boost::urls::parse_relative_ref(uri);
217dd1c4a9cSSzymon Dompke 
218dd1c4a9cSSzymon Dompke     if (!parsed)
2191b7e696bSLukasz Kazmierczak     {
2201b7e696bSLukasz Kazmierczak         return std::nullopt;
2211b7e696bSLukasz Kazmierczak     }
2221b7e696bSLukasz Kazmierczak 
223dd1c4a9cSSzymon Dompke     std::string id;
224dd1c4a9cSSzymon Dompke     if (!crow::utility::readUrlSegments(
225dd1c4a9cSSzymon Dompke             *parsed, "redfish", "v1", "TelemetryService",
226dd1c4a9cSSzymon Dompke             "MetricReportDefinitions", std::ref(id)))
227dd1c4a9cSSzymon Dompke     {
228dd1c4a9cSSzymon Dompke         return std::nullopt;
2291b7e696bSLukasz Kazmierczak     }
2301b7e696bSLukasz Kazmierczak 
231dd1c4a9cSSzymon Dompke     return sdbusplus::message::object_path(
232dd1c4a9cSSzymon Dompke                "/xyz/openbmc_project/Telemetry/Reports") /
233dd1c4a9cSSzymon Dompke            "TelemetryService" / id;
234dd1c4a9cSSzymon Dompke }
235dd1c4a9cSSzymon Dompke 
236dd1c4a9cSSzymon Dompke inline std::optional<MetricType> getMetricType(const std::string& metricType)
237dd1c4a9cSSzymon Dompke {
238dd1c4a9cSSzymon Dompke     if (metricType == "Discrete")
239dd1c4a9cSSzymon Dompke     {
240dd1c4a9cSSzymon Dompke         return MetricType::Discrete;
241dd1c4a9cSSzymon Dompke     }
242dd1c4a9cSSzymon Dompke     if (metricType == "Numeric")
243dd1c4a9cSSzymon Dompke     {
244dd1c4a9cSSzymon Dompke         return MetricType::Numeric;
245dd1c4a9cSSzymon Dompke     }
246dd1c4a9cSSzymon Dompke     return std::nullopt;
247dd1c4a9cSSzymon Dompke }
248dd1c4a9cSSzymon Dompke 
249dd1c4a9cSSzymon Dompke inline std::optional<DiscreteCondition>
250dd1c4a9cSSzymon Dompke     getDiscreteCondition(const std::string& discreteTriggerCondition)
251dd1c4a9cSSzymon Dompke {
252dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Specified")
253dd1c4a9cSSzymon Dompke     {
254dd1c4a9cSSzymon Dompke         return DiscreteCondition::Specified;
255dd1c4a9cSSzymon Dompke     }
256dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Changed")
257dd1c4a9cSSzymon Dompke     {
258dd1c4a9cSSzymon Dompke         return DiscreteCondition::Changed;
259dd1c4a9cSSzymon Dompke     }
260dd1c4a9cSSzymon Dompke     return std::nullopt;
261dd1c4a9cSSzymon Dompke }
262dd1c4a9cSSzymon Dompke 
2632932dcb6SEd Tanous inline bool parseThreshold(crow::Response& res,
2642932dcb6SEd Tanous                            nlohmann::json::object_t& threshold,
2652932dcb6SEd Tanous                            std::string_view dbusThresholdName,
2662932dcb6SEd Tanous                            std::vector<NumericThresholdParams>& parsedParams)
267dd1c4a9cSSzymon Dompke {
268dd1c4a9cSSzymon Dompke     double reading = 0.0;
269dd1c4a9cSSzymon Dompke     std::string activation;
270dd1c4a9cSSzymon Dompke     std::string dwellTimeStr;
271dd1c4a9cSSzymon Dompke 
272afc474aeSMyung Bae     if (!json_util::readJsonObject( //
273afc474aeSMyung Bae             threshold, res, //
274afc474aeSMyung Bae             "Activation", activation, //
275afc474aeSMyung Bae             "DwellTime", dwellTimeStr, //
276afc474aeSMyung Bae             "Reading", reading //
277afc474aeSMyung Bae             ))
278dd1c4a9cSSzymon Dompke     {
279dd1c4a9cSSzymon Dompke         return false;
280dd1c4a9cSSzymon Dompke     }
281dd1c4a9cSSzymon Dompke 
282dd1c4a9cSSzymon Dompke     std::string dbusActivation = toDbusActivation(activation);
283dd1c4a9cSSzymon Dompke 
284dd1c4a9cSSzymon Dompke     if (dbusActivation.empty())
285dd1c4a9cSSzymon Dompke     {
286dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "Activation", activation);
287dd1c4a9cSSzymon Dompke         return false;
288dd1c4a9cSSzymon Dompke     }
289dd1c4a9cSSzymon Dompke 
290dd1c4a9cSSzymon Dompke     std::optional<std::chrono::milliseconds> dwellTime =
291dd1c4a9cSSzymon Dompke         time_utils::fromDurationString(dwellTimeStr);
292dd1c4a9cSSzymon Dompke     if (!dwellTime)
293dd1c4a9cSSzymon Dompke     {
294dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
295dd1c4a9cSSzymon Dompke         return false;
296dd1c4a9cSSzymon Dompke     }
297dd1c4a9cSSzymon Dompke 
298dd1c4a9cSSzymon Dompke     parsedParams.emplace_back(dbusThresholdName,
299dd1c4a9cSSzymon Dompke                               static_cast<uint64_t>(dwellTime->count()),
300dd1c4a9cSSzymon Dompke                               dbusActivation, reading);
3012932dcb6SEd Tanous     return true;
3022932dcb6SEd Tanous }
3032932dcb6SEd Tanous 
3042932dcb6SEd Tanous struct NumericThresholds
3052932dcb6SEd Tanous {
3062932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperCritical;
3072932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperWarning;
3082932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerWarning;
3092932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerCritical;
3102932dcb6SEd Tanous 
3112932dcb6SEd Tanous     bool any() const
3122932dcb6SEd Tanous     {
3132932dcb6SEd Tanous         return upperCritical || upperWarning || lowerWarning || lowerCritical;
3142932dcb6SEd Tanous     }
3152932dcb6SEd Tanous };
3162932dcb6SEd Tanous 
317bd79bce8SPatrick Williams inline bool parseNumericThresholds(
318bd79bce8SPatrick Williams     crow::Response& res, NumericThresholds& numericThresholds, Context& ctx)
3192932dcb6SEd Tanous {
3202932dcb6SEd Tanous     std::vector<NumericThresholdParams> parsedParams;
3212932dcb6SEd Tanous     if (numericThresholds.upperCritical)
3222932dcb6SEd Tanous     {
3232932dcb6SEd Tanous         if (!parseThreshold(
3242932dcb6SEd Tanous                 res, *numericThresholds.upperCritical,
3252932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical",
3262932dcb6SEd Tanous                 parsedParams))
3272932dcb6SEd Tanous         {
3282932dcb6SEd Tanous             return false;
3292932dcb6SEd Tanous         }
3302932dcb6SEd Tanous     }
3312932dcb6SEd Tanous     if (numericThresholds.upperWarning)
3322932dcb6SEd Tanous     {
3332932dcb6SEd Tanous         if (!parseThreshold(
3342932dcb6SEd Tanous                 res, *numericThresholds.upperWarning,
3352932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning",
3362932dcb6SEd Tanous                 parsedParams))
3372932dcb6SEd Tanous         {
3382932dcb6SEd Tanous             return false;
3392932dcb6SEd Tanous         }
3402932dcb6SEd Tanous     }
3412932dcb6SEd Tanous     if (numericThresholds.lowerWarning)
3422932dcb6SEd Tanous     {
3432932dcb6SEd Tanous         if (!parseThreshold(
3442932dcb6SEd Tanous                 res, *numericThresholds.lowerWarning,
3452932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning",
3462932dcb6SEd Tanous                 parsedParams))
3472932dcb6SEd Tanous         {
3482932dcb6SEd Tanous             return false;
3492932dcb6SEd Tanous         }
3502932dcb6SEd Tanous     }
3512932dcb6SEd Tanous     if (numericThresholds.lowerCritical)
3522932dcb6SEd Tanous     {
3532932dcb6SEd Tanous         if (!parseThreshold(
3542932dcb6SEd Tanous                 res, *numericThresholds.lowerCritical,
3552932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical",
3562932dcb6SEd Tanous                 parsedParams))
3572932dcb6SEd Tanous         {
3582932dcb6SEd Tanous             return false;
3592932dcb6SEd Tanous         }
360dd1c4a9cSSzymon Dompke     }
361dd1c4a9cSSzymon Dompke 
36258c71488SEd Tanous     ctx.numericThresholds = std::move(parsedParams);
363dd1c4a9cSSzymon Dompke     return true;
364dd1c4a9cSSzymon Dompke }
365dd1c4a9cSSzymon Dompke 
366dd1c4a9cSSzymon Dompke inline bool parseDiscreteTriggers(
367dd1c4a9cSSzymon Dompke     crow::Response& res,
3682932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
3692932dcb6SEd Tanous     Context& ctx)
370dd1c4a9cSSzymon Dompke {
371dd1c4a9cSSzymon Dompke     std::vector<DiscreteThresholdParams> parsedParams;
372dd1c4a9cSSzymon Dompke     if (!discreteTriggers)
373dd1c4a9cSSzymon Dompke     {
37458c71488SEd Tanous         ctx.discreteThresholds = std::move(parsedParams);
375dd1c4a9cSSzymon Dompke         return true;
376dd1c4a9cSSzymon Dompke     }
377dd1c4a9cSSzymon Dompke 
378dd1c4a9cSSzymon Dompke     parsedParams.reserve(discreteTriggers->size());
3792932dcb6SEd Tanous     for (nlohmann::json::object_t& thresholdInfo : *discreteTriggers)
380dd1c4a9cSSzymon Dompke     {
381dd1c4a9cSSzymon Dompke         std::optional<std::string> name = "";
382dd1c4a9cSSzymon Dompke         std::string value;
383dd1c4a9cSSzymon Dompke         std::string dwellTimeStr;
384dd1c4a9cSSzymon Dompke         std::string severity;
385dd1c4a9cSSzymon Dompke 
386afc474aeSMyung Bae         if (!json_util::readJsonObject( //
387afc474aeSMyung Bae                 thresholdInfo, res, //
388afc474aeSMyung Bae                 "DwellTime", dwellTimeStr, //
389afc474aeSMyung Bae                 "Name", name, //
390afc474aeSMyung Bae                 "Severity", severity, //
391afc474aeSMyung Bae                 "Value", value //
392afc474aeSMyung Bae                 ))
393dd1c4a9cSSzymon Dompke         {
394dd1c4a9cSSzymon Dompke             return false;
395dd1c4a9cSSzymon Dompke         }
396dd1c4a9cSSzymon Dompke 
397dd1c4a9cSSzymon Dompke         std::optional<std::chrono::milliseconds> dwellTime =
398dd1c4a9cSSzymon Dompke             time_utils::fromDurationString(dwellTimeStr);
399dd1c4a9cSSzymon Dompke         if (!dwellTime)
400dd1c4a9cSSzymon Dompke         {
401dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
402dd1c4a9cSSzymon Dompke             return false;
403dd1c4a9cSSzymon Dompke         }
404dd1c4a9cSSzymon Dompke 
405dd1c4a9cSSzymon Dompke         std::string dbusSeverity = toDbusSeverity(severity);
406dd1c4a9cSSzymon Dompke         if (dbusSeverity.empty())
407dd1c4a9cSSzymon Dompke         {
408dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "Severity", severity);
409dd1c4a9cSSzymon Dompke             return false;
410dd1c4a9cSSzymon Dompke         }
411dd1c4a9cSSzymon Dompke 
412dd1c4a9cSSzymon Dompke         parsedParams.emplace_back(*name, dbusSeverity,
413dd1c4a9cSSzymon Dompke                                   static_cast<uint64_t>(dwellTime->count()),
414dd1c4a9cSSzymon Dompke                                   value);
415dd1c4a9cSSzymon Dompke     }
416dd1c4a9cSSzymon Dompke 
41758c71488SEd Tanous     ctx.discreteThresholds = std::move(parsedParams);
418dd1c4a9cSSzymon Dompke     return true;
419dd1c4a9cSSzymon Dompke }
420dd1c4a9cSSzymon Dompke 
421dd1c4a9cSSzymon Dompke inline bool parseTriggerThresholds(
422dd1c4a9cSSzymon Dompke     crow::Response& res,
4232932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
4242932dcb6SEd Tanous     NumericThresholds& numericThresholds, Context& ctx)
425dd1c4a9cSSzymon Dompke {
4262932dcb6SEd Tanous     if (discreteTriggers && numericThresholds.any())
427dd1c4a9cSSzymon Dompke     {
428dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "DiscreteTriggers",
429dd1c4a9cSSzymon Dompke                                         "NumericThresholds");
430dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "NumericThresholds",
431dd1c4a9cSSzymon Dompke                                         "DiscreteTriggers");
432dd1c4a9cSSzymon Dompke         return false;
433dd1c4a9cSSzymon Dompke     }
434dd1c4a9cSSzymon Dompke 
435dd1c4a9cSSzymon Dompke     if (ctx.discreteCondition)
436dd1c4a9cSSzymon Dompke     {
4372932dcb6SEd Tanous         if (numericThresholds.any())
438dd1c4a9cSSzymon Dompke         {
439dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggerCondition",
440dd1c4a9cSSzymon Dompke                                             "NumericThresholds");
441dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
442dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
443dd1c4a9cSSzymon Dompke             return false;
444dd1c4a9cSSzymon Dompke         }
445dd1c4a9cSSzymon Dompke     }
446dd1c4a9cSSzymon Dompke 
447dd1c4a9cSSzymon Dompke     if (ctx.metricType)
448dd1c4a9cSSzymon Dompke     {
4492932dcb6SEd Tanous         if (*ctx.metricType == MetricType::Discrete && numericThresholds.any())
450dd1c4a9cSSzymon Dompke         {
451dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
452dd1c4a9cSSzymon Dompke                                             "MetricType");
453dd1c4a9cSSzymon Dompke             return false;
454dd1c4a9cSSzymon Dompke         }
455dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && discreteTriggers)
456dd1c4a9cSSzymon Dompke         {
457dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
458dd1c4a9cSSzymon Dompke                                             "MetricType");
459dd1c4a9cSSzymon Dompke             return false;
460dd1c4a9cSSzymon Dompke         }
461dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && ctx.discreteCondition)
462dd1c4a9cSSzymon Dompke         {
463dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
464dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
465dd1c4a9cSSzymon Dompke             return false;
466dd1c4a9cSSzymon Dompke         }
467dd1c4a9cSSzymon Dompke     }
468dd1c4a9cSSzymon Dompke 
469dd1c4a9cSSzymon Dompke     if (discreteTriggers || ctx.discreteCondition ||
470dd1c4a9cSSzymon Dompke         (ctx.metricType && *ctx.metricType == MetricType::Discrete))
471dd1c4a9cSSzymon Dompke     {
472dd1c4a9cSSzymon Dompke         if (ctx.discreteCondition)
473dd1c4a9cSSzymon Dompke         {
474dd1c4a9cSSzymon Dompke             if (*ctx.discreteCondition == DiscreteCondition::Specified &&
475dd1c4a9cSSzymon Dompke                 !discreteTriggers)
476dd1c4a9cSSzymon Dompke             {
477dd1c4a9cSSzymon Dompke                 messages::createFailedMissingReqProperties(res,
478dd1c4a9cSSzymon Dompke                                                            "DiscreteTriggers");
479dd1c4a9cSSzymon Dompke                 return false;
480dd1c4a9cSSzymon Dompke             }
481dd1c4a9cSSzymon Dompke             if (discreteTriggers &&
482dd1c4a9cSSzymon Dompke                 ((*ctx.discreteCondition == DiscreteCondition::Specified &&
483dd1c4a9cSSzymon Dompke                   discreteTriggers->empty()) ||
484dd1c4a9cSSzymon Dompke                  (*ctx.discreteCondition == DiscreteCondition::Changed &&
485dd1c4a9cSSzymon Dompke                   !discreteTriggers->empty())))
486dd1c4a9cSSzymon Dompke             {
487dd1c4a9cSSzymon Dompke                 messages::propertyValueConflict(res, "DiscreteTriggers",
488dd1c4a9cSSzymon Dompke                                                 "DiscreteTriggerCondition");
489dd1c4a9cSSzymon Dompke                 return false;
490dd1c4a9cSSzymon Dompke             }
491dd1c4a9cSSzymon Dompke         }
492dd1c4a9cSSzymon Dompke         if (!parseDiscreteTriggers(res, discreteTriggers, ctx))
493dd1c4a9cSSzymon Dompke         {
494dd1c4a9cSSzymon Dompke             return false;
495dd1c4a9cSSzymon Dompke         }
496dd1c4a9cSSzymon Dompke     }
4972932dcb6SEd Tanous     else if (numericThresholds.any())
498dd1c4a9cSSzymon Dompke     {
4992932dcb6SEd Tanous         if (!parseNumericThresholds(res, numericThresholds, ctx))
500dd1c4a9cSSzymon Dompke         {
501dd1c4a9cSSzymon Dompke             return false;
502dd1c4a9cSSzymon Dompke         }
503dd1c4a9cSSzymon Dompke     }
504dd1c4a9cSSzymon Dompke     else
505dd1c4a9cSSzymon Dompke     {
506dd1c4a9cSSzymon Dompke         messages::createFailedMissingReqProperties(
507dd1c4a9cSSzymon Dompke             res, "'DiscreteTriggers', 'NumericThresholds', "
508dd1c4a9cSSzymon Dompke                  "'DiscreteTriggerCondition' or 'MetricType'");
509dd1c4a9cSSzymon Dompke         return false;
510dd1c4a9cSSzymon Dompke     }
511dd1c4a9cSSzymon Dompke     return true;
512dd1c4a9cSSzymon Dompke }
513dd1c4a9cSSzymon Dompke 
5142932dcb6SEd Tanous inline bool parseLinks(crow::Response& res,
5152932dcb6SEd Tanous                        const std::vector<std::string>& metricReportDefinitions,
5162932dcb6SEd Tanous                        Context& ctx)
517dd1c4a9cSSzymon Dompke {
5182932dcb6SEd Tanous     ctx.reports.reserve(metricReportDefinitions.size());
5192932dcb6SEd Tanous     for (const std::string& reportDefinionUri : metricReportDefinitions)
520dd1c4a9cSSzymon Dompke     {
521dd1c4a9cSSzymon Dompke         std::optional<sdbusplus::message::object_path> reportPath =
522dd1c4a9cSSzymon Dompke             getReportPathFromReportDefinitionUri(reportDefinionUri);
523dd1c4a9cSSzymon Dompke         if (!reportPath)
524dd1c4a9cSSzymon Dompke         {
525dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricReportDefinitions",
526dd1c4a9cSSzymon Dompke                                              reportDefinionUri);
527dd1c4a9cSSzymon Dompke             return false;
528dd1c4a9cSSzymon Dompke         }
529dd1c4a9cSSzymon Dompke         ctx.reports.emplace_back(*reportPath);
530dd1c4a9cSSzymon Dompke     }
531dd1c4a9cSSzymon Dompke     return true;
532dd1c4a9cSSzymon Dompke }
533dd1c4a9cSSzymon Dompke 
534dd1c4a9cSSzymon Dompke inline bool parseMetricProperties(crow::Response& res, Context& ctx)
535dd1c4a9cSSzymon Dompke {
536dd1c4a9cSSzymon Dompke     if (!ctx.metricProperties)
537dd1c4a9cSSzymon Dompke     {
538dd1c4a9cSSzymon Dompke         return true;
539dd1c4a9cSSzymon Dompke     }
540dd1c4a9cSSzymon Dompke 
541dd1c4a9cSSzymon Dompke     ctx.sensors.reserve(ctx.metricProperties->size());
542dd1c4a9cSSzymon Dompke 
543dd1c4a9cSSzymon Dompke     size_t uriIdx = 0;
544dd1c4a9cSSzymon Dompke     for (const std::string& uriStr : *ctx.metricProperties)
545dd1c4a9cSSzymon Dompke     {
5464a7fbefdSEd Tanous         boost::system::result<boost::urls::url> uri =
547dd1c4a9cSSzymon Dompke             boost::urls::parse_relative_ref(uriStr);
548dd1c4a9cSSzymon Dompke         if (!uri)
549dd1c4a9cSSzymon Dompke         {
550dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
551dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
552dd1c4a9cSSzymon Dompke             return false;
553dd1c4a9cSSzymon Dompke         }
554dd1c4a9cSSzymon Dompke         std::string chassisName;
555dd1c4a9cSSzymon Dompke         std::string sensorName;
556dd1c4a9cSSzymon Dompke         if (!crow::utility::readUrlSegments(*uri, "redfish", "v1", "Chassis",
557dd1c4a9cSSzymon Dompke                                             std::ref(chassisName), "Sensors",
558dd1c4a9cSSzymon Dompke                                             std::ref(sensorName)))
559dd1c4a9cSSzymon Dompke         {
560dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
561dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
562dd1c4a9cSSzymon Dompke             return false;
563dd1c4a9cSSzymon Dompke         }
564dd1c4a9cSSzymon Dompke 
565dd1c4a9cSSzymon Dompke         std::pair<std::string, std::string> split =
5661516c21bSJanet Adkins             redfish::sensor_utils::splitSensorNameAndType(sensorName);
567dd1c4a9cSSzymon Dompke         if (split.first.empty() || split.second.empty())
568dd1c4a9cSSzymon Dompke         {
569dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
570dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
571dd1c4a9cSSzymon Dompke             return false;
572dd1c4a9cSSzymon Dompke         }
573dd1c4a9cSSzymon Dompke 
574bd79bce8SPatrick Williams         std::string sensorPath =
575bd79bce8SPatrick Williams             "/xyz/openbmc_project/sensors/" + split.first + '/' + split.second;
576dd1c4a9cSSzymon Dompke 
577dd1c4a9cSSzymon Dompke         ctx.sensors.emplace_back(sensorPath, uriStr);
578dd1c4a9cSSzymon Dompke         uriIdx++;
579dd1c4a9cSSzymon Dompke     }
580dd1c4a9cSSzymon Dompke     return true;
581dd1c4a9cSSzymon Dompke }
582dd1c4a9cSSzymon Dompke 
583dd1c4a9cSSzymon Dompke inline bool parsePostTriggerParams(crow::Response& res,
584dd1c4a9cSSzymon Dompke                                    const crow::Request& req, Context& ctx)
585dd1c4a9cSSzymon Dompke {
586dd1c4a9cSSzymon Dompke     std::optional<std::string> id = "";
587dd1c4a9cSSzymon Dompke     std::optional<std::string> name = "";
588dd1c4a9cSSzymon Dompke     std::optional<std::string> metricType;
589dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> triggerActions;
590dd1c4a9cSSzymon Dompke     std::optional<std::string> discreteTriggerCondition;
5912932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>> discreteTriggers;
5922932dcb6SEd Tanous     std::optional<std::vector<std::string>> metricReportDefinitions;
5932932dcb6SEd Tanous     NumericThresholds thresholds;
594afc474aeSMyung Bae 
595afc474aeSMyung Bae     if (!json_util::readJsonPatch( //
596afc474aeSMyung Bae             req, res, //
597afc474aeSMyung Bae             "Id", id, //
598afc474aeSMyung Bae             "DiscreteTriggerCondition", discreteTriggerCondition, //
599afc474aeSMyung Bae             "DiscreteTriggers", discreteTriggers, //
600afc474aeSMyung Bae             "Links/MetricReportDefinitions", metricReportDefinitions, //
601afc474aeSMyung Bae             "MetricProperties", ctx.metricProperties, //
602afc474aeSMyung Bae             "MetricType", metricType, //
603afc474aeSMyung Bae             "Name", name, //
604afc474aeSMyung Bae             "NumericThresholds/LowerCritical", thresholds.lowerCritical, //
605afc474aeSMyung Bae             "NumericThresholds/LowerWarning", thresholds.lowerWarning, //
606afc474aeSMyung Bae             "NumericThresholds/UpperCritical", thresholds.upperCritical, //
607afc474aeSMyung Bae             "NumericThresholds/UpperWarning", thresholds.upperWarning, //
608afc474aeSMyung Bae             "TriggerActions", triggerActions //
609afc474aeSMyung Bae             ))
610dd1c4a9cSSzymon Dompke     {
611dd1c4a9cSSzymon Dompke         return false;
612dd1c4a9cSSzymon Dompke     }
613dd1c4a9cSSzymon Dompke 
614dd1c4a9cSSzymon Dompke     ctx.id = *id;
615dd1c4a9cSSzymon Dompke     ctx.name = *name;
616dd1c4a9cSSzymon Dompke 
617dd1c4a9cSSzymon Dompke     if (metricType)
618dd1c4a9cSSzymon Dompke     {
619d5736ef2SEd Tanous         ctx.metricType = getMetricType(*metricType);
620d5736ef2SEd Tanous         if (!ctx.metricType)
621dd1c4a9cSSzymon Dompke         {
622dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricType", *metricType);
623dd1c4a9cSSzymon Dompke             return false;
624dd1c4a9cSSzymon Dompke         }
625dd1c4a9cSSzymon Dompke     }
626dd1c4a9cSSzymon Dompke 
627dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition)
628dd1c4a9cSSzymon Dompke     {
629d5736ef2SEd Tanous         ctx.discreteCondition = getDiscreteCondition(*discreteTriggerCondition);
630d5736ef2SEd Tanous         if (!ctx.discreteCondition)
631dd1c4a9cSSzymon Dompke         {
632dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DiscreteTriggerCondition",
633dd1c4a9cSSzymon Dompke                                              *discreteTriggerCondition);
634dd1c4a9cSSzymon Dompke             return false;
635dd1c4a9cSSzymon Dompke         }
636dd1c4a9cSSzymon Dompke     }
637dd1c4a9cSSzymon Dompke 
638dd1c4a9cSSzymon Dompke     if (triggerActions)
639dd1c4a9cSSzymon Dompke     {
640dd1c4a9cSSzymon Dompke         ctx.actions.reserve(triggerActions->size());
641dd1c4a9cSSzymon Dompke         for (const std::string& action : *triggerActions)
642dd1c4a9cSSzymon Dompke         {
643dd1c4a9cSSzymon Dompke             std::string dbusAction = toDbusTriggerAction(action);
644dd1c4a9cSSzymon Dompke 
645dd1c4a9cSSzymon Dompke             if (dbusAction.empty())
646dd1c4a9cSSzymon Dompke             {
647dd1c4a9cSSzymon Dompke                 messages::propertyValueNotInList(res, action, "TriggerActions");
648dd1c4a9cSSzymon Dompke                 return false;
649dd1c4a9cSSzymon Dompke             }
650dd1c4a9cSSzymon Dompke 
651dd1c4a9cSSzymon Dompke             ctx.actions.emplace_back(dbusAction);
652dd1c4a9cSSzymon Dompke         }
653dd1c4a9cSSzymon Dompke     }
654dd1c4a9cSSzymon Dompke     if (!parseMetricProperties(res, ctx))
655dd1c4a9cSSzymon Dompke     {
656dd1c4a9cSSzymon Dompke         return false;
657dd1c4a9cSSzymon Dompke     }
658dd1c4a9cSSzymon Dompke 
6592932dcb6SEd Tanous     if (!parseTriggerThresholds(res, discreteTriggers, thresholds, ctx))
660dd1c4a9cSSzymon Dompke     {
661dd1c4a9cSSzymon Dompke         return false;
662dd1c4a9cSSzymon Dompke     }
663dd1c4a9cSSzymon Dompke 
6642932dcb6SEd Tanous     if (metricReportDefinitions)
665dd1c4a9cSSzymon Dompke     {
6662932dcb6SEd Tanous         if (!parseLinks(res, *metricReportDefinitions, ctx))
667dd1c4a9cSSzymon Dompke         {
668dd1c4a9cSSzymon Dompke             return false;
669dd1c4a9cSSzymon Dompke         }
670dd1c4a9cSSzymon Dompke     }
671dd1c4a9cSSzymon Dompke     return true;
672dd1c4a9cSSzymon Dompke }
673dd1c4a9cSSzymon Dompke 
674dd1c4a9cSSzymon Dompke inline void afterCreateTrigger(
675dd1c4a9cSSzymon Dompke     const boost::system::error_code& ec, const std::string& dbusPath,
676dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
677dd1c4a9cSSzymon Dompke {
678dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::file_exists)
679dd1c4a9cSSzymon Dompke     {
680dd1c4a9cSSzymon Dompke         messages::resourceAlreadyExists(asyncResp->res, "Trigger", "Id", id);
681dd1c4a9cSSzymon Dompke         return;
682dd1c4a9cSSzymon Dompke     }
683dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::too_many_files_open)
684dd1c4a9cSSzymon Dompke     {
685dd1c4a9cSSzymon Dompke         messages::createLimitReachedForResource(asyncResp->res);
686dd1c4a9cSSzymon Dompke         return;
687dd1c4a9cSSzymon Dompke     }
688dd1c4a9cSSzymon Dompke     if (ec)
689dd1c4a9cSSzymon Dompke     {
690dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
69162598e31SEd Tanous         BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
692dd1c4a9cSSzymon Dompke         return;
693dd1c4a9cSSzymon Dompke     }
694dd1c4a9cSSzymon Dompke 
695dd1c4a9cSSzymon Dompke     const std::optional<std::string>& triggerId =
696dd1c4a9cSSzymon Dompke         getTriggerIdFromDbusPath(dbusPath);
697dd1c4a9cSSzymon Dompke     if (!triggerId)
698dd1c4a9cSSzymon Dompke     {
699dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
70062598e31SEd Tanous         BMCWEB_LOG_ERROR("Unknown data returned by "
70162598e31SEd Tanous                          "AddTrigger DBus method");
702dd1c4a9cSSzymon Dompke         return;
703dd1c4a9cSSzymon Dompke     }
704dd1c4a9cSSzymon Dompke 
705dd1c4a9cSSzymon Dompke     messages::created(asyncResp->res);
706dd1c4a9cSSzymon Dompke     boost::urls::url locationUrl = boost::urls::format(
707dd1c4a9cSSzymon Dompke         "/redfish/v1/TelemetryService/Triggers/{}", *triggerId);
708dd1c4a9cSSzymon Dompke     asyncResp->res.addHeader("Location", locationUrl.buffer());
709dd1c4a9cSSzymon Dompke }
710dd1c4a9cSSzymon Dompke 
711dd1c4a9cSSzymon Dompke inline std::optional<nlohmann::json::array_t>
712dd1c4a9cSSzymon Dompke     getTriggerActions(const std::vector<std::string>& dbusActions)
713dd1c4a9cSSzymon Dompke {
714dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggerActions;
715dd1c4a9cSSzymon Dompke     for (const std::string& dbusAction : dbusActions)
716dd1c4a9cSSzymon Dompke     {
717dd1c4a9cSSzymon Dompke         triggers::TriggerActionEnum redfishAction =
718dd1c4a9cSSzymon Dompke             toRedfishTriggerAction(dbusAction);
719dd1c4a9cSSzymon Dompke 
720dd1c4a9cSSzymon Dompke         if (redfishAction == triggers::TriggerActionEnum::Invalid)
721dd1c4a9cSSzymon Dompke         {
722dd1c4a9cSSzymon Dompke             return std::nullopt;
723dd1c4a9cSSzymon Dompke         }
724dd1c4a9cSSzymon Dompke 
725dd1c4a9cSSzymon Dompke         triggerActions.emplace_back(redfishAction);
726dd1c4a9cSSzymon Dompke     }
727dd1c4a9cSSzymon Dompke 
728dd1c4a9cSSzymon Dompke     return triggerActions;
7291b7e696bSLukasz Kazmierczak }
7301b7e696bSLukasz Kazmierczak 
73158c71488SEd Tanous inline std::optional<nlohmann::json::array_t> getDiscreteTriggers(
73258c71488SEd Tanous     const std::vector<DiscreteThresholdParams>& discreteParams)
7331b7e696bSLukasz Kazmierczak {
734dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggers;
73558c71488SEd Tanous     for (const auto& [name, severity, dwellTime, value] : discreteParams)
7361b7e696bSLukasz Kazmierczak     {
7371b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7381b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7391b7e696bSLukasz Kazmierczak 
7401b7e696bSLukasz Kazmierczak         if (!duration)
7411b7e696bSLukasz Kazmierczak         {
7421b7e696bSLukasz Kazmierczak             return std::nullopt;
7431b7e696bSLukasz Kazmierczak         }
744613dabeaSEd Tanous         nlohmann::json::object_t trigger;
745613dabeaSEd Tanous         trigger["Name"] = name;
746dd1c4a9cSSzymon Dompke         trigger["Severity"] = toRedfishSeverity(severity);
747613dabeaSEd Tanous         trigger["DwellTime"] = *duration;
748613dabeaSEd Tanous         trigger["Value"] = value;
749ad539545SPatrick Williams         triggers.emplace_back(std::move(trigger));
7501b7e696bSLukasz Kazmierczak     }
7511b7e696bSLukasz Kazmierczak 
752dd1c4a9cSSzymon Dompke     return triggers;
7531b7e696bSLukasz Kazmierczak }
7541b7e696bSLukasz Kazmierczak 
75558c71488SEd Tanous inline std::optional<nlohmann::json::object_t> getNumericThresholds(
75658c71488SEd Tanous     const std::vector<NumericThresholdParams>& numericParams)
7571b7e696bSLukasz Kazmierczak {
758dd1c4a9cSSzymon Dompke     nlohmann::json::object_t thresholds;
7591b7e696bSLukasz Kazmierczak 
76058c71488SEd Tanous     for (const auto& [type, dwellTime, activation, reading] : numericParams)
7611b7e696bSLukasz Kazmierczak     {
7621b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7631b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7641b7e696bSLukasz Kazmierczak 
7651b7e696bSLukasz Kazmierczak         if (!duration)
7661b7e696bSLukasz Kazmierczak         {
7671b7e696bSLukasz Kazmierczak             return std::nullopt;
7681b7e696bSLukasz Kazmierczak         }
769dd1c4a9cSSzymon Dompke         nlohmann::json& threshold = thresholds[toRedfishThresholdName(type)];
7701476687dSEd Tanous         threshold["Reading"] = reading;
771dd1c4a9cSSzymon Dompke         threshold["Activation"] = toRedfishActivation(activation);
7721476687dSEd Tanous         threshold["DwellTime"] = *duration;
7731b7e696bSLukasz Kazmierczak     }
7741b7e696bSLukasz Kazmierczak 
775dd1c4a9cSSzymon Dompke     return thresholds;
7761b7e696bSLukasz Kazmierczak }
7771b7e696bSLukasz Kazmierczak 
7783f215c92SSzymon Dompke inline std::optional<nlohmann::json> getMetricReportDefinitions(
7793f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>& reportPaths)
7801b7e696bSLukasz Kazmierczak {
7811b7e696bSLukasz Kazmierczak     nlohmann::json reports = nlohmann::json::array();
7823f215c92SSzymon Dompke 
7833f215c92SSzymon Dompke     for (const sdbusplus::message::object_path& path : reportPaths)
7841b7e696bSLukasz Kazmierczak     {
7853f215c92SSzymon Dompke         std::string reportId = path.filename();
7863f215c92SSzymon Dompke         if (reportId.empty())
7873f215c92SSzymon Dompke         {
7883f215c92SSzymon Dompke             {
78962598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Reports contains invalid value: {}",
79062598e31SEd Tanous                                  path.str);
7913f215c92SSzymon Dompke                 return std::nullopt;
7923f215c92SSzymon Dompke             }
7933f215c92SSzymon Dompke         }
7943f215c92SSzymon Dompke 
7951476687dSEd Tanous         nlohmann::json::object_t report;
796ef4c65b7SEd Tanous         report["@odata.id"] = boost::urls::format(
797ef4c65b7SEd Tanous             "/redfish/v1/TelemetryService/MetricReportDefinitions/{}",
798ef4c65b7SEd Tanous             reportId);
799b2ba3072SPatrick Williams         reports.emplace_back(std::move(report));
8001b7e696bSLukasz Kazmierczak     }
8011b7e696bSLukasz Kazmierczak 
8023f215c92SSzymon Dompke     return {std::move(reports)};
8031b7e696bSLukasz Kazmierczak }
8041b7e696bSLukasz Kazmierczak 
8051b7e696bSLukasz Kazmierczak inline std::vector<std::string>
8061b7e696bSLukasz Kazmierczak     getMetricProperties(const TriggerSensorsParams& sensors)
8071b7e696bSLukasz Kazmierczak {
8081b7e696bSLukasz Kazmierczak     std::vector<std::string> metricProperties;
8091b7e696bSLukasz Kazmierczak     metricProperties.reserve(sensors.size());
8101b7e696bSLukasz Kazmierczak     for (const auto& [_, metadata] : sensors)
8111b7e696bSLukasz Kazmierczak     {
8121b7e696bSLukasz Kazmierczak         metricProperties.emplace_back(metadata);
8131b7e696bSLukasz Kazmierczak     }
8141b7e696bSLukasz Kazmierczak 
8151b7e696bSLukasz Kazmierczak     return metricProperties;
8161b7e696bSLukasz Kazmierczak }
8171b7e696bSLukasz Kazmierczak 
818e3648032SEd Tanous inline bool fillTrigger(nlohmann::json& json, const std::string& id,
819e3648032SEd Tanous                         const dbus::utility::DBusPropertiesMap& properties)
8201b7e696bSLukasz Kazmierczak {
8211b7e696bSLukasz Kazmierczak     const std::string* name = nullptr;
8221b7e696bSLukasz Kazmierczak     const bool* discrete = nullptr;
8231b7e696bSLukasz Kazmierczak     const TriggerSensorsParams* sensors = nullptr;
8243f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>* reports = nullptr;
82589474494SKrzysztof Grobelny     const std::vector<std::string>* triggerActions = nullptr;
82658c71488SEd Tanous 
82758c71488SEd Tanous     const std::vector<DiscreteThresholdParams>* discreteThresholds = nullptr;
82858c71488SEd Tanous     const std::vector<NumericThresholdParams>* numericThresholds = nullptr;
8291b7e696bSLukasz Kazmierczak 
83089474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
83189474494SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "Name", name, "Discrete",
83289474494SKrzysztof Grobelny         discrete, "Sensors", sensors, "Reports", reports, "TriggerActions",
83358c71488SEd Tanous         triggerActions, "DiscreteThresholds", discreteThresholds,
83458c71488SEd Tanous         "NumericThresholds", numericThresholds);
83589474494SKrzysztof Grobelny 
83689474494SKrzysztof Grobelny     if (!success)
8371b7e696bSLukasz Kazmierczak     {
83889474494SKrzysztof Grobelny         return false;
8391b7e696bSLukasz Kazmierczak     }
8401b7e696bSLukasz Kazmierczak 
84189474494SKrzysztof Grobelny     if (triggerActions != nullptr)
84289474494SKrzysztof Grobelny     {
843dd1c4a9cSSzymon Dompke         std::optional<nlohmann::json::array_t> redfishTriggerActions =
84489474494SKrzysztof Grobelny             getTriggerActions(*triggerActions);
84589474494SKrzysztof Grobelny         if (!redfishTriggerActions)
8461b7e696bSLukasz Kazmierczak         {
84762598e31SEd Tanous             BMCWEB_LOG_ERROR(
84862598e31SEd Tanous                 "Property TriggerActions is invalid in Trigger: {}", id);
8491b7e696bSLukasz Kazmierczak             return false;
8501b7e696bSLukasz Kazmierczak         }
851dd1c4a9cSSzymon Dompke         json["TriggerActions"] = *redfishTriggerActions;
85289474494SKrzysztof Grobelny     }
8531b7e696bSLukasz Kazmierczak 
85489474494SKrzysztof Grobelny     if (reports != nullptr)
8553f215c92SSzymon Dompke     {
8563f215c92SSzymon Dompke         std::optional<nlohmann::json> linkedReports =
8573f215c92SSzymon Dompke             getMetricReportDefinitions(*reports);
8583f215c92SSzymon Dompke         if (!linkedReports)
8593f215c92SSzymon Dompke         {
86062598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Reports is invalid in Trigger: {}", id);
8613f215c92SSzymon Dompke             return false;
8623f215c92SSzymon Dompke         }
86389474494SKrzysztof Grobelny         json["Links"]["MetricReportDefinitions"] = *linkedReports;
86489474494SKrzysztof Grobelny     }
8651b7e696bSLukasz Kazmierczak 
86658c71488SEd Tanous     if (discreteThresholds != nullptr)
8671b7e696bSLukasz Kazmierczak     {
8683f215c92SSzymon Dompke         std::optional<nlohmann::json::array_t> discreteTriggers =
86958c71488SEd Tanous             getDiscreteTriggers(*discreteThresholds);
8701b7e696bSLukasz Kazmierczak 
8711b7e696bSLukasz Kazmierczak         if (!discreteTriggers)
8721b7e696bSLukasz Kazmierczak         {
87362598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Thresholds is invalid for discrete "
87462598e31SEd Tanous                              "triggers in Trigger: {}",
87562598e31SEd Tanous                              id);
8761b7e696bSLukasz Kazmierczak             return false;
8771b7e696bSLukasz Kazmierczak         }
8781b7e696bSLukasz Kazmierczak 
8791b7e696bSLukasz Kazmierczak         json["DiscreteTriggers"] = *discreteTriggers;
8801b7e696bSLukasz Kazmierczak         json["DiscreteTriggerCondition"] =
8811b7e696bSLukasz Kazmierczak             discreteTriggers->empty() ? "Changed" : "Specified";
882539d8c6bSEd Tanous         json["MetricType"] = metric_definition::MetricType::Discrete;
8831b7e696bSLukasz Kazmierczak     }
88458c71488SEd Tanous     if (numericThresholds != nullptr)
8851b7e696bSLukasz Kazmierczak     {
88658c71488SEd Tanous         std::optional<nlohmann::json::object_t> jnumericThresholds =
88758c71488SEd Tanous             getNumericThresholds(*numericThresholds);
8881b7e696bSLukasz Kazmierczak 
88958c71488SEd Tanous         if (!jnumericThresholds)
8901b7e696bSLukasz Kazmierczak         {
89162598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Thresholds is invalid for numeric "
89262598e31SEd Tanous                              "thresholds in Trigger: {}",
89362598e31SEd Tanous                              id);
8941b7e696bSLukasz Kazmierczak             return false;
8951b7e696bSLukasz Kazmierczak         }
8961b7e696bSLukasz Kazmierczak 
89758c71488SEd Tanous         json["NumericThresholds"] = *jnumericThresholds;
898539d8c6bSEd Tanous         json["MetricType"] = metric_definition::MetricType::Numeric;
8991b7e696bSLukasz Kazmierczak     }
90089474494SKrzysztof Grobelny 
90189474494SKrzysztof Grobelny     if (name != nullptr)
90289474494SKrzysztof Grobelny     {
90389474494SKrzysztof Grobelny         json["Name"] = *name;
90489474494SKrzysztof Grobelny     }
90589474494SKrzysztof Grobelny 
90689474494SKrzysztof Grobelny     if (sensors != nullptr)
90789474494SKrzysztof Grobelny     {
90889474494SKrzysztof Grobelny         json["MetricProperties"] = getMetricProperties(*sensors);
90989474494SKrzysztof Grobelny     }
9101b7e696bSLukasz Kazmierczak 
9113f215c92SSzymon Dompke     json["@odata.type"] = "#Triggers.v1_2_0.Triggers";
912ef4c65b7SEd Tanous     json["@odata.id"] =
913ef4c65b7SEd Tanous         boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
9143f215c92SSzymon Dompke     json["Id"] = id;
9151b7e696bSLukasz Kazmierczak 
9161b7e696bSLukasz Kazmierczak     return true;
9171b7e696bSLukasz Kazmierczak }
9181b7e696bSLukasz Kazmierczak 
919dd1c4a9cSSzymon Dompke inline void handleTriggerCollectionPost(
920dd1c4a9cSSzymon Dompke     App& app, const crow::Request& req,
921dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
922dd1c4a9cSSzymon Dompke {
923dd1c4a9cSSzymon Dompke     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
924dd1c4a9cSSzymon Dompke     {
925dd1c4a9cSSzymon Dompke         return;
926dd1c4a9cSSzymon Dompke     }
927dd1c4a9cSSzymon Dompke 
928dd1c4a9cSSzymon Dompke     telemetry::Context ctx;
929dd1c4a9cSSzymon Dompke     if (!telemetry::parsePostTriggerParams(asyncResp->res, req, ctx))
930dd1c4a9cSSzymon Dompke     {
931dd1c4a9cSSzymon Dompke         return;
932dd1c4a9cSSzymon Dompke     }
933dd1c4a9cSSzymon Dompke 
934dd1c4a9cSSzymon Dompke     crow::connections::systemBus->async_method_call(
935dd1c4a9cSSzymon Dompke         [asyncResp, id = ctx.id](const boost::system::error_code& ec,
936dd1c4a9cSSzymon Dompke                                  const std::string& dbusPath) {
937dd1c4a9cSSzymon Dompke             afterCreateTrigger(ec, dbusPath, asyncResp, id);
938dd1c4a9cSSzymon Dompke         },
939dd1c4a9cSSzymon Dompke         service, "/xyz/openbmc_project/Telemetry/Triggers",
940dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.TriggerManager", "AddTrigger",
941dd1c4a9cSSzymon Dompke         "TelemetryService/" + ctx.id, ctx.name, ctx.actions, ctx.sensors,
94258c71488SEd Tanous         ctx.reports, ctx.numericThresholds, ctx.discreteThresholds);
943dd1c4a9cSSzymon Dompke }
944dd1c4a9cSSzymon Dompke 
94507148cf2SLukasz Kazmierczak } // namespace telemetry
94607148cf2SLukasz Kazmierczak 
94707148cf2SLukasz Kazmierczak inline void requestRoutesTriggerCollection(App& app)
94807148cf2SLukasz Kazmierczak {
94907148cf2SLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
95007148cf2SLukasz Kazmierczak         .privileges(redfish::privileges::getTriggersCollection)
95107148cf2SLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
95245ca1b86SEd Tanous             [&app](const crow::Request& req,
95307148cf2SLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9543ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
95545ca1b86SEd Tanous                 {
95645ca1b86SEd Tanous                     return;
95745ca1b86SEd Tanous                 }
95807148cf2SLukasz Kazmierczak                 asyncResp->res.jsonValue["@odata.type"] =
95907148cf2SLukasz Kazmierczak                     "#TriggersCollection.TriggersCollection";
960ae9031f0SWilly Tu                 asyncResp->res.jsonValue["@odata.id"] =
961ae9031f0SWilly Tu                     "/redfish/v1/TelemetryService/Triggers";
96207148cf2SLukasz Kazmierczak                 asyncResp->res.jsonValue["Name"] = "Triggers Collection";
9637a1dbc48SGeorge Liu                 constexpr std::array<std::string_view, 1> interfaces{
9647a1dbc48SGeorge Liu                     telemetry::triggerInterface};
96507148cf2SLukasz Kazmierczak                 collection_util::getCollectionMembers(
966ae9031f0SWilly Tu                     asyncResp,
967ae9031f0SWilly Tu                     boost::urls::url("/redfish/v1/TelemetryService/Triggers"),
968ae9031f0SWilly Tu                     interfaces,
96907148cf2SLukasz Kazmierczak                     "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
97007148cf2SLukasz Kazmierczak             });
971dd1c4a9cSSzymon Dompke 
972dd1c4a9cSSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
973dd1c4a9cSSzymon Dompke         .privileges(redfish::privileges::postTriggersCollection)
974dd1c4a9cSSzymon Dompke         .methods(boost::beast::http::verb::post)(std::bind_front(
975dd1c4a9cSSzymon Dompke             telemetry::handleTriggerCollectionPost, std::ref(app)));
97607148cf2SLukasz Kazmierczak }
97707148cf2SLukasz Kazmierczak 
9781b7e696bSLukasz Kazmierczak inline void requestRoutesTrigger(App& app)
9791b7e696bSLukasz Kazmierczak {
9801b7e696bSLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
9811b7e696bSLukasz Kazmierczak         .privileges(redfish::privileges::getTriggers)
9821b7e696bSLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
98345ca1b86SEd Tanous             [&app](const crow::Request& req,
9841b7e696bSLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9851b7e696bSLukasz Kazmierczak                    const std::string& id) {
9863ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
98745ca1b86SEd Tanous                 {
98845ca1b86SEd Tanous                     return;
98945ca1b86SEd Tanous                 }
99089474494SKrzysztof Grobelny                 sdbusplus::asio::getAllProperties(
99189474494SKrzysztof Grobelny                     *crow::connections::systemBus, telemetry::service,
992bd79bce8SPatrick Williams                     telemetry::getDbusTriggerPath(id),
993bd79bce8SPatrick Williams                     telemetry::triggerInterface,
9941b7e696bSLukasz Kazmierczak                     [asyncResp,
9955e7e2dc5SEd Tanous                      id](const boost::system::error_code& ec,
996e3648032SEd Tanous                          const dbus::utility::DBusPropertiesMap& ret) {
9971b7e696bSLukasz Kazmierczak                         if (ec.value() == EBADR ||
9981b7e696bSLukasz Kazmierczak                             ec == boost::system::errc::host_unreachable)
9991b7e696bSLukasz Kazmierczak                         {
1000bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
1001bd79bce8SPatrick Williams                                                        "Triggers", id);
10021b7e696bSLukasz Kazmierczak                             return;
10031b7e696bSLukasz Kazmierczak                         }
10041b7e696bSLukasz Kazmierczak                         if (ec)
10051b7e696bSLukasz Kazmierczak                         {
100662598e31SEd Tanous                             BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
10071b7e696bSLukasz Kazmierczak                             messages::internalError(asyncResp->res);
10081b7e696bSLukasz Kazmierczak                             return;
10091b7e696bSLukasz Kazmierczak                         }
10101b7e696bSLukasz Kazmierczak 
1011bd79bce8SPatrick Williams                         if (!telemetry::fillTrigger(asyncResp->res.jsonValue,
1012bd79bce8SPatrick Williams                                                     id, ret))
10131b7e696bSLukasz Kazmierczak                         {
10141b7e696bSLukasz Kazmierczak                             messages::internalError(asyncResp->res);
10151b7e696bSLukasz Kazmierczak                         }
101689474494SKrzysztof Grobelny                     });
10171b7e696bSLukasz Kazmierczak             });
1018163994a8SSzymon Dompke 
1019163994a8SSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
1020163994a8SSzymon Dompke         .privileges(redfish::privileges::deleteTriggers)
1021163994a8SSzymon Dompke         .methods(boost::beast::http::verb::delete_)(
102245ca1b86SEd Tanous             [&app](const crow::Request& req,
1023163994a8SSzymon Dompke                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1024163994a8SSzymon Dompke                    const std::string& id) {
10253ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
102645ca1b86SEd Tanous                 {
102745ca1b86SEd Tanous                     return;
102845ca1b86SEd Tanous                 }
1029bd79bce8SPatrick Williams                 const std::string triggerPath =
1030bd79bce8SPatrick Williams                     telemetry::getDbusTriggerPath(id);
1031163994a8SSzymon Dompke 
1032163994a8SSzymon Dompke                 crow::connections::systemBus->async_method_call(
10335e7e2dc5SEd Tanous                     [asyncResp, id](const boost::system::error_code& ec) {
1034163994a8SSzymon Dompke                         if (ec.value() == EBADR)
1035163994a8SSzymon Dompke                         {
1036bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
1037bd79bce8SPatrick Williams                                                        "Triggers", id);
1038163994a8SSzymon Dompke                             return;
1039163994a8SSzymon Dompke                         }
1040163994a8SSzymon Dompke 
1041163994a8SSzymon Dompke                         if (ec)
1042163994a8SSzymon Dompke                         {
104362598e31SEd Tanous                             BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
1044163994a8SSzymon Dompke                             messages::internalError(asyncResp->res);
1045163994a8SSzymon Dompke                             return;
1046163994a8SSzymon Dompke                         }
1047163994a8SSzymon Dompke 
1048bd79bce8SPatrick Williams                         asyncResp->res.result(
1049bd79bce8SPatrick Williams                             boost::beast::http::status::no_content);
1050163994a8SSzymon Dompke                     },
1051163994a8SSzymon Dompke                     telemetry::service, triggerPath,
1052163994a8SSzymon Dompke                     "xyz.openbmc_project.Object.Delete", "Delete");
1053163994a8SSzymon Dompke             });
10541b7e696bSLukasz Kazmierczak }
10551b7e696bSLukasz Kazmierczak 
105607148cf2SLukasz Kazmierczak } // namespace redfish
1057