xref: /openbmc/bmcweb/features/redfish/lib/trigger.hpp (revision 539d8c6bc399e516d39bcaa18262cf206f4c1035)
107148cf2SLukasz Kazmierczak #pragma once
207148cf2SLukasz Kazmierczak 
33ccb3adbSEd Tanous #include "app.hpp"
4*539d8c6bSEd Tanous #include "generated/enums/metric_definition.hpp"
5dd1c4a9cSSzymon Dompke #include "generated/enums/resource.hpp"
6dd1c4a9cSSzymon Dompke #include "generated/enums/triggers.hpp"
73ccb3adbSEd Tanous #include "query.hpp"
83ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
9dd1c4a9cSSzymon Dompke #include "sensors.hpp"
10dd1c4a9cSSzymon Dompke #include "utility.hpp"
1107148cf2SLukasz Kazmierczak #include "utils/collection.hpp"
123ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
135b90429aSEd Tanous #include "utils/json_utils.hpp"
1407148cf2SLukasz Kazmierczak #include "utils/telemetry_utils.hpp"
153ccb3adbSEd Tanous #include "utils/time_utils.hpp"
1607148cf2SLukasz Kazmierczak 
17ef4c65b7SEd Tanous #include <boost/url/format.hpp>
1889474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
1989474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
2007148cf2SLukasz Kazmierczak 
217a1dbc48SGeorge Liu #include <array>
227a1dbc48SGeorge Liu #include <string_view>
231b7e696bSLukasz Kazmierczak #include <tuple>
241b7e696bSLukasz Kazmierczak #include <variant>
251b7e696bSLukasz Kazmierczak #include <vector>
261b7e696bSLukasz Kazmierczak 
2707148cf2SLukasz Kazmierczak namespace redfish
2807148cf2SLukasz Kazmierczak {
2907148cf2SLukasz Kazmierczak namespace telemetry
3007148cf2SLukasz Kazmierczak {
3107148cf2SLukasz Kazmierczak constexpr const char* triggerInterface =
3207148cf2SLukasz Kazmierczak     "xyz.openbmc_project.Telemetry.Trigger";
3307148cf2SLukasz Kazmierczak 
341b7e696bSLukasz Kazmierczak using NumericThresholdParams =
351b7e696bSLukasz Kazmierczak     std::tuple<std::string, uint64_t, std::string, double>;
361b7e696bSLukasz Kazmierczak 
371b7e696bSLukasz Kazmierczak using DiscreteThresholdParams =
381b7e696bSLukasz Kazmierczak     std::tuple<std::string, std::string, uint64_t, std::string>;
391b7e696bSLukasz Kazmierczak 
40dd1c4a9cSSzymon Dompke using TriggerThresholdParams =
41dd1c4a9cSSzymon Dompke     std::variant<std::vector<NumericThresholdParams>,
42dd1c4a9cSSzymon Dompke                  std::vector<DiscreteThresholdParams>>;
43dd1c4a9cSSzymon Dompke 
441b7e696bSLukasz Kazmierczak using TriggerThresholdParamsExt =
451b7e696bSLukasz Kazmierczak     std::variant<std::monostate, std::vector<NumericThresholdParams>,
461b7e696bSLukasz Kazmierczak                  std::vector<DiscreteThresholdParams>>;
471b7e696bSLukasz Kazmierczak 
481b7e696bSLukasz Kazmierczak using TriggerSensorsParams =
491b7e696bSLukasz Kazmierczak     std::vector<std::pair<sdbusplus::message::object_path, std::string>>;
501b7e696bSLukasz Kazmierczak 
511b7e696bSLukasz Kazmierczak using TriggerGetParamsVariant =
521b7e696bSLukasz Kazmierczak     std::variant<std::monostate, bool, std::string, TriggerThresholdParamsExt,
533f215c92SSzymon Dompke                  TriggerSensorsParams, std::vector<std::string>,
543f215c92SSzymon Dompke                  std::vector<sdbusplus::message::object_path>>;
551b7e696bSLukasz Kazmierczak 
56dd1c4a9cSSzymon Dompke inline triggers::TriggerActionEnum
57dd1c4a9cSSzymon Dompke     toRedfishTriggerAction(std::string_view dbusValue)
581b7e696bSLukasz Kazmierczak {
59dd1c4a9cSSzymon Dompke     if (dbusValue ==
60dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport")
611b7e696bSLukasz Kazmierczak     {
62dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishMetricReport;
631b7e696bSLukasz Kazmierczak     }
64dd1c4a9cSSzymon Dompke     if (dbusValue ==
65dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog")
661b7e696bSLukasz Kazmierczak     {
67dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishEvent;
681b7e696bSLukasz Kazmierczak     }
69dd1c4a9cSSzymon Dompke     if (dbusValue ==
70dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal")
711b7e696bSLukasz Kazmierczak     {
72dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::LogToLogService;
731b7e696bSLukasz Kazmierczak     }
74dd1c4a9cSSzymon Dompke     return triggers::TriggerActionEnum::Invalid;
751b7e696bSLukasz Kazmierczak }
761b7e696bSLukasz Kazmierczak 
77dd1c4a9cSSzymon Dompke inline std::string toDbusTriggerAction(std::string_view redfishValue)
781b7e696bSLukasz Kazmierczak {
79dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishMetricReport")
801b7e696bSLukasz Kazmierczak     {
81dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport";
82dd1c4a9cSSzymon Dompke     }
83dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishEvent")
84dd1c4a9cSSzymon Dompke     {
85dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog";
86dd1c4a9cSSzymon Dompke     }
87dd1c4a9cSSzymon Dompke     if (redfishValue == "LogToLogService")
88dd1c4a9cSSzymon Dompke     {
89dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal";
90dd1c4a9cSSzymon Dompke     }
91dd1c4a9cSSzymon Dompke     return "";
92dd1c4a9cSSzymon Dompke }
931b7e696bSLukasz Kazmierczak 
94dd1c4a9cSSzymon Dompke inline std::string toDbusSeverity(std::string_view redfishValue)
95dd1c4a9cSSzymon Dompke {
96dd1c4a9cSSzymon Dompke     if (redfishValue == "OK")
97dd1c4a9cSSzymon Dompke     {
98dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.OK";
99dd1c4a9cSSzymon Dompke     }
100dd1c4a9cSSzymon Dompke     if (redfishValue == "Warning")
101dd1c4a9cSSzymon Dompke     {
102dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning";
103dd1c4a9cSSzymon Dompke     }
104dd1c4a9cSSzymon Dompke     if (redfishValue == "Critical")
105dd1c4a9cSSzymon Dompke     {
106dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical";
107dd1c4a9cSSzymon Dompke     }
108dd1c4a9cSSzymon Dompke     return "";
109dd1c4a9cSSzymon Dompke }
110dd1c4a9cSSzymon Dompke 
111dd1c4a9cSSzymon Dompke inline resource::Health toRedfishSeverity(std::string_view dbusValue)
112dd1c4a9cSSzymon Dompke {
113dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.OK")
114dd1c4a9cSSzymon Dompke     {
115dd1c4a9cSSzymon Dompke         return resource::Health::OK;
116dd1c4a9cSSzymon Dompke     }
117dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning")
118dd1c4a9cSSzymon Dompke     {
119dd1c4a9cSSzymon Dompke         return resource::Health::Warning;
120dd1c4a9cSSzymon Dompke     }
121dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical")
122dd1c4a9cSSzymon Dompke     {
123dd1c4a9cSSzymon Dompke         return resource::Health::Critical;
124dd1c4a9cSSzymon Dompke     }
125dd1c4a9cSSzymon Dompke     return resource::Health::Invalid;
126dd1c4a9cSSzymon Dompke }
127dd1c4a9cSSzymon Dompke 
128dd1c4a9cSSzymon Dompke inline std::string toRedfishThresholdName(std::string_view dbusValue)
129dd1c4a9cSSzymon Dompke {
130dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical")
131dd1c4a9cSSzymon Dompke     {
132dd1c4a9cSSzymon Dompke         return "UpperCritical";
133dd1c4a9cSSzymon Dompke     }
134dd1c4a9cSSzymon Dompke 
135dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical")
136dd1c4a9cSSzymon Dompke     {
137dd1c4a9cSSzymon Dompke         return "LowerCritical";
138dd1c4a9cSSzymon Dompke     }
139dd1c4a9cSSzymon Dompke 
140dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning")
141dd1c4a9cSSzymon Dompke     {
142dd1c4a9cSSzymon Dompke         return "UpperWarning";
143dd1c4a9cSSzymon Dompke     }
144dd1c4a9cSSzymon Dompke 
145dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning")
146dd1c4a9cSSzymon Dompke     {
147dd1c4a9cSSzymon Dompke         return "LowerWarning";
148dd1c4a9cSSzymon Dompke     }
149dd1c4a9cSSzymon Dompke 
150dd1c4a9cSSzymon Dompke     return "";
151dd1c4a9cSSzymon Dompke }
152dd1c4a9cSSzymon Dompke 
153dd1c4a9cSSzymon Dompke inline std::string toDbusActivation(std::string_view redfishValue)
154dd1c4a9cSSzymon Dompke {
155dd1c4a9cSSzymon Dompke     if (redfishValue == "Either")
156dd1c4a9cSSzymon Dompke     {
157dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Either";
158dd1c4a9cSSzymon Dompke     }
159dd1c4a9cSSzymon Dompke 
160dd1c4a9cSSzymon Dompke     if (redfishValue == "Decreasing")
161dd1c4a9cSSzymon Dompke     {
162dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing";
163dd1c4a9cSSzymon Dompke     }
164dd1c4a9cSSzymon Dompke 
165dd1c4a9cSSzymon Dompke     if (redfishValue == "Increasing")
166dd1c4a9cSSzymon Dompke     {
167dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing";
168dd1c4a9cSSzymon Dompke     }
169dd1c4a9cSSzymon Dompke 
170dd1c4a9cSSzymon Dompke     return "";
171dd1c4a9cSSzymon Dompke }
172dd1c4a9cSSzymon Dompke 
173dd1c4a9cSSzymon Dompke inline triggers::ThresholdActivation
174dd1c4a9cSSzymon Dompke     toRedfishActivation(std::string_view dbusValue)
175dd1c4a9cSSzymon Dompke {
176dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Direction.Either")
177dd1c4a9cSSzymon Dompke     {
178dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Either;
179dd1c4a9cSSzymon Dompke     }
180dd1c4a9cSSzymon Dompke 
181dd1c4a9cSSzymon Dompke     if (dbusValue ==
182dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing")
183dd1c4a9cSSzymon Dompke     {
184dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Decreasing;
185dd1c4a9cSSzymon Dompke     }
186dd1c4a9cSSzymon Dompke 
187dd1c4a9cSSzymon Dompke     if (dbusValue ==
188dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing")
189dd1c4a9cSSzymon Dompke     {
190dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Increasing;
191dd1c4a9cSSzymon Dompke     }
192dd1c4a9cSSzymon Dompke 
193dd1c4a9cSSzymon Dompke     return triggers::ThresholdActivation::Invalid;
194dd1c4a9cSSzymon Dompke }
195dd1c4a9cSSzymon Dompke 
196dd1c4a9cSSzymon Dompke enum class MetricType
197dd1c4a9cSSzymon Dompke {
198dd1c4a9cSSzymon Dompke     Discrete,
199dd1c4a9cSSzymon Dompke     Numeric
200dd1c4a9cSSzymon Dompke };
201dd1c4a9cSSzymon Dompke 
202dd1c4a9cSSzymon Dompke enum class DiscreteCondition
203dd1c4a9cSSzymon Dompke {
204dd1c4a9cSSzymon Dompke     Specified,
205dd1c4a9cSSzymon Dompke     Changed
206dd1c4a9cSSzymon Dompke };
207dd1c4a9cSSzymon Dompke 
208dd1c4a9cSSzymon Dompke struct Context
209dd1c4a9cSSzymon Dompke {
210dd1c4a9cSSzymon Dompke     std::string id;
211dd1c4a9cSSzymon Dompke     std::string name;
212dd1c4a9cSSzymon Dompke     std::vector<std::string> actions;
213dd1c4a9cSSzymon Dompke     std::vector<std::pair<sdbusplus::message::object_path, std::string>>
214dd1c4a9cSSzymon Dompke         sensors;
215dd1c4a9cSSzymon Dompke     std::vector<sdbusplus::message::object_path> reports;
216dd1c4a9cSSzymon Dompke     TriggerThresholdParams thresholds;
217dd1c4a9cSSzymon Dompke 
218dd1c4a9cSSzymon Dompke     std::optional<DiscreteCondition> discreteCondition;
219dd1c4a9cSSzymon Dompke     std::optional<MetricType> metricType;
220dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> metricProperties;
221dd1c4a9cSSzymon Dompke };
222dd1c4a9cSSzymon Dompke 
223dd1c4a9cSSzymon Dompke inline std::optional<sdbusplus::message::object_path>
224dd1c4a9cSSzymon Dompke     getReportPathFromReportDefinitionUri(const std::string& uri)
225dd1c4a9cSSzymon Dompke {
2266fd29553SEd Tanous     boost::system::result<boost::urls::url_view> parsed =
227dd1c4a9cSSzymon Dompke         boost::urls::parse_relative_ref(uri);
228dd1c4a9cSSzymon Dompke 
229dd1c4a9cSSzymon Dompke     if (!parsed)
2301b7e696bSLukasz Kazmierczak     {
2311b7e696bSLukasz Kazmierczak         return std::nullopt;
2321b7e696bSLukasz Kazmierczak     }
2331b7e696bSLukasz Kazmierczak 
234dd1c4a9cSSzymon Dompke     std::string id;
235dd1c4a9cSSzymon Dompke     if (!crow::utility::readUrlSegments(
236dd1c4a9cSSzymon Dompke             *parsed, "redfish", "v1", "TelemetryService",
237dd1c4a9cSSzymon Dompke             "MetricReportDefinitions", std::ref(id)))
238dd1c4a9cSSzymon Dompke     {
239dd1c4a9cSSzymon Dompke         return std::nullopt;
2401b7e696bSLukasz Kazmierczak     }
2411b7e696bSLukasz Kazmierczak 
242dd1c4a9cSSzymon Dompke     return sdbusplus::message::object_path(
243dd1c4a9cSSzymon Dompke                "/xyz/openbmc_project/Telemetry/Reports") /
244dd1c4a9cSSzymon Dompke            "TelemetryService" / id;
245dd1c4a9cSSzymon Dompke }
246dd1c4a9cSSzymon Dompke 
247dd1c4a9cSSzymon Dompke inline std::optional<MetricType> getMetricType(const std::string& metricType)
248dd1c4a9cSSzymon Dompke {
249dd1c4a9cSSzymon Dompke     if (metricType == "Discrete")
250dd1c4a9cSSzymon Dompke     {
251dd1c4a9cSSzymon Dompke         return MetricType::Discrete;
252dd1c4a9cSSzymon Dompke     }
253dd1c4a9cSSzymon Dompke     if (metricType == "Numeric")
254dd1c4a9cSSzymon Dompke     {
255dd1c4a9cSSzymon Dompke         return MetricType::Numeric;
256dd1c4a9cSSzymon Dompke     }
257dd1c4a9cSSzymon Dompke     return std::nullopt;
258dd1c4a9cSSzymon Dompke }
259dd1c4a9cSSzymon Dompke 
260dd1c4a9cSSzymon Dompke inline std::optional<DiscreteCondition>
261dd1c4a9cSSzymon Dompke     getDiscreteCondition(const std::string& discreteTriggerCondition)
262dd1c4a9cSSzymon Dompke {
263dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Specified")
264dd1c4a9cSSzymon Dompke     {
265dd1c4a9cSSzymon Dompke         return DiscreteCondition::Specified;
266dd1c4a9cSSzymon Dompke     }
267dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Changed")
268dd1c4a9cSSzymon Dompke     {
269dd1c4a9cSSzymon Dompke         return DiscreteCondition::Changed;
270dd1c4a9cSSzymon Dompke     }
271dd1c4a9cSSzymon Dompke     return std::nullopt;
272dd1c4a9cSSzymon Dompke }
273dd1c4a9cSSzymon Dompke 
2742932dcb6SEd Tanous inline bool parseThreshold(crow::Response& res,
2752932dcb6SEd Tanous                            nlohmann::json::object_t& threshold,
2762932dcb6SEd Tanous                            std::string_view dbusThresholdName,
2772932dcb6SEd Tanous                            std::vector<NumericThresholdParams>& parsedParams)
278dd1c4a9cSSzymon Dompke {
279dd1c4a9cSSzymon Dompke     double reading = 0.0;
280dd1c4a9cSSzymon Dompke     std::string activation;
281dd1c4a9cSSzymon Dompke     std::string dwellTimeStr;
282dd1c4a9cSSzymon Dompke 
2832932dcb6SEd Tanous     if (!json_util::readJsonObject(threshold, res, "Reading", reading,
284dd1c4a9cSSzymon Dompke                                    "Activation", activation, "DwellTime",
285dd1c4a9cSSzymon Dompke                                    dwellTimeStr))
286dd1c4a9cSSzymon Dompke     {
287dd1c4a9cSSzymon Dompke         return false;
288dd1c4a9cSSzymon Dompke     }
289dd1c4a9cSSzymon Dompke 
290dd1c4a9cSSzymon Dompke     std::string dbusActivation = toDbusActivation(activation);
291dd1c4a9cSSzymon Dompke 
292dd1c4a9cSSzymon Dompke     if (dbusActivation.empty())
293dd1c4a9cSSzymon Dompke     {
294dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "Activation", activation);
295dd1c4a9cSSzymon Dompke         return false;
296dd1c4a9cSSzymon Dompke     }
297dd1c4a9cSSzymon Dompke 
298dd1c4a9cSSzymon Dompke     std::optional<std::chrono::milliseconds> dwellTime =
299dd1c4a9cSSzymon Dompke         time_utils::fromDurationString(dwellTimeStr);
300dd1c4a9cSSzymon Dompke     if (!dwellTime)
301dd1c4a9cSSzymon Dompke     {
302dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
303dd1c4a9cSSzymon Dompke         return false;
304dd1c4a9cSSzymon Dompke     }
305dd1c4a9cSSzymon Dompke 
306dd1c4a9cSSzymon Dompke     parsedParams.emplace_back(dbusThresholdName,
307dd1c4a9cSSzymon Dompke                               static_cast<uint64_t>(dwellTime->count()),
308dd1c4a9cSSzymon Dompke                               dbusActivation, reading);
3092932dcb6SEd Tanous     return true;
3102932dcb6SEd Tanous }
3112932dcb6SEd Tanous 
3122932dcb6SEd Tanous struct NumericThresholds
3132932dcb6SEd Tanous {
3142932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperCritical;
3152932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperWarning;
3162932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerWarning;
3172932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerCritical;
3182932dcb6SEd Tanous 
3192932dcb6SEd Tanous     bool any() const
3202932dcb6SEd Tanous     {
3212932dcb6SEd Tanous         return upperCritical || upperWarning || lowerWarning || lowerCritical;
3222932dcb6SEd Tanous     }
3232932dcb6SEd Tanous };
3242932dcb6SEd Tanous 
3252932dcb6SEd Tanous inline bool parseNumericThresholds(crow::Response& res,
3262932dcb6SEd Tanous                                    NumericThresholds& numericThresholds,
3272932dcb6SEd Tanous                                    Context& ctx)
3282932dcb6SEd Tanous {
3292932dcb6SEd Tanous     std::vector<NumericThresholdParams> parsedParams;
3302932dcb6SEd Tanous     if (numericThresholds.upperCritical)
3312932dcb6SEd Tanous     {
3322932dcb6SEd Tanous         if (!parseThreshold(
3332932dcb6SEd Tanous                 res, *numericThresholds.upperCritical,
3342932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical",
3352932dcb6SEd Tanous                 parsedParams))
3362932dcb6SEd Tanous         {
3372932dcb6SEd Tanous             return false;
3382932dcb6SEd Tanous         }
3392932dcb6SEd Tanous     }
3402932dcb6SEd Tanous     if (numericThresholds.upperWarning)
3412932dcb6SEd Tanous     {
3422932dcb6SEd Tanous         if (!parseThreshold(
3432932dcb6SEd Tanous                 res, *numericThresholds.upperWarning,
3442932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning",
3452932dcb6SEd Tanous                 parsedParams))
3462932dcb6SEd Tanous         {
3472932dcb6SEd Tanous             return false;
3482932dcb6SEd Tanous         }
3492932dcb6SEd Tanous     }
3502932dcb6SEd Tanous     if (numericThresholds.lowerWarning)
3512932dcb6SEd Tanous     {
3522932dcb6SEd Tanous         if (!parseThreshold(
3532932dcb6SEd Tanous                 res, *numericThresholds.lowerWarning,
3542932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning",
3552932dcb6SEd Tanous                 parsedParams))
3562932dcb6SEd Tanous         {
3572932dcb6SEd Tanous             return false;
3582932dcb6SEd Tanous         }
3592932dcb6SEd Tanous     }
3602932dcb6SEd Tanous     if (numericThresholds.lowerCritical)
3612932dcb6SEd Tanous     {
3622932dcb6SEd Tanous         if (!parseThreshold(
3632932dcb6SEd Tanous                 res, *numericThresholds.lowerCritical,
3642932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical",
3652932dcb6SEd Tanous                 parsedParams))
3662932dcb6SEd Tanous         {
3672932dcb6SEd Tanous             return false;
3682932dcb6SEd Tanous         }
369dd1c4a9cSSzymon Dompke     }
370dd1c4a9cSSzymon Dompke 
371dd1c4a9cSSzymon Dompke     ctx.thresholds = std::move(parsedParams);
372dd1c4a9cSSzymon Dompke     return true;
373dd1c4a9cSSzymon Dompke }
374dd1c4a9cSSzymon Dompke 
375dd1c4a9cSSzymon Dompke inline bool parseDiscreteTriggers(
376dd1c4a9cSSzymon Dompke     crow::Response& res,
3772932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
3782932dcb6SEd Tanous     Context& ctx)
379dd1c4a9cSSzymon Dompke {
380dd1c4a9cSSzymon Dompke     std::vector<DiscreteThresholdParams> parsedParams;
381dd1c4a9cSSzymon Dompke     if (!discreteTriggers)
382dd1c4a9cSSzymon Dompke     {
383dd1c4a9cSSzymon Dompke         ctx.thresholds = std::move(parsedParams);
384dd1c4a9cSSzymon Dompke         return true;
385dd1c4a9cSSzymon Dompke     }
386dd1c4a9cSSzymon Dompke 
387dd1c4a9cSSzymon Dompke     parsedParams.reserve(discreteTriggers->size());
3882932dcb6SEd Tanous     for (nlohmann::json::object_t& thresholdInfo : *discreteTriggers)
389dd1c4a9cSSzymon Dompke     {
390dd1c4a9cSSzymon Dompke         std::optional<std::string> name = "";
391dd1c4a9cSSzymon Dompke         std::string value;
392dd1c4a9cSSzymon Dompke         std::string dwellTimeStr;
393dd1c4a9cSSzymon Dompke         std::string severity;
394dd1c4a9cSSzymon Dompke 
3952932dcb6SEd Tanous         if (!json_util::readJsonObject(thresholdInfo, res, "Name", name,
3962932dcb6SEd Tanous                                        "Value", value, "DwellTime",
3972932dcb6SEd Tanous                                        dwellTimeStr, "Severity", severity))
398dd1c4a9cSSzymon Dompke         {
399dd1c4a9cSSzymon Dompke             return false;
400dd1c4a9cSSzymon Dompke         }
401dd1c4a9cSSzymon Dompke 
402dd1c4a9cSSzymon Dompke         std::optional<std::chrono::milliseconds> dwellTime =
403dd1c4a9cSSzymon Dompke             time_utils::fromDurationString(dwellTimeStr);
404dd1c4a9cSSzymon Dompke         if (!dwellTime)
405dd1c4a9cSSzymon Dompke         {
406dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
407dd1c4a9cSSzymon Dompke             return false;
408dd1c4a9cSSzymon Dompke         }
409dd1c4a9cSSzymon Dompke 
410dd1c4a9cSSzymon Dompke         std::string dbusSeverity = toDbusSeverity(severity);
411dd1c4a9cSSzymon Dompke         if (dbusSeverity.empty())
412dd1c4a9cSSzymon Dompke         {
413dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "Severity", severity);
414dd1c4a9cSSzymon Dompke             return false;
415dd1c4a9cSSzymon Dompke         }
416dd1c4a9cSSzymon Dompke 
417dd1c4a9cSSzymon Dompke         parsedParams.emplace_back(*name, dbusSeverity,
418dd1c4a9cSSzymon Dompke                                   static_cast<uint64_t>(dwellTime->count()),
419dd1c4a9cSSzymon Dompke                                   value);
420dd1c4a9cSSzymon Dompke     }
421dd1c4a9cSSzymon Dompke 
422dd1c4a9cSSzymon Dompke     ctx.thresholds = std::move(parsedParams);
423dd1c4a9cSSzymon Dompke     return true;
424dd1c4a9cSSzymon Dompke }
425dd1c4a9cSSzymon Dompke 
426dd1c4a9cSSzymon Dompke inline bool parseTriggerThresholds(
427dd1c4a9cSSzymon Dompke     crow::Response& res,
4282932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
4292932dcb6SEd Tanous     NumericThresholds& numericThresholds, Context& ctx)
430dd1c4a9cSSzymon Dompke {
4312932dcb6SEd Tanous     if (discreteTriggers && numericThresholds.any())
432dd1c4a9cSSzymon Dompke     {
433dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "DiscreteTriggers",
434dd1c4a9cSSzymon Dompke                                         "NumericThresholds");
435dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "NumericThresholds",
436dd1c4a9cSSzymon Dompke                                         "DiscreteTriggers");
437dd1c4a9cSSzymon Dompke         return false;
438dd1c4a9cSSzymon Dompke     }
439dd1c4a9cSSzymon Dompke 
440dd1c4a9cSSzymon Dompke     if (ctx.discreteCondition)
441dd1c4a9cSSzymon Dompke     {
4422932dcb6SEd Tanous         if (numericThresholds.any())
443dd1c4a9cSSzymon Dompke         {
444dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggerCondition",
445dd1c4a9cSSzymon Dompke                                             "NumericThresholds");
446dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
447dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
448dd1c4a9cSSzymon Dompke             return false;
449dd1c4a9cSSzymon Dompke         }
450dd1c4a9cSSzymon Dompke     }
451dd1c4a9cSSzymon Dompke 
452dd1c4a9cSSzymon Dompke     if (ctx.metricType)
453dd1c4a9cSSzymon Dompke     {
4542932dcb6SEd Tanous         if (*ctx.metricType == MetricType::Discrete && numericThresholds.any())
455dd1c4a9cSSzymon Dompke         {
456dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
457dd1c4a9cSSzymon Dompke                                             "MetricType");
458dd1c4a9cSSzymon Dompke             return false;
459dd1c4a9cSSzymon Dompke         }
460dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && discreteTriggers)
461dd1c4a9cSSzymon Dompke         {
462dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
463dd1c4a9cSSzymon Dompke                                             "MetricType");
464dd1c4a9cSSzymon Dompke             return false;
465dd1c4a9cSSzymon Dompke         }
466dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && ctx.discreteCondition)
467dd1c4a9cSSzymon Dompke         {
468dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
469dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
470dd1c4a9cSSzymon Dompke             return false;
471dd1c4a9cSSzymon Dompke         }
472dd1c4a9cSSzymon Dompke     }
473dd1c4a9cSSzymon Dompke 
474dd1c4a9cSSzymon Dompke     if (discreteTriggers || ctx.discreteCondition ||
475dd1c4a9cSSzymon Dompke         (ctx.metricType && *ctx.metricType == MetricType::Discrete))
476dd1c4a9cSSzymon Dompke     {
477dd1c4a9cSSzymon Dompke         if (ctx.discreteCondition)
478dd1c4a9cSSzymon Dompke         {
479dd1c4a9cSSzymon Dompke             if (*ctx.discreteCondition == DiscreteCondition::Specified &&
480dd1c4a9cSSzymon Dompke                 !discreteTriggers)
481dd1c4a9cSSzymon Dompke             {
482dd1c4a9cSSzymon Dompke                 messages::createFailedMissingReqProperties(res,
483dd1c4a9cSSzymon Dompke                                                            "DiscreteTriggers");
484dd1c4a9cSSzymon Dompke                 return false;
485dd1c4a9cSSzymon Dompke             }
486dd1c4a9cSSzymon Dompke             if (discreteTriggers &&
487dd1c4a9cSSzymon Dompke                 ((*ctx.discreteCondition == DiscreteCondition::Specified &&
488dd1c4a9cSSzymon Dompke                   discreteTriggers->empty()) ||
489dd1c4a9cSSzymon Dompke                  (*ctx.discreteCondition == DiscreteCondition::Changed &&
490dd1c4a9cSSzymon Dompke                   !discreteTriggers->empty())))
491dd1c4a9cSSzymon Dompke             {
492dd1c4a9cSSzymon Dompke                 messages::propertyValueConflict(res, "DiscreteTriggers",
493dd1c4a9cSSzymon Dompke                                                 "DiscreteTriggerCondition");
494dd1c4a9cSSzymon Dompke                 return false;
495dd1c4a9cSSzymon Dompke             }
496dd1c4a9cSSzymon Dompke         }
497dd1c4a9cSSzymon Dompke         if (!parseDiscreteTriggers(res, discreteTriggers, ctx))
498dd1c4a9cSSzymon Dompke         {
499dd1c4a9cSSzymon Dompke             return false;
500dd1c4a9cSSzymon Dompke         }
501dd1c4a9cSSzymon Dompke     }
5022932dcb6SEd Tanous     else if (numericThresholds.any())
503dd1c4a9cSSzymon Dompke     {
5042932dcb6SEd Tanous         if (!parseNumericThresholds(res, numericThresholds, ctx))
505dd1c4a9cSSzymon Dompke         {
506dd1c4a9cSSzymon Dompke             return false;
507dd1c4a9cSSzymon Dompke         }
508dd1c4a9cSSzymon Dompke     }
509dd1c4a9cSSzymon Dompke     else
510dd1c4a9cSSzymon Dompke     {
511dd1c4a9cSSzymon Dompke         messages::createFailedMissingReqProperties(
512dd1c4a9cSSzymon Dompke             res, "'DiscreteTriggers', 'NumericThresholds', "
513dd1c4a9cSSzymon Dompke                  "'DiscreteTriggerCondition' or 'MetricType'");
514dd1c4a9cSSzymon Dompke         return false;
515dd1c4a9cSSzymon Dompke     }
516dd1c4a9cSSzymon Dompke     return true;
517dd1c4a9cSSzymon Dompke }
518dd1c4a9cSSzymon Dompke 
5192932dcb6SEd Tanous inline bool parseLinks(crow::Response& res,
5202932dcb6SEd Tanous                        const std::vector<std::string>& metricReportDefinitions,
5212932dcb6SEd Tanous                        Context& ctx)
522dd1c4a9cSSzymon Dompke {
5232932dcb6SEd Tanous     ctx.reports.reserve(metricReportDefinitions.size());
5242932dcb6SEd Tanous     for (const std::string& reportDefinionUri : metricReportDefinitions)
525dd1c4a9cSSzymon Dompke     {
526dd1c4a9cSSzymon Dompke         std::optional<sdbusplus::message::object_path> reportPath =
527dd1c4a9cSSzymon Dompke             getReportPathFromReportDefinitionUri(reportDefinionUri);
528dd1c4a9cSSzymon Dompke         if (!reportPath)
529dd1c4a9cSSzymon Dompke         {
530dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricReportDefinitions",
531dd1c4a9cSSzymon Dompke                                              reportDefinionUri);
532dd1c4a9cSSzymon Dompke             return false;
533dd1c4a9cSSzymon Dompke         }
534dd1c4a9cSSzymon Dompke         ctx.reports.emplace_back(*reportPath);
535dd1c4a9cSSzymon Dompke     }
536dd1c4a9cSSzymon Dompke     return true;
537dd1c4a9cSSzymon Dompke }
538dd1c4a9cSSzymon Dompke 
539dd1c4a9cSSzymon Dompke inline bool parseMetricProperties(crow::Response& res, Context& ctx)
540dd1c4a9cSSzymon Dompke {
541dd1c4a9cSSzymon Dompke     if (!ctx.metricProperties)
542dd1c4a9cSSzymon Dompke     {
543dd1c4a9cSSzymon Dompke         return true;
544dd1c4a9cSSzymon Dompke     }
545dd1c4a9cSSzymon Dompke 
546dd1c4a9cSSzymon Dompke     ctx.sensors.reserve(ctx.metricProperties->size());
547dd1c4a9cSSzymon Dompke 
548dd1c4a9cSSzymon Dompke     size_t uriIdx = 0;
549dd1c4a9cSSzymon Dompke     for (const std::string& uriStr : *ctx.metricProperties)
550dd1c4a9cSSzymon Dompke     {
5514a7fbefdSEd Tanous         boost::system::result<boost::urls::url> uri =
552dd1c4a9cSSzymon Dompke             boost::urls::parse_relative_ref(uriStr);
553dd1c4a9cSSzymon Dompke         if (!uri)
554dd1c4a9cSSzymon Dompke         {
555dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
556dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
557dd1c4a9cSSzymon Dompke             return false;
558dd1c4a9cSSzymon Dompke         }
559dd1c4a9cSSzymon Dompke         std::string chassisName;
560dd1c4a9cSSzymon Dompke         std::string sensorName;
561dd1c4a9cSSzymon Dompke         if (!crow::utility::readUrlSegments(*uri, "redfish", "v1", "Chassis",
562dd1c4a9cSSzymon Dompke                                             std::ref(chassisName), "Sensors",
563dd1c4a9cSSzymon Dompke                                             std::ref(sensorName)))
564dd1c4a9cSSzymon Dompke         {
565dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
566dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
567dd1c4a9cSSzymon Dompke             return false;
568dd1c4a9cSSzymon Dompke         }
569dd1c4a9cSSzymon Dompke 
570dd1c4a9cSSzymon Dompke         std::pair<std::string, std::string> split =
571dd1c4a9cSSzymon Dompke             splitSensorNameAndType(sensorName);
572dd1c4a9cSSzymon Dompke         if (split.first.empty() || split.second.empty())
573dd1c4a9cSSzymon Dompke         {
574dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
575dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
576dd1c4a9cSSzymon Dompke             return false;
577dd1c4a9cSSzymon Dompke         }
578dd1c4a9cSSzymon Dompke 
579dd1c4a9cSSzymon Dompke         std::string sensorPath = "/xyz/openbmc_project/sensors/" + split.first +
580dd1c4a9cSSzymon Dompke                                  '/' + split.second;
581dd1c4a9cSSzymon Dompke 
582dd1c4a9cSSzymon Dompke         ctx.sensors.emplace_back(sensorPath, uriStr);
583dd1c4a9cSSzymon Dompke         uriIdx++;
584dd1c4a9cSSzymon Dompke     }
585dd1c4a9cSSzymon Dompke     return true;
586dd1c4a9cSSzymon Dompke }
587dd1c4a9cSSzymon Dompke 
588dd1c4a9cSSzymon Dompke inline bool parsePostTriggerParams(crow::Response& res,
589dd1c4a9cSSzymon Dompke                                    const crow::Request& req, Context& ctx)
590dd1c4a9cSSzymon Dompke {
591dd1c4a9cSSzymon Dompke     std::optional<std::string> id = "";
592dd1c4a9cSSzymon Dompke     std::optional<std::string> name = "";
593dd1c4a9cSSzymon Dompke     std::optional<std::string> metricType;
594dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> triggerActions;
595dd1c4a9cSSzymon Dompke     std::optional<std::string> discreteTriggerCondition;
5962932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>> discreteTriggers;
5972932dcb6SEd Tanous     std::optional<std::vector<std::string>> metricReportDefinitions;
5982932dcb6SEd Tanous     NumericThresholds thresholds;
5992932dcb6SEd Tanous     // clang-format off
600dd1c4a9cSSzymon Dompke     if (!json_util::readJsonPatch(
6012932dcb6SEd Tanous             req, res,
6022932dcb6SEd Tanous 	    "Id", id,
6032932dcb6SEd Tanous             "Name", name,
6042932dcb6SEd Tanous 	    "MetricType", metricType,
6052932dcb6SEd Tanous             "TriggerActions", triggerActions,
6062932dcb6SEd Tanous             "DiscreteTriggerCondition", discreteTriggerCondition,
6072932dcb6SEd Tanous             "DiscreteTriggers", discreteTriggers,
6082932dcb6SEd Tanous             "NumericThresholds/UpperCritical", thresholds.upperCritical,
6092932dcb6SEd Tanous             "NumericThresholds/UpperWarning", thresholds.upperWarning,
6102932dcb6SEd Tanous             "NumericThresholds/LowerWarning", thresholds.lowerWarning,
6112932dcb6SEd Tanous             "NumericThresholds/LowerCritical", thresholds.lowerCritical,
6122932dcb6SEd Tanous             "MetricProperties", ctx.metricProperties,
6132932dcb6SEd Tanous             "Links/MetricReportDefinitions", metricReportDefinitions)
6142932dcb6SEd Tanous     )
615dd1c4a9cSSzymon Dompke     {
616dd1c4a9cSSzymon Dompke         return false;
617dd1c4a9cSSzymon Dompke     }
6182932dcb6SEd Tanous     // clang-format on
619dd1c4a9cSSzymon Dompke 
620dd1c4a9cSSzymon Dompke     ctx.id = *id;
621dd1c4a9cSSzymon Dompke     ctx.name = *name;
622dd1c4a9cSSzymon Dompke 
623dd1c4a9cSSzymon Dompke     if (metricType)
624dd1c4a9cSSzymon Dompke     {
625d5736ef2SEd Tanous         ctx.metricType = getMetricType(*metricType);
626d5736ef2SEd Tanous         if (!ctx.metricType)
627dd1c4a9cSSzymon Dompke         {
628dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricType", *metricType);
629dd1c4a9cSSzymon Dompke             return false;
630dd1c4a9cSSzymon Dompke         }
631dd1c4a9cSSzymon Dompke     }
632dd1c4a9cSSzymon Dompke 
633dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition)
634dd1c4a9cSSzymon Dompke     {
635d5736ef2SEd Tanous         ctx.discreteCondition = getDiscreteCondition(*discreteTriggerCondition);
636d5736ef2SEd Tanous         if (!ctx.discreteCondition)
637dd1c4a9cSSzymon Dompke         {
638dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DiscreteTriggerCondition",
639dd1c4a9cSSzymon Dompke                                              *discreteTriggerCondition);
640dd1c4a9cSSzymon Dompke             return false;
641dd1c4a9cSSzymon Dompke         }
642dd1c4a9cSSzymon Dompke     }
643dd1c4a9cSSzymon Dompke 
644dd1c4a9cSSzymon Dompke     if (triggerActions)
645dd1c4a9cSSzymon Dompke     {
646dd1c4a9cSSzymon Dompke         ctx.actions.reserve(triggerActions->size());
647dd1c4a9cSSzymon Dompke         for (const std::string& action : *triggerActions)
648dd1c4a9cSSzymon Dompke         {
649dd1c4a9cSSzymon Dompke             std::string dbusAction = toDbusTriggerAction(action);
650dd1c4a9cSSzymon Dompke 
651dd1c4a9cSSzymon Dompke             if (dbusAction.empty())
652dd1c4a9cSSzymon Dompke             {
653dd1c4a9cSSzymon Dompke                 messages::propertyValueNotInList(res, action, "TriggerActions");
654dd1c4a9cSSzymon Dompke                 return false;
655dd1c4a9cSSzymon Dompke             }
656dd1c4a9cSSzymon Dompke 
657dd1c4a9cSSzymon Dompke             ctx.actions.emplace_back(dbusAction);
658dd1c4a9cSSzymon Dompke         }
659dd1c4a9cSSzymon Dompke     }
660dd1c4a9cSSzymon Dompke     if (!parseMetricProperties(res, ctx))
661dd1c4a9cSSzymon Dompke     {
662dd1c4a9cSSzymon Dompke         return false;
663dd1c4a9cSSzymon Dompke     }
664dd1c4a9cSSzymon Dompke 
6652932dcb6SEd Tanous     if (!parseTriggerThresholds(res, discreteTriggers, thresholds, ctx))
666dd1c4a9cSSzymon Dompke     {
667dd1c4a9cSSzymon Dompke         return false;
668dd1c4a9cSSzymon Dompke     }
669dd1c4a9cSSzymon Dompke 
6702932dcb6SEd Tanous     if (metricReportDefinitions)
671dd1c4a9cSSzymon Dompke     {
6722932dcb6SEd Tanous         if (!parseLinks(res, *metricReportDefinitions, ctx))
673dd1c4a9cSSzymon Dompke         {
674dd1c4a9cSSzymon Dompke             return false;
675dd1c4a9cSSzymon Dompke         }
676dd1c4a9cSSzymon Dompke     }
677dd1c4a9cSSzymon Dompke     return true;
678dd1c4a9cSSzymon Dompke }
679dd1c4a9cSSzymon Dompke 
680dd1c4a9cSSzymon Dompke inline void afterCreateTrigger(
681dd1c4a9cSSzymon Dompke     const boost::system::error_code& ec, const std::string& dbusPath,
682dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
683dd1c4a9cSSzymon Dompke {
684dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::file_exists)
685dd1c4a9cSSzymon Dompke     {
686dd1c4a9cSSzymon Dompke         messages::resourceAlreadyExists(asyncResp->res, "Trigger", "Id", id);
687dd1c4a9cSSzymon Dompke         return;
688dd1c4a9cSSzymon Dompke     }
689dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::too_many_files_open)
690dd1c4a9cSSzymon Dompke     {
691dd1c4a9cSSzymon Dompke         messages::createLimitReachedForResource(asyncResp->res);
692dd1c4a9cSSzymon Dompke         return;
693dd1c4a9cSSzymon Dompke     }
694dd1c4a9cSSzymon Dompke     if (ec)
695dd1c4a9cSSzymon Dompke     {
696dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
69762598e31SEd Tanous         BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
698dd1c4a9cSSzymon Dompke         return;
699dd1c4a9cSSzymon Dompke     }
700dd1c4a9cSSzymon Dompke 
701dd1c4a9cSSzymon Dompke     const std::optional<std::string>& triggerId =
702dd1c4a9cSSzymon Dompke         getTriggerIdFromDbusPath(dbusPath);
703dd1c4a9cSSzymon Dompke     if (!triggerId)
704dd1c4a9cSSzymon Dompke     {
705dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
70662598e31SEd Tanous         BMCWEB_LOG_ERROR("Unknown data returned by "
70762598e31SEd Tanous                          "AddTrigger DBus method");
708dd1c4a9cSSzymon Dompke         return;
709dd1c4a9cSSzymon Dompke     }
710dd1c4a9cSSzymon Dompke 
711dd1c4a9cSSzymon Dompke     messages::created(asyncResp->res);
712dd1c4a9cSSzymon Dompke     boost::urls::url locationUrl = boost::urls::format(
713dd1c4a9cSSzymon Dompke         "/redfish/v1/TelemetryService/Triggers/{}", *triggerId);
714dd1c4a9cSSzymon Dompke     asyncResp->res.addHeader("Location", locationUrl.buffer());
715dd1c4a9cSSzymon Dompke }
716dd1c4a9cSSzymon Dompke 
717dd1c4a9cSSzymon Dompke inline std::optional<nlohmann::json::array_t>
718dd1c4a9cSSzymon Dompke     getTriggerActions(const std::vector<std::string>& dbusActions)
719dd1c4a9cSSzymon Dompke {
720dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggerActions;
721dd1c4a9cSSzymon Dompke     for (const std::string& dbusAction : dbusActions)
722dd1c4a9cSSzymon Dompke     {
723dd1c4a9cSSzymon Dompke         triggers::TriggerActionEnum redfishAction =
724dd1c4a9cSSzymon Dompke             toRedfishTriggerAction(dbusAction);
725dd1c4a9cSSzymon Dompke 
726dd1c4a9cSSzymon Dompke         if (redfishAction == triggers::TriggerActionEnum::Invalid)
727dd1c4a9cSSzymon Dompke         {
728dd1c4a9cSSzymon Dompke             return std::nullopt;
729dd1c4a9cSSzymon Dompke         }
730dd1c4a9cSSzymon Dompke 
731dd1c4a9cSSzymon Dompke         triggerActions.emplace_back(redfishAction);
732dd1c4a9cSSzymon Dompke     }
733dd1c4a9cSSzymon Dompke 
734dd1c4a9cSSzymon Dompke     return triggerActions;
7351b7e696bSLukasz Kazmierczak }
7361b7e696bSLukasz Kazmierczak 
7373f215c92SSzymon Dompke inline std::optional<nlohmann::json::array_t>
7381b7e696bSLukasz Kazmierczak     getDiscreteTriggers(const TriggerThresholdParamsExt& thresholdParams)
7391b7e696bSLukasz Kazmierczak {
740dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggers;
7411b7e696bSLukasz Kazmierczak     const std::vector<DiscreteThresholdParams>* discreteParams =
7421b7e696bSLukasz Kazmierczak         std::get_if<std::vector<DiscreteThresholdParams>>(&thresholdParams);
7431b7e696bSLukasz Kazmierczak 
744e662eae8SEd Tanous     if (discreteParams == nullptr)
7451b7e696bSLukasz Kazmierczak     {
7461b7e696bSLukasz Kazmierczak         return std::nullopt;
7471b7e696bSLukasz Kazmierczak     }
7481b7e696bSLukasz Kazmierczak 
7491b7e696bSLukasz Kazmierczak     for (const auto& [name, severity, dwellTime, value] : *discreteParams)
7501b7e696bSLukasz Kazmierczak     {
7511b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7521b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7531b7e696bSLukasz Kazmierczak 
7541b7e696bSLukasz Kazmierczak         if (!duration)
7551b7e696bSLukasz Kazmierczak         {
7561b7e696bSLukasz Kazmierczak             return std::nullopt;
7571b7e696bSLukasz Kazmierczak         }
758613dabeaSEd Tanous         nlohmann::json::object_t trigger;
759613dabeaSEd Tanous         trigger["Name"] = name;
760dd1c4a9cSSzymon Dompke         trigger["Severity"] = toRedfishSeverity(severity);
761613dabeaSEd Tanous         trigger["DwellTime"] = *duration;
762613dabeaSEd Tanous         trigger["Value"] = value;
763ad539545SPatrick Williams         triggers.emplace_back(std::move(trigger));
7641b7e696bSLukasz Kazmierczak     }
7651b7e696bSLukasz Kazmierczak 
766dd1c4a9cSSzymon Dompke     return triggers;
7671b7e696bSLukasz Kazmierczak }
7681b7e696bSLukasz Kazmierczak 
7691b7e696bSLukasz Kazmierczak inline std::optional<nlohmann::json>
7701b7e696bSLukasz Kazmierczak     getNumericThresholds(const TriggerThresholdParamsExt& thresholdParams)
7711b7e696bSLukasz Kazmierczak {
772dd1c4a9cSSzymon Dompke     nlohmann::json::object_t thresholds;
7731b7e696bSLukasz Kazmierczak     const std::vector<NumericThresholdParams>* numericParams =
7741b7e696bSLukasz Kazmierczak         std::get_if<std::vector<NumericThresholdParams>>(&thresholdParams);
7751b7e696bSLukasz Kazmierczak 
776e662eae8SEd Tanous     if (numericParams == nullptr)
7771b7e696bSLukasz Kazmierczak     {
7781b7e696bSLukasz Kazmierczak         return std::nullopt;
7791b7e696bSLukasz Kazmierczak     }
7801b7e696bSLukasz Kazmierczak 
7811b7e696bSLukasz Kazmierczak     for (const auto& [type, dwellTime, activation, reading] : *numericParams)
7821b7e696bSLukasz Kazmierczak     {
7831b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7841b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7851b7e696bSLukasz Kazmierczak 
7861b7e696bSLukasz Kazmierczak         if (!duration)
7871b7e696bSLukasz Kazmierczak         {
7881b7e696bSLukasz Kazmierczak             return std::nullopt;
7891b7e696bSLukasz Kazmierczak         }
790dd1c4a9cSSzymon Dompke         nlohmann::json& threshold = thresholds[toRedfishThresholdName(type)];
7911476687dSEd Tanous         threshold["Reading"] = reading;
792dd1c4a9cSSzymon Dompke         threshold["Activation"] = toRedfishActivation(activation);
7931476687dSEd Tanous         threshold["DwellTime"] = *duration;
7941b7e696bSLukasz Kazmierczak     }
7951b7e696bSLukasz Kazmierczak 
796dd1c4a9cSSzymon Dompke     return thresholds;
7971b7e696bSLukasz Kazmierczak }
7981b7e696bSLukasz Kazmierczak 
7993f215c92SSzymon Dompke inline std::optional<nlohmann::json> getMetricReportDefinitions(
8003f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>& reportPaths)
8011b7e696bSLukasz Kazmierczak {
8021b7e696bSLukasz Kazmierczak     nlohmann::json reports = nlohmann::json::array();
8033f215c92SSzymon Dompke 
8043f215c92SSzymon Dompke     for (const sdbusplus::message::object_path& path : reportPaths)
8051b7e696bSLukasz Kazmierczak     {
8063f215c92SSzymon Dompke         std::string reportId = path.filename();
8073f215c92SSzymon Dompke         if (reportId.empty())
8083f215c92SSzymon Dompke         {
8093f215c92SSzymon Dompke             {
81062598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Reports contains invalid value: {}",
81162598e31SEd Tanous                                  path.str);
8123f215c92SSzymon Dompke                 return std::nullopt;
8133f215c92SSzymon Dompke             }
8143f215c92SSzymon Dompke         }
8153f215c92SSzymon Dompke 
8161476687dSEd Tanous         nlohmann::json::object_t report;
817ef4c65b7SEd Tanous         report["@odata.id"] = boost::urls::format(
818ef4c65b7SEd Tanous             "/redfish/v1/TelemetryService/MetricReportDefinitions/{}",
819ef4c65b7SEd Tanous             reportId);
820b2ba3072SPatrick Williams         reports.emplace_back(std::move(report));
8211b7e696bSLukasz Kazmierczak     }
8221b7e696bSLukasz Kazmierczak 
8233f215c92SSzymon Dompke     return {std::move(reports)};
8241b7e696bSLukasz Kazmierczak }
8251b7e696bSLukasz Kazmierczak 
8261b7e696bSLukasz Kazmierczak inline std::vector<std::string>
8271b7e696bSLukasz Kazmierczak     getMetricProperties(const TriggerSensorsParams& sensors)
8281b7e696bSLukasz Kazmierczak {
8291b7e696bSLukasz Kazmierczak     std::vector<std::string> metricProperties;
8301b7e696bSLukasz Kazmierczak     metricProperties.reserve(sensors.size());
8311b7e696bSLukasz Kazmierczak     for (const auto& [_, metadata] : sensors)
8321b7e696bSLukasz Kazmierczak     {
8331b7e696bSLukasz Kazmierczak         metricProperties.emplace_back(metadata);
8341b7e696bSLukasz Kazmierczak     }
8351b7e696bSLukasz Kazmierczak 
8361b7e696bSLukasz Kazmierczak     return metricProperties;
8371b7e696bSLukasz Kazmierczak }
8381b7e696bSLukasz Kazmierczak 
8391b7e696bSLukasz Kazmierczak inline bool fillTrigger(
8401b7e696bSLukasz Kazmierczak     nlohmann::json& json, const std::string& id,
8411b7e696bSLukasz Kazmierczak     const std::vector<std::pair<std::string, TriggerGetParamsVariant>>&
8421b7e696bSLukasz Kazmierczak         properties)
8431b7e696bSLukasz Kazmierczak {
8441b7e696bSLukasz Kazmierczak     const std::string* name = nullptr;
8451b7e696bSLukasz Kazmierczak     const bool* discrete = nullptr;
8461b7e696bSLukasz Kazmierczak     const TriggerSensorsParams* sensors = nullptr;
8473f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>* reports = nullptr;
84889474494SKrzysztof Grobelny     const std::vector<std::string>* triggerActions = nullptr;
8491b7e696bSLukasz Kazmierczak     const TriggerThresholdParamsExt* thresholds = nullptr;
8501b7e696bSLukasz Kazmierczak 
85189474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
85289474494SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "Name", name, "Discrete",
85389474494SKrzysztof Grobelny         discrete, "Sensors", sensors, "Reports", reports, "TriggerActions",
85489474494SKrzysztof Grobelny         triggerActions, "Thresholds", thresholds);
85589474494SKrzysztof Grobelny 
85689474494SKrzysztof Grobelny     if (!success)
8571b7e696bSLukasz Kazmierczak     {
85889474494SKrzysztof Grobelny         return false;
8591b7e696bSLukasz Kazmierczak     }
8601b7e696bSLukasz Kazmierczak 
86189474494SKrzysztof Grobelny     if (triggerActions != nullptr)
86289474494SKrzysztof Grobelny     {
863dd1c4a9cSSzymon Dompke         std::optional<nlohmann::json::array_t> redfishTriggerActions =
86489474494SKrzysztof Grobelny             getTriggerActions(*triggerActions);
86589474494SKrzysztof Grobelny         if (!redfishTriggerActions)
8661b7e696bSLukasz Kazmierczak         {
86762598e31SEd Tanous             BMCWEB_LOG_ERROR(
86862598e31SEd Tanous                 "Property TriggerActions is invalid in Trigger: {}", id);
8691b7e696bSLukasz Kazmierczak             return false;
8701b7e696bSLukasz Kazmierczak         }
871dd1c4a9cSSzymon Dompke         json["TriggerActions"] = *redfishTriggerActions;
87289474494SKrzysztof Grobelny     }
8731b7e696bSLukasz Kazmierczak 
87489474494SKrzysztof Grobelny     if (reports != nullptr)
8753f215c92SSzymon Dompke     {
8763f215c92SSzymon Dompke         std::optional<nlohmann::json> linkedReports =
8773f215c92SSzymon Dompke             getMetricReportDefinitions(*reports);
8783f215c92SSzymon Dompke         if (!linkedReports)
8793f215c92SSzymon Dompke         {
88062598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Reports is invalid in Trigger: {}", id);
8813f215c92SSzymon Dompke             return false;
8823f215c92SSzymon Dompke         }
88389474494SKrzysztof Grobelny         json["Links"]["MetricReportDefinitions"] = *linkedReports;
88489474494SKrzysztof Grobelny     }
8851b7e696bSLukasz Kazmierczak 
88689474494SKrzysztof Grobelny     if (discrete != nullptr)
88789474494SKrzysztof Grobelny     {
8881b7e696bSLukasz Kazmierczak         if (*discrete)
8891b7e696bSLukasz Kazmierczak         {
8903f215c92SSzymon Dompke             std::optional<nlohmann::json::array_t> discreteTriggers =
8911b7e696bSLukasz Kazmierczak                 getDiscreteTriggers(*thresholds);
8921b7e696bSLukasz Kazmierczak 
8931b7e696bSLukasz Kazmierczak             if (!discreteTriggers)
8941b7e696bSLukasz Kazmierczak             {
89562598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Thresholds is invalid for discrete "
89662598e31SEd Tanous                                  "triggers in Trigger: {}",
89762598e31SEd Tanous                                  id);
8981b7e696bSLukasz Kazmierczak                 return false;
8991b7e696bSLukasz Kazmierczak             }
9001b7e696bSLukasz Kazmierczak 
9011b7e696bSLukasz Kazmierczak             json["DiscreteTriggers"] = *discreteTriggers;
9021b7e696bSLukasz Kazmierczak             json["DiscreteTriggerCondition"] =
9031b7e696bSLukasz Kazmierczak                 discreteTriggers->empty() ? "Changed" : "Specified";
904*539d8c6bSEd Tanous             json["MetricType"] = metric_definition::MetricType::Discrete;
9051b7e696bSLukasz Kazmierczak         }
9061b7e696bSLukasz Kazmierczak         else
9071b7e696bSLukasz Kazmierczak         {
9081b7e696bSLukasz Kazmierczak             std::optional<nlohmann::json> numericThresholds =
9091b7e696bSLukasz Kazmierczak                 getNumericThresholds(*thresholds);
9101b7e696bSLukasz Kazmierczak 
9111b7e696bSLukasz Kazmierczak             if (!numericThresholds)
9121b7e696bSLukasz Kazmierczak             {
91362598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Thresholds is invalid for numeric "
91462598e31SEd Tanous                                  "thresholds in Trigger: {}",
91562598e31SEd Tanous                                  id);
9161b7e696bSLukasz Kazmierczak                 return false;
9171b7e696bSLukasz Kazmierczak             }
9181b7e696bSLukasz Kazmierczak 
9191b7e696bSLukasz Kazmierczak             json["NumericThresholds"] = *numericThresholds;
920*539d8c6bSEd Tanous             json["MetricType"] = metric_definition::MetricType::Numeric;
9211b7e696bSLukasz Kazmierczak         }
92289474494SKrzysztof Grobelny     }
92389474494SKrzysztof Grobelny 
92489474494SKrzysztof Grobelny     if (name != nullptr)
92589474494SKrzysztof Grobelny     {
92689474494SKrzysztof Grobelny         json["Name"] = *name;
92789474494SKrzysztof Grobelny     }
92889474494SKrzysztof Grobelny 
92989474494SKrzysztof Grobelny     if (sensors != nullptr)
93089474494SKrzysztof Grobelny     {
93189474494SKrzysztof Grobelny         json["MetricProperties"] = getMetricProperties(*sensors);
93289474494SKrzysztof Grobelny     }
9331b7e696bSLukasz Kazmierczak 
9343f215c92SSzymon Dompke     json["@odata.type"] = "#Triggers.v1_2_0.Triggers";
935ef4c65b7SEd Tanous     json["@odata.id"] =
936ef4c65b7SEd Tanous         boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
9373f215c92SSzymon Dompke     json["Id"] = id;
9381b7e696bSLukasz Kazmierczak 
9391b7e696bSLukasz Kazmierczak     return true;
9401b7e696bSLukasz Kazmierczak }
9411b7e696bSLukasz Kazmierczak 
942dd1c4a9cSSzymon Dompke inline void handleTriggerCollectionPost(
943dd1c4a9cSSzymon Dompke     App& app, const crow::Request& req,
944dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
945dd1c4a9cSSzymon Dompke {
946dd1c4a9cSSzymon Dompke     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
947dd1c4a9cSSzymon Dompke     {
948dd1c4a9cSSzymon Dompke         return;
949dd1c4a9cSSzymon Dompke     }
950dd1c4a9cSSzymon Dompke 
951dd1c4a9cSSzymon Dompke     telemetry::Context ctx;
952dd1c4a9cSSzymon Dompke     if (!telemetry::parsePostTriggerParams(asyncResp->res, req, ctx))
953dd1c4a9cSSzymon Dompke     {
954dd1c4a9cSSzymon Dompke         return;
955dd1c4a9cSSzymon Dompke     }
956dd1c4a9cSSzymon Dompke 
957dd1c4a9cSSzymon Dompke     crow::connections::systemBus->async_method_call(
958dd1c4a9cSSzymon Dompke         [asyncResp, id = ctx.id](const boost::system::error_code& ec,
959dd1c4a9cSSzymon Dompke                                  const std::string& dbusPath) {
960dd1c4a9cSSzymon Dompke         afterCreateTrigger(ec, dbusPath, asyncResp, id);
961dd1c4a9cSSzymon Dompke     },
962dd1c4a9cSSzymon Dompke         service, "/xyz/openbmc_project/Telemetry/Triggers",
963dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.TriggerManager", "AddTrigger",
964dd1c4a9cSSzymon Dompke         "TelemetryService/" + ctx.id, ctx.name, ctx.actions, ctx.sensors,
965dd1c4a9cSSzymon Dompke         ctx.reports, ctx.thresholds);
966dd1c4a9cSSzymon Dompke }
967dd1c4a9cSSzymon Dompke 
96807148cf2SLukasz Kazmierczak } // namespace telemetry
96907148cf2SLukasz Kazmierczak 
97007148cf2SLukasz Kazmierczak inline void requestRoutesTriggerCollection(App& app)
97107148cf2SLukasz Kazmierczak {
97207148cf2SLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
97307148cf2SLukasz Kazmierczak         .privileges(redfish::privileges::getTriggersCollection)
97407148cf2SLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
97545ca1b86SEd Tanous             [&app](const crow::Request& req,
97607148cf2SLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9773ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
97845ca1b86SEd Tanous         {
97945ca1b86SEd Tanous             return;
98045ca1b86SEd Tanous         }
98107148cf2SLukasz Kazmierczak         asyncResp->res.jsonValue["@odata.type"] =
98207148cf2SLukasz Kazmierczak             "#TriggersCollection.TriggersCollection";
983ae9031f0SWilly Tu         asyncResp->res.jsonValue["@odata.id"] =
984ae9031f0SWilly Tu             "/redfish/v1/TelemetryService/Triggers";
98507148cf2SLukasz Kazmierczak         asyncResp->res.jsonValue["Name"] = "Triggers Collection";
9867a1dbc48SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces{
9877a1dbc48SGeorge Liu             telemetry::triggerInterface};
98807148cf2SLukasz Kazmierczak         collection_util::getCollectionMembers(
989ae9031f0SWilly Tu             asyncResp,
990ae9031f0SWilly Tu             boost::urls::url("/redfish/v1/TelemetryService/Triggers"),
991ae9031f0SWilly Tu             interfaces,
99207148cf2SLukasz Kazmierczak             "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
99307148cf2SLukasz Kazmierczak     });
994dd1c4a9cSSzymon Dompke 
995dd1c4a9cSSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
996dd1c4a9cSSzymon Dompke         .privileges(redfish::privileges::postTriggersCollection)
997dd1c4a9cSSzymon Dompke         .methods(boost::beast::http::verb::post)(std::bind_front(
998dd1c4a9cSSzymon Dompke             telemetry::handleTriggerCollectionPost, std::ref(app)));
99907148cf2SLukasz Kazmierczak }
100007148cf2SLukasz Kazmierczak 
10011b7e696bSLukasz Kazmierczak inline void requestRoutesTrigger(App& app)
10021b7e696bSLukasz Kazmierczak {
10031b7e696bSLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
10041b7e696bSLukasz Kazmierczak         .privileges(redfish::privileges::getTriggers)
10051b7e696bSLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
100645ca1b86SEd Tanous             [&app](const crow::Request& req,
10071b7e696bSLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10081b7e696bSLukasz Kazmierczak                    const std::string& id) {
10093ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
101045ca1b86SEd Tanous         {
101145ca1b86SEd Tanous             return;
101245ca1b86SEd Tanous         }
101389474494SKrzysztof Grobelny         sdbusplus::asio::getAllProperties(
101489474494SKrzysztof Grobelny             *crow::connections::systemBus, telemetry::service,
101589474494SKrzysztof Grobelny             telemetry::getDbusTriggerPath(id), telemetry::triggerInterface,
10161b7e696bSLukasz Kazmierczak             [asyncResp,
10175e7e2dc5SEd Tanous              id](const boost::system::error_code& ec,
10181b7e696bSLukasz Kazmierczak                  const std::vector<std::pair<
1019002d39b4SEd Tanous                      std::string, telemetry::TriggerGetParamsVariant>>& ret) {
10201b7e696bSLukasz Kazmierczak             if (ec.value() == EBADR ||
10211b7e696bSLukasz Kazmierczak                 ec == boost::system::errc::host_unreachable)
10221b7e696bSLukasz Kazmierczak             {
1023002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "Triggers", id);
10241b7e696bSLukasz Kazmierczak                 return;
10251b7e696bSLukasz Kazmierczak             }
10261b7e696bSLukasz Kazmierczak             if (ec)
10271b7e696bSLukasz Kazmierczak             {
102862598e31SEd Tanous                 BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
10291b7e696bSLukasz Kazmierczak                 messages::internalError(asyncResp->res);
10301b7e696bSLukasz Kazmierczak                 return;
10311b7e696bSLukasz Kazmierczak             }
10321b7e696bSLukasz Kazmierczak 
1033002d39b4SEd Tanous             if (!telemetry::fillTrigger(asyncResp->res.jsonValue, id, ret))
10341b7e696bSLukasz Kazmierczak             {
10351b7e696bSLukasz Kazmierczak                 messages::internalError(asyncResp->res);
10361b7e696bSLukasz Kazmierczak             }
103789474494SKrzysztof Grobelny         });
10381b7e696bSLukasz Kazmierczak     });
1039163994a8SSzymon Dompke 
1040163994a8SSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
1041163994a8SSzymon Dompke         .privileges(redfish::privileges::deleteTriggers)
1042163994a8SSzymon Dompke         .methods(boost::beast::http::verb::delete_)(
104345ca1b86SEd Tanous             [&app](const crow::Request& req,
1044163994a8SSzymon Dompke                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1045163994a8SSzymon Dompke                    const std::string& id) {
10463ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
104745ca1b86SEd Tanous         {
104845ca1b86SEd Tanous             return;
104945ca1b86SEd Tanous         }
1050002d39b4SEd Tanous         const std::string triggerPath = telemetry::getDbusTriggerPath(id);
1051163994a8SSzymon Dompke 
1052163994a8SSzymon Dompke         crow::connections::systemBus->async_method_call(
10535e7e2dc5SEd Tanous             [asyncResp, id](const boost::system::error_code& ec) {
1054163994a8SSzymon Dompke             if (ec.value() == EBADR)
1055163994a8SSzymon Dompke             {
1056002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "Triggers", id);
1057163994a8SSzymon Dompke                 return;
1058163994a8SSzymon Dompke             }
1059163994a8SSzymon Dompke 
1060163994a8SSzymon Dompke             if (ec)
1061163994a8SSzymon Dompke             {
106262598e31SEd Tanous                 BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
1063163994a8SSzymon Dompke                 messages::internalError(asyncResp->res);
1064163994a8SSzymon Dompke                 return;
1065163994a8SSzymon Dompke             }
1066163994a8SSzymon Dompke 
1067002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
1068163994a8SSzymon Dompke         },
1069163994a8SSzymon Dompke             telemetry::service, triggerPath,
1070163994a8SSzymon Dompke             "xyz.openbmc_project.Object.Delete", "Delete");
1071163994a8SSzymon Dompke     });
10721b7e696bSLukasz Kazmierczak }
10731b7e696bSLukasz Kazmierczak 
107407148cf2SLukasz Kazmierczak } // namespace redfish
1075