xref: /openbmc/bmcweb/features/redfish/lib/trigger.hpp (revision 4a7fbefdff330f06d5698a1e60ce893225cd389e)
107148cf2SLukasz Kazmierczak #pragma once
207148cf2SLukasz Kazmierczak 
33ccb3adbSEd Tanous #include "app.hpp"
4dd1c4a9cSSzymon Dompke #include "generated/enums/resource.hpp"
5dd1c4a9cSSzymon Dompke #include "generated/enums/triggers.hpp"
63ccb3adbSEd Tanous #include "query.hpp"
73ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
8dd1c4a9cSSzymon Dompke #include "sensors.hpp"
9dd1c4a9cSSzymon Dompke #include "utility.hpp"
1007148cf2SLukasz Kazmierczak #include "utils/collection.hpp"
113ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
1207148cf2SLukasz Kazmierczak #include "utils/telemetry_utils.hpp"
133ccb3adbSEd Tanous #include "utils/time_utils.hpp"
1407148cf2SLukasz Kazmierczak 
15ef4c65b7SEd Tanous #include <boost/url/format.hpp>
1689474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
1789474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
1807148cf2SLukasz Kazmierczak 
197a1dbc48SGeorge Liu #include <array>
207a1dbc48SGeorge Liu #include <string_view>
211b7e696bSLukasz Kazmierczak #include <tuple>
221b7e696bSLukasz Kazmierczak #include <variant>
231b7e696bSLukasz Kazmierczak #include <vector>
241b7e696bSLukasz Kazmierczak 
2507148cf2SLukasz Kazmierczak namespace redfish
2607148cf2SLukasz Kazmierczak {
2707148cf2SLukasz Kazmierczak namespace telemetry
2807148cf2SLukasz Kazmierczak {
2907148cf2SLukasz Kazmierczak constexpr const char* triggerInterface =
3007148cf2SLukasz Kazmierczak     "xyz.openbmc_project.Telemetry.Trigger";
3107148cf2SLukasz Kazmierczak 
321b7e696bSLukasz Kazmierczak using NumericThresholdParams =
331b7e696bSLukasz Kazmierczak     std::tuple<std::string, uint64_t, std::string, double>;
341b7e696bSLukasz Kazmierczak 
351b7e696bSLukasz Kazmierczak using DiscreteThresholdParams =
361b7e696bSLukasz Kazmierczak     std::tuple<std::string, std::string, uint64_t, std::string>;
371b7e696bSLukasz Kazmierczak 
38dd1c4a9cSSzymon Dompke using TriggerThresholdParams =
39dd1c4a9cSSzymon Dompke     std::variant<std::vector<NumericThresholdParams>,
40dd1c4a9cSSzymon Dompke                  std::vector<DiscreteThresholdParams>>;
41dd1c4a9cSSzymon Dompke 
421b7e696bSLukasz Kazmierczak using TriggerThresholdParamsExt =
431b7e696bSLukasz Kazmierczak     std::variant<std::monostate, std::vector<NumericThresholdParams>,
441b7e696bSLukasz Kazmierczak                  std::vector<DiscreteThresholdParams>>;
451b7e696bSLukasz Kazmierczak 
461b7e696bSLukasz Kazmierczak using TriggerSensorsParams =
471b7e696bSLukasz Kazmierczak     std::vector<std::pair<sdbusplus::message::object_path, std::string>>;
481b7e696bSLukasz Kazmierczak 
491b7e696bSLukasz Kazmierczak using TriggerGetParamsVariant =
501b7e696bSLukasz Kazmierczak     std::variant<std::monostate, bool, std::string, TriggerThresholdParamsExt,
513f215c92SSzymon Dompke                  TriggerSensorsParams, std::vector<std::string>,
523f215c92SSzymon Dompke                  std::vector<sdbusplus::message::object_path>>;
531b7e696bSLukasz Kazmierczak 
54dd1c4a9cSSzymon Dompke inline triggers::TriggerActionEnum
55dd1c4a9cSSzymon Dompke     toRedfishTriggerAction(std::string_view dbusValue)
561b7e696bSLukasz Kazmierczak {
57dd1c4a9cSSzymon Dompke     if (dbusValue ==
58dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport")
591b7e696bSLukasz Kazmierczak     {
60dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishMetricReport;
611b7e696bSLukasz Kazmierczak     }
62dd1c4a9cSSzymon Dompke     if (dbusValue ==
63dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog")
641b7e696bSLukasz Kazmierczak     {
65dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishEvent;
661b7e696bSLukasz Kazmierczak     }
67dd1c4a9cSSzymon Dompke     if (dbusValue ==
68dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal")
691b7e696bSLukasz Kazmierczak     {
70dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::LogToLogService;
711b7e696bSLukasz Kazmierczak     }
72dd1c4a9cSSzymon Dompke     return triggers::TriggerActionEnum::Invalid;
731b7e696bSLukasz Kazmierczak }
741b7e696bSLukasz Kazmierczak 
75dd1c4a9cSSzymon Dompke inline std::string toDbusTriggerAction(std::string_view redfishValue)
761b7e696bSLukasz Kazmierczak {
77dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishMetricReport")
781b7e696bSLukasz Kazmierczak     {
79dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport";
80dd1c4a9cSSzymon Dompke     }
81dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishEvent")
82dd1c4a9cSSzymon Dompke     {
83dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog";
84dd1c4a9cSSzymon Dompke     }
85dd1c4a9cSSzymon Dompke     if (redfishValue == "LogToLogService")
86dd1c4a9cSSzymon Dompke     {
87dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal";
88dd1c4a9cSSzymon Dompke     }
89dd1c4a9cSSzymon Dompke     return "";
90dd1c4a9cSSzymon Dompke }
911b7e696bSLukasz Kazmierczak 
92dd1c4a9cSSzymon Dompke inline std::string toDbusSeverity(std::string_view redfishValue)
93dd1c4a9cSSzymon Dompke {
94dd1c4a9cSSzymon Dompke     if (redfishValue == "OK")
95dd1c4a9cSSzymon Dompke     {
96dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.OK";
97dd1c4a9cSSzymon Dompke     }
98dd1c4a9cSSzymon Dompke     if (redfishValue == "Warning")
99dd1c4a9cSSzymon Dompke     {
100dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning";
101dd1c4a9cSSzymon Dompke     }
102dd1c4a9cSSzymon Dompke     if (redfishValue == "Critical")
103dd1c4a9cSSzymon Dompke     {
104dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical";
105dd1c4a9cSSzymon Dompke     }
106dd1c4a9cSSzymon Dompke     return "";
107dd1c4a9cSSzymon Dompke }
108dd1c4a9cSSzymon Dompke 
109dd1c4a9cSSzymon Dompke inline resource::Health toRedfishSeverity(std::string_view dbusValue)
110dd1c4a9cSSzymon Dompke {
111dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.OK")
112dd1c4a9cSSzymon Dompke     {
113dd1c4a9cSSzymon Dompke         return resource::Health::OK;
114dd1c4a9cSSzymon Dompke     }
115dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning")
116dd1c4a9cSSzymon Dompke     {
117dd1c4a9cSSzymon Dompke         return resource::Health::Warning;
118dd1c4a9cSSzymon Dompke     }
119dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical")
120dd1c4a9cSSzymon Dompke     {
121dd1c4a9cSSzymon Dompke         return resource::Health::Critical;
122dd1c4a9cSSzymon Dompke     }
123dd1c4a9cSSzymon Dompke     return resource::Health::Invalid;
124dd1c4a9cSSzymon Dompke }
125dd1c4a9cSSzymon Dompke 
126dd1c4a9cSSzymon Dompke inline std::string toRedfishThresholdName(std::string_view dbusValue)
127dd1c4a9cSSzymon Dompke {
128dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical")
129dd1c4a9cSSzymon Dompke     {
130dd1c4a9cSSzymon Dompke         return "UpperCritical";
131dd1c4a9cSSzymon Dompke     }
132dd1c4a9cSSzymon Dompke 
133dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical")
134dd1c4a9cSSzymon Dompke     {
135dd1c4a9cSSzymon Dompke         return "LowerCritical";
136dd1c4a9cSSzymon Dompke     }
137dd1c4a9cSSzymon Dompke 
138dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning")
139dd1c4a9cSSzymon Dompke     {
140dd1c4a9cSSzymon Dompke         return "UpperWarning";
141dd1c4a9cSSzymon Dompke     }
142dd1c4a9cSSzymon Dompke 
143dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning")
144dd1c4a9cSSzymon Dompke     {
145dd1c4a9cSSzymon Dompke         return "LowerWarning";
146dd1c4a9cSSzymon Dompke     }
147dd1c4a9cSSzymon Dompke 
148dd1c4a9cSSzymon Dompke     return "";
149dd1c4a9cSSzymon Dompke }
150dd1c4a9cSSzymon Dompke 
151dd1c4a9cSSzymon Dompke inline std::string toDbusActivation(std::string_view redfishValue)
152dd1c4a9cSSzymon Dompke {
153dd1c4a9cSSzymon Dompke     if (redfishValue == "Either")
154dd1c4a9cSSzymon Dompke     {
155dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Either";
156dd1c4a9cSSzymon Dompke     }
157dd1c4a9cSSzymon Dompke 
158dd1c4a9cSSzymon Dompke     if (redfishValue == "Decreasing")
159dd1c4a9cSSzymon Dompke     {
160dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing";
161dd1c4a9cSSzymon Dompke     }
162dd1c4a9cSSzymon Dompke 
163dd1c4a9cSSzymon Dompke     if (redfishValue == "Increasing")
164dd1c4a9cSSzymon Dompke     {
165dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing";
166dd1c4a9cSSzymon Dompke     }
167dd1c4a9cSSzymon Dompke 
168dd1c4a9cSSzymon Dompke     return "";
169dd1c4a9cSSzymon Dompke }
170dd1c4a9cSSzymon Dompke 
171dd1c4a9cSSzymon Dompke inline triggers::ThresholdActivation
172dd1c4a9cSSzymon Dompke     toRedfishActivation(std::string_view dbusValue)
173dd1c4a9cSSzymon Dompke {
174dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Direction.Either")
175dd1c4a9cSSzymon Dompke     {
176dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Either;
177dd1c4a9cSSzymon Dompke     }
178dd1c4a9cSSzymon Dompke 
179dd1c4a9cSSzymon Dompke     if (dbusValue ==
180dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing")
181dd1c4a9cSSzymon Dompke     {
182dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Decreasing;
183dd1c4a9cSSzymon Dompke     }
184dd1c4a9cSSzymon Dompke 
185dd1c4a9cSSzymon Dompke     if (dbusValue ==
186dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing")
187dd1c4a9cSSzymon Dompke     {
188dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Increasing;
189dd1c4a9cSSzymon Dompke     }
190dd1c4a9cSSzymon Dompke 
191dd1c4a9cSSzymon Dompke     return triggers::ThresholdActivation::Invalid;
192dd1c4a9cSSzymon Dompke }
193dd1c4a9cSSzymon Dompke 
194dd1c4a9cSSzymon Dompke enum class MetricType
195dd1c4a9cSSzymon Dompke {
196dd1c4a9cSSzymon Dompke     Discrete,
197dd1c4a9cSSzymon Dompke     Numeric
198dd1c4a9cSSzymon Dompke };
199dd1c4a9cSSzymon Dompke 
200dd1c4a9cSSzymon Dompke enum class DiscreteCondition
201dd1c4a9cSSzymon Dompke {
202dd1c4a9cSSzymon Dompke     Specified,
203dd1c4a9cSSzymon Dompke     Changed
204dd1c4a9cSSzymon Dompke };
205dd1c4a9cSSzymon Dompke 
206dd1c4a9cSSzymon Dompke struct Context
207dd1c4a9cSSzymon Dompke {
208dd1c4a9cSSzymon Dompke     std::string id;
209dd1c4a9cSSzymon Dompke     std::string name;
210dd1c4a9cSSzymon Dompke     std::vector<std::string> actions;
211dd1c4a9cSSzymon Dompke     std::vector<std::pair<sdbusplus::message::object_path, std::string>>
212dd1c4a9cSSzymon Dompke         sensors;
213dd1c4a9cSSzymon Dompke     std::vector<sdbusplus::message::object_path> reports;
214dd1c4a9cSSzymon Dompke     TriggerThresholdParams thresholds;
215dd1c4a9cSSzymon Dompke 
216dd1c4a9cSSzymon Dompke     std::optional<DiscreteCondition> discreteCondition;
217dd1c4a9cSSzymon Dompke     std::optional<MetricType> metricType;
218dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> metricProperties;
219dd1c4a9cSSzymon Dompke };
220dd1c4a9cSSzymon Dompke 
221dd1c4a9cSSzymon Dompke inline std::optional<sdbusplus::message::object_path>
222dd1c4a9cSSzymon Dompke     getReportPathFromReportDefinitionUri(const std::string& uri)
223dd1c4a9cSSzymon Dompke {
2246fd29553SEd Tanous     boost::system::result<boost::urls::url_view> parsed =
225dd1c4a9cSSzymon Dompke         boost::urls::parse_relative_ref(uri);
226dd1c4a9cSSzymon Dompke 
227dd1c4a9cSSzymon Dompke     if (!parsed)
2281b7e696bSLukasz Kazmierczak     {
2291b7e696bSLukasz Kazmierczak         return std::nullopt;
2301b7e696bSLukasz Kazmierczak     }
2311b7e696bSLukasz Kazmierczak 
232dd1c4a9cSSzymon Dompke     std::string id;
233dd1c4a9cSSzymon Dompke     if (!crow::utility::readUrlSegments(
234dd1c4a9cSSzymon Dompke             *parsed, "redfish", "v1", "TelemetryService",
235dd1c4a9cSSzymon Dompke             "MetricReportDefinitions", std::ref(id)))
236dd1c4a9cSSzymon Dompke     {
237dd1c4a9cSSzymon Dompke         return std::nullopt;
2381b7e696bSLukasz Kazmierczak     }
2391b7e696bSLukasz Kazmierczak 
240dd1c4a9cSSzymon Dompke     return sdbusplus::message::object_path(
241dd1c4a9cSSzymon Dompke                "/xyz/openbmc_project/Telemetry/Reports") /
242dd1c4a9cSSzymon Dompke            "TelemetryService" / id;
243dd1c4a9cSSzymon Dompke }
244dd1c4a9cSSzymon Dompke 
245dd1c4a9cSSzymon Dompke inline std::optional<MetricType> getMetricType(const std::string& metricType)
246dd1c4a9cSSzymon Dompke {
247dd1c4a9cSSzymon Dompke     if (metricType == "Discrete")
248dd1c4a9cSSzymon Dompke     {
249dd1c4a9cSSzymon Dompke         return MetricType::Discrete;
250dd1c4a9cSSzymon Dompke     }
251dd1c4a9cSSzymon Dompke     if (metricType == "Numeric")
252dd1c4a9cSSzymon Dompke     {
253dd1c4a9cSSzymon Dompke         return MetricType::Numeric;
254dd1c4a9cSSzymon Dompke     }
255dd1c4a9cSSzymon Dompke     return std::nullopt;
256dd1c4a9cSSzymon Dompke }
257dd1c4a9cSSzymon Dompke 
258dd1c4a9cSSzymon Dompke inline std::optional<DiscreteCondition>
259dd1c4a9cSSzymon Dompke     getDiscreteCondition(const std::string& discreteTriggerCondition)
260dd1c4a9cSSzymon Dompke {
261dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Specified")
262dd1c4a9cSSzymon Dompke     {
263dd1c4a9cSSzymon Dompke         return DiscreteCondition::Specified;
264dd1c4a9cSSzymon Dompke     }
265dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Changed")
266dd1c4a9cSSzymon Dompke     {
267dd1c4a9cSSzymon Dompke         return DiscreteCondition::Changed;
268dd1c4a9cSSzymon Dompke     }
269dd1c4a9cSSzymon Dompke     return std::nullopt;
270dd1c4a9cSSzymon Dompke }
271dd1c4a9cSSzymon Dompke 
2722932dcb6SEd Tanous inline bool parseThreshold(crow::Response& res,
2732932dcb6SEd Tanous                            nlohmann::json::object_t& threshold,
2742932dcb6SEd Tanous                            std::string_view dbusThresholdName,
2752932dcb6SEd Tanous                            std::vector<NumericThresholdParams>& parsedParams)
276dd1c4a9cSSzymon Dompke {
277dd1c4a9cSSzymon Dompke     double reading = 0.0;
278dd1c4a9cSSzymon Dompke     std::string activation;
279dd1c4a9cSSzymon Dompke     std::string dwellTimeStr;
280dd1c4a9cSSzymon Dompke 
2812932dcb6SEd Tanous     if (!json_util::readJsonObject(threshold, res, "Reading", reading,
282dd1c4a9cSSzymon Dompke                                    "Activation", activation, "DwellTime",
283dd1c4a9cSSzymon Dompke                                    dwellTimeStr))
284dd1c4a9cSSzymon Dompke     {
285dd1c4a9cSSzymon Dompke         return false;
286dd1c4a9cSSzymon Dompke     }
287dd1c4a9cSSzymon Dompke 
288dd1c4a9cSSzymon Dompke     std::string dbusActivation = toDbusActivation(activation);
289dd1c4a9cSSzymon Dompke 
290dd1c4a9cSSzymon Dompke     if (dbusActivation.empty())
291dd1c4a9cSSzymon Dompke     {
292dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "Activation", activation);
293dd1c4a9cSSzymon Dompke         return false;
294dd1c4a9cSSzymon Dompke     }
295dd1c4a9cSSzymon Dompke 
296dd1c4a9cSSzymon Dompke     std::optional<std::chrono::milliseconds> dwellTime =
297dd1c4a9cSSzymon Dompke         time_utils::fromDurationString(dwellTimeStr);
298dd1c4a9cSSzymon Dompke     if (!dwellTime)
299dd1c4a9cSSzymon Dompke     {
300dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
301dd1c4a9cSSzymon Dompke         return false;
302dd1c4a9cSSzymon Dompke     }
303dd1c4a9cSSzymon Dompke 
304dd1c4a9cSSzymon Dompke     parsedParams.emplace_back(dbusThresholdName,
305dd1c4a9cSSzymon Dompke                               static_cast<uint64_t>(dwellTime->count()),
306dd1c4a9cSSzymon Dompke                               dbusActivation, reading);
3072932dcb6SEd Tanous     return true;
3082932dcb6SEd Tanous }
3092932dcb6SEd Tanous 
3102932dcb6SEd Tanous struct NumericThresholds
3112932dcb6SEd Tanous {
3122932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperCritical;
3132932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperWarning;
3142932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerWarning;
3152932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerCritical;
3162932dcb6SEd Tanous 
3172932dcb6SEd Tanous     bool any() const
3182932dcb6SEd Tanous     {
3192932dcb6SEd Tanous         return upperCritical || upperWarning || lowerWarning || lowerCritical;
3202932dcb6SEd Tanous     }
3212932dcb6SEd Tanous };
3222932dcb6SEd Tanous 
3232932dcb6SEd Tanous inline bool parseNumericThresholds(crow::Response& res,
3242932dcb6SEd Tanous                                    NumericThresholds& numericThresholds,
3252932dcb6SEd Tanous                                    Context& ctx)
3262932dcb6SEd Tanous {
3272932dcb6SEd Tanous     std::vector<NumericThresholdParams> parsedParams;
3282932dcb6SEd Tanous     if (numericThresholds.upperCritical)
3292932dcb6SEd Tanous     {
3302932dcb6SEd Tanous         if (!parseThreshold(
3312932dcb6SEd Tanous                 res, *numericThresholds.upperCritical,
3322932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical",
3332932dcb6SEd Tanous                 parsedParams))
3342932dcb6SEd Tanous         {
3352932dcb6SEd Tanous             return false;
3362932dcb6SEd Tanous         }
3372932dcb6SEd Tanous     }
3382932dcb6SEd Tanous     if (numericThresholds.upperWarning)
3392932dcb6SEd Tanous     {
3402932dcb6SEd Tanous         if (!parseThreshold(
3412932dcb6SEd Tanous                 res, *numericThresholds.upperWarning,
3422932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning",
3432932dcb6SEd Tanous                 parsedParams))
3442932dcb6SEd Tanous         {
3452932dcb6SEd Tanous             return false;
3462932dcb6SEd Tanous         }
3472932dcb6SEd Tanous     }
3482932dcb6SEd Tanous     if (numericThresholds.lowerWarning)
3492932dcb6SEd Tanous     {
3502932dcb6SEd Tanous         if (!parseThreshold(
3512932dcb6SEd Tanous                 res, *numericThresholds.lowerWarning,
3522932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning",
3532932dcb6SEd Tanous                 parsedParams))
3542932dcb6SEd Tanous         {
3552932dcb6SEd Tanous             return false;
3562932dcb6SEd Tanous         }
3572932dcb6SEd Tanous     }
3582932dcb6SEd Tanous     if (numericThresholds.lowerCritical)
3592932dcb6SEd Tanous     {
3602932dcb6SEd Tanous         if (!parseThreshold(
3612932dcb6SEd Tanous                 res, *numericThresholds.lowerCritical,
3622932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical",
3632932dcb6SEd Tanous                 parsedParams))
3642932dcb6SEd Tanous         {
3652932dcb6SEd Tanous             return false;
3662932dcb6SEd Tanous         }
367dd1c4a9cSSzymon Dompke     }
368dd1c4a9cSSzymon Dompke 
369dd1c4a9cSSzymon Dompke     ctx.thresholds = std::move(parsedParams);
370dd1c4a9cSSzymon Dompke     return true;
371dd1c4a9cSSzymon Dompke }
372dd1c4a9cSSzymon Dompke 
373dd1c4a9cSSzymon Dompke inline bool parseDiscreteTriggers(
374dd1c4a9cSSzymon Dompke     crow::Response& res,
3752932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
3762932dcb6SEd Tanous     Context& ctx)
377dd1c4a9cSSzymon Dompke {
378dd1c4a9cSSzymon Dompke     std::vector<DiscreteThresholdParams> parsedParams;
379dd1c4a9cSSzymon Dompke     if (!discreteTriggers)
380dd1c4a9cSSzymon Dompke     {
381dd1c4a9cSSzymon Dompke         ctx.thresholds = std::move(parsedParams);
382dd1c4a9cSSzymon Dompke         return true;
383dd1c4a9cSSzymon Dompke     }
384dd1c4a9cSSzymon Dompke 
385dd1c4a9cSSzymon Dompke     parsedParams.reserve(discreteTriggers->size());
3862932dcb6SEd Tanous     for (nlohmann::json::object_t& thresholdInfo : *discreteTriggers)
387dd1c4a9cSSzymon Dompke     {
388dd1c4a9cSSzymon Dompke         std::optional<std::string> name = "";
389dd1c4a9cSSzymon Dompke         std::string value;
390dd1c4a9cSSzymon Dompke         std::string dwellTimeStr;
391dd1c4a9cSSzymon Dompke         std::string severity;
392dd1c4a9cSSzymon Dompke 
3932932dcb6SEd Tanous         if (!json_util::readJsonObject(thresholdInfo, res, "Name", name,
3942932dcb6SEd Tanous                                        "Value", value, "DwellTime",
3952932dcb6SEd Tanous                                        dwellTimeStr, "Severity", severity))
396dd1c4a9cSSzymon Dompke         {
397dd1c4a9cSSzymon Dompke             return false;
398dd1c4a9cSSzymon Dompke         }
399dd1c4a9cSSzymon Dompke 
400dd1c4a9cSSzymon Dompke         std::optional<std::chrono::milliseconds> dwellTime =
401dd1c4a9cSSzymon Dompke             time_utils::fromDurationString(dwellTimeStr);
402dd1c4a9cSSzymon Dompke         if (!dwellTime)
403dd1c4a9cSSzymon Dompke         {
404dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
405dd1c4a9cSSzymon Dompke             return false;
406dd1c4a9cSSzymon Dompke         }
407dd1c4a9cSSzymon Dompke 
408dd1c4a9cSSzymon Dompke         std::string dbusSeverity = toDbusSeverity(severity);
409dd1c4a9cSSzymon Dompke         if (dbusSeverity.empty())
410dd1c4a9cSSzymon Dompke         {
411dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "Severity", severity);
412dd1c4a9cSSzymon Dompke             return false;
413dd1c4a9cSSzymon Dompke         }
414dd1c4a9cSSzymon Dompke 
415dd1c4a9cSSzymon Dompke         parsedParams.emplace_back(*name, dbusSeverity,
416dd1c4a9cSSzymon Dompke                                   static_cast<uint64_t>(dwellTime->count()),
417dd1c4a9cSSzymon Dompke                                   value);
418dd1c4a9cSSzymon Dompke     }
419dd1c4a9cSSzymon Dompke 
420dd1c4a9cSSzymon Dompke     ctx.thresholds = std::move(parsedParams);
421dd1c4a9cSSzymon Dompke     return true;
422dd1c4a9cSSzymon Dompke }
423dd1c4a9cSSzymon Dompke 
424dd1c4a9cSSzymon Dompke inline bool parseTriggerThresholds(
425dd1c4a9cSSzymon Dompke     crow::Response& res,
4262932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
4272932dcb6SEd Tanous     NumericThresholds& numericThresholds, Context& ctx)
428dd1c4a9cSSzymon Dompke {
4292932dcb6SEd Tanous     if (discreteTriggers && numericThresholds.any())
430dd1c4a9cSSzymon Dompke     {
431dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "DiscreteTriggers",
432dd1c4a9cSSzymon Dompke                                         "NumericThresholds");
433dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "NumericThresholds",
434dd1c4a9cSSzymon Dompke                                         "DiscreteTriggers");
435dd1c4a9cSSzymon Dompke         return false;
436dd1c4a9cSSzymon Dompke     }
437dd1c4a9cSSzymon Dompke 
438dd1c4a9cSSzymon Dompke     if (ctx.discreteCondition)
439dd1c4a9cSSzymon Dompke     {
4402932dcb6SEd Tanous         if (numericThresholds.any())
441dd1c4a9cSSzymon Dompke         {
442dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggerCondition",
443dd1c4a9cSSzymon Dompke                                             "NumericThresholds");
444dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
445dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
446dd1c4a9cSSzymon Dompke             return false;
447dd1c4a9cSSzymon Dompke         }
448dd1c4a9cSSzymon Dompke     }
449dd1c4a9cSSzymon Dompke 
450dd1c4a9cSSzymon Dompke     if (ctx.metricType)
451dd1c4a9cSSzymon Dompke     {
4522932dcb6SEd Tanous         if (*ctx.metricType == MetricType::Discrete && numericThresholds.any())
453dd1c4a9cSSzymon Dompke         {
454dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
455dd1c4a9cSSzymon Dompke                                             "MetricType");
456dd1c4a9cSSzymon Dompke             return false;
457dd1c4a9cSSzymon Dompke         }
458dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && discreteTriggers)
459dd1c4a9cSSzymon Dompke         {
460dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
461dd1c4a9cSSzymon Dompke                                             "MetricType");
462dd1c4a9cSSzymon Dompke             return false;
463dd1c4a9cSSzymon Dompke         }
464dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && ctx.discreteCondition)
465dd1c4a9cSSzymon Dompke         {
466dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
467dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
468dd1c4a9cSSzymon Dompke             return false;
469dd1c4a9cSSzymon Dompke         }
470dd1c4a9cSSzymon Dompke     }
471dd1c4a9cSSzymon Dompke 
472dd1c4a9cSSzymon Dompke     if (discreteTriggers || ctx.discreteCondition ||
473dd1c4a9cSSzymon Dompke         (ctx.metricType && *ctx.metricType == MetricType::Discrete))
474dd1c4a9cSSzymon Dompke     {
475dd1c4a9cSSzymon Dompke         if (ctx.discreteCondition)
476dd1c4a9cSSzymon Dompke         {
477dd1c4a9cSSzymon Dompke             if (*ctx.discreteCondition == DiscreteCondition::Specified &&
478dd1c4a9cSSzymon Dompke                 !discreteTriggers)
479dd1c4a9cSSzymon Dompke             {
480dd1c4a9cSSzymon Dompke                 messages::createFailedMissingReqProperties(res,
481dd1c4a9cSSzymon Dompke                                                            "DiscreteTriggers");
482dd1c4a9cSSzymon Dompke                 return false;
483dd1c4a9cSSzymon Dompke             }
484dd1c4a9cSSzymon Dompke             if (discreteTriggers &&
485dd1c4a9cSSzymon Dompke                 ((*ctx.discreteCondition == DiscreteCondition::Specified &&
486dd1c4a9cSSzymon Dompke                   discreteTriggers->empty()) ||
487dd1c4a9cSSzymon Dompke                  (*ctx.discreteCondition == DiscreteCondition::Changed &&
488dd1c4a9cSSzymon Dompke                   !discreteTriggers->empty())))
489dd1c4a9cSSzymon Dompke             {
490dd1c4a9cSSzymon Dompke                 messages::propertyValueConflict(res, "DiscreteTriggers",
491dd1c4a9cSSzymon Dompke                                                 "DiscreteTriggerCondition");
492dd1c4a9cSSzymon Dompke                 return false;
493dd1c4a9cSSzymon Dompke             }
494dd1c4a9cSSzymon Dompke         }
495dd1c4a9cSSzymon Dompke         if (!parseDiscreteTriggers(res, discreteTriggers, ctx))
496dd1c4a9cSSzymon Dompke         {
497dd1c4a9cSSzymon Dompke             return false;
498dd1c4a9cSSzymon Dompke         }
499dd1c4a9cSSzymon Dompke     }
5002932dcb6SEd Tanous     else if (numericThresholds.any())
501dd1c4a9cSSzymon Dompke     {
5022932dcb6SEd Tanous         if (!parseNumericThresholds(res, numericThresholds, ctx))
503dd1c4a9cSSzymon Dompke         {
504dd1c4a9cSSzymon Dompke             return false;
505dd1c4a9cSSzymon Dompke         }
506dd1c4a9cSSzymon Dompke     }
507dd1c4a9cSSzymon Dompke     else
508dd1c4a9cSSzymon Dompke     {
509dd1c4a9cSSzymon Dompke         messages::createFailedMissingReqProperties(
510dd1c4a9cSSzymon Dompke             res, "'DiscreteTriggers', 'NumericThresholds', "
511dd1c4a9cSSzymon Dompke                  "'DiscreteTriggerCondition' or 'MetricType'");
512dd1c4a9cSSzymon Dompke         return false;
513dd1c4a9cSSzymon Dompke     }
514dd1c4a9cSSzymon Dompke     return true;
515dd1c4a9cSSzymon Dompke }
516dd1c4a9cSSzymon Dompke 
5172932dcb6SEd Tanous inline bool parseLinks(crow::Response& res,
5182932dcb6SEd Tanous                        const std::vector<std::string>& metricReportDefinitions,
5192932dcb6SEd Tanous                        Context& ctx)
520dd1c4a9cSSzymon Dompke {
5212932dcb6SEd Tanous     ctx.reports.reserve(metricReportDefinitions.size());
5222932dcb6SEd Tanous     for (const std::string& reportDefinionUri : metricReportDefinitions)
523dd1c4a9cSSzymon Dompke     {
524dd1c4a9cSSzymon Dompke         std::optional<sdbusplus::message::object_path> reportPath =
525dd1c4a9cSSzymon Dompke             getReportPathFromReportDefinitionUri(reportDefinionUri);
526dd1c4a9cSSzymon Dompke         if (!reportPath)
527dd1c4a9cSSzymon Dompke         {
528dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricReportDefinitions",
529dd1c4a9cSSzymon Dompke                                              reportDefinionUri);
530dd1c4a9cSSzymon Dompke             return false;
531dd1c4a9cSSzymon Dompke         }
532dd1c4a9cSSzymon Dompke         ctx.reports.emplace_back(*reportPath);
533dd1c4a9cSSzymon Dompke     }
534dd1c4a9cSSzymon Dompke     return true;
535dd1c4a9cSSzymon Dompke }
536dd1c4a9cSSzymon Dompke 
537dd1c4a9cSSzymon Dompke inline bool parseMetricProperties(crow::Response& res, Context& ctx)
538dd1c4a9cSSzymon Dompke {
539dd1c4a9cSSzymon Dompke     if (!ctx.metricProperties)
540dd1c4a9cSSzymon Dompke     {
541dd1c4a9cSSzymon Dompke         return true;
542dd1c4a9cSSzymon Dompke     }
543dd1c4a9cSSzymon Dompke 
544dd1c4a9cSSzymon Dompke     ctx.sensors.reserve(ctx.metricProperties->size());
545dd1c4a9cSSzymon Dompke 
546dd1c4a9cSSzymon Dompke     size_t uriIdx = 0;
547dd1c4a9cSSzymon Dompke     for (const std::string& uriStr : *ctx.metricProperties)
548dd1c4a9cSSzymon Dompke     {
549*4a7fbefdSEd Tanous         boost::system::result<boost::urls::url> uri =
550dd1c4a9cSSzymon Dompke             boost::urls::parse_relative_ref(uriStr);
551dd1c4a9cSSzymon Dompke         if (!uri)
552dd1c4a9cSSzymon Dompke         {
553dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
554dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
555dd1c4a9cSSzymon Dompke             return false;
556dd1c4a9cSSzymon Dompke         }
557dd1c4a9cSSzymon Dompke         std::string chassisName;
558dd1c4a9cSSzymon Dompke         std::string sensorName;
559dd1c4a9cSSzymon Dompke         if (!crow::utility::readUrlSegments(*uri, "redfish", "v1", "Chassis",
560dd1c4a9cSSzymon Dompke                                             std::ref(chassisName), "Sensors",
561dd1c4a9cSSzymon Dompke                                             std::ref(sensorName)))
562dd1c4a9cSSzymon Dompke         {
563dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
564dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
565dd1c4a9cSSzymon Dompke             return false;
566dd1c4a9cSSzymon Dompke         }
567dd1c4a9cSSzymon Dompke 
568dd1c4a9cSSzymon Dompke         std::pair<std::string, std::string> split =
569dd1c4a9cSSzymon Dompke             splitSensorNameAndType(sensorName);
570dd1c4a9cSSzymon Dompke         if (split.first.empty() || split.second.empty())
571dd1c4a9cSSzymon Dompke         {
572dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
573dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
574dd1c4a9cSSzymon Dompke             return false;
575dd1c4a9cSSzymon Dompke         }
576dd1c4a9cSSzymon Dompke 
577dd1c4a9cSSzymon Dompke         std::string sensorPath = "/xyz/openbmc_project/sensors/" + split.first +
578dd1c4a9cSSzymon Dompke                                  '/' + split.second;
579dd1c4a9cSSzymon Dompke 
580dd1c4a9cSSzymon Dompke         ctx.sensors.emplace_back(sensorPath, uriStr);
581dd1c4a9cSSzymon Dompke         uriIdx++;
582dd1c4a9cSSzymon Dompke     }
583dd1c4a9cSSzymon Dompke     return true;
584dd1c4a9cSSzymon Dompke }
585dd1c4a9cSSzymon Dompke 
586dd1c4a9cSSzymon Dompke inline bool parsePostTriggerParams(crow::Response& res,
587dd1c4a9cSSzymon Dompke                                    const crow::Request& req, Context& ctx)
588dd1c4a9cSSzymon Dompke {
589dd1c4a9cSSzymon Dompke     std::optional<std::string> id = "";
590dd1c4a9cSSzymon Dompke     std::optional<std::string> name = "";
591dd1c4a9cSSzymon Dompke     std::optional<std::string> metricType;
592dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> triggerActions;
593dd1c4a9cSSzymon Dompke     std::optional<std::string> discreteTriggerCondition;
5942932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>> discreteTriggers;
5952932dcb6SEd Tanous     std::optional<std::vector<std::string>> metricReportDefinitions;
5962932dcb6SEd Tanous     NumericThresholds thresholds;
5972932dcb6SEd Tanous     // clang-format off
598dd1c4a9cSSzymon Dompke     if (!json_util::readJsonPatch(
5992932dcb6SEd Tanous             req, res,
6002932dcb6SEd Tanous 	    "Id", id,
6012932dcb6SEd Tanous             "Name", name,
6022932dcb6SEd Tanous 	    "MetricType", metricType,
6032932dcb6SEd Tanous             "TriggerActions", triggerActions,
6042932dcb6SEd Tanous             "DiscreteTriggerCondition", discreteTriggerCondition,
6052932dcb6SEd Tanous             "DiscreteTriggers", discreteTriggers,
6062932dcb6SEd Tanous             "NumericThresholds/UpperCritical", thresholds.upperCritical,
6072932dcb6SEd Tanous             "NumericThresholds/UpperWarning", thresholds.upperWarning,
6082932dcb6SEd Tanous             "NumericThresholds/LowerWarning", thresholds.lowerWarning,
6092932dcb6SEd Tanous             "NumericThresholds/LowerCritical", thresholds.lowerCritical,
6102932dcb6SEd Tanous             "MetricProperties", ctx.metricProperties,
6112932dcb6SEd Tanous             "Links/MetricReportDefinitions", metricReportDefinitions)
6122932dcb6SEd Tanous     )
613dd1c4a9cSSzymon Dompke     {
614dd1c4a9cSSzymon Dompke         return false;
615dd1c4a9cSSzymon Dompke     }
6162932dcb6SEd Tanous     // clang-format on
617dd1c4a9cSSzymon Dompke 
618dd1c4a9cSSzymon Dompke     ctx.id = *id;
619dd1c4a9cSSzymon Dompke     ctx.name = *name;
620dd1c4a9cSSzymon Dompke 
621dd1c4a9cSSzymon Dompke     if (metricType)
622dd1c4a9cSSzymon Dompke     {
623d5736ef2SEd Tanous         ctx.metricType = getMetricType(*metricType);
624d5736ef2SEd Tanous         if (!ctx.metricType)
625dd1c4a9cSSzymon Dompke         {
626dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricType", *metricType);
627dd1c4a9cSSzymon Dompke             return false;
628dd1c4a9cSSzymon Dompke         }
629dd1c4a9cSSzymon Dompke     }
630dd1c4a9cSSzymon Dompke 
631dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition)
632dd1c4a9cSSzymon Dompke     {
633d5736ef2SEd Tanous         ctx.discreteCondition = getDiscreteCondition(*discreteTriggerCondition);
634d5736ef2SEd Tanous         if (!ctx.discreteCondition)
635dd1c4a9cSSzymon Dompke         {
636dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DiscreteTriggerCondition",
637dd1c4a9cSSzymon Dompke                                              *discreteTriggerCondition);
638dd1c4a9cSSzymon Dompke             return false;
639dd1c4a9cSSzymon Dompke         }
640dd1c4a9cSSzymon Dompke     }
641dd1c4a9cSSzymon Dompke 
642dd1c4a9cSSzymon Dompke     if (triggerActions)
643dd1c4a9cSSzymon Dompke     {
644dd1c4a9cSSzymon Dompke         ctx.actions.reserve(triggerActions->size());
645dd1c4a9cSSzymon Dompke         for (const std::string& action : *triggerActions)
646dd1c4a9cSSzymon Dompke         {
647dd1c4a9cSSzymon Dompke             std::string dbusAction = toDbusTriggerAction(action);
648dd1c4a9cSSzymon Dompke 
649dd1c4a9cSSzymon Dompke             if (dbusAction.empty())
650dd1c4a9cSSzymon Dompke             {
651dd1c4a9cSSzymon Dompke                 messages::propertyValueNotInList(res, action, "TriggerActions");
652dd1c4a9cSSzymon Dompke                 return false;
653dd1c4a9cSSzymon Dompke             }
654dd1c4a9cSSzymon Dompke 
655dd1c4a9cSSzymon Dompke             ctx.actions.emplace_back(dbusAction);
656dd1c4a9cSSzymon Dompke         }
657dd1c4a9cSSzymon Dompke     }
658dd1c4a9cSSzymon Dompke     if (!parseMetricProperties(res, ctx))
659dd1c4a9cSSzymon Dompke     {
660dd1c4a9cSSzymon Dompke         return false;
661dd1c4a9cSSzymon Dompke     }
662dd1c4a9cSSzymon Dompke 
6632932dcb6SEd Tanous     if (!parseTriggerThresholds(res, discreteTriggers, thresholds, ctx))
664dd1c4a9cSSzymon Dompke     {
665dd1c4a9cSSzymon Dompke         return false;
666dd1c4a9cSSzymon Dompke     }
667dd1c4a9cSSzymon Dompke 
6682932dcb6SEd Tanous     if (metricReportDefinitions)
669dd1c4a9cSSzymon Dompke     {
6702932dcb6SEd Tanous         if (!parseLinks(res, *metricReportDefinitions, ctx))
671dd1c4a9cSSzymon Dompke         {
672dd1c4a9cSSzymon Dompke             return false;
673dd1c4a9cSSzymon Dompke         }
674dd1c4a9cSSzymon Dompke     }
675dd1c4a9cSSzymon Dompke     return true;
676dd1c4a9cSSzymon Dompke }
677dd1c4a9cSSzymon Dompke 
678dd1c4a9cSSzymon Dompke inline void afterCreateTrigger(
679dd1c4a9cSSzymon Dompke     const boost::system::error_code& ec, const std::string& dbusPath,
680dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
681dd1c4a9cSSzymon Dompke {
682dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::file_exists)
683dd1c4a9cSSzymon Dompke     {
684dd1c4a9cSSzymon Dompke         messages::resourceAlreadyExists(asyncResp->res, "Trigger", "Id", id);
685dd1c4a9cSSzymon Dompke         return;
686dd1c4a9cSSzymon Dompke     }
687dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::too_many_files_open)
688dd1c4a9cSSzymon Dompke     {
689dd1c4a9cSSzymon Dompke         messages::createLimitReachedForResource(asyncResp->res);
690dd1c4a9cSSzymon Dompke         return;
691dd1c4a9cSSzymon Dompke     }
692dd1c4a9cSSzymon Dompke     if (ec)
693dd1c4a9cSSzymon Dompke     {
694dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
69562598e31SEd Tanous         BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
696dd1c4a9cSSzymon Dompke         return;
697dd1c4a9cSSzymon Dompke     }
698dd1c4a9cSSzymon Dompke 
699dd1c4a9cSSzymon Dompke     const std::optional<std::string>& triggerId =
700dd1c4a9cSSzymon Dompke         getTriggerIdFromDbusPath(dbusPath);
701dd1c4a9cSSzymon Dompke     if (!triggerId)
702dd1c4a9cSSzymon Dompke     {
703dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
70462598e31SEd Tanous         BMCWEB_LOG_ERROR("Unknown data returned by "
70562598e31SEd Tanous                          "AddTrigger DBus method");
706dd1c4a9cSSzymon Dompke         return;
707dd1c4a9cSSzymon Dompke     }
708dd1c4a9cSSzymon Dompke 
709dd1c4a9cSSzymon Dompke     messages::created(asyncResp->res);
710dd1c4a9cSSzymon Dompke     boost::urls::url locationUrl = boost::urls::format(
711dd1c4a9cSSzymon Dompke         "/redfish/v1/TelemetryService/Triggers/{}", *triggerId);
712dd1c4a9cSSzymon Dompke     asyncResp->res.addHeader("Location", locationUrl.buffer());
713dd1c4a9cSSzymon Dompke }
714dd1c4a9cSSzymon Dompke 
715dd1c4a9cSSzymon Dompke inline std::optional<nlohmann::json::array_t>
716dd1c4a9cSSzymon Dompke     getTriggerActions(const std::vector<std::string>& dbusActions)
717dd1c4a9cSSzymon Dompke {
718dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggerActions;
719dd1c4a9cSSzymon Dompke     for (const std::string& dbusAction : dbusActions)
720dd1c4a9cSSzymon Dompke     {
721dd1c4a9cSSzymon Dompke         triggers::TriggerActionEnum redfishAction =
722dd1c4a9cSSzymon Dompke             toRedfishTriggerAction(dbusAction);
723dd1c4a9cSSzymon Dompke 
724dd1c4a9cSSzymon Dompke         if (redfishAction == triggers::TriggerActionEnum::Invalid)
725dd1c4a9cSSzymon Dompke         {
726dd1c4a9cSSzymon Dompke             return std::nullopt;
727dd1c4a9cSSzymon Dompke         }
728dd1c4a9cSSzymon Dompke 
729dd1c4a9cSSzymon Dompke         triggerActions.emplace_back(redfishAction);
730dd1c4a9cSSzymon Dompke     }
731dd1c4a9cSSzymon Dompke 
732dd1c4a9cSSzymon Dompke     return triggerActions;
7331b7e696bSLukasz Kazmierczak }
7341b7e696bSLukasz Kazmierczak 
7353f215c92SSzymon Dompke inline std::optional<nlohmann::json::array_t>
7361b7e696bSLukasz Kazmierczak     getDiscreteTriggers(const TriggerThresholdParamsExt& thresholdParams)
7371b7e696bSLukasz Kazmierczak {
738dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggers;
7391b7e696bSLukasz Kazmierczak     const std::vector<DiscreteThresholdParams>* discreteParams =
7401b7e696bSLukasz Kazmierczak         std::get_if<std::vector<DiscreteThresholdParams>>(&thresholdParams);
7411b7e696bSLukasz Kazmierczak 
742e662eae8SEd Tanous     if (discreteParams == nullptr)
7431b7e696bSLukasz Kazmierczak     {
7441b7e696bSLukasz Kazmierczak         return std::nullopt;
7451b7e696bSLukasz Kazmierczak     }
7461b7e696bSLukasz Kazmierczak 
7471b7e696bSLukasz Kazmierczak     for (const auto& [name, severity, dwellTime, value] : *discreteParams)
7481b7e696bSLukasz Kazmierczak     {
7491b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7501b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7511b7e696bSLukasz Kazmierczak 
7521b7e696bSLukasz Kazmierczak         if (!duration)
7531b7e696bSLukasz Kazmierczak         {
7541b7e696bSLukasz Kazmierczak             return std::nullopt;
7551b7e696bSLukasz Kazmierczak         }
756613dabeaSEd Tanous         nlohmann::json::object_t trigger;
757613dabeaSEd Tanous         trigger["Name"] = name;
758dd1c4a9cSSzymon Dompke         trigger["Severity"] = toRedfishSeverity(severity);
759613dabeaSEd Tanous         trigger["DwellTime"] = *duration;
760613dabeaSEd Tanous         trigger["Value"] = value;
761ad539545SPatrick Williams         triggers.emplace_back(std::move(trigger));
7621b7e696bSLukasz Kazmierczak     }
7631b7e696bSLukasz Kazmierczak 
764dd1c4a9cSSzymon Dompke     return triggers;
7651b7e696bSLukasz Kazmierczak }
7661b7e696bSLukasz Kazmierczak 
7671b7e696bSLukasz Kazmierczak inline std::optional<nlohmann::json>
7681b7e696bSLukasz Kazmierczak     getNumericThresholds(const TriggerThresholdParamsExt& thresholdParams)
7691b7e696bSLukasz Kazmierczak {
770dd1c4a9cSSzymon Dompke     nlohmann::json::object_t thresholds;
7711b7e696bSLukasz Kazmierczak     const std::vector<NumericThresholdParams>* numericParams =
7721b7e696bSLukasz Kazmierczak         std::get_if<std::vector<NumericThresholdParams>>(&thresholdParams);
7731b7e696bSLukasz Kazmierczak 
774e662eae8SEd Tanous     if (numericParams == nullptr)
7751b7e696bSLukasz Kazmierczak     {
7761b7e696bSLukasz Kazmierczak         return std::nullopt;
7771b7e696bSLukasz Kazmierczak     }
7781b7e696bSLukasz Kazmierczak 
7791b7e696bSLukasz Kazmierczak     for (const auto& [type, dwellTime, activation, reading] : *numericParams)
7801b7e696bSLukasz Kazmierczak     {
7811b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7821b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7831b7e696bSLukasz Kazmierczak 
7841b7e696bSLukasz Kazmierczak         if (!duration)
7851b7e696bSLukasz Kazmierczak         {
7861b7e696bSLukasz Kazmierczak             return std::nullopt;
7871b7e696bSLukasz Kazmierczak         }
788dd1c4a9cSSzymon Dompke         nlohmann::json& threshold = thresholds[toRedfishThresholdName(type)];
7891476687dSEd Tanous         threshold["Reading"] = reading;
790dd1c4a9cSSzymon Dompke         threshold["Activation"] = toRedfishActivation(activation);
7911476687dSEd Tanous         threshold["DwellTime"] = *duration;
7921b7e696bSLukasz Kazmierczak     }
7931b7e696bSLukasz Kazmierczak 
794dd1c4a9cSSzymon Dompke     return thresholds;
7951b7e696bSLukasz Kazmierczak }
7961b7e696bSLukasz Kazmierczak 
7973f215c92SSzymon Dompke inline std::optional<nlohmann::json> getMetricReportDefinitions(
7983f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>& reportPaths)
7991b7e696bSLukasz Kazmierczak {
8001b7e696bSLukasz Kazmierczak     nlohmann::json reports = nlohmann::json::array();
8013f215c92SSzymon Dompke 
8023f215c92SSzymon Dompke     for (const sdbusplus::message::object_path& path : reportPaths)
8031b7e696bSLukasz Kazmierczak     {
8043f215c92SSzymon Dompke         std::string reportId = path.filename();
8053f215c92SSzymon Dompke         if (reportId.empty())
8063f215c92SSzymon Dompke         {
8073f215c92SSzymon Dompke             {
80862598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Reports contains invalid value: {}",
80962598e31SEd Tanous                                  path.str);
8103f215c92SSzymon Dompke                 return std::nullopt;
8113f215c92SSzymon Dompke             }
8123f215c92SSzymon Dompke         }
8133f215c92SSzymon Dompke 
8141476687dSEd Tanous         nlohmann::json::object_t report;
815ef4c65b7SEd Tanous         report["@odata.id"] = boost::urls::format(
816ef4c65b7SEd Tanous             "/redfish/v1/TelemetryService/MetricReportDefinitions/{}",
817ef4c65b7SEd Tanous             reportId);
818b2ba3072SPatrick Williams         reports.emplace_back(std::move(report));
8191b7e696bSLukasz Kazmierczak     }
8201b7e696bSLukasz Kazmierczak 
8213f215c92SSzymon Dompke     return {std::move(reports)};
8221b7e696bSLukasz Kazmierczak }
8231b7e696bSLukasz Kazmierczak 
8241b7e696bSLukasz Kazmierczak inline std::vector<std::string>
8251b7e696bSLukasz Kazmierczak     getMetricProperties(const TriggerSensorsParams& sensors)
8261b7e696bSLukasz Kazmierczak {
8271b7e696bSLukasz Kazmierczak     std::vector<std::string> metricProperties;
8281b7e696bSLukasz Kazmierczak     metricProperties.reserve(sensors.size());
8291b7e696bSLukasz Kazmierczak     for (const auto& [_, metadata] : sensors)
8301b7e696bSLukasz Kazmierczak     {
8311b7e696bSLukasz Kazmierczak         metricProperties.emplace_back(metadata);
8321b7e696bSLukasz Kazmierczak     }
8331b7e696bSLukasz Kazmierczak 
8341b7e696bSLukasz Kazmierczak     return metricProperties;
8351b7e696bSLukasz Kazmierczak }
8361b7e696bSLukasz Kazmierczak 
8371b7e696bSLukasz Kazmierczak inline bool fillTrigger(
8381b7e696bSLukasz Kazmierczak     nlohmann::json& json, const std::string& id,
8391b7e696bSLukasz Kazmierczak     const std::vector<std::pair<std::string, TriggerGetParamsVariant>>&
8401b7e696bSLukasz Kazmierczak         properties)
8411b7e696bSLukasz Kazmierczak {
8421b7e696bSLukasz Kazmierczak     const std::string* name = nullptr;
8431b7e696bSLukasz Kazmierczak     const bool* discrete = nullptr;
8441b7e696bSLukasz Kazmierczak     const TriggerSensorsParams* sensors = nullptr;
8453f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>* reports = nullptr;
84689474494SKrzysztof Grobelny     const std::vector<std::string>* triggerActions = nullptr;
8471b7e696bSLukasz Kazmierczak     const TriggerThresholdParamsExt* thresholds = nullptr;
8481b7e696bSLukasz Kazmierczak 
84989474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
85089474494SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "Name", name, "Discrete",
85189474494SKrzysztof Grobelny         discrete, "Sensors", sensors, "Reports", reports, "TriggerActions",
85289474494SKrzysztof Grobelny         triggerActions, "Thresholds", thresholds);
85389474494SKrzysztof Grobelny 
85489474494SKrzysztof Grobelny     if (!success)
8551b7e696bSLukasz Kazmierczak     {
85689474494SKrzysztof Grobelny         return false;
8571b7e696bSLukasz Kazmierczak     }
8581b7e696bSLukasz Kazmierczak 
85989474494SKrzysztof Grobelny     if (triggerActions != nullptr)
86089474494SKrzysztof Grobelny     {
861dd1c4a9cSSzymon Dompke         std::optional<nlohmann::json::array_t> redfishTriggerActions =
86289474494SKrzysztof Grobelny             getTriggerActions(*triggerActions);
86389474494SKrzysztof Grobelny         if (!redfishTriggerActions)
8641b7e696bSLukasz Kazmierczak         {
86562598e31SEd Tanous             BMCWEB_LOG_ERROR(
86662598e31SEd Tanous                 "Property TriggerActions is invalid in Trigger: {}", id);
8671b7e696bSLukasz Kazmierczak             return false;
8681b7e696bSLukasz Kazmierczak         }
869dd1c4a9cSSzymon Dompke         json["TriggerActions"] = *redfishTriggerActions;
87089474494SKrzysztof Grobelny     }
8711b7e696bSLukasz Kazmierczak 
87289474494SKrzysztof Grobelny     if (reports != nullptr)
8733f215c92SSzymon Dompke     {
8743f215c92SSzymon Dompke         std::optional<nlohmann::json> linkedReports =
8753f215c92SSzymon Dompke             getMetricReportDefinitions(*reports);
8763f215c92SSzymon Dompke         if (!linkedReports)
8773f215c92SSzymon Dompke         {
87862598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Reports is invalid in Trigger: {}", id);
8793f215c92SSzymon Dompke             return false;
8803f215c92SSzymon Dompke         }
88189474494SKrzysztof Grobelny         json["Links"]["MetricReportDefinitions"] = *linkedReports;
88289474494SKrzysztof Grobelny     }
8831b7e696bSLukasz Kazmierczak 
88489474494SKrzysztof Grobelny     if (discrete != nullptr)
88589474494SKrzysztof Grobelny     {
8861b7e696bSLukasz Kazmierczak         if (*discrete)
8871b7e696bSLukasz Kazmierczak         {
8883f215c92SSzymon Dompke             std::optional<nlohmann::json::array_t> discreteTriggers =
8891b7e696bSLukasz Kazmierczak                 getDiscreteTriggers(*thresholds);
8901b7e696bSLukasz Kazmierczak 
8911b7e696bSLukasz Kazmierczak             if (!discreteTriggers)
8921b7e696bSLukasz Kazmierczak             {
89362598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Thresholds is invalid for discrete "
89462598e31SEd Tanous                                  "triggers in Trigger: {}",
89562598e31SEd Tanous                                  id);
8961b7e696bSLukasz Kazmierczak                 return false;
8971b7e696bSLukasz Kazmierczak             }
8981b7e696bSLukasz Kazmierczak 
8991b7e696bSLukasz Kazmierczak             json["DiscreteTriggers"] = *discreteTriggers;
9001b7e696bSLukasz Kazmierczak             json["DiscreteTriggerCondition"] =
9011b7e696bSLukasz Kazmierczak                 discreteTriggers->empty() ? "Changed" : "Specified";
9021b7e696bSLukasz Kazmierczak             json["MetricType"] = "Discrete";
9031b7e696bSLukasz Kazmierczak         }
9041b7e696bSLukasz Kazmierczak         else
9051b7e696bSLukasz Kazmierczak         {
9061b7e696bSLukasz Kazmierczak             std::optional<nlohmann::json> numericThresholds =
9071b7e696bSLukasz Kazmierczak                 getNumericThresholds(*thresholds);
9081b7e696bSLukasz Kazmierczak 
9091b7e696bSLukasz Kazmierczak             if (!numericThresholds)
9101b7e696bSLukasz Kazmierczak             {
91162598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Thresholds is invalid for numeric "
91262598e31SEd Tanous                                  "thresholds in Trigger: {}",
91362598e31SEd Tanous                                  id);
9141b7e696bSLukasz Kazmierczak                 return false;
9151b7e696bSLukasz Kazmierczak             }
9161b7e696bSLukasz Kazmierczak 
9171b7e696bSLukasz Kazmierczak             json["NumericThresholds"] = *numericThresholds;
9181b7e696bSLukasz Kazmierczak             json["MetricType"] = "Numeric";
9191b7e696bSLukasz Kazmierczak         }
92089474494SKrzysztof Grobelny     }
92189474494SKrzysztof Grobelny 
92289474494SKrzysztof Grobelny     if (name != nullptr)
92389474494SKrzysztof Grobelny     {
92489474494SKrzysztof Grobelny         json["Name"] = *name;
92589474494SKrzysztof Grobelny     }
92689474494SKrzysztof Grobelny 
92789474494SKrzysztof Grobelny     if (sensors != nullptr)
92889474494SKrzysztof Grobelny     {
92989474494SKrzysztof Grobelny         json["MetricProperties"] = getMetricProperties(*sensors);
93089474494SKrzysztof Grobelny     }
9311b7e696bSLukasz Kazmierczak 
9323f215c92SSzymon Dompke     json["@odata.type"] = "#Triggers.v1_2_0.Triggers";
933ef4c65b7SEd Tanous     json["@odata.id"] =
934ef4c65b7SEd Tanous         boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
9353f215c92SSzymon Dompke     json["Id"] = id;
9361b7e696bSLukasz Kazmierczak 
9371b7e696bSLukasz Kazmierczak     return true;
9381b7e696bSLukasz Kazmierczak }
9391b7e696bSLukasz Kazmierczak 
940dd1c4a9cSSzymon Dompke inline void handleTriggerCollectionPost(
941dd1c4a9cSSzymon Dompke     App& app, const crow::Request& req,
942dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
943dd1c4a9cSSzymon Dompke {
944dd1c4a9cSSzymon Dompke     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
945dd1c4a9cSSzymon Dompke     {
946dd1c4a9cSSzymon Dompke         return;
947dd1c4a9cSSzymon Dompke     }
948dd1c4a9cSSzymon Dompke 
949dd1c4a9cSSzymon Dompke     telemetry::Context ctx;
950dd1c4a9cSSzymon Dompke     if (!telemetry::parsePostTriggerParams(asyncResp->res, req, ctx))
951dd1c4a9cSSzymon Dompke     {
952dd1c4a9cSSzymon Dompke         return;
953dd1c4a9cSSzymon Dompke     }
954dd1c4a9cSSzymon Dompke 
955dd1c4a9cSSzymon Dompke     crow::connections::systemBus->async_method_call(
956dd1c4a9cSSzymon Dompke         [asyncResp, id = ctx.id](const boost::system::error_code& ec,
957dd1c4a9cSSzymon Dompke                                  const std::string& dbusPath) {
958dd1c4a9cSSzymon Dompke         afterCreateTrigger(ec, dbusPath, asyncResp, id);
959dd1c4a9cSSzymon Dompke     },
960dd1c4a9cSSzymon Dompke         service, "/xyz/openbmc_project/Telemetry/Triggers",
961dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.TriggerManager", "AddTrigger",
962dd1c4a9cSSzymon Dompke         "TelemetryService/" + ctx.id, ctx.name, ctx.actions, ctx.sensors,
963dd1c4a9cSSzymon Dompke         ctx.reports, ctx.thresholds);
964dd1c4a9cSSzymon Dompke }
965dd1c4a9cSSzymon Dompke 
96607148cf2SLukasz Kazmierczak } // namespace telemetry
96707148cf2SLukasz Kazmierczak 
96807148cf2SLukasz Kazmierczak inline void requestRoutesTriggerCollection(App& app)
96907148cf2SLukasz Kazmierczak {
97007148cf2SLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
97107148cf2SLukasz Kazmierczak         .privileges(redfish::privileges::getTriggersCollection)
97207148cf2SLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
97345ca1b86SEd Tanous             [&app](const crow::Request& req,
97407148cf2SLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9753ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
97645ca1b86SEd Tanous         {
97745ca1b86SEd Tanous             return;
97845ca1b86SEd Tanous         }
97907148cf2SLukasz Kazmierczak         asyncResp->res.jsonValue["@odata.type"] =
98007148cf2SLukasz Kazmierczak             "#TriggersCollection.TriggersCollection";
981ae9031f0SWilly Tu         asyncResp->res.jsonValue["@odata.id"] =
982ae9031f0SWilly Tu             "/redfish/v1/TelemetryService/Triggers";
98307148cf2SLukasz Kazmierczak         asyncResp->res.jsonValue["Name"] = "Triggers Collection";
9847a1dbc48SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces{
9857a1dbc48SGeorge Liu             telemetry::triggerInterface};
98607148cf2SLukasz Kazmierczak         collection_util::getCollectionMembers(
987ae9031f0SWilly Tu             asyncResp,
988ae9031f0SWilly Tu             boost::urls::url("/redfish/v1/TelemetryService/Triggers"),
989ae9031f0SWilly Tu             interfaces,
99007148cf2SLukasz Kazmierczak             "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
99107148cf2SLukasz Kazmierczak     });
992dd1c4a9cSSzymon Dompke 
993dd1c4a9cSSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
994dd1c4a9cSSzymon Dompke         .privileges(redfish::privileges::postTriggersCollection)
995dd1c4a9cSSzymon Dompke         .methods(boost::beast::http::verb::post)(std::bind_front(
996dd1c4a9cSSzymon Dompke             telemetry::handleTriggerCollectionPost, std::ref(app)));
99707148cf2SLukasz Kazmierczak }
99807148cf2SLukasz Kazmierczak 
9991b7e696bSLukasz Kazmierczak inline void requestRoutesTrigger(App& app)
10001b7e696bSLukasz Kazmierczak {
10011b7e696bSLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
10021b7e696bSLukasz Kazmierczak         .privileges(redfish::privileges::getTriggers)
10031b7e696bSLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
100445ca1b86SEd Tanous             [&app](const crow::Request& req,
10051b7e696bSLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10061b7e696bSLukasz Kazmierczak                    const std::string& id) {
10073ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
100845ca1b86SEd Tanous         {
100945ca1b86SEd Tanous             return;
101045ca1b86SEd Tanous         }
101189474494SKrzysztof Grobelny         sdbusplus::asio::getAllProperties(
101289474494SKrzysztof Grobelny             *crow::connections::systemBus, telemetry::service,
101389474494SKrzysztof Grobelny             telemetry::getDbusTriggerPath(id), telemetry::triggerInterface,
10141b7e696bSLukasz Kazmierczak             [asyncResp,
10155e7e2dc5SEd Tanous              id](const boost::system::error_code& ec,
10161b7e696bSLukasz Kazmierczak                  const std::vector<std::pair<
1017002d39b4SEd Tanous                      std::string, telemetry::TriggerGetParamsVariant>>& ret) {
10181b7e696bSLukasz Kazmierczak             if (ec.value() == EBADR ||
10191b7e696bSLukasz Kazmierczak                 ec == boost::system::errc::host_unreachable)
10201b7e696bSLukasz Kazmierczak             {
1021002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "Triggers", id);
10221b7e696bSLukasz Kazmierczak                 return;
10231b7e696bSLukasz Kazmierczak             }
10241b7e696bSLukasz Kazmierczak             if (ec)
10251b7e696bSLukasz Kazmierczak             {
102662598e31SEd Tanous                 BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
10271b7e696bSLukasz Kazmierczak                 messages::internalError(asyncResp->res);
10281b7e696bSLukasz Kazmierczak                 return;
10291b7e696bSLukasz Kazmierczak             }
10301b7e696bSLukasz Kazmierczak 
1031002d39b4SEd Tanous             if (!telemetry::fillTrigger(asyncResp->res.jsonValue, id, ret))
10321b7e696bSLukasz Kazmierczak             {
10331b7e696bSLukasz Kazmierczak                 messages::internalError(asyncResp->res);
10341b7e696bSLukasz Kazmierczak             }
103589474494SKrzysztof Grobelny         });
10361b7e696bSLukasz Kazmierczak     });
1037163994a8SSzymon Dompke 
1038163994a8SSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
1039163994a8SSzymon Dompke         .privileges(redfish::privileges::deleteTriggers)
1040163994a8SSzymon Dompke         .methods(boost::beast::http::verb::delete_)(
104145ca1b86SEd Tanous             [&app](const crow::Request& req,
1042163994a8SSzymon Dompke                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1043163994a8SSzymon Dompke                    const std::string& id) {
10443ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
104545ca1b86SEd Tanous         {
104645ca1b86SEd Tanous             return;
104745ca1b86SEd Tanous         }
1048002d39b4SEd Tanous         const std::string triggerPath = telemetry::getDbusTriggerPath(id);
1049163994a8SSzymon Dompke 
1050163994a8SSzymon Dompke         crow::connections::systemBus->async_method_call(
10515e7e2dc5SEd Tanous             [asyncResp, id](const boost::system::error_code& ec) {
1052163994a8SSzymon Dompke             if (ec.value() == EBADR)
1053163994a8SSzymon Dompke             {
1054002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "Triggers", id);
1055163994a8SSzymon Dompke                 return;
1056163994a8SSzymon Dompke             }
1057163994a8SSzymon Dompke 
1058163994a8SSzymon Dompke             if (ec)
1059163994a8SSzymon Dompke             {
106062598e31SEd Tanous                 BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
1061163994a8SSzymon Dompke                 messages::internalError(asyncResp->res);
1062163994a8SSzymon Dompke                 return;
1063163994a8SSzymon Dompke             }
1064163994a8SSzymon Dompke 
1065002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
1066163994a8SSzymon Dompke         },
1067163994a8SSzymon Dompke             telemetry::service, triggerPath,
1068163994a8SSzymon Dompke             "xyz.openbmc_project.Object.Delete", "Delete");
1069163994a8SSzymon Dompke     });
10701b7e696bSLukasz Kazmierczak }
10711b7e696bSLukasz Kazmierczak 
107207148cf2SLukasz Kazmierczak } // namespace redfish
1073