xref: /openbmc/telemetry/src/trigger.cpp (revision e6d4887453f0b23b46c012da7cb26f2beb38ef0e)
1 #include "trigger.hpp"
2 
3 #include "messages/collect_trigger_id.hpp"
4 #include "messages/trigger_presence_changed_ind.hpp"
5 #include "trigger_manager.hpp"
6 #include "types/report_types.hpp"
7 #include "types/trigger_types.hpp"
8 #include "utils/contains.hpp"
9 #include "utils/conversion_trigger.hpp"
10 #include "utils/transform.hpp"
11 
12 #include <phosphor-logging/log.hpp>
13 
14 Trigger::Trigger(
15     boost::asio::io_context& ioc,
16     const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
17     const std::string& idIn, const std::string& nameIn,
18     const std::vector<TriggerAction>& triggerActionsIn,
19     const std::shared_ptr<std::vector<std::string>> reportIdsIn,
20     std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn,
21     interfaces::TriggerManager& triggerManager,
22     interfaces::JsonStorage& triggerStorageIn,
23     const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) :
24     id(idIn),
25     name(nameIn), triggerActions(std::move(triggerActionsIn)),
26     path(triggerDir + id), reportIds(std::move(reportIdsIn)),
27     thresholds(std::move(thresholdsIn)),
28     fileName(std::to_string(std::hash<std::string>{}(id))),
29     triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)),
30     messanger(ioc)
31 {
32     deleteIface = objServer->add_unique_interface(
33         path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) {
34             dbusIface.register_method("Delete", [this, &ioc, &triggerManager] {
35                 if (persistent)
36                 {
37                     triggerStorage.remove(fileName);
38                 }
39                 messanger.send(messages::TriggerPresenceChangedInd{
40                     messages::Presence::Removed, id, {}});
41                 boost::asio::post(ioc, [this, &triggerManager] {
42                     triggerManager.removeTrigger(this);
43                 });
44             });
45         });
46 
47     triggerIface = objServer->add_unique_interface(
48         path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) {
49             persistent = storeConfiguration();
50             dbusIface.register_property_rw(
51                 "Persistent", persistent,
52                 sdbusplus::vtable::property_::emits_change,
53                 [this](bool newVal, const auto&) {
54                     if (newVal == persistent)
55                     {
56                         return 1;
57                     }
58                     if (newVal)
59                     {
60                         persistent = storeConfiguration();
61                     }
62                     else
63                     {
64                         triggerStorage.remove(fileName);
65                         persistent = false;
66                     }
67                     return 1;
68                 },
69                 [this](const auto&) { return persistent; });
70 
71             dbusIface.register_property_rw(
72                 "Thresholds", TriggerThresholdParams{},
73                 sdbusplus::vtable::property_::emits_change,
74                 [this, &triggerFactory](auto newVal, auto& oldVal) {
75                     auto newThresholdParams = std::visit(
76                         utils::ToLabeledThresholdParamConversion(), newVal);
77                     triggerFactory.updateThresholds(thresholds, triggerActions,
78                                                     reportIds, sensors,
79                                                     newThresholdParams);
80                     oldVal = std::move(newVal);
81                     return 1;
82                 },
83                 [this](const auto&) {
84                     return fromLabeledThresholdParam(
85                         utils::transform(thresholds, [](const auto& threshold) {
86                             return threshold->getThresholdParam();
87                         }));
88                 });
89 
90             dbusIface.register_property_rw(
91                 "Sensors", SensorsInfo{},
92                 sdbusplus::vtable::property_::emits_change,
93                 [this, &triggerFactory](auto newVal, auto& oldVal) {
94                     auto labeledSensorInfo =
95                         triggerFactory.getLabeledSensorsInfo(newVal);
96                     triggerFactory.updateSensors(sensors, labeledSensorInfo);
97                     for (const auto& threshold : thresholds)
98                     {
99                         threshold->updateSensors(sensors);
100                     }
101                     oldVal = std::move(newVal);
102                     return 1;
103                 },
104                 [this](const auto&) {
105                     return utils::fromLabeledSensorsInfo(
106                         utils::transform(sensors, [](const auto& sensor) {
107                             return sensor->getLabeledSensorInfo();
108                         }));
109                 });
110 
111             dbusIface.register_property_rw(
112                 "ReportNames", std::vector<std::string>{},
113                 sdbusplus::vtable::property_::emits_change,
114                 [this](auto newVal, auto& oldVal) {
115                     TriggerManager::verifyReportIds(newVal);
116                     *reportIds = newVal;
117                     messanger.send(messages::TriggerPresenceChangedInd{
118                         messages::Presence::Exist, id, *reportIds});
119                     oldVal = std::move(newVal);
120                     return 1;
121                 },
122                 [this](const auto&) { return *reportIds; });
123 
124             dbusIface.register_property_r(
125                 "Discrete", false, sdbusplus::vtable::property_::const_,
126                 [this](const auto& x) {
127                     return !std::holds_alternative<
128                         numeric::LabeledThresholdParam>(
129                         thresholds.back()->getThresholdParam());
130                 });
131 
132             dbusIface.register_property_rw(
133                 "Name", std::string(),
134                 sdbusplus::vtable::property_::emits_change,
135                 [this](auto newVal, auto& oldVal) {
136                     name = oldVal = newVal;
137                     return 1;
138                 },
139                 [this](const auto&) { return name; });
140 
141             dbusIface.register_property_r(
142                 "TriggerActions", std::vector<std::string>(),
143                 sdbusplus::vtable::property_::const_, [this](const auto&) {
144                     return utils::transform(triggerActions,
145                                             [](const auto& action) {
146                                                 return actionToString(action);
147                                             });
148                 });
149         });
150 
151     for (const auto& threshold : thresholds)
152     {
153         threshold->initialize();
154     }
155 
156     messanger.on_receive<messages::CollectTriggerIdReq>(
157         [this](const auto& msg) {
158             if (utils::contains(*reportIds, msg.reportId))
159             {
160                 messanger.send(messages::CollectTriggerIdResp{id});
161             }
162         });
163 
164     messanger.send(messages::TriggerPresenceChangedInd{
165         messages::Presence::Exist, id, *reportIds});
166 }
167 
168 bool Trigger::storeConfiguration() const
169 {
170     try
171     {
172         nlohmann::json data;
173 
174         auto labeledThresholdParams =
175             std::visit(utils::ToLabeledThresholdParamConversion(),
176                        fromLabeledThresholdParam(utils::transform(
177                            thresholds, [](const auto& threshold) {
178                                return threshold->getThresholdParam();
179                            })));
180 
181         data["Version"] = triggerVersion;
182         data["Id"] = id;
183         data["Name"] = name;
184         data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index();
185         data["TriggerActions"] =
186             utils::transform(triggerActions, [](const auto& action) {
187                 return actionToString(action);
188             });
189         data["ThresholdParams"] =
190             utils::labeledThresholdParamsToJson(labeledThresholdParams);
191         data["ReportIds"] = *reportIds;
192         data["Sensors"] = utils::transform(sensors, [](const auto& sensor) {
193             return sensor->getLabeledSensorInfo();
194         });
195 
196         triggerStorage.store(fileName, data);
197     }
198     catch (const std::exception& e)
199     {
200         phosphor::logging::log<phosphor::logging::level::ERR>(
201             "Failed to store a trigger in storage",
202             phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
203         return false;
204     }
205     return true;
206 }
207