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/dbus_path_utils.hpp"
11 #include "utils/transform.hpp"
12
13 #include <phosphor-logging/log.hpp>
14
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)15 Trigger::Trigger(
16 boost::asio::io_context& ioc,
17 const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
18 TriggerId&& idIn, const std::string& nameIn,
19 const std::vector<TriggerAction>& triggerActionsIn,
20 const std::shared_ptr<std::vector<std::string>> reportIdsIn,
21 std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn,
22 interfaces::TriggerManager& triggerManager,
23 interfaces::JsonStorage& triggerStorageIn,
24 const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) :
25 id(std::move(idIn)),
26 path(utils::pathAppend(utils::constants::triggerDirPath, *id)),
27 name(nameIn), triggerActions(std::move(triggerActionsIn)),
28 reportIds(std::move(reportIdsIn)), thresholds(std::move(thresholdsIn)),
29 fileName(std::to_string(std::hash<std::string>{}(*id))),
30 triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)),
31 messanger(ioc)
32 {
33 deleteIface = objServer->add_unique_interface(
__anon5e4599b80102(auto& dbusIface) 34 path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) {
35 dbusIface.register_method("Delete", [this, &ioc, &triggerManager] {
36 if (persistent)
37 {
38 triggerStorage.remove(fileName);
39 }
40 messanger.send(messages::TriggerPresenceChangedInd{
41 messages::Presence::Removed, *id, {}});
42 boost::asio::post(ioc, [this, &triggerManager] {
43 triggerManager.removeTrigger(this);
44 });
45 });
46 });
47
48 triggerIface = objServer->add_unique_interface(
__anon5e4599b80402(auto& dbusIface) 49 path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) {
50 persistent = storeConfiguration();
51 dbusIface.register_property_rw(
52 "Persistent", persistent,
53 sdbusplus::vtable::property_::emits_change,
54 [this](bool newVal, const auto&) {
55 if (newVal == persistent)
56 {
57 return 1;
58 }
59 if (newVal)
60 {
61 persistent = storeConfiguration();
62 }
63 else
64 {
65 triggerStorage.remove(fileName);
66 persistent = false;
67 }
68 return 1;
69 },
70 [this](const auto&) { return persistent; });
71
72 dbusIface.register_property_rw(
73 "Thresholds", TriggerThresholdParams{},
74 sdbusplus::vtable::property_::emits_change,
75 [this, &triggerFactory](auto newVal, auto& oldVal) {
76 auto newThresholdParams = std::visit(
77 utils::ToLabeledThresholdParamConversion(), newVal);
78 TriggerManager::verifyThresholdParams(newThresholdParams);
79 triggerFactory.updateThresholds(
80 thresholds, *id, triggerActions, reportIds, sensors,
81 newThresholdParams);
82 oldVal = std::move(newVal);
83 return 1;
84 },
85 [this](const auto&) {
86 return fromLabeledThresholdParam(getLabeledThresholds());
87 });
88
89 dbusIface.register_property_rw(
90 "DiscreteThresholds", std::vector<discrete::ThresholdParam>{},
91 sdbusplus::vtable::property_::emits_change,
92 [this, &triggerFactory](
93 const std::vector<discrete::ThresholdParam>& newVal,
94 std::vector<discrete::ThresholdParam>& oldVal) {
95 LabeledTriggerThresholdParams newThresholdParams =
96 utils::ToLabeledThresholdParamConversion()(newVal);
97 TriggerManager::verifyThresholdParams(newThresholdParams);
98 triggerFactory.updateThresholds(
99 thresholds, *id, triggerActions, reportIds, sensors,
100 newThresholdParams);
101 oldVal = std::move(newVal);
102 return 1;
103 },
104 [this](const auto&) {
105 TriggerThresholdParams unlabeled =
106 fromLabeledThresholdParam(getLabeledThresholds());
107 auto* ptr =
108 std::get_if<std::vector<discrete::ThresholdParam>>(
109 &unlabeled);
110 if (ptr == nullptr)
111 {
112 // If internal type doesn't match, return empty set
113 return std::vector<discrete::ThresholdParam>{};
114 }
115 return *ptr;
116 });
117
118 dbusIface.register_property_rw(
119 "NumericThresholds", std::vector<numeric::ThresholdParam>{},
120 sdbusplus::vtable::property_::emits_change,
121 [this, &triggerFactory](
122 const std::vector<numeric::ThresholdParam>& newVal,
123 std::vector<numeric::ThresholdParam>& oldVal) {
124 LabeledTriggerThresholdParams newThresholdParams =
125 utils::ToLabeledThresholdParamConversion()(newVal);
126 TriggerManager::verifyThresholdParams(newThresholdParams);
127 triggerFactory.updateThresholds(
128 thresholds, *id, triggerActions, reportIds, sensors,
129 newThresholdParams);
130 oldVal = std::move(newVal);
131 return 1;
132 },
133 [this](const auto&) {
134 TriggerThresholdParams unlabeled =
135 fromLabeledThresholdParam(getLabeledThresholds());
136 auto* ptr =
137 std::get_if<std::vector<numeric::ThresholdParam>>(
138 &unlabeled);
139 if (ptr == nullptr)
140 {
141 // If internal type doesn't match, return empty set
142 return std::vector<numeric::ThresholdParam>{};
143 }
144 return *ptr;
145 });
146 dbusIface.register_property_rw(
147 "Sensors", SensorsInfo{},
148 sdbusplus::vtable::property_::emits_change,
149 [this, &triggerFactory](auto newVal, auto& oldVal) {
150 auto labeledSensorInfo =
151 triggerFactory.getLabeledSensorsInfo(newVal);
152 triggerFactory.updateSensors(sensors, labeledSensorInfo);
153 for (const auto& threshold : thresholds)
154 {
155 threshold->updateSensors(sensors);
156 }
157 oldVal = std::move(newVal);
158 return 1;
159 },
160 [this](const auto&) {
161 return utils::fromLabeledSensorsInfo(
162 getLabeledSensorInfo());
163 });
164
165 dbusIface.register_property_rw(
166 "Reports", std::vector<sdbusplus::message::object_path>(),
167 sdbusplus::vtable::property_::emits_change,
168 [this](auto newVal, auto& oldVal) {
169 auto newReportIds = utils::transform<std::vector>(
170 newVal, [](const auto& path) {
171 return utils::reportPathToId(path);
172 });
173 TriggerManager::verifyReportIds(newReportIds);
174 *reportIds = newReportIds;
175 messanger.send(messages::TriggerPresenceChangedInd{
176 messages::Presence::Exist, *id, *reportIds});
177 oldVal = std::move(newVal);
178 return 1;
179 },
180 [this](const auto&) {
181 return utils::transform<std::vector>(
182 *reportIds, [](const auto& id) {
183 return utils::pathAppend(
184 utils::constants::reportDirPath, id);
185 });
186 });
187
188 dbusIface.register_property_r(
189 "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_,
190 [this](const auto& x) { return isDiscreate(); });
191
192 dbusIface.register_property_rw(
193 "Name", name, sdbusplus::vtable::property_::emits_change,
194 [this](auto newVal, auto& oldVal) {
195 if (newVal.length() > utils::constants::maxIdNameLength)
196 {
197 throw errors::InvalidArgument("Name",
198 "Name is too long.");
199 }
200 name = oldVal = newVal;
201 return 1;
202 },
203 [this](const auto&) { return name; });
204
205 dbusIface.register_property_r(
206 "TriggerActions", std::vector<std::string>(),
207 sdbusplus::vtable::property_::const_, [this](const auto&) {
208 return utils::transform(triggerActions,
209 [](const auto& action) {
210 return actionToString(action);
211 });
212 });
213 });
214
215 for (const auto& threshold : thresholds)
216 {
217 threshold->initialize();
218 }
219
220 messanger.on_receive<messages::CollectTriggerIdReq>(
__anon5e4599b81802(const auto& msg) 221 [this](const auto& msg) {
222 if (utils::contains(*reportIds, msg.reportId))
223 {
224 messanger.send(messages::CollectTriggerIdResp{*id});
225 }
226 });
227
228 messanger.send(messages::TriggerPresenceChangedInd{
229 messages::Presence::Exist, *id, *reportIds});
230 }
231
storeConfiguration() const232 bool Trigger::storeConfiguration() const
233 {
234 try
235 {
236 nlohmann::json data;
237
238 auto labeledThresholdParams =
239 std::visit(utils::ToLabeledThresholdParamConversion(),
240 fromLabeledThresholdParam(getLabeledThresholds()));
241
242 data["Version"] = triggerVersion;
243 data["Id"] = *id;
244 data["Name"] = name;
245 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index();
246 data["TriggerActions"] =
247 utils::transform(triggerActions, [](const auto& action) {
248 return actionToString(action);
249 });
250 data["ThresholdParams"] =
251 utils::labeledThresholdParamsToJson(labeledThresholdParams);
252 data["ReportIds"] = *reportIds;
253 data["Sensors"] = getLabeledSensorInfo();
254
255 triggerStorage.store(fileName, data);
256 }
257 catch (const std::exception& e)
258 {
259 phosphor::logging::log<phosphor::logging::level::ERR>(
260 "Failed to store a trigger in storage",
261 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
262 return false;
263 }
264 return true;
265 }
266
getLabeledSensorInfo() const267 std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const
268 {
269 return utils::transform(sensors, [](const auto& sensor) {
270 return sensor->getLabeledSensorInfo();
271 });
272 }
273
getLabeledThresholds() const274 std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const
275 {
276 return utils::transform(thresholds, [](const auto& threshold) {
277 return threshold->getThresholdParam();
278 });
279 }
280
isDiscreate() const281 bool Trigger::isDiscreate() const
282 {
283 const auto labeledThresholds = getLabeledThresholds();
284
285 return utils::isFirstElementOfType<std::monostate>(labeledThresholds) ||
286 utils::isFirstElementOfType<discrete::LabeledThresholdParam>(
287 labeledThresholds);
288 }
289