xref: /openbmc/bmcweb/features/redfish/lib/trigger.hpp (revision d78572018fc2022091ff8b8eb5a7fef2172ba3d6)
140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
307148cf2SLukasz Kazmierczak #pragma once
407148cf2SLukasz Kazmierczak 
53ccb3adbSEd Tanous #include "app.hpp"
6*d7857201SEd Tanous #include "async_resp.hpp"
7*d7857201SEd Tanous #include "dbus_singleton.hpp"
8*d7857201SEd Tanous #include "dbus_utility.hpp"
9*d7857201SEd Tanous #include "error_messages.hpp"
10539d8c6bSEd Tanous #include "generated/enums/metric_definition.hpp"
11dd1c4a9cSSzymon Dompke #include "generated/enums/resource.hpp"
12dd1c4a9cSSzymon Dompke #include "generated/enums/triggers.hpp"
13*d7857201SEd Tanous #include "http_request.hpp"
14*d7857201SEd Tanous #include "http_response.hpp"
15*d7857201SEd Tanous #include "logging.hpp"
163ccb3adbSEd Tanous #include "query.hpp"
173ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
18dd1c4a9cSSzymon Dompke #include "utility.hpp"
1907148cf2SLukasz Kazmierczak #include "utils/collection.hpp"
203ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
215b90429aSEd Tanous #include "utils/json_utils.hpp"
221516c21bSJanet Adkins #include "utils/sensor_utils.hpp"
2307148cf2SLukasz Kazmierczak #include "utils/telemetry_utils.hpp"
243ccb3adbSEd Tanous #include "utils/time_utils.hpp"
2507148cf2SLukasz Kazmierczak 
26*d7857201SEd Tanous #include <asm-generic/errno.h>
27*d7857201SEd Tanous 
28*d7857201SEd Tanous #include <boost/beast/http/status.hpp>
29*d7857201SEd Tanous #include <boost/beast/http/verb.hpp>
30*d7857201SEd Tanous #include <boost/system/result.hpp>
31ef4c65b7SEd Tanous #include <boost/url/format.hpp>
32*d7857201SEd Tanous #include <boost/url/parse.hpp>
33*d7857201SEd Tanous #include <boost/url/url.hpp>
34*d7857201SEd Tanous #include <boost/url/url_view.hpp>
35*d7857201SEd Tanous #include <nlohmann/json.hpp>
3689474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
37*d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp>
3889474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
3907148cf2SLukasz Kazmierczak 
407a1dbc48SGeorge Liu #include <array>
41*d7857201SEd Tanous #include <chrono>
42*d7857201SEd Tanous #include <cstddef>
43*d7857201SEd Tanous #include <cstdint>
44*d7857201SEd Tanous #include <functional>
45*d7857201SEd Tanous #include <memory>
46*d7857201SEd Tanous #include <optional>
47*d7857201SEd Tanous #include <string>
487a1dbc48SGeorge Liu #include <string_view>
491b7e696bSLukasz Kazmierczak #include <tuple>
50*d7857201SEd Tanous #include <utility>
511b7e696bSLukasz Kazmierczak #include <vector>
521b7e696bSLukasz Kazmierczak 
5307148cf2SLukasz Kazmierczak namespace redfish
5407148cf2SLukasz Kazmierczak {
5507148cf2SLukasz Kazmierczak namespace telemetry
5607148cf2SLukasz Kazmierczak {
5707148cf2SLukasz Kazmierczak constexpr const char* triggerInterface =
5807148cf2SLukasz Kazmierczak     "xyz.openbmc_project.Telemetry.Trigger";
5907148cf2SLukasz Kazmierczak 
601b7e696bSLukasz Kazmierczak using NumericThresholdParams =
611b7e696bSLukasz Kazmierczak     std::tuple<std::string, uint64_t, std::string, double>;
621b7e696bSLukasz Kazmierczak 
631b7e696bSLukasz Kazmierczak using DiscreteThresholdParams =
641b7e696bSLukasz Kazmierczak     std::tuple<std::string, std::string, uint64_t, std::string>;
651b7e696bSLukasz Kazmierczak 
661b7e696bSLukasz Kazmierczak using TriggerSensorsParams =
671b7e696bSLukasz Kazmierczak     std::vector<std::pair<sdbusplus::message::object_path, std::string>>;
681b7e696bSLukasz Kazmierczak 
69dd1c4a9cSSzymon Dompke inline triggers::TriggerActionEnum
70dd1c4a9cSSzymon Dompke     toRedfishTriggerAction(std::string_view dbusValue)
711b7e696bSLukasz Kazmierczak {
72dd1c4a9cSSzymon Dompke     if (dbusValue ==
73dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport")
741b7e696bSLukasz Kazmierczak     {
75dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishMetricReport;
761b7e696bSLukasz Kazmierczak     }
77dd1c4a9cSSzymon Dompke     if (dbusValue ==
78dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog")
791b7e696bSLukasz Kazmierczak     {
80dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::RedfishEvent;
811b7e696bSLukasz Kazmierczak     }
82dd1c4a9cSSzymon Dompke     if (dbusValue ==
83dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal")
841b7e696bSLukasz Kazmierczak     {
85dd1c4a9cSSzymon Dompke         return triggers::TriggerActionEnum::LogToLogService;
861b7e696bSLukasz Kazmierczak     }
87dd1c4a9cSSzymon Dompke     return triggers::TriggerActionEnum::Invalid;
881b7e696bSLukasz Kazmierczak }
891b7e696bSLukasz Kazmierczak 
90dd1c4a9cSSzymon Dompke inline std::string toDbusTriggerAction(std::string_view redfishValue)
911b7e696bSLukasz Kazmierczak {
92dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishMetricReport")
931b7e696bSLukasz Kazmierczak     {
94dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport";
95dd1c4a9cSSzymon Dompke     }
96dd1c4a9cSSzymon Dompke     if (redfishValue == "RedfishEvent")
97dd1c4a9cSSzymon Dompke     {
98dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog";
99dd1c4a9cSSzymon Dompke     }
100dd1c4a9cSSzymon Dompke     if (redfishValue == "LogToLogService")
101dd1c4a9cSSzymon Dompke     {
102dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal";
103dd1c4a9cSSzymon Dompke     }
104dd1c4a9cSSzymon Dompke     return "";
105dd1c4a9cSSzymon Dompke }
1061b7e696bSLukasz Kazmierczak 
107dd1c4a9cSSzymon Dompke inline std::string toDbusSeverity(std::string_view redfishValue)
108dd1c4a9cSSzymon Dompke {
109dd1c4a9cSSzymon Dompke     if (redfishValue == "OK")
110dd1c4a9cSSzymon Dompke     {
111dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.OK";
112dd1c4a9cSSzymon Dompke     }
113dd1c4a9cSSzymon Dompke     if (redfishValue == "Warning")
114dd1c4a9cSSzymon Dompke     {
115dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning";
116dd1c4a9cSSzymon Dompke     }
117dd1c4a9cSSzymon Dompke     if (redfishValue == "Critical")
118dd1c4a9cSSzymon Dompke     {
119dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical";
120dd1c4a9cSSzymon Dompke     }
121dd1c4a9cSSzymon Dompke     return "";
122dd1c4a9cSSzymon Dompke }
123dd1c4a9cSSzymon Dompke 
124dd1c4a9cSSzymon Dompke inline resource::Health toRedfishSeverity(std::string_view dbusValue)
125dd1c4a9cSSzymon Dompke {
126dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.OK")
127dd1c4a9cSSzymon Dompke     {
128dd1c4a9cSSzymon Dompke         return resource::Health::OK;
129dd1c4a9cSSzymon Dompke     }
130dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning")
131dd1c4a9cSSzymon Dompke     {
132dd1c4a9cSSzymon Dompke         return resource::Health::Warning;
133dd1c4a9cSSzymon Dompke     }
134dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical")
135dd1c4a9cSSzymon Dompke     {
136dd1c4a9cSSzymon Dompke         return resource::Health::Critical;
137dd1c4a9cSSzymon Dompke     }
138dd1c4a9cSSzymon Dompke     return resource::Health::Invalid;
139dd1c4a9cSSzymon Dompke }
140dd1c4a9cSSzymon Dompke 
141dd1c4a9cSSzymon Dompke inline std::string toRedfishThresholdName(std::string_view dbusValue)
142dd1c4a9cSSzymon Dompke {
143dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical")
144dd1c4a9cSSzymon Dompke     {
145dd1c4a9cSSzymon Dompke         return "UpperCritical";
146dd1c4a9cSSzymon Dompke     }
147dd1c4a9cSSzymon Dompke 
148dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical")
149dd1c4a9cSSzymon Dompke     {
150dd1c4a9cSSzymon Dompke         return "LowerCritical";
151dd1c4a9cSSzymon Dompke     }
152dd1c4a9cSSzymon Dompke 
153dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning")
154dd1c4a9cSSzymon Dompke     {
155dd1c4a9cSSzymon Dompke         return "UpperWarning";
156dd1c4a9cSSzymon Dompke     }
157dd1c4a9cSSzymon Dompke 
158dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning")
159dd1c4a9cSSzymon Dompke     {
160dd1c4a9cSSzymon Dompke         return "LowerWarning";
161dd1c4a9cSSzymon Dompke     }
162dd1c4a9cSSzymon Dompke 
163dd1c4a9cSSzymon Dompke     return "";
164dd1c4a9cSSzymon Dompke }
165dd1c4a9cSSzymon Dompke 
166dd1c4a9cSSzymon Dompke inline std::string toDbusActivation(std::string_view redfishValue)
167dd1c4a9cSSzymon Dompke {
168dd1c4a9cSSzymon Dompke     if (redfishValue == "Either")
169dd1c4a9cSSzymon Dompke     {
170dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Either";
171dd1c4a9cSSzymon Dompke     }
172dd1c4a9cSSzymon Dompke 
173dd1c4a9cSSzymon Dompke     if (redfishValue == "Decreasing")
174dd1c4a9cSSzymon Dompke     {
175dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing";
176dd1c4a9cSSzymon Dompke     }
177dd1c4a9cSSzymon Dompke 
178dd1c4a9cSSzymon Dompke     if (redfishValue == "Increasing")
179dd1c4a9cSSzymon Dompke     {
180dd1c4a9cSSzymon Dompke         return "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing";
181dd1c4a9cSSzymon Dompke     }
182dd1c4a9cSSzymon Dompke 
183dd1c4a9cSSzymon Dompke     return "";
184dd1c4a9cSSzymon Dompke }
185dd1c4a9cSSzymon Dompke 
186dd1c4a9cSSzymon Dompke inline triggers::ThresholdActivation
187dd1c4a9cSSzymon Dompke     toRedfishActivation(std::string_view dbusValue)
188dd1c4a9cSSzymon Dompke {
189dd1c4a9cSSzymon Dompke     if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Direction.Either")
190dd1c4a9cSSzymon Dompke     {
191dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Either;
192dd1c4a9cSSzymon Dompke     }
193dd1c4a9cSSzymon Dompke 
194dd1c4a9cSSzymon Dompke     if (dbusValue ==
195dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing")
196dd1c4a9cSSzymon Dompke     {
197dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Decreasing;
198dd1c4a9cSSzymon Dompke     }
199dd1c4a9cSSzymon Dompke 
200dd1c4a9cSSzymon Dompke     if (dbusValue ==
201dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing")
202dd1c4a9cSSzymon Dompke     {
203dd1c4a9cSSzymon Dompke         return triggers::ThresholdActivation::Increasing;
204dd1c4a9cSSzymon Dompke     }
205dd1c4a9cSSzymon Dompke 
206dd1c4a9cSSzymon Dompke     return triggers::ThresholdActivation::Invalid;
207dd1c4a9cSSzymon Dompke }
208dd1c4a9cSSzymon Dompke 
209dd1c4a9cSSzymon Dompke enum class MetricType
210dd1c4a9cSSzymon Dompke {
211dd1c4a9cSSzymon Dompke     Discrete,
212dd1c4a9cSSzymon Dompke     Numeric
213dd1c4a9cSSzymon Dompke };
214dd1c4a9cSSzymon Dompke 
215dd1c4a9cSSzymon Dompke enum class DiscreteCondition
216dd1c4a9cSSzymon Dompke {
217dd1c4a9cSSzymon Dompke     Specified,
218dd1c4a9cSSzymon Dompke     Changed
219dd1c4a9cSSzymon Dompke };
220dd1c4a9cSSzymon Dompke 
221dd1c4a9cSSzymon Dompke struct Context
222dd1c4a9cSSzymon Dompke {
223dd1c4a9cSSzymon Dompke     std::string id;
224dd1c4a9cSSzymon Dompke     std::string name;
225dd1c4a9cSSzymon Dompke     std::vector<std::string> actions;
226dd1c4a9cSSzymon Dompke     std::vector<std::pair<sdbusplus::message::object_path, std::string>>
227dd1c4a9cSSzymon Dompke         sensors;
228dd1c4a9cSSzymon Dompke     std::vector<sdbusplus::message::object_path> reports;
22958c71488SEd Tanous     std::vector<NumericThresholdParams> numericThresholds;
23058c71488SEd Tanous     std::vector<DiscreteThresholdParams> discreteThresholds;
231dd1c4a9cSSzymon Dompke     std::optional<DiscreteCondition> discreteCondition;
232dd1c4a9cSSzymon Dompke     std::optional<MetricType> metricType;
233dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> metricProperties;
234dd1c4a9cSSzymon Dompke };
235dd1c4a9cSSzymon Dompke 
236dd1c4a9cSSzymon Dompke inline std::optional<sdbusplus::message::object_path>
237dd1c4a9cSSzymon Dompke     getReportPathFromReportDefinitionUri(const std::string& uri)
238dd1c4a9cSSzymon Dompke {
2396fd29553SEd Tanous     boost::system::result<boost::urls::url_view> parsed =
240dd1c4a9cSSzymon Dompke         boost::urls::parse_relative_ref(uri);
241dd1c4a9cSSzymon Dompke 
242dd1c4a9cSSzymon Dompke     if (!parsed)
2431b7e696bSLukasz Kazmierczak     {
2441b7e696bSLukasz Kazmierczak         return std::nullopt;
2451b7e696bSLukasz Kazmierczak     }
2461b7e696bSLukasz Kazmierczak 
247dd1c4a9cSSzymon Dompke     std::string id;
248dd1c4a9cSSzymon Dompke     if (!crow::utility::readUrlSegments(
249dd1c4a9cSSzymon Dompke             *parsed, "redfish", "v1", "TelemetryService",
250dd1c4a9cSSzymon Dompke             "MetricReportDefinitions", std::ref(id)))
251dd1c4a9cSSzymon Dompke     {
252dd1c4a9cSSzymon Dompke         return std::nullopt;
2531b7e696bSLukasz Kazmierczak     }
2541b7e696bSLukasz Kazmierczak 
255dd1c4a9cSSzymon Dompke     return sdbusplus::message::object_path(
256dd1c4a9cSSzymon Dompke                "/xyz/openbmc_project/Telemetry/Reports") /
257dd1c4a9cSSzymon Dompke            "TelemetryService" / id;
258dd1c4a9cSSzymon Dompke }
259dd1c4a9cSSzymon Dompke 
260dd1c4a9cSSzymon Dompke inline std::optional<MetricType> getMetricType(const std::string& metricType)
261dd1c4a9cSSzymon Dompke {
262dd1c4a9cSSzymon Dompke     if (metricType == "Discrete")
263dd1c4a9cSSzymon Dompke     {
264dd1c4a9cSSzymon Dompke         return MetricType::Discrete;
265dd1c4a9cSSzymon Dompke     }
266dd1c4a9cSSzymon Dompke     if (metricType == "Numeric")
267dd1c4a9cSSzymon Dompke     {
268dd1c4a9cSSzymon Dompke         return MetricType::Numeric;
269dd1c4a9cSSzymon Dompke     }
270dd1c4a9cSSzymon Dompke     return std::nullopt;
271dd1c4a9cSSzymon Dompke }
272dd1c4a9cSSzymon Dompke 
273dd1c4a9cSSzymon Dompke inline std::optional<DiscreteCondition>
274dd1c4a9cSSzymon Dompke     getDiscreteCondition(const std::string& discreteTriggerCondition)
275dd1c4a9cSSzymon Dompke {
276dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Specified")
277dd1c4a9cSSzymon Dompke     {
278dd1c4a9cSSzymon Dompke         return DiscreteCondition::Specified;
279dd1c4a9cSSzymon Dompke     }
280dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition == "Changed")
281dd1c4a9cSSzymon Dompke     {
282dd1c4a9cSSzymon Dompke         return DiscreteCondition::Changed;
283dd1c4a9cSSzymon Dompke     }
284dd1c4a9cSSzymon Dompke     return std::nullopt;
285dd1c4a9cSSzymon Dompke }
286dd1c4a9cSSzymon Dompke 
2872932dcb6SEd Tanous inline bool parseThreshold(crow::Response& res,
2882932dcb6SEd Tanous                            nlohmann::json::object_t& threshold,
2892932dcb6SEd Tanous                            std::string_view dbusThresholdName,
2902932dcb6SEd Tanous                            std::vector<NumericThresholdParams>& parsedParams)
291dd1c4a9cSSzymon Dompke {
292dd1c4a9cSSzymon Dompke     double reading = 0.0;
293dd1c4a9cSSzymon Dompke     std::string activation;
294dd1c4a9cSSzymon Dompke     std::string dwellTimeStr;
295dd1c4a9cSSzymon Dompke 
296afc474aeSMyung Bae     if (!json_util::readJsonObject( //
297afc474aeSMyung Bae             threshold, res, //
298afc474aeSMyung Bae             "Activation", activation, //
299afc474aeSMyung Bae             "DwellTime", dwellTimeStr, //
300afc474aeSMyung Bae             "Reading", reading //
301afc474aeSMyung Bae             ))
302dd1c4a9cSSzymon Dompke     {
303dd1c4a9cSSzymon Dompke         return false;
304dd1c4a9cSSzymon Dompke     }
305dd1c4a9cSSzymon Dompke 
306dd1c4a9cSSzymon Dompke     std::string dbusActivation = toDbusActivation(activation);
307dd1c4a9cSSzymon Dompke 
308dd1c4a9cSSzymon Dompke     if (dbusActivation.empty())
309dd1c4a9cSSzymon Dompke     {
310dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "Activation", activation);
311dd1c4a9cSSzymon Dompke         return false;
312dd1c4a9cSSzymon Dompke     }
313dd1c4a9cSSzymon Dompke 
314dd1c4a9cSSzymon Dompke     std::optional<std::chrono::milliseconds> dwellTime =
315dd1c4a9cSSzymon Dompke         time_utils::fromDurationString(dwellTimeStr);
316dd1c4a9cSSzymon Dompke     if (!dwellTime)
317dd1c4a9cSSzymon Dompke     {
318dd1c4a9cSSzymon Dompke         messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
319dd1c4a9cSSzymon Dompke         return false;
320dd1c4a9cSSzymon Dompke     }
321dd1c4a9cSSzymon Dompke 
322dd1c4a9cSSzymon Dompke     parsedParams.emplace_back(dbusThresholdName,
323dd1c4a9cSSzymon Dompke                               static_cast<uint64_t>(dwellTime->count()),
324dd1c4a9cSSzymon Dompke                               dbusActivation, reading);
3252932dcb6SEd Tanous     return true;
3262932dcb6SEd Tanous }
3272932dcb6SEd Tanous 
3282932dcb6SEd Tanous struct NumericThresholds
3292932dcb6SEd Tanous {
3302932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperCritical;
3312932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> upperWarning;
3322932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerWarning;
3332932dcb6SEd Tanous     std::optional<nlohmann::json::object_t> lowerCritical;
3342932dcb6SEd Tanous 
3352932dcb6SEd Tanous     bool any() const
3362932dcb6SEd Tanous     {
3372932dcb6SEd Tanous         return upperCritical || upperWarning || lowerWarning || lowerCritical;
3382932dcb6SEd Tanous     }
3392932dcb6SEd Tanous };
3402932dcb6SEd Tanous 
341bd79bce8SPatrick Williams inline bool parseNumericThresholds(
342bd79bce8SPatrick Williams     crow::Response& res, NumericThresholds& numericThresholds, Context& ctx)
3432932dcb6SEd Tanous {
3442932dcb6SEd Tanous     std::vector<NumericThresholdParams> parsedParams;
3452932dcb6SEd Tanous     if (numericThresholds.upperCritical)
3462932dcb6SEd Tanous     {
3472932dcb6SEd Tanous         if (!parseThreshold(
3482932dcb6SEd Tanous                 res, *numericThresholds.upperCritical,
3492932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical",
3502932dcb6SEd Tanous                 parsedParams))
3512932dcb6SEd Tanous         {
3522932dcb6SEd Tanous             return false;
3532932dcb6SEd Tanous         }
3542932dcb6SEd Tanous     }
3552932dcb6SEd Tanous     if (numericThresholds.upperWarning)
3562932dcb6SEd Tanous     {
3572932dcb6SEd Tanous         if (!parseThreshold(
3582932dcb6SEd Tanous                 res, *numericThresholds.upperWarning,
3592932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning",
3602932dcb6SEd Tanous                 parsedParams))
3612932dcb6SEd Tanous         {
3622932dcb6SEd Tanous             return false;
3632932dcb6SEd Tanous         }
3642932dcb6SEd Tanous     }
3652932dcb6SEd Tanous     if (numericThresholds.lowerWarning)
3662932dcb6SEd Tanous     {
3672932dcb6SEd Tanous         if (!parseThreshold(
3682932dcb6SEd Tanous                 res, *numericThresholds.lowerWarning,
3692932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning",
3702932dcb6SEd Tanous                 parsedParams))
3712932dcb6SEd Tanous         {
3722932dcb6SEd Tanous             return false;
3732932dcb6SEd Tanous         }
3742932dcb6SEd Tanous     }
3752932dcb6SEd Tanous     if (numericThresholds.lowerCritical)
3762932dcb6SEd Tanous     {
3772932dcb6SEd Tanous         if (!parseThreshold(
3782932dcb6SEd Tanous                 res, *numericThresholds.lowerCritical,
3792932dcb6SEd Tanous                 "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical",
3802932dcb6SEd Tanous                 parsedParams))
3812932dcb6SEd Tanous         {
3822932dcb6SEd Tanous             return false;
3832932dcb6SEd Tanous         }
384dd1c4a9cSSzymon Dompke     }
385dd1c4a9cSSzymon Dompke 
38658c71488SEd Tanous     ctx.numericThresholds = std::move(parsedParams);
387dd1c4a9cSSzymon Dompke     return true;
388dd1c4a9cSSzymon Dompke }
389dd1c4a9cSSzymon Dompke 
390dd1c4a9cSSzymon Dompke inline bool parseDiscreteTriggers(
391dd1c4a9cSSzymon Dompke     crow::Response& res,
3922932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
3932932dcb6SEd Tanous     Context& ctx)
394dd1c4a9cSSzymon Dompke {
395dd1c4a9cSSzymon Dompke     std::vector<DiscreteThresholdParams> parsedParams;
396dd1c4a9cSSzymon Dompke     if (!discreteTriggers)
397dd1c4a9cSSzymon Dompke     {
39858c71488SEd Tanous         ctx.discreteThresholds = std::move(parsedParams);
399dd1c4a9cSSzymon Dompke         return true;
400dd1c4a9cSSzymon Dompke     }
401dd1c4a9cSSzymon Dompke 
402dd1c4a9cSSzymon Dompke     parsedParams.reserve(discreteTriggers->size());
4032932dcb6SEd Tanous     for (nlohmann::json::object_t& thresholdInfo : *discreteTriggers)
404dd1c4a9cSSzymon Dompke     {
405dd1c4a9cSSzymon Dompke         std::optional<std::string> name = "";
406dd1c4a9cSSzymon Dompke         std::string value;
407dd1c4a9cSSzymon Dompke         std::string dwellTimeStr;
408dd1c4a9cSSzymon Dompke         std::string severity;
409dd1c4a9cSSzymon Dompke 
410afc474aeSMyung Bae         if (!json_util::readJsonObject( //
411afc474aeSMyung Bae                 thresholdInfo, res, //
412afc474aeSMyung Bae                 "DwellTime", dwellTimeStr, //
413afc474aeSMyung Bae                 "Name", name, //
414afc474aeSMyung Bae                 "Severity", severity, //
415afc474aeSMyung Bae                 "Value", value //
416afc474aeSMyung Bae                 ))
417dd1c4a9cSSzymon Dompke         {
418dd1c4a9cSSzymon Dompke             return false;
419dd1c4a9cSSzymon Dompke         }
420dd1c4a9cSSzymon Dompke 
421dd1c4a9cSSzymon Dompke         std::optional<std::chrono::milliseconds> dwellTime =
422dd1c4a9cSSzymon Dompke             time_utils::fromDurationString(dwellTimeStr);
423dd1c4a9cSSzymon Dompke         if (!dwellTime)
424dd1c4a9cSSzymon Dompke         {
425dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr);
426dd1c4a9cSSzymon Dompke             return false;
427dd1c4a9cSSzymon Dompke         }
428dd1c4a9cSSzymon Dompke 
429dd1c4a9cSSzymon Dompke         std::string dbusSeverity = toDbusSeverity(severity);
430dd1c4a9cSSzymon Dompke         if (dbusSeverity.empty())
431dd1c4a9cSSzymon Dompke         {
432dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "Severity", severity);
433dd1c4a9cSSzymon Dompke             return false;
434dd1c4a9cSSzymon Dompke         }
435dd1c4a9cSSzymon Dompke 
436dd1c4a9cSSzymon Dompke         parsedParams.emplace_back(*name, dbusSeverity,
437dd1c4a9cSSzymon Dompke                                   static_cast<uint64_t>(dwellTime->count()),
438dd1c4a9cSSzymon Dompke                                   value);
439dd1c4a9cSSzymon Dompke     }
440dd1c4a9cSSzymon Dompke 
44158c71488SEd Tanous     ctx.discreteThresholds = std::move(parsedParams);
442dd1c4a9cSSzymon Dompke     return true;
443dd1c4a9cSSzymon Dompke }
444dd1c4a9cSSzymon Dompke 
445dd1c4a9cSSzymon Dompke inline bool parseTriggerThresholds(
446dd1c4a9cSSzymon Dompke     crow::Response& res,
4472932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers,
4482932dcb6SEd Tanous     NumericThresholds& numericThresholds, Context& ctx)
449dd1c4a9cSSzymon Dompke {
4502932dcb6SEd Tanous     if (discreteTriggers && numericThresholds.any())
451dd1c4a9cSSzymon Dompke     {
452dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "DiscreteTriggers",
453dd1c4a9cSSzymon Dompke                                         "NumericThresholds");
454dd1c4a9cSSzymon Dompke         messages::propertyValueConflict(res, "NumericThresholds",
455dd1c4a9cSSzymon Dompke                                         "DiscreteTriggers");
456dd1c4a9cSSzymon Dompke         return false;
457dd1c4a9cSSzymon Dompke     }
458dd1c4a9cSSzymon Dompke 
459dd1c4a9cSSzymon Dompke     if (ctx.discreteCondition)
460dd1c4a9cSSzymon Dompke     {
4612932dcb6SEd Tanous         if (numericThresholds.any())
462dd1c4a9cSSzymon Dompke         {
463dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggerCondition",
464dd1c4a9cSSzymon Dompke                                             "NumericThresholds");
465dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
466dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
467dd1c4a9cSSzymon Dompke             return false;
468dd1c4a9cSSzymon Dompke         }
469dd1c4a9cSSzymon Dompke     }
470dd1c4a9cSSzymon Dompke 
471dd1c4a9cSSzymon Dompke     if (ctx.metricType)
472dd1c4a9cSSzymon Dompke     {
4732932dcb6SEd Tanous         if (*ctx.metricType == MetricType::Discrete && numericThresholds.any())
474dd1c4a9cSSzymon Dompke         {
475dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "NumericThresholds",
476dd1c4a9cSSzymon Dompke                                             "MetricType");
477dd1c4a9cSSzymon Dompke             return false;
478dd1c4a9cSSzymon Dompke         }
479dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && discreteTriggers)
480dd1c4a9cSSzymon Dompke         {
481dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
482dd1c4a9cSSzymon Dompke                                             "MetricType");
483dd1c4a9cSSzymon Dompke             return false;
484dd1c4a9cSSzymon Dompke         }
485dd1c4a9cSSzymon Dompke         if (*ctx.metricType == MetricType::Numeric && ctx.discreteCondition)
486dd1c4a9cSSzymon Dompke         {
487dd1c4a9cSSzymon Dompke             messages::propertyValueConflict(res, "DiscreteTriggers",
488dd1c4a9cSSzymon Dompke                                             "DiscreteTriggerCondition");
489dd1c4a9cSSzymon Dompke             return false;
490dd1c4a9cSSzymon Dompke         }
491dd1c4a9cSSzymon Dompke     }
492dd1c4a9cSSzymon Dompke 
493dd1c4a9cSSzymon Dompke     if (discreteTriggers || ctx.discreteCondition ||
494dd1c4a9cSSzymon Dompke         (ctx.metricType && *ctx.metricType == MetricType::Discrete))
495dd1c4a9cSSzymon Dompke     {
496dd1c4a9cSSzymon Dompke         if (ctx.discreteCondition)
497dd1c4a9cSSzymon Dompke         {
498dd1c4a9cSSzymon Dompke             if (*ctx.discreteCondition == DiscreteCondition::Specified &&
499dd1c4a9cSSzymon Dompke                 !discreteTriggers)
500dd1c4a9cSSzymon Dompke             {
501dd1c4a9cSSzymon Dompke                 messages::createFailedMissingReqProperties(res,
502dd1c4a9cSSzymon Dompke                                                            "DiscreteTriggers");
503dd1c4a9cSSzymon Dompke                 return false;
504dd1c4a9cSSzymon Dompke             }
505dd1c4a9cSSzymon Dompke             if (discreteTriggers &&
506dd1c4a9cSSzymon Dompke                 ((*ctx.discreteCondition == DiscreteCondition::Specified &&
507dd1c4a9cSSzymon Dompke                   discreteTriggers->empty()) ||
508dd1c4a9cSSzymon Dompke                  (*ctx.discreteCondition == DiscreteCondition::Changed &&
509dd1c4a9cSSzymon Dompke                   !discreteTriggers->empty())))
510dd1c4a9cSSzymon Dompke             {
511dd1c4a9cSSzymon Dompke                 messages::propertyValueConflict(res, "DiscreteTriggers",
512dd1c4a9cSSzymon Dompke                                                 "DiscreteTriggerCondition");
513dd1c4a9cSSzymon Dompke                 return false;
514dd1c4a9cSSzymon Dompke             }
515dd1c4a9cSSzymon Dompke         }
516dd1c4a9cSSzymon Dompke         if (!parseDiscreteTriggers(res, discreteTriggers, ctx))
517dd1c4a9cSSzymon Dompke         {
518dd1c4a9cSSzymon Dompke             return false;
519dd1c4a9cSSzymon Dompke         }
520dd1c4a9cSSzymon Dompke     }
5212932dcb6SEd Tanous     else if (numericThresholds.any())
522dd1c4a9cSSzymon Dompke     {
5232932dcb6SEd Tanous         if (!parseNumericThresholds(res, numericThresholds, ctx))
524dd1c4a9cSSzymon Dompke         {
525dd1c4a9cSSzymon Dompke             return false;
526dd1c4a9cSSzymon Dompke         }
527dd1c4a9cSSzymon Dompke     }
528dd1c4a9cSSzymon Dompke     else
529dd1c4a9cSSzymon Dompke     {
530dd1c4a9cSSzymon Dompke         messages::createFailedMissingReqProperties(
531dd1c4a9cSSzymon Dompke             res, "'DiscreteTriggers', 'NumericThresholds', "
532dd1c4a9cSSzymon Dompke                  "'DiscreteTriggerCondition' or 'MetricType'");
533dd1c4a9cSSzymon Dompke         return false;
534dd1c4a9cSSzymon Dompke     }
535dd1c4a9cSSzymon Dompke     return true;
536dd1c4a9cSSzymon Dompke }
537dd1c4a9cSSzymon Dompke 
5382932dcb6SEd Tanous inline bool parseLinks(crow::Response& res,
5392932dcb6SEd Tanous                        const std::vector<std::string>& metricReportDefinitions,
5402932dcb6SEd Tanous                        Context& ctx)
541dd1c4a9cSSzymon Dompke {
5422932dcb6SEd Tanous     ctx.reports.reserve(metricReportDefinitions.size());
5432932dcb6SEd Tanous     for (const std::string& reportDefinionUri : metricReportDefinitions)
544dd1c4a9cSSzymon Dompke     {
545dd1c4a9cSSzymon Dompke         std::optional<sdbusplus::message::object_path> reportPath =
546dd1c4a9cSSzymon Dompke             getReportPathFromReportDefinitionUri(reportDefinionUri);
547dd1c4a9cSSzymon Dompke         if (!reportPath)
548dd1c4a9cSSzymon Dompke         {
549dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricReportDefinitions",
550dd1c4a9cSSzymon Dompke                                              reportDefinionUri);
551dd1c4a9cSSzymon Dompke             return false;
552dd1c4a9cSSzymon Dompke         }
553dd1c4a9cSSzymon Dompke         ctx.reports.emplace_back(*reportPath);
554dd1c4a9cSSzymon Dompke     }
555dd1c4a9cSSzymon Dompke     return true;
556dd1c4a9cSSzymon Dompke }
557dd1c4a9cSSzymon Dompke 
558dd1c4a9cSSzymon Dompke inline bool parseMetricProperties(crow::Response& res, Context& ctx)
559dd1c4a9cSSzymon Dompke {
560dd1c4a9cSSzymon Dompke     if (!ctx.metricProperties)
561dd1c4a9cSSzymon Dompke     {
562dd1c4a9cSSzymon Dompke         return true;
563dd1c4a9cSSzymon Dompke     }
564dd1c4a9cSSzymon Dompke 
565dd1c4a9cSSzymon Dompke     ctx.sensors.reserve(ctx.metricProperties->size());
566dd1c4a9cSSzymon Dompke 
567dd1c4a9cSSzymon Dompke     size_t uriIdx = 0;
568dd1c4a9cSSzymon Dompke     for (const std::string& uriStr : *ctx.metricProperties)
569dd1c4a9cSSzymon Dompke     {
5704a7fbefdSEd Tanous         boost::system::result<boost::urls::url> uri =
571dd1c4a9cSSzymon Dompke             boost::urls::parse_relative_ref(uriStr);
572dd1c4a9cSSzymon Dompke         if (!uri)
573dd1c4a9cSSzymon Dompke         {
574dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
575dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
576dd1c4a9cSSzymon Dompke             return false;
577dd1c4a9cSSzymon Dompke         }
578dd1c4a9cSSzymon Dompke         std::string chassisName;
579dd1c4a9cSSzymon Dompke         std::string sensorName;
580dd1c4a9cSSzymon Dompke         if (!crow::utility::readUrlSegments(*uri, "redfish", "v1", "Chassis",
581dd1c4a9cSSzymon Dompke                                             std::ref(chassisName), "Sensors",
582dd1c4a9cSSzymon Dompke                                             std::ref(sensorName)))
583dd1c4a9cSSzymon Dompke         {
584dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
585dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
586dd1c4a9cSSzymon Dompke             return false;
587dd1c4a9cSSzymon Dompke         }
588dd1c4a9cSSzymon Dompke 
589dd1c4a9cSSzymon Dompke         std::pair<std::string, std::string> split =
5901516c21bSJanet Adkins             redfish::sensor_utils::splitSensorNameAndType(sensorName);
591dd1c4a9cSSzymon Dompke         if (split.first.empty() || split.second.empty())
592dd1c4a9cSSzymon Dompke         {
593dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(
594dd1c4a9cSSzymon Dompke                 res, "MetricProperties/" + std::to_string(uriIdx), uriStr);
595dd1c4a9cSSzymon Dompke             return false;
596dd1c4a9cSSzymon Dompke         }
597dd1c4a9cSSzymon Dompke 
598bd79bce8SPatrick Williams         std::string sensorPath =
599bd79bce8SPatrick Williams             "/xyz/openbmc_project/sensors/" + split.first + '/' + split.second;
600dd1c4a9cSSzymon Dompke 
601dd1c4a9cSSzymon Dompke         ctx.sensors.emplace_back(sensorPath, uriStr);
602dd1c4a9cSSzymon Dompke         uriIdx++;
603dd1c4a9cSSzymon Dompke     }
604dd1c4a9cSSzymon Dompke     return true;
605dd1c4a9cSSzymon Dompke }
606dd1c4a9cSSzymon Dompke 
607dd1c4a9cSSzymon Dompke inline bool parsePostTriggerParams(crow::Response& res,
608dd1c4a9cSSzymon Dompke                                    const crow::Request& req, Context& ctx)
609dd1c4a9cSSzymon Dompke {
610dd1c4a9cSSzymon Dompke     std::optional<std::string> id = "";
611dd1c4a9cSSzymon Dompke     std::optional<std::string> name = "";
612dd1c4a9cSSzymon Dompke     std::optional<std::string> metricType;
613dd1c4a9cSSzymon Dompke     std::optional<std::vector<std::string>> triggerActions;
614dd1c4a9cSSzymon Dompke     std::optional<std::string> discreteTriggerCondition;
6152932dcb6SEd Tanous     std::optional<std::vector<nlohmann::json::object_t>> discreteTriggers;
6162932dcb6SEd Tanous     std::optional<std::vector<std::string>> metricReportDefinitions;
6172932dcb6SEd Tanous     NumericThresholds thresholds;
618afc474aeSMyung Bae 
619afc474aeSMyung Bae     if (!json_util::readJsonPatch( //
620afc474aeSMyung Bae             req, res, //
621afc474aeSMyung Bae             "Id", id, //
622afc474aeSMyung Bae             "DiscreteTriggerCondition", discreteTriggerCondition, //
623afc474aeSMyung Bae             "DiscreteTriggers", discreteTriggers, //
624afc474aeSMyung Bae             "Links/MetricReportDefinitions", metricReportDefinitions, //
625afc474aeSMyung Bae             "MetricProperties", ctx.metricProperties, //
626afc474aeSMyung Bae             "MetricType", metricType, //
627afc474aeSMyung Bae             "Name", name, //
628afc474aeSMyung Bae             "NumericThresholds/LowerCritical", thresholds.lowerCritical, //
629afc474aeSMyung Bae             "NumericThresholds/LowerWarning", thresholds.lowerWarning, //
630afc474aeSMyung Bae             "NumericThresholds/UpperCritical", thresholds.upperCritical, //
631afc474aeSMyung Bae             "NumericThresholds/UpperWarning", thresholds.upperWarning, //
632afc474aeSMyung Bae             "TriggerActions", triggerActions //
633afc474aeSMyung Bae             ))
634dd1c4a9cSSzymon Dompke     {
635dd1c4a9cSSzymon Dompke         return false;
636dd1c4a9cSSzymon Dompke     }
637dd1c4a9cSSzymon Dompke 
638dd1c4a9cSSzymon Dompke     ctx.id = *id;
639dd1c4a9cSSzymon Dompke     ctx.name = *name;
640dd1c4a9cSSzymon Dompke 
641dd1c4a9cSSzymon Dompke     if (metricType)
642dd1c4a9cSSzymon Dompke     {
643d5736ef2SEd Tanous         ctx.metricType = getMetricType(*metricType);
644d5736ef2SEd Tanous         if (!ctx.metricType)
645dd1c4a9cSSzymon Dompke         {
646dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "MetricType", *metricType);
647dd1c4a9cSSzymon Dompke             return false;
648dd1c4a9cSSzymon Dompke         }
649dd1c4a9cSSzymon Dompke     }
650dd1c4a9cSSzymon Dompke 
651dd1c4a9cSSzymon Dompke     if (discreteTriggerCondition)
652dd1c4a9cSSzymon Dompke     {
653d5736ef2SEd Tanous         ctx.discreteCondition = getDiscreteCondition(*discreteTriggerCondition);
654d5736ef2SEd Tanous         if (!ctx.discreteCondition)
655dd1c4a9cSSzymon Dompke         {
656dd1c4a9cSSzymon Dompke             messages::propertyValueIncorrect(res, "DiscreteTriggerCondition",
657dd1c4a9cSSzymon Dompke                                              *discreteTriggerCondition);
658dd1c4a9cSSzymon Dompke             return false;
659dd1c4a9cSSzymon Dompke         }
660dd1c4a9cSSzymon Dompke     }
661dd1c4a9cSSzymon Dompke 
662dd1c4a9cSSzymon Dompke     if (triggerActions)
663dd1c4a9cSSzymon Dompke     {
664dd1c4a9cSSzymon Dompke         ctx.actions.reserve(triggerActions->size());
665dd1c4a9cSSzymon Dompke         for (const std::string& action : *triggerActions)
666dd1c4a9cSSzymon Dompke         {
667dd1c4a9cSSzymon Dompke             std::string dbusAction = toDbusTriggerAction(action);
668dd1c4a9cSSzymon Dompke 
669dd1c4a9cSSzymon Dompke             if (dbusAction.empty())
670dd1c4a9cSSzymon Dompke             {
671dd1c4a9cSSzymon Dompke                 messages::propertyValueNotInList(res, action, "TriggerActions");
672dd1c4a9cSSzymon Dompke                 return false;
673dd1c4a9cSSzymon Dompke             }
674dd1c4a9cSSzymon Dompke 
675dd1c4a9cSSzymon Dompke             ctx.actions.emplace_back(dbusAction);
676dd1c4a9cSSzymon Dompke         }
677dd1c4a9cSSzymon Dompke     }
678dd1c4a9cSSzymon Dompke     if (!parseMetricProperties(res, ctx))
679dd1c4a9cSSzymon Dompke     {
680dd1c4a9cSSzymon Dompke         return false;
681dd1c4a9cSSzymon Dompke     }
682dd1c4a9cSSzymon Dompke 
6832932dcb6SEd Tanous     if (!parseTriggerThresholds(res, discreteTriggers, thresholds, ctx))
684dd1c4a9cSSzymon Dompke     {
685dd1c4a9cSSzymon Dompke         return false;
686dd1c4a9cSSzymon Dompke     }
687dd1c4a9cSSzymon Dompke 
6882932dcb6SEd Tanous     if (metricReportDefinitions)
689dd1c4a9cSSzymon Dompke     {
6902932dcb6SEd Tanous         if (!parseLinks(res, *metricReportDefinitions, ctx))
691dd1c4a9cSSzymon Dompke         {
692dd1c4a9cSSzymon Dompke             return false;
693dd1c4a9cSSzymon Dompke         }
694dd1c4a9cSSzymon Dompke     }
695dd1c4a9cSSzymon Dompke     return true;
696dd1c4a9cSSzymon Dompke }
697dd1c4a9cSSzymon Dompke 
698dd1c4a9cSSzymon Dompke inline void afterCreateTrigger(
699dd1c4a9cSSzymon Dompke     const boost::system::error_code& ec, const std::string& dbusPath,
700dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
701dd1c4a9cSSzymon Dompke {
702dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::file_exists)
703dd1c4a9cSSzymon Dompke     {
704dd1c4a9cSSzymon Dompke         messages::resourceAlreadyExists(asyncResp->res, "Trigger", "Id", id);
705dd1c4a9cSSzymon Dompke         return;
706dd1c4a9cSSzymon Dompke     }
707dd1c4a9cSSzymon Dompke     if (ec == boost::system::errc::too_many_files_open)
708dd1c4a9cSSzymon Dompke     {
709dd1c4a9cSSzymon Dompke         messages::createLimitReachedForResource(asyncResp->res);
710dd1c4a9cSSzymon Dompke         return;
711dd1c4a9cSSzymon Dompke     }
712dd1c4a9cSSzymon Dompke     if (ec)
713dd1c4a9cSSzymon Dompke     {
714dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
71562598e31SEd Tanous         BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
716dd1c4a9cSSzymon Dompke         return;
717dd1c4a9cSSzymon Dompke     }
718dd1c4a9cSSzymon Dompke 
719dd1c4a9cSSzymon Dompke     const std::optional<std::string>& triggerId =
720dd1c4a9cSSzymon Dompke         getTriggerIdFromDbusPath(dbusPath);
721dd1c4a9cSSzymon Dompke     if (!triggerId)
722dd1c4a9cSSzymon Dompke     {
723dd1c4a9cSSzymon Dompke         messages::internalError(asyncResp->res);
72462598e31SEd Tanous         BMCWEB_LOG_ERROR("Unknown data returned by "
72562598e31SEd Tanous                          "AddTrigger DBus method");
726dd1c4a9cSSzymon Dompke         return;
727dd1c4a9cSSzymon Dompke     }
728dd1c4a9cSSzymon Dompke 
729dd1c4a9cSSzymon Dompke     messages::created(asyncResp->res);
730dd1c4a9cSSzymon Dompke     boost::urls::url locationUrl = boost::urls::format(
731dd1c4a9cSSzymon Dompke         "/redfish/v1/TelemetryService/Triggers/{}", *triggerId);
732dd1c4a9cSSzymon Dompke     asyncResp->res.addHeader("Location", locationUrl.buffer());
733dd1c4a9cSSzymon Dompke }
734dd1c4a9cSSzymon Dompke 
735dd1c4a9cSSzymon Dompke inline std::optional<nlohmann::json::array_t>
736dd1c4a9cSSzymon Dompke     getTriggerActions(const std::vector<std::string>& dbusActions)
737dd1c4a9cSSzymon Dompke {
738dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggerActions;
739dd1c4a9cSSzymon Dompke     for (const std::string& dbusAction : dbusActions)
740dd1c4a9cSSzymon Dompke     {
741dd1c4a9cSSzymon Dompke         triggers::TriggerActionEnum redfishAction =
742dd1c4a9cSSzymon Dompke             toRedfishTriggerAction(dbusAction);
743dd1c4a9cSSzymon Dompke 
744dd1c4a9cSSzymon Dompke         if (redfishAction == triggers::TriggerActionEnum::Invalid)
745dd1c4a9cSSzymon Dompke         {
746dd1c4a9cSSzymon Dompke             return std::nullopt;
747dd1c4a9cSSzymon Dompke         }
748dd1c4a9cSSzymon Dompke 
749dd1c4a9cSSzymon Dompke         triggerActions.emplace_back(redfishAction);
750dd1c4a9cSSzymon Dompke     }
751dd1c4a9cSSzymon Dompke 
752dd1c4a9cSSzymon Dompke     return triggerActions;
7531b7e696bSLukasz Kazmierczak }
7541b7e696bSLukasz Kazmierczak 
75558c71488SEd Tanous inline std::optional<nlohmann::json::array_t> getDiscreteTriggers(
75658c71488SEd Tanous     const std::vector<DiscreteThresholdParams>& discreteParams)
7571b7e696bSLukasz Kazmierczak {
758dd1c4a9cSSzymon Dompke     nlohmann::json::array_t triggers;
75958c71488SEd Tanous     for (const auto& [name, severity, dwellTime, value] : discreteParams)
7601b7e696bSLukasz Kazmierczak     {
7611b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7621b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7631b7e696bSLukasz Kazmierczak 
7641b7e696bSLukasz Kazmierczak         if (!duration)
7651b7e696bSLukasz Kazmierczak         {
7661b7e696bSLukasz Kazmierczak             return std::nullopt;
7671b7e696bSLukasz Kazmierczak         }
768613dabeaSEd Tanous         nlohmann::json::object_t trigger;
769613dabeaSEd Tanous         trigger["Name"] = name;
770dd1c4a9cSSzymon Dompke         trigger["Severity"] = toRedfishSeverity(severity);
771613dabeaSEd Tanous         trigger["DwellTime"] = *duration;
772613dabeaSEd Tanous         trigger["Value"] = value;
773ad539545SPatrick Williams         triggers.emplace_back(std::move(trigger));
7741b7e696bSLukasz Kazmierczak     }
7751b7e696bSLukasz Kazmierczak 
776dd1c4a9cSSzymon Dompke     return triggers;
7771b7e696bSLukasz Kazmierczak }
7781b7e696bSLukasz Kazmierczak 
77958c71488SEd Tanous inline std::optional<nlohmann::json::object_t> getNumericThresholds(
78058c71488SEd Tanous     const std::vector<NumericThresholdParams>& numericParams)
7811b7e696bSLukasz Kazmierczak {
782dd1c4a9cSSzymon Dompke     nlohmann::json::object_t thresholds;
7831b7e696bSLukasz Kazmierczak 
78458c71488SEd Tanous     for (const auto& [type, dwellTime, activation, reading] : numericParams)
7851b7e696bSLukasz Kazmierczak     {
7861b7e696bSLukasz Kazmierczak         std::optional<std::string> duration =
7871b7e696bSLukasz Kazmierczak             time_utils::toDurationStringFromUint(dwellTime);
7881b7e696bSLukasz Kazmierczak 
7891b7e696bSLukasz Kazmierczak         if (!duration)
7901b7e696bSLukasz Kazmierczak         {
7911b7e696bSLukasz Kazmierczak             return std::nullopt;
7921b7e696bSLukasz Kazmierczak         }
793dd1c4a9cSSzymon Dompke         nlohmann::json& threshold = thresholds[toRedfishThresholdName(type)];
7941476687dSEd Tanous         threshold["Reading"] = reading;
795dd1c4a9cSSzymon Dompke         threshold["Activation"] = toRedfishActivation(activation);
7961476687dSEd Tanous         threshold["DwellTime"] = *duration;
7971b7e696bSLukasz Kazmierczak     }
7981b7e696bSLukasz Kazmierczak 
799dd1c4a9cSSzymon Dompke     return thresholds;
8001b7e696bSLukasz Kazmierczak }
8011b7e696bSLukasz Kazmierczak 
8023f215c92SSzymon Dompke inline std::optional<nlohmann::json> getMetricReportDefinitions(
8033f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>& reportPaths)
8041b7e696bSLukasz Kazmierczak {
8051b7e696bSLukasz Kazmierczak     nlohmann::json reports = nlohmann::json::array();
8063f215c92SSzymon Dompke 
8073f215c92SSzymon Dompke     for (const sdbusplus::message::object_path& path : reportPaths)
8081b7e696bSLukasz Kazmierczak     {
8093f215c92SSzymon Dompke         std::string reportId = path.filename();
8103f215c92SSzymon Dompke         if (reportId.empty())
8113f215c92SSzymon Dompke         {
8123f215c92SSzymon Dompke             {
81362598e31SEd Tanous                 BMCWEB_LOG_ERROR("Property Reports contains invalid value: {}",
81462598e31SEd Tanous                                  path.str);
8153f215c92SSzymon Dompke                 return std::nullopt;
8163f215c92SSzymon Dompke             }
8173f215c92SSzymon Dompke         }
8183f215c92SSzymon Dompke 
8191476687dSEd Tanous         nlohmann::json::object_t report;
820ef4c65b7SEd Tanous         report["@odata.id"] = boost::urls::format(
821ef4c65b7SEd Tanous             "/redfish/v1/TelemetryService/MetricReportDefinitions/{}",
822ef4c65b7SEd Tanous             reportId);
823b2ba3072SPatrick Williams         reports.emplace_back(std::move(report));
8241b7e696bSLukasz Kazmierczak     }
8251b7e696bSLukasz Kazmierczak 
8263f215c92SSzymon Dompke     return {std::move(reports)};
8271b7e696bSLukasz Kazmierczak }
8281b7e696bSLukasz Kazmierczak 
8291b7e696bSLukasz Kazmierczak inline std::vector<std::string>
8301b7e696bSLukasz Kazmierczak     getMetricProperties(const TriggerSensorsParams& sensors)
8311b7e696bSLukasz Kazmierczak {
8321b7e696bSLukasz Kazmierczak     std::vector<std::string> metricProperties;
8331b7e696bSLukasz Kazmierczak     metricProperties.reserve(sensors.size());
8341b7e696bSLukasz Kazmierczak     for (const auto& [_, metadata] : sensors)
8351b7e696bSLukasz Kazmierczak     {
8361b7e696bSLukasz Kazmierczak         metricProperties.emplace_back(metadata);
8371b7e696bSLukasz Kazmierczak     }
8381b7e696bSLukasz Kazmierczak 
8391b7e696bSLukasz Kazmierczak     return metricProperties;
8401b7e696bSLukasz Kazmierczak }
8411b7e696bSLukasz Kazmierczak 
842e3648032SEd Tanous inline bool fillTrigger(nlohmann::json& json, const std::string& id,
843e3648032SEd Tanous                         const dbus::utility::DBusPropertiesMap& properties)
8441b7e696bSLukasz Kazmierczak {
8451b7e696bSLukasz Kazmierczak     const std::string* name = nullptr;
8461b7e696bSLukasz Kazmierczak     const bool* discrete = nullptr;
8471b7e696bSLukasz Kazmierczak     const TriggerSensorsParams* sensors = nullptr;
8483f215c92SSzymon Dompke     const std::vector<sdbusplus::message::object_path>* reports = nullptr;
84989474494SKrzysztof Grobelny     const std::vector<std::string>* triggerActions = nullptr;
85058c71488SEd Tanous 
85158c71488SEd Tanous     const std::vector<DiscreteThresholdParams>* discreteThresholds = nullptr;
85258c71488SEd Tanous     const std::vector<NumericThresholdParams>* numericThresholds = nullptr;
8531b7e696bSLukasz Kazmierczak 
85489474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
85589474494SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "Name", name, "Discrete",
85689474494SKrzysztof Grobelny         discrete, "Sensors", sensors, "Reports", reports, "TriggerActions",
85758c71488SEd Tanous         triggerActions, "DiscreteThresholds", discreteThresholds,
85858c71488SEd Tanous         "NumericThresholds", numericThresholds);
85989474494SKrzysztof Grobelny 
86089474494SKrzysztof Grobelny     if (!success)
8611b7e696bSLukasz Kazmierczak     {
86289474494SKrzysztof Grobelny         return false;
8631b7e696bSLukasz Kazmierczak     }
8641b7e696bSLukasz Kazmierczak 
86589474494SKrzysztof Grobelny     if (triggerActions != nullptr)
86689474494SKrzysztof Grobelny     {
867dd1c4a9cSSzymon Dompke         std::optional<nlohmann::json::array_t> redfishTriggerActions =
86889474494SKrzysztof Grobelny             getTriggerActions(*triggerActions);
86989474494SKrzysztof Grobelny         if (!redfishTriggerActions)
8701b7e696bSLukasz Kazmierczak         {
87162598e31SEd Tanous             BMCWEB_LOG_ERROR(
87262598e31SEd Tanous                 "Property TriggerActions is invalid in Trigger: {}", id);
8731b7e696bSLukasz Kazmierczak             return false;
8741b7e696bSLukasz Kazmierczak         }
875dd1c4a9cSSzymon Dompke         json["TriggerActions"] = *redfishTriggerActions;
87689474494SKrzysztof Grobelny     }
8771b7e696bSLukasz Kazmierczak 
87889474494SKrzysztof Grobelny     if (reports != nullptr)
8793f215c92SSzymon Dompke     {
8803f215c92SSzymon Dompke         std::optional<nlohmann::json> linkedReports =
8813f215c92SSzymon Dompke             getMetricReportDefinitions(*reports);
8823f215c92SSzymon Dompke         if (!linkedReports)
8833f215c92SSzymon Dompke         {
88462598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Reports is invalid in Trigger: {}", id);
8853f215c92SSzymon Dompke             return false;
8863f215c92SSzymon Dompke         }
88789474494SKrzysztof Grobelny         json["Links"]["MetricReportDefinitions"] = *linkedReports;
88889474494SKrzysztof Grobelny     }
8891b7e696bSLukasz Kazmierczak 
89058c71488SEd Tanous     if (discreteThresholds != nullptr)
8911b7e696bSLukasz Kazmierczak     {
8923f215c92SSzymon Dompke         std::optional<nlohmann::json::array_t> discreteTriggers =
89358c71488SEd Tanous             getDiscreteTriggers(*discreteThresholds);
8941b7e696bSLukasz Kazmierczak 
8951b7e696bSLukasz Kazmierczak         if (!discreteTriggers)
8961b7e696bSLukasz Kazmierczak         {
89762598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Thresholds is invalid for discrete "
89862598e31SEd Tanous                              "triggers in Trigger: {}",
89962598e31SEd Tanous                              id);
9001b7e696bSLukasz Kazmierczak             return false;
9011b7e696bSLukasz Kazmierczak         }
9021b7e696bSLukasz Kazmierczak 
9031b7e696bSLukasz Kazmierczak         json["DiscreteTriggers"] = *discreteTriggers;
9041b7e696bSLukasz Kazmierczak         json["DiscreteTriggerCondition"] =
9051b7e696bSLukasz Kazmierczak             discreteTriggers->empty() ? "Changed" : "Specified";
906539d8c6bSEd Tanous         json["MetricType"] = metric_definition::MetricType::Discrete;
9071b7e696bSLukasz Kazmierczak     }
90858c71488SEd Tanous     if (numericThresholds != nullptr)
9091b7e696bSLukasz Kazmierczak     {
91058c71488SEd Tanous         std::optional<nlohmann::json::object_t> jnumericThresholds =
91158c71488SEd Tanous             getNumericThresholds(*numericThresholds);
9121b7e696bSLukasz Kazmierczak 
91358c71488SEd Tanous         if (!jnumericThresholds)
9141b7e696bSLukasz Kazmierczak         {
91562598e31SEd Tanous             BMCWEB_LOG_ERROR("Property Thresholds is invalid for numeric "
91662598e31SEd Tanous                              "thresholds in Trigger: {}",
91762598e31SEd Tanous                              id);
9181b7e696bSLukasz Kazmierczak             return false;
9191b7e696bSLukasz Kazmierczak         }
9201b7e696bSLukasz Kazmierczak 
92158c71488SEd Tanous         json["NumericThresholds"] = *jnumericThresholds;
922539d8c6bSEd Tanous         json["MetricType"] = metric_definition::MetricType::Numeric;
9231b7e696bSLukasz Kazmierczak     }
92489474494SKrzysztof Grobelny 
92589474494SKrzysztof Grobelny     if (name != nullptr)
92689474494SKrzysztof Grobelny     {
92789474494SKrzysztof Grobelny         json["Name"] = *name;
92889474494SKrzysztof Grobelny     }
92989474494SKrzysztof Grobelny 
93089474494SKrzysztof Grobelny     if (sensors != nullptr)
93189474494SKrzysztof Grobelny     {
93289474494SKrzysztof Grobelny         json["MetricProperties"] = getMetricProperties(*sensors);
93389474494SKrzysztof Grobelny     }
9341b7e696bSLukasz Kazmierczak 
9353f215c92SSzymon Dompke     json["@odata.type"] = "#Triggers.v1_2_0.Triggers";
936ef4c65b7SEd Tanous     json["@odata.id"] =
937ef4c65b7SEd Tanous         boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
9383f215c92SSzymon Dompke     json["Id"] = id;
9391b7e696bSLukasz Kazmierczak 
9401b7e696bSLukasz Kazmierczak     return true;
9411b7e696bSLukasz Kazmierczak }
9421b7e696bSLukasz Kazmierczak 
943dd1c4a9cSSzymon Dompke inline void handleTriggerCollectionPost(
944dd1c4a9cSSzymon Dompke     App& app, const crow::Request& req,
945dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
946dd1c4a9cSSzymon Dompke {
947dd1c4a9cSSzymon Dompke     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
948dd1c4a9cSSzymon Dompke     {
949dd1c4a9cSSzymon Dompke         return;
950dd1c4a9cSSzymon Dompke     }
951dd1c4a9cSSzymon Dompke 
952dd1c4a9cSSzymon Dompke     telemetry::Context ctx;
953dd1c4a9cSSzymon Dompke     if (!telemetry::parsePostTriggerParams(asyncResp->res, req, ctx))
954dd1c4a9cSSzymon Dompke     {
955dd1c4a9cSSzymon Dompke         return;
956dd1c4a9cSSzymon Dompke     }
957dd1c4a9cSSzymon Dompke 
958dd1c4a9cSSzymon Dompke     crow::connections::systemBus->async_method_call(
959dd1c4a9cSSzymon Dompke         [asyncResp, id = ctx.id](const boost::system::error_code& ec,
960dd1c4a9cSSzymon Dompke                                  const std::string& dbusPath) {
961dd1c4a9cSSzymon Dompke             afterCreateTrigger(ec, dbusPath, asyncResp, id);
962dd1c4a9cSSzymon Dompke         },
963dd1c4a9cSSzymon Dompke         service, "/xyz/openbmc_project/Telemetry/Triggers",
964dd1c4a9cSSzymon Dompke         "xyz.openbmc_project.Telemetry.TriggerManager", "AddTrigger",
965dd1c4a9cSSzymon Dompke         "TelemetryService/" + ctx.id, ctx.name, ctx.actions, ctx.sensors,
96658c71488SEd Tanous         ctx.reports, ctx.numericThresholds, ctx.discreteThresholds);
967dd1c4a9cSSzymon Dompke }
968dd1c4a9cSSzymon Dompke 
96907148cf2SLukasz Kazmierczak } // namespace telemetry
97007148cf2SLukasz Kazmierczak 
97107148cf2SLukasz Kazmierczak inline void requestRoutesTriggerCollection(App& app)
97207148cf2SLukasz Kazmierczak {
97307148cf2SLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
97407148cf2SLukasz Kazmierczak         .privileges(redfish::privileges::getTriggersCollection)
97507148cf2SLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
97645ca1b86SEd Tanous             [&app](const crow::Request& req,
97707148cf2SLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9783ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
97945ca1b86SEd Tanous                 {
98045ca1b86SEd Tanous                     return;
98145ca1b86SEd Tanous                 }
98207148cf2SLukasz Kazmierczak                 asyncResp->res.jsonValue["@odata.type"] =
98307148cf2SLukasz Kazmierczak                     "#TriggersCollection.TriggersCollection";
984ae9031f0SWilly Tu                 asyncResp->res.jsonValue["@odata.id"] =
985ae9031f0SWilly Tu                     "/redfish/v1/TelemetryService/Triggers";
98607148cf2SLukasz Kazmierczak                 asyncResp->res.jsonValue["Name"] = "Triggers Collection";
9877a1dbc48SGeorge Liu                 constexpr std::array<std::string_view, 1> interfaces{
9887a1dbc48SGeorge Liu                     telemetry::triggerInterface};
98907148cf2SLukasz Kazmierczak                 collection_util::getCollectionMembers(
990ae9031f0SWilly Tu                     asyncResp,
991ae9031f0SWilly Tu                     boost::urls::url("/redfish/v1/TelemetryService/Triggers"),
992ae9031f0SWilly Tu                     interfaces,
99307148cf2SLukasz Kazmierczak                     "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
99407148cf2SLukasz Kazmierczak             });
995dd1c4a9cSSzymon Dompke 
996dd1c4a9cSSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
997dd1c4a9cSSzymon Dompke         .privileges(redfish::privileges::postTriggersCollection)
998dd1c4a9cSSzymon Dompke         .methods(boost::beast::http::verb::post)(std::bind_front(
999dd1c4a9cSSzymon Dompke             telemetry::handleTriggerCollectionPost, std::ref(app)));
100007148cf2SLukasz Kazmierczak }
100107148cf2SLukasz Kazmierczak 
10021b7e696bSLukasz Kazmierczak inline void requestRoutesTrigger(App& app)
10031b7e696bSLukasz Kazmierczak {
10041b7e696bSLukasz Kazmierczak     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
10051b7e696bSLukasz Kazmierczak         .privileges(redfish::privileges::getTriggers)
10061b7e696bSLukasz Kazmierczak         .methods(boost::beast::http::verb::get)(
100745ca1b86SEd Tanous             [&app](const crow::Request& req,
10081b7e696bSLukasz Kazmierczak                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10091b7e696bSLukasz Kazmierczak                    const std::string& id) {
10103ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
101145ca1b86SEd Tanous                 {
101245ca1b86SEd Tanous                     return;
101345ca1b86SEd Tanous                 }
101489474494SKrzysztof Grobelny                 sdbusplus::asio::getAllProperties(
101589474494SKrzysztof Grobelny                     *crow::connections::systemBus, telemetry::service,
1016bd79bce8SPatrick Williams                     telemetry::getDbusTriggerPath(id),
1017bd79bce8SPatrick Williams                     telemetry::triggerInterface,
10181b7e696bSLukasz Kazmierczak                     [asyncResp,
10195e7e2dc5SEd Tanous                      id](const boost::system::error_code& ec,
1020e3648032SEd Tanous                          const dbus::utility::DBusPropertiesMap& ret) {
10211b7e696bSLukasz Kazmierczak                         if (ec.value() == EBADR ||
10221b7e696bSLukasz Kazmierczak                             ec == boost::system::errc::host_unreachable)
10231b7e696bSLukasz Kazmierczak                         {
1024bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
1025bd79bce8SPatrick Williams                                                        "Triggers", id);
10261b7e696bSLukasz Kazmierczak                             return;
10271b7e696bSLukasz Kazmierczak                         }
10281b7e696bSLukasz Kazmierczak                         if (ec)
10291b7e696bSLukasz Kazmierczak                         {
103062598e31SEd Tanous                             BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
10311b7e696bSLukasz Kazmierczak                             messages::internalError(asyncResp->res);
10321b7e696bSLukasz Kazmierczak                             return;
10331b7e696bSLukasz Kazmierczak                         }
10341b7e696bSLukasz Kazmierczak 
1035bd79bce8SPatrick Williams                         if (!telemetry::fillTrigger(asyncResp->res.jsonValue,
1036bd79bce8SPatrick Williams                                                     id, ret))
10371b7e696bSLukasz Kazmierczak                         {
10381b7e696bSLukasz Kazmierczak                             messages::internalError(asyncResp->res);
10391b7e696bSLukasz Kazmierczak                         }
104089474494SKrzysztof Grobelny                     });
10411b7e696bSLukasz Kazmierczak             });
1042163994a8SSzymon Dompke 
1043163994a8SSzymon Dompke     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
1044163994a8SSzymon Dompke         .privileges(redfish::privileges::deleteTriggers)
1045163994a8SSzymon Dompke         .methods(boost::beast::http::verb::delete_)(
104645ca1b86SEd Tanous             [&app](const crow::Request& req,
1047163994a8SSzymon Dompke                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1048163994a8SSzymon Dompke                    const std::string& id) {
10493ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
105045ca1b86SEd Tanous                 {
105145ca1b86SEd Tanous                     return;
105245ca1b86SEd Tanous                 }
1053bd79bce8SPatrick Williams                 const std::string triggerPath =
1054bd79bce8SPatrick Williams                     telemetry::getDbusTriggerPath(id);
1055163994a8SSzymon Dompke 
1056163994a8SSzymon Dompke                 crow::connections::systemBus->async_method_call(
10575e7e2dc5SEd Tanous                     [asyncResp, id](const boost::system::error_code& ec) {
1058163994a8SSzymon Dompke                         if (ec.value() == EBADR)
1059163994a8SSzymon Dompke                         {
1060bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res,
1061bd79bce8SPatrick Williams                                                        "Triggers", id);
1062163994a8SSzymon Dompke                             return;
1063163994a8SSzymon Dompke                         }
1064163994a8SSzymon Dompke 
1065163994a8SSzymon Dompke                         if (ec)
1066163994a8SSzymon Dompke                         {
106762598e31SEd Tanous                             BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
1068163994a8SSzymon Dompke                             messages::internalError(asyncResp->res);
1069163994a8SSzymon Dompke                             return;
1070163994a8SSzymon Dompke                         }
1071163994a8SSzymon Dompke 
1072bd79bce8SPatrick Williams                         asyncResp->res.result(
1073bd79bce8SPatrick Williams                             boost::beast::http::status::no_content);
1074163994a8SSzymon Dompke                     },
1075163994a8SSzymon Dompke                     telemetry::service, triggerPath,
1076163994a8SSzymon Dompke                     "xyz.openbmc_project.Object.Delete", "Delete");
1077163994a8SSzymon Dompke             });
10781b7e696bSLukasz Kazmierczak }
10791b7e696bSLukasz Kazmierczak 
108007148cf2SLukasz Kazmierczak } // namespace redfish
1081