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