blob: 3c06b11267d6e03b231b40cd22afc3c04178bc11 [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"
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +01006#include "utils/generate_id.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01007#include "utils/transform.hpp"
8
9#include <phosphor-logging/log.hpp>
10
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010011#include <unordered_set>
12
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010013TriggerManager::TriggerManager(
14 std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
Cezary Zwolaka4e67612021-02-18 13:16:16 +010015 std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010016 const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
Cezary Zwolaka4e67612021-02-18 13:16:16 +010017 triggerFactory(std::move(triggerFactoryIn)),
18 triggerStorage(std::move(triggerStorageIn))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010019{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010020 loadFromPersistent();
21
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010022 managerIface = objServer->add_unique_interface(
23 triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) {
24 iface.register_method(
25 "AddTrigger",
Szymon Dompkee28aa532021-10-27 12:33:12 +020026 [this](boost::asio::yield_context& yield, const std::string& id,
Szymon Dompke20013012021-07-23 09:54:20 +020027 const std::string& name,
28 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010029 const SensorsInfo& sensors,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010030 const std::vector<std::string>& reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010031 const TriggerThresholdParamsExt& thresholds) {
32 LabeledTriggerThresholdParams
33 labeledTriggerThresholdParams = std::visit(
34 utils::ToLabeledThresholdParamConversion(),
35 thresholds);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010036
Cezary Zwolak4416fce2021-03-17 03:21:06 +010037 std::vector<LabeledSensorInfo> labeledSensorsInfo =
38 triggerFactory->getLabeledSensorsInfo(yield, sensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010039
Szymon Dompkee28aa532021-10-27 12:33:12 +020040 return addTrigger(id, name, triggerActions,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010041 labeledSensorsInfo, reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010042 labeledTriggerThresholdParams)
43 .getPath();
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010044 });
45 });
46}
47
48void TriggerManager::removeTrigger(const interfaces::Trigger* trigger)
49{
50 triggers.erase(
51 std::remove_if(triggers.begin(), triggers.end(),
52 [trigger](const auto& x) { return trigger == x.get(); }),
53 triggers.end());
54}
Cezary Zwolak4416fce2021-03-17 03:21:06 +010055
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010056void TriggerManager::verifyReportIds(
57 const std::vector<std::string>& newReportIds)
58{
59 if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() !=
60 newReportIds.size())
61 {
62 throw sdbusplus::exception::SdBusError(
63 static_cast<int>(std::errc::invalid_argument),
64 "Duplicate element in ReportIds");
65 }
66}
67
68void TriggerManager::verifyAddTrigger(
69 const std::string& triggerId, const std::string& triggerName,
70 const std::vector<std::string>& newReportIds) const
Cezary Zwolak4416fce2021-03-17 03:21:06 +010071{
72 if (triggers.size() >= maxTriggers)
73 {
74 throw sdbusplus::exception::SdBusError(
75 static_cast<int>(std::errc::too_many_files_open),
76 "Reached maximal trigger count");
77 }
78
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010079 utils::verifyIdCharacters(triggerId);
Szymon Dompkee28aa532021-10-27 12:33:12 +020080
Cezary Zwolak4416fce2021-03-17 03:21:06 +010081 for (const auto& trigger : triggers)
82 {
Szymon Dompkee28aa532021-10-27 12:33:12 +020083 if (trigger->getId() == triggerId)
Cezary Zwolak4416fce2021-03-17 03:21:06 +010084 {
85 throw sdbusplus::exception::SdBusError(
86 static_cast<int>(std::errc::file_exists), "Duplicate trigger");
87 }
88 }
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +010089
90 verifyReportIds(newReportIds);
Cezary Zwolak4416fce2021-03-17 03:21:06 +010091}
92
93interfaces::Trigger& TriggerManager::addTrigger(
Szymon Dompkee28aa532021-10-27 12:33:12 +020094 const std::string& triggerIdIn, const std::string& triggerNameIn,
Szymon Dompke20013012021-07-23 09:54:20 +020095 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010096 const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010097 const std::vector<std::string>& reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010098 const LabeledTriggerThresholdParams& labeledThresholdParams)
99{
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100100 const auto existingTriggerIds = utils::transform(
101 triggers, [](const auto& trigger) { return trigger->getId(); });
Szymon Dompkee28aa532021-10-27 12:33:12 +0200102
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100103 auto [id, name] =
104 utils::generateId(triggerIdIn, triggerNameIn, triggerNameDefault,
105 existingTriggerIds, maxTriggerIdLength);
Szymon Dompkee28aa532021-10-27 12:33:12 +0200106
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100107 verifyAddTrigger(id, name, reportIds);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100108
109 triggers.emplace_back(triggerFactory->make(
Krzysztof Grobelnya950e422021-12-31 13:49:00 +0100110 id, name, triggerActions, reportIds, *this, *triggerStorage,
111 labeledThresholdParams, labeledSensorsInfo));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100112
113 return *triggers.back();
114}
115
116void TriggerManager::loadFromPersistent()
117{
118 std::vector<interfaces::JsonStorage::FilePath> paths =
119 triggerStorage->list();
120
121 for (const auto& path : paths)
122 {
123 std::optional<nlohmann::json> data = triggerStorage->load(path);
124 try
125 {
126 if (!data.has_value())
127 {
128 throw std::runtime_error("Empty storage");
129 }
130 size_t version = data->at("Version").get<size_t>();
131 if (version != Trigger::triggerVersion)
132 {
133 throw std::runtime_error("Invalid version");
134 }
Szymon Dompkee28aa532021-10-27 12:33:12 +0200135 const std::string& id = data->at("Id").get_ref<std::string&>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100136 const std::string& name = data->at("Name").get_ref<std::string&>();
137 int thresholdParamsDiscriminator =
138 data->at("ThresholdParamsDiscriminator").get<int>();
Szymon Dompke20013012021-07-23 09:54:20 +0200139 const std::vector<std::string> triggerActions =
140 data->at("TriggerActions").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100141
142 LabeledTriggerThresholdParams labeledThresholdParams;
143 if (0 == thresholdParamsDiscriminator)
144 {
145 labeledThresholdParams =
146 data->at("ThresholdParams")
147 .get<std::vector<numeric::LabeledThresholdParam>>();
148 }
149 else
150 {
151 labeledThresholdParams =
152 data->at("ThresholdParams")
153 .get<std::vector<discrete::LabeledThresholdParam>>();
154 }
155
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100156 auto reportIds =
157 data->at("ReportIds").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100158
159 auto labeledSensorsInfo =
160 data->at("Sensors").get<std::vector<LabeledSensorInfo>>();
161
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100162 addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds,
163 labeledThresholdParams);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100164 }
165 catch (const std::exception& e)
166 {
167 phosphor::logging::log<phosphor::logging::level::ERR>(
168 "Failed to load trigger from storage",
169 phosphor::logging::entry(
170 "FILENAME=%s",
171 static_cast<std::filesystem::path>(path).c_str()),
172 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
173 triggerStorage->remove(path);
174 }
175 }
176}