xref: /openbmc/telemetry/src/trigger.cpp (revision 583ba441654657bb4ba9d051b747144a7258c159)
176833cb5SWludzik, Jozef #include "trigger.hpp"
276833cb5SWludzik, Jozef 
3e6d48874SKrzysztof Grobelny #include "messages/collect_trigger_id.hpp"
4e6d48874SKrzysztof Grobelny #include "messages/trigger_presence_changed_ind.hpp"
5e28aa53dSSzymon Dompke #include "trigger_manager.hpp"
6dcc4e193SKrzysztof Grobelny #include "types/report_types.hpp"
7dcc4e193SKrzysztof Grobelny #include "types/trigger_types.hpp"
8e6d48874SKrzysztof Grobelny #include "utils/contains.hpp"
94416fce6SCezary Zwolak #include "utils/conversion_trigger.hpp"
101cdd7e4fSSzymon Dompke #include "utils/dbus_path_utils.hpp"
11a4e67616SCezary Zwolak #include "utils/transform.hpp"
12a4e67616SCezary Zwolak 
13a4e67616SCezary Zwolak #include <phosphor-logging/log.hpp>
14a4e67616SCezary Zwolak 
Trigger(boost::asio::io_context & ioc,const std::shared_ptr<sdbusplus::asio::object_server> & objServer,TriggerId && idIn,const std::string & nameIn,const std::vector<TriggerAction> & triggerActionsIn,const std::shared_ptr<std::vector<std::string>> reportIdsIn,std::vector<std::shared_ptr<interfaces::Threshold>> && thresholdsIn,interfaces::TriggerManager & triggerManager,interfaces::JsonStorage & triggerStorageIn,const interfaces::TriggerFactory & triggerFactory,Sensors sensorsIn)1576833cb5SWludzik, Jozef Trigger::Trigger(
1676833cb5SWludzik, Jozef     boost::asio::io_context& ioc,
1776833cb5SWludzik, Jozef     const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
18b7b7e1b6SSzymon Dompke     TriggerId&& idIn, const std::string& nameIn,
1994f71c51SSzymon Dompke     const std::vector<TriggerAction>& triggerActionsIn,
2094f71c51SSzymon Dompke     const std::shared_ptr<std::vector<std::string>> reportIdsIn,
211477fe6aSWludzik, Jozef     std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn,
22a4e67616SCezary Zwolak     interfaces::TriggerManager& triggerManager,
2394f71c51SSzymon Dompke     interfaces::JsonStorage& triggerStorageIn,
24e6d48874SKrzysztof Grobelny     const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) :
25b7b7e1b6SSzymon Dompke     id(std::move(idIn)),
261cdd7e4fSSzymon Dompke     path(utils::pathAppend(utils::constants::triggerDirPath, *id)),
27e28aa53dSSzymon Dompke     name(nameIn), triggerActions(std::move(triggerActionsIn)),
281cdd7e4fSSzymon Dompke     reportIds(std::move(reportIdsIn)), thresholds(std::move(thresholdsIn)),
29b7b7e1b6SSzymon Dompke     fileName(std::to_string(std::hash<std::string>{}(*id))),
30b4ef22e4SSzymon Dompke     triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)),
31e6d48874SKrzysztof Grobelny     messanger(ioc)
3276833cb5SWludzik, Jozef {
3376833cb5SWludzik, Jozef     deleteIface = objServer->add_unique_interface(
__anon5e4599b80102(auto& dbusIface) 3476833cb5SWludzik, Jozef         path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) {
3576833cb5SWludzik, Jozef             dbusIface.register_method("Delete", [this, &ioc, &triggerManager] {
36a4e67616SCezary Zwolak                 if (persistent)
37a4e67616SCezary Zwolak                 {
38a4e67616SCezary Zwolak                     triggerStorage.remove(fileName);
39a4e67616SCezary Zwolak                 }
40e6d48874SKrzysztof Grobelny                 messanger.send(messages::TriggerPresenceChangedInd{
41b7b7e1b6SSzymon Dompke                     messages::Presence::Removed, *id, {}});
4276833cb5SWludzik, Jozef                 boost::asio::post(ioc, [this, &triggerManager] {
4376833cb5SWludzik, Jozef                     triggerManager.removeTrigger(this);
4476833cb5SWludzik, Jozef                 });
4576833cb5SWludzik, Jozef             });
4676833cb5SWludzik, Jozef         });
4776833cb5SWludzik, Jozef 
4876833cb5SWludzik, Jozef     triggerIface = objServer->add_unique_interface(
__anon5e4599b80402(auto& dbusIface) 4994f71c51SSzymon Dompke         path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) {
50a4e67616SCezary Zwolak             persistent = storeConfiguration();
51a4e67616SCezary Zwolak             dbusIface.register_property_rw(
5276833cb5SWludzik, Jozef                 "Persistent", persistent,
5376833cb5SWludzik, Jozef                 sdbusplus::vtable::property_::emits_change,
54a4e67616SCezary Zwolak                 [this](bool newVal, const auto&) {
55a4e67616SCezary Zwolak                     if (newVal == persistent)
56a4e67616SCezary Zwolak                     {
573e2cc9d4SSzymon Dompke                         return 1;
58a4e67616SCezary Zwolak                     }
59a4e67616SCezary Zwolak                     if (newVal)
60a4e67616SCezary Zwolak                     {
61a4e67616SCezary Zwolak                         persistent = storeConfiguration();
62a4e67616SCezary Zwolak                     }
63a4e67616SCezary Zwolak                     else
64a4e67616SCezary Zwolak                     {
65a4e67616SCezary Zwolak                         triggerStorage.remove(fileName);
66a4e67616SCezary Zwolak                         persistent = false;
67a4e67616SCezary Zwolak                     }
683e2cc9d4SSzymon Dompke                     return 1;
69*583ba441SPatrick Williams                 },
70*583ba441SPatrick Williams                 [this](const auto&) { return persistent; });
71a4e67616SCezary Zwolak 
7294f71c51SSzymon Dompke             dbusIface.register_property_rw(
734416fce6SCezary Zwolak                 "Thresholds", TriggerThresholdParams{},
7476833cb5SWludzik, Jozef                 sdbusplus::vtable::property_::emits_change,
7594f71c51SSzymon Dompke                 [this, &triggerFactory](auto newVal, auto& oldVal) {
76*583ba441SPatrick Williams                     auto newThresholdParams = std::visit(
77*583ba441SPatrick Williams                         utils::ToLabeledThresholdParamConversion(), newVal);
7832305f14SSzymon Dompke                     TriggerManager::verifyThresholdParams(newThresholdParams);
79*583ba441SPatrick Williams                     triggerFactory.updateThresholds(
80*583ba441SPatrick Williams                         thresholds, *id, triggerActions, reportIds, sensors,
8194f71c51SSzymon Dompke                         newThresholdParams);
8294f71c51SSzymon Dompke                     oldVal = std::move(newVal);
8394f71c51SSzymon Dompke                     return 1;
84*583ba441SPatrick Williams                 },
85*583ba441SPatrick Williams                 [this](const auto&) {
8655824558SKrzysztof Grobelny                     return fromLabeledThresholdParam(getLabeledThresholds());
874416fce6SCezary Zwolak                 });
884416fce6SCezary Zwolak 
8994f71c51SSzymon Dompke             dbusIface.register_property_rw(
902efa95d8SEd Tanous                 "DiscreteThresholds", std::vector<discrete::ThresholdParam>{},
912efa95d8SEd Tanous                 sdbusplus::vtable::property_::emits_change,
922efa95d8SEd Tanous                 [this, &triggerFactory](
932efa95d8SEd Tanous                     const std::vector<discrete::ThresholdParam>& newVal,
942efa95d8SEd Tanous                     std::vector<discrete::ThresholdParam>& oldVal) {
952efa95d8SEd Tanous                     LabeledTriggerThresholdParams newThresholdParams =
962efa95d8SEd Tanous                         utils::ToLabeledThresholdParamConversion()(newVal);
972efa95d8SEd Tanous                     TriggerManager::verifyThresholdParams(newThresholdParams);
98*583ba441SPatrick Williams                     triggerFactory.updateThresholds(
99*583ba441SPatrick Williams                         thresholds, *id, triggerActions, reportIds, sensors,
1002efa95d8SEd Tanous                         newThresholdParams);
1012efa95d8SEd Tanous                     oldVal = std::move(newVal);
1022efa95d8SEd Tanous                     return 1;
1032efa95d8SEd Tanous                 },
1042efa95d8SEd Tanous                 [this](const auto&) {
1052efa95d8SEd Tanous                     TriggerThresholdParams unlabeled =
1062efa95d8SEd Tanous                         fromLabeledThresholdParam(getLabeledThresholds());
1072efa95d8SEd Tanous                     auto* ptr =
108*583ba441SPatrick Williams                         std::get_if<std::vector<discrete::ThresholdParam>>(
109*583ba441SPatrick Williams                             &unlabeled);
1102efa95d8SEd Tanous                     if (ptr == nullptr)
1112efa95d8SEd Tanous                     {
1122efa95d8SEd Tanous                         // If internal type doesn't match, return empty set
1132efa95d8SEd Tanous                         return std::vector<discrete::ThresholdParam>{};
1142efa95d8SEd Tanous                     }
1152efa95d8SEd Tanous                     return *ptr;
1162efa95d8SEd Tanous                 });
1172efa95d8SEd Tanous 
1182efa95d8SEd Tanous             dbusIface.register_property_rw(
1192efa95d8SEd Tanous                 "NumericThresholds", std::vector<numeric::ThresholdParam>{},
1202efa95d8SEd Tanous                 sdbusplus::vtable::property_::emits_change,
1212efa95d8SEd Tanous                 [this, &triggerFactory](
1222efa95d8SEd Tanous                     const std::vector<numeric::ThresholdParam>& newVal,
1232efa95d8SEd Tanous                     std::vector<numeric::ThresholdParam>& oldVal) {
1242efa95d8SEd Tanous                     LabeledTriggerThresholdParams newThresholdParams =
1252efa95d8SEd Tanous                         utils::ToLabeledThresholdParamConversion()(newVal);
1262efa95d8SEd Tanous                     TriggerManager::verifyThresholdParams(newThresholdParams);
127*583ba441SPatrick Williams                     triggerFactory.updateThresholds(
128*583ba441SPatrick Williams                         thresholds, *id, triggerActions, reportIds, sensors,
1292efa95d8SEd Tanous                         newThresholdParams);
1302efa95d8SEd Tanous                     oldVal = std::move(newVal);
1312efa95d8SEd Tanous                     return 1;
1322efa95d8SEd Tanous                 },
1332efa95d8SEd Tanous                 [this](const auto&) {
1342efa95d8SEd Tanous                     TriggerThresholdParams unlabeled =
1352efa95d8SEd Tanous                         fromLabeledThresholdParam(getLabeledThresholds());
1362efa95d8SEd Tanous                     auto* ptr =
137*583ba441SPatrick Williams                         std::get_if<std::vector<numeric::ThresholdParam>>(
138*583ba441SPatrick Williams                             &unlabeled);
1392efa95d8SEd Tanous                     if (ptr == nullptr)
1402efa95d8SEd Tanous                     {
1412efa95d8SEd Tanous                         // If internal type doesn't match, return empty set
1422efa95d8SEd Tanous                         return std::vector<numeric::ThresholdParam>{};
1432efa95d8SEd Tanous                     }
1442efa95d8SEd Tanous                     return *ptr;
1452efa95d8SEd Tanous                 });
1462efa95d8SEd Tanous             dbusIface.register_property_rw(
1474416fce6SCezary Zwolak                 "Sensors", SensorsInfo{},
1484416fce6SCezary Zwolak                 sdbusplus::vtable::property_::emits_change,
14994f71c51SSzymon Dompke                 [this, &triggerFactory](auto newVal, auto& oldVal) {
15094f71c51SSzymon Dompke                     auto labeledSensorInfo =
15194f71c51SSzymon Dompke                         triggerFactory.getLabeledSensorsInfo(newVal);
15294f71c51SSzymon Dompke                     triggerFactory.updateSensors(sensors, labeledSensorInfo);
15394f71c51SSzymon Dompke                     for (const auto& threshold : thresholds)
15494f71c51SSzymon Dompke                     {
15594f71c51SSzymon Dompke                         threshold->updateSensors(sensors);
15694f71c51SSzymon Dompke                     }
15794f71c51SSzymon Dompke                     oldVal = std::move(newVal);
15894f71c51SSzymon Dompke                     return 1;
159*583ba441SPatrick Williams                 },
160*583ba441SPatrick Williams                 [this](const auto&) {
161*583ba441SPatrick Williams                     return utils::fromLabeledSensorsInfo(
162*583ba441SPatrick Williams                         getLabeledSensorInfo());
1634416fce6SCezary Zwolak                 });
1644416fce6SCezary Zwolak 
16594f71c51SSzymon Dompke             dbusIface.register_property_rw(
1661cdd7e4fSSzymon Dompke                 "Reports", std::vector<sdbusplus::message::object_path>(),
16776833cb5SWludzik, Jozef                 sdbusplus::vtable::property_::emits_change,
16894f71c51SSzymon Dompke                 [this](auto newVal, auto& oldVal) {
1691cdd7e4fSSzymon Dompke                     auto newReportIds = utils::transform<std::vector>(
170*583ba441SPatrick Williams                         newVal, [](const auto& path) {
171*583ba441SPatrick Williams                             return utils::reportPathToId(path);
172*583ba441SPatrick Williams                         });
1731cdd7e4fSSzymon Dompke                     TriggerManager::verifyReportIds(newReportIds);
1741cdd7e4fSSzymon Dompke                     *reportIds = newReportIds;
175e6d48874SKrzysztof Grobelny                     messanger.send(messages::TriggerPresenceChangedInd{
176b7b7e1b6SSzymon Dompke                         messages::Presence::Exist, *id, *reportIds});
17794f71c51SSzymon Dompke                     oldVal = std::move(newVal);
17894f71c51SSzymon Dompke                     return 1;
179*583ba441SPatrick Williams                 },
180*583ba441SPatrick Williams                 [this](const auto&) {
181*583ba441SPatrick Williams                     return utils::transform<std::vector>(
182*583ba441SPatrick Williams                         *reportIds, [](const auto& id) {
183*583ba441SPatrick Williams                             return utils::pathAppend(
184*583ba441SPatrick Williams                                 utils::constants::reportDirPath, id);
1851cdd7e4fSSzymon Dompke                         });
1861cdd7e4fSSzymon Dompke                 });
1872001301aSSzymon Dompke 
1882001301aSSzymon Dompke             dbusIface.register_property_r(
18955824558SKrzysztof Grobelny                 "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_,
19055824558SKrzysztof Grobelny                 [this](const auto& x) { return isDiscreate(); });
1912001301aSSzymon Dompke 
192e28aa53dSSzymon Dompke             dbusIface.register_property_rw(
19355824558SKrzysztof Grobelny                 "Name", name, sdbusplus::vtable::property_::emits_change,
194e28aa53dSSzymon Dompke                 [this](auto newVal, auto& oldVal) {
19532305f14SSzymon Dompke                     if (newVal.length() > utils::constants::maxIdNameLength)
19632305f14SSzymon Dompke                     {
197*583ba441SPatrick Williams                         throw errors::InvalidArgument("Name",
198*583ba441SPatrick Williams                                                       "Name is too long.");
19932305f14SSzymon Dompke                     }
200e28aa53dSSzymon Dompke                     name = oldVal = newVal;
2013e2cc9d4SSzymon Dompke                     return 1;
202*583ba441SPatrick Williams                 },
203*583ba441SPatrick Williams                 [this](const auto&) { return name; });
204e28aa53dSSzymon Dompke 
205c7935fa1SPatrick Williams             dbusIface.register_property_r(
206c7935fa1SPatrick Williams                 "TriggerActions", std::vector<std::string>(),
207c7935fa1SPatrick Williams                 sdbusplus::vtable::property_::const_, [this](const auto&) {
208*583ba441SPatrick Williams                     return utils::transform(triggerActions,
209*583ba441SPatrick Williams                                             [](const auto& action) {
21094f71c51SSzymon Dompke                                                 return actionToString(action);
21194f71c51SSzymon Dompke                                             });
21294f71c51SSzymon Dompke                 });
21376833cb5SWludzik, Jozef         });
2141477fe6aSWludzik, Jozef 
2151477fe6aSWludzik, Jozef     for (const auto& threshold : thresholds)
2161477fe6aSWludzik, Jozef     {
2171477fe6aSWludzik, Jozef         threshold->initialize();
2181477fe6aSWludzik, Jozef     }
219b4ef22e4SSzymon Dompke 
220e6d48874SKrzysztof Grobelny     messanger.on_receive<messages::CollectTriggerIdReq>(
__anon5e4599b81802(const auto& msg) 221e6d48874SKrzysztof Grobelny         [this](const auto& msg) {
222e6d48874SKrzysztof Grobelny             if (utils::contains(*reportIds, msg.reportId))
223b4ef22e4SSzymon Dompke             {
224b7b7e1b6SSzymon Dompke                 messanger.send(messages::CollectTriggerIdResp{*id});
225b4ef22e4SSzymon Dompke             }
226e6d48874SKrzysztof Grobelny         });
227e6d48874SKrzysztof Grobelny 
228e6d48874SKrzysztof Grobelny     messanger.send(messages::TriggerPresenceChangedInd{
229b7b7e1b6SSzymon Dompke         messages::Presence::Exist, *id, *reportIds});
23076833cb5SWludzik, Jozef }
231a4e67616SCezary Zwolak 
storeConfiguration() const232a4e67616SCezary Zwolak bool Trigger::storeConfiguration() const
233a4e67616SCezary Zwolak {
234a4e67616SCezary Zwolak     try
235a4e67616SCezary Zwolak     {
236a4e67616SCezary Zwolak         nlohmann::json data;
237a4e67616SCezary Zwolak 
23894f71c51SSzymon Dompke         auto labeledThresholdParams =
23994f71c51SSzymon Dompke             std::visit(utils::ToLabeledThresholdParamConversion(),
24055824558SKrzysztof Grobelny                        fromLabeledThresholdParam(getLabeledThresholds()));
24194f71c51SSzymon Dompke 
242a4e67616SCezary Zwolak         data["Version"] = triggerVersion;
243b7b7e1b6SSzymon Dompke         data["Id"] = *id;
244a4e67616SCezary Zwolak         data["Name"] = name;
2454416fce6SCezary Zwolak         data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index();
246*583ba441SPatrick Williams         data["TriggerActions"] =
247*583ba441SPatrick Williams             utils::transform(triggerActions, [](const auto& action) {
248*583ba441SPatrick Williams                 return actionToString(action);
249*583ba441SPatrick Williams             });
250a4e67616SCezary Zwolak         data["ThresholdParams"] =
2514416fce6SCezary Zwolak             utils::labeledThresholdParamsToJson(labeledThresholdParams);
25294f71c51SSzymon Dompke         data["ReportIds"] = *reportIds;
25355824558SKrzysztof Grobelny         data["Sensors"] = getLabeledSensorInfo();
254a4e67616SCezary Zwolak 
255a4e67616SCezary Zwolak         triggerStorage.store(fileName, data);
256a4e67616SCezary Zwolak     }
257a4e67616SCezary Zwolak     catch (const std::exception& e)
258a4e67616SCezary Zwolak     {
259a4e67616SCezary Zwolak         phosphor::logging::log<phosphor::logging::level::ERR>(
260a4e67616SCezary Zwolak             "Failed to store a trigger in storage",
261a4e67616SCezary Zwolak             phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
262a4e67616SCezary Zwolak         return false;
263a4e67616SCezary Zwolak     }
264a4e67616SCezary Zwolak     return true;
265a4e67616SCezary Zwolak }
26655824558SKrzysztof Grobelny 
getLabeledSensorInfo() const26755824558SKrzysztof Grobelny std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const
26855824558SKrzysztof Grobelny {
26955824558SKrzysztof Grobelny     return utils::transform(sensors, [](const auto& sensor) {
27055824558SKrzysztof Grobelny         return sensor->getLabeledSensorInfo();
27155824558SKrzysztof Grobelny     });
27255824558SKrzysztof Grobelny }
27355824558SKrzysztof Grobelny 
getLabeledThresholds() const27455824558SKrzysztof Grobelny std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const
27555824558SKrzysztof Grobelny {
27655824558SKrzysztof Grobelny     return utils::transform(thresholds, [](const auto& threshold) {
27755824558SKrzysztof Grobelny         return threshold->getThresholdParam();
27855824558SKrzysztof Grobelny     });
27955824558SKrzysztof Grobelny }
28055824558SKrzysztof Grobelny 
isDiscreate() const28155824558SKrzysztof Grobelny bool Trigger::isDiscreate() const
28255824558SKrzysztof Grobelny {
28355824558SKrzysztof Grobelny     const auto labeledThresholds = getLabeledThresholds();
28455824558SKrzysztof Grobelny 
28555824558SKrzysztof Grobelny     return utils::isFirstElementOfType<std::monostate>(labeledThresholds) ||
28655824558SKrzysztof Grobelny            utils::isFirstElementOfType<discrete::LabeledThresholdParam>(
28755824558SKrzysztof Grobelny                labeledThresholds);
28855824558SKrzysztof Grobelny }
289