blob: df8dea983bb293bc0d6555661a782993afd5e6cf [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"
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +01007#include "utils/generate_id.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01008#include "utils/transform.hpp"
9
10#include <phosphor-logging/log.hpp>
11
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010012#include <unordered_set>
13
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010014TriggerManager::TriggerManager(
15 std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
Cezary Zwolaka4e67612021-02-18 13:16:16 +010016 std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010017 const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
Cezary Zwolaka4e67612021-02-18 13:16:16 +010018 triggerFactory(std::move(triggerFactoryIn)),
19 triggerStorage(std::move(triggerStorageIn))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010020{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010021 loadFromPersistent();
22
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010023 managerIface = objServer->add_unique_interface(
24 triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) {
25 iface.register_method(
26 "AddTrigger",
Szymon Dompke1cdd7e42022-06-08 14:43:13 +020027 [this](
28 boost::asio::yield_context& yield, const std::string& id,
29 const std::string& name,
30 const std::vector<std::string>& triggerActions,
31 const SensorsInfo& sensors,
32 const std::vector<sdbusplus::message::object_path>& reports,
33 const TriggerThresholdParamsExt& thresholds) {
Cezary Zwolak4416fce2021-03-17 03:21:06 +010034 LabeledTriggerThresholdParams
35 labeledTriggerThresholdParams = std::visit(
36 utils::ToLabeledThresholdParamConversion(),
37 thresholds);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010038
Cezary Zwolak4416fce2021-03-17 03:21:06 +010039 std::vector<LabeledSensorInfo> labeledSensorsInfo =
40 triggerFactory->getLabeledSensorsInfo(yield, sensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010041
Szymon Dompke1cdd7e42022-06-08 14:43:13 +020042 auto reportIds = utils::transform<std::vector>(
43 reports, [](const auto& item) {
44 return utils::reportPathToId(item);
45 });
46
Szymon Dompkee28aa532021-10-27 12:33:12 +020047 return addTrigger(id, name, triggerActions,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010048 labeledSensorsInfo, reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010049 labeledTriggerThresholdParams)
50 .getPath();
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010051 });
52 });
53}
54
55void TriggerManager::removeTrigger(const interfaces::Trigger* trigger)
56{
57 triggers.erase(
58 std::remove_if(triggers.begin(), triggers.end(),
59 [trigger](const auto& x) { return trigger == x.get(); }),
60 triggers.end());
61}
Cezary Zwolak4416fce2021-03-17 03:21:06 +010062
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010063void TriggerManager::verifyReportIds(
64 const std::vector<std::string>& newReportIds)
65{
66 if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() !=
67 newReportIds.size())
68 {
69 throw sdbusplus::exception::SdBusError(
70 static_cast<int>(std::errc::invalid_argument),
71 "Duplicate element in ReportIds");
72 }
73}
74
75void TriggerManager::verifyAddTrigger(
76 const std::string& triggerId, const std::string& triggerName,
77 const std::vector<std::string>& newReportIds) const
Cezary Zwolak4416fce2021-03-17 03:21:06 +010078{
79 if (triggers.size() >= maxTriggers)
80 {
81 throw sdbusplus::exception::SdBusError(
82 static_cast<int>(std::errc::too_many_files_open),
83 "Reached maximal trigger count");
84 }
85
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010086 utils::verifyIdCharacters(triggerId);
Szymon Dompkee28aa532021-10-27 12:33:12 +020087
Cezary Zwolak4416fce2021-03-17 03:21:06 +010088 for (const auto& trigger : triggers)
89 {
Szymon Dompkee28aa532021-10-27 12:33:12 +020090 if (trigger->getId() == triggerId)
Cezary Zwolak4416fce2021-03-17 03:21:06 +010091 {
92 throw sdbusplus::exception::SdBusError(
93 static_cast<int>(std::errc::file_exists), "Duplicate trigger");
94 }
95 }
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010096
97 verifyReportIds(newReportIds);
Cezary Zwolak4416fce2021-03-17 03:21:06 +010098}
99
100interfaces::Trigger& TriggerManager::addTrigger(
Szymon Dompkee28aa532021-10-27 12:33:12 +0200101 const std::string& triggerIdIn, const std::string& triggerNameIn,
Szymon Dompke20013012021-07-23 09:54:20 +0200102 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100103 const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100104 const std::vector<std::string>& reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100105 const LabeledTriggerThresholdParams& labeledThresholdParams)
106{
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100107 const auto existingTriggerIds = utils::transform(
108 triggers, [](const auto& trigger) { return trigger->getId(); });
Szymon Dompkee28aa532021-10-27 12:33:12 +0200109
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100110 auto [id, name] =
111 utils::generateId(triggerIdIn, triggerNameIn, triggerNameDefault,
112 existingTriggerIds, maxTriggerIdLength);
Szymon Dompkee28aa532021-10-27 12:33:12 +0200113
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100114 verifyAddTrigger(id, name, reportIds);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100115
116 triggers.emplace_back(triggerFactory->make(
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100117 id, name, triggerActions, reportIds, *this, *triggerStorage,
118 labeledThresholdParams, labeledSensorsInfo));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100119
120 return *triggers.back();
121}
122
123void TriggerManager::loadFromPersistent()
124{
125 std::vector<interfaces::JsonStorage::FilePath> paths =
126 triggerStorage->list();
127
128 for (const auto& path : paths)
129 {
130 std::optional<nlohmann::json> data = triggerStorage->load(path);
131 try
132 {
133 if (!data.has_value())
134 {
135 throw std::runtime_error("Empty storage");
136 }
137 size_t version = data->at("Version").get<size_t>();
138 if (version != Trigger::triggerVersion)
139 {
140 throw std::runtime_error("Invalid version");
141 }
Szymon Dompkee28aa532021-10-27 12:33:12 +0200142 const std::string& id = data->at("Id").get_ref<std::string&>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100143 const std::string& name = data->at("Name").get_ref<std::string&>();
144 int thresholdParamsDiscriminator =
145 data->at("ThresholdParamsDiscriminator").get<int>();
Szymon Dompke20013012021-07-23 09:54:20 +0200146 const std::vector<std::string> triggerActions =
147 data->at("TriggerActions").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100148
149 LabeledTriggerThresholdParams labeledThresholdParams;
150 if (0 == thresholdParamsDiscriminator)
151 {
152 labeledThresholdParams =
153 data->at("ThresholdParams")
154 .get<std::vector<numeric::LabeledThresholdParam>>();
155 }
156 else
157 {
158 labeledThresholdParams =
159 data->at("ThresholdParams")
160 .get<std::vector<discrete::LabeledThresholdParam>>();
161 }
162
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100163 auto reportIds =
164 data->at("ReportIds").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100165
166 auto labeledSensorsInfo =
167 data->at("Sensors").get<std::vector<LabeledSensorInfo>>();
168
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100169 addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds,
170 labeledThresholdParams);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100171 }
172 catch (const std::exception& e)
173 {
174 phosphor::logging::log<phosphor::logging::level::ERR>(
175 "Failed to load trigger from storage",
176 phosphor::logging::entry(
177 "FILENAME=%s",
178 static_cast<std::filesystem::path>(path).c_str()),
179 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
180 triggerStorage->remove(path);
181 }
182 }
183}