blob: e337bcac91d9d895a93d34c17f8c63ef39d5ec7a [file] [log] [blame]
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01001#include "trigger_manager.hpp"
2
Cezary Zwolak4416fce2021-03-17 03:21:06 +01003#include "trigger.hpp"
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +00004#include "types/trigger_types.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01005#include "utils/conversion_trigger.hpp"
Szymon Dompke1cdd7e42022-06-08 14:43:13 +02006#include "utils/dbus_path_utils.hpp"
Szymon Dompke32305f12022-07-05 15:37:21 +02007#include "utils/make_id_name.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01008#include "utils/transform.hpp"
Szymon Dompke32305f12022-07-05 15:37:21 +02009#include "utils/tstring.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +010010
11#include <phosphor-logging/log.hpp>
12
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010013#include <unordered_set>
14
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010015TriggerManager::TriggerManager(
16 std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
Cezary Zwolaka4e67612021-02-18 13:16:16 +010017 std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010018 const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
Cezary Zwolaka4e67612021-02-18 13:16:16 +010019 triggerFactory(std::move(triggerFactoryIn)),
20 triggerStorage(std::move(triggerStorageIn))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010021{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010022 loadFromPersistent();
23
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010024 managerIface = objServer->add_unique_interface(
25 triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) {
26 iface.register_method(
27 "AddTrigger",
Szymon Dompke1cdd7e42022-06-08 14:43:13 +020028 [this](
29 boost::asio::yield_context& yield, const std::string& id,
30 const std::string& name,
31 const std::vector<std::string>& triggerActions,
32 const SensorsInfo& sensors,
33 const std::vector<sdbusplus::message::object_path>& reports,
34 const TriggerThresholdParamsExt& thresholds) {
Cezary Zwolak4416fce2021-03-17 03:21:06 +010035 LabeledTriggerThresholdParams
36 labeledTriggerThresholdParams = std::visit(
37 utils::ToLabeledThresholdParamConversion(),
38 thresholds);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010039
Cezary Zwolak4416fce2021-03-17 03:21:06 +010040 std::vector<LabeledSensorInfo> labeledSensorsInfo =
41 triggerFactory->getLabeledSensorsInfo(yield, sensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010042
Szymon Dompke1cdd7e42022-06-08 14:43:13 +020043 auto reportIds = utils::transform<std::vector>(
44 reports, [](const auto& item) {
45 return utils::reportPathToId(item);
46 });
47
Szymon Dompkee28aa532021-10-27 12:33:12 +020048 return addTrigger(id, name, triggerActions,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010049 labeledSensorsInfo, reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010050 labeledTriggerThresholdParams)
51 .getPath();
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010052 });
53 });
54}
55
56void TriggerManager::removeTrigger(const interfaces::Trigger* trigger)
57{
58 triggers.erase(
59 std::remove_if(triggers.begin(), triggers.end(),
60 [trigger](const auto& x) { return trigger == x.get(); }),
61 triggers.end());
62}
Cezary Zwolak4416fce2021-03-17 03:21:06 +010063
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010064void TriggerManager::verifyReportIds(
65 const std::vector<std::string>& newReportIds)
66{
67 if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() !=
68 newReportIds.size())
69 {
70 throw sdbusplus::exception::SdBusError(
71 static_cast<int>(std::errc::invalid_argument),
72 "Duplicate element in ReportIds");
73 }
74}
75
Szymon Dompke32305f12022-07-05 15:37:21 +020076void TriggerManager::verifyThresholdParams(
77 const LabeledTriggerThresholdParams& thresholdParams)
78{
79 namespace ts = utils::tstring;
80
81 if (auto discreteParams =
82 std::get_if<std::vector<discrete::LabeledThresholdParam>>(
83 &thresholdParams);
84 discreteParams != nullptr)
85 {
86 for (auto discreteParam : *discreteParams)
87 {
88 if (discreteParam.at_label<ts::UserId>().length() >
89 utils::constants::maxIdNameLength)
90 {
91 throw sdbusplus::exception::SdBusError(
92 static_cast<int>(std::errc::invalid_argument),
93 "UserId too long");
94 }
95 }
96 }
97}
98
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010099void TriggerManager::verifyAddTrigger(
Szymon Dompke32305f12022-07-05 15:37:21 +0200100 const std::vector<std::string>& reportIds,
101 const LabeledTriggerThresholdParams& thresholdParams) const
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100102{
103 if (triggers.size() >= maxTriggers)
104 {
105 throw sdbusplus::exception::SdBusError(
106 static_cast<int>(std::errc::too_many_files_open),
107 "Reached maximal trigger count");
108 }
109
Szymon Dompke32305f12022-07-05 15:37:21 +0200110 verifyReportIds(reportIds);
111 verifyThresholdParams(thresholdParams);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100112}
113
114interfaces::Trigger& TriggerManager::addTrigger(
Szymon Dompkee28aa532021-10-27 12:33:12 +0200115 const std::string& triggerIdIn, const std::string& triggerNameIn,
Szymon Dompke20013012021-07-23 09:54:20 +0200116 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100117 const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100118 const std::vector<std::string>& reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100119 const LabeledTriggerThresholdParams& labeledThresholdParams)
120{
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100121 const auto existingTriggerIds = utils::transform(
122 triggers, [](const auto& trigger) { return trigger->getId(); });
Szymon Dompkee28aa532021-10-27 12:33:12 +0200123
Szymon Dompke32305f12022-07-05 15:37:21 +0200124 auto [id, name] = utils::makeIdName(triggerIdIn, triggerNameIn,
125 triggerNameDefault, existingTriggerIds);
Szymon Dompkee28aa532021-10-27 12:33:12 +0200126
Szymon Dompke32305f12022-07-05 15:37:21 +0200127 verifyAddTrigger(reportIds, labeledThresholdParams);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100128
129 triggers.emplace_back(triggerFactory->make(
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100130 id, name, triggerActions, reportIds, *this, *triggerStorage,
131 labeledThresholdParams, labeledSensorsInfo));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100132
133 return *triggers.back();
134}
135
136void TriggerManager::loadFromPersistent()
137{
138 std::vector<interfaces::JsonStorage::FilePath> paths =
139 triggerStorage->list();
140
141 for (const auto& path : paths)
142 {
143 std::optional<nlohmann::json> data = triggerStorage->load(path);
144 try
145 {
146 if (!data.has_value())
147 {
148 throw std::runtime_error("Empty storage");
149 }
150 size_t version = data->at("Version").get<size_t>();
151 if (version != Trigger::triggerVersion)
152 {
153 throw std::runtime_error("Invalid version");
154 }
Szymon Dompkee28aa532021-10-27 12:33:12 +0200155 const std::string& id = data->at("Id").get_ref<std::string&>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100156 const std::string& name = data->at("Name").get_ref<std::string&>();
157 int thresholdParamsDiscriminator =
158 data->at("ThresholdParamsDiscriminator").get<int>();
Szymon Dompke20013012021-07-23 09:54:20 +0200159 const std::vector<std::string> triggerActions =
160 data->at("TriggerActions").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100161
162 LabeledTriggerThresholdParams labeledThresholdParams;
163 if (0 == thresholdParamsDiscriminator)
164 {
165 labeledThresholdParams =
166 data->at("ThresholdParams")
167 .get<std::vector<numeric::LabeledThresholdParam>>();
168 }
169 else
170 {
171 labeledThresholdParams =
172 data->at("ThresholdParams")
173 .get<std::vector<discrete::LabeledThresholdParam>>();
174 }
175
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100176 auto reportIds =
177 data->at("ReportIds").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100178
179 auto labeledSensorsInfo =
180 data->at("Sensors").get<std::vector<LabeledSensorInfo>>();
181
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100182 addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds,
183 labeledThresholdParams);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100184 }
185 catch (const std::exception& e)
186 {
187 phosphor::logging::log<phosphor::logging::level::ERR>(
188 "Failed to load trigger from storage",
189 phosphor::logging::entry(
190 "FILENAME=%s",
191 static_cast<std::filesystem::path>(path).c_str()),
192 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
193 triggerStorage->remove(path);
194 }
195 }
196}