blob: 358ee780911b61caade572a45460e8b65d41c80c [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
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010011TriggerManager::TriggerManager(
12 std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
Cezary Zwolaka4e67612021-02-18 13:16:16 +010013 std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010014 const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
Cezary Zwolaka4e67612021-02-18 13:16:16 +010015 triggerFactory(std::move(triggerFactoryIn)),
16 triggerStorage(std::move(triggerStorageIn))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010017{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010018 loadFromPersistent();
19
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010020 managerIface = objServer->add_unique_interface(
21 triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) {
22 iface.register_method(
23 "AddTrigger",
Szymon Dompkee28aa532021-10-27 12:33:12 +020024 [this](boost::asio::yield_context& yield, const std::string& id,
Szymon Dompke20013012021-07-23 09:54:20 +020025 const std::string& name,
26 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010027 const SensorsInfo& sensors,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010028 const std::vector<std::string>& reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010029 const TriggerThresholdParamsExt& thresholds) {
30 LabeledTriggerThresholdParams
31 labeledTriggerThresholdParams = std::visit(
32 utils::ToLabeledThresholdParamConversion(),
33 thresholds);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010034
Cezary Zwolak4416fce2021-03-17 03:21:06 +010035 std::vector<LabeledSensorInfo> labeledSensorsInfo =
36 triggerFactory->getLabeledSensorsInfo(yield, sensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010037
Szymon Dompkee28aa532021-10-27 12:33:12 +020038 return addTrigger(id, name, triggerActions,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010039 labeledSensorsInfo, reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010040 labeledTriggerThresholdParams)
41 .getPath();
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010042 });
43 });
44}
45
46void TriggerManager::removeTrigger(const interfaces::Trigger* trigger)
47{
48 triggers.erase(
49 std::remove_if(triggers.begin(), triggers.end(),
50 [trigger](const auto& x) { return trigger == x.get(); }),
51 triggers.end());
52}
Cezary Zwolak4416fce2021-03-17 03:21:06 +010053
Szymon Dompkee28aa532021-10-27 12:33:12 +020054void TriggerManager::verifyAddTrigger(const std::string& triggerId,
55 const std::string& triggerName) const
Cezary Zwolak4416fce2021-03-17 03:21:06 +010056{
57 if (triggers.size() >= maxTriggers)
58 {
59 throw sdbusplus::exception::SdBusError(
60 static_cast<int>(std::errc::too_many_files_open),
61 "Reached maximal trigger count");
62 }
63
Szymon Dompkee28aa532021-10-27 12:33:12 +020064 verifyTriggerIdLength(triggerId);
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010065 utils::verifyIdCharacters(triggerId);
Szymon Dompkee28aa532021-10-27 12:33:12 +020066
Cezary Zwolak4416fce2021-03-17 03:21:06 +010067 for (const auto& trigger : triggers)
68 {
Szymon Dompkee28aa532021-10-27 12:33:12 +020069 if (trigger->getId() == triggerId)
Cezary Zwolak4416fce2021-03-17 03:21:06 +010070 {
71 throw sdbusplus::exception::SdBusError(
72 static_cast<int>(std::errc::file_exists), "Duplicate trigger");
73 }
74 }
75}
76
Szymon Dompkee28aa532021-10-27 12:33:12 +020077void TriggerManager::verifyTriggerIdLength(const std::string& triggerId)
78{
79 if (triggerId.length() > maxTriggerIdLength)
80 {
81 throw sdbusplus::exception::SdBusError(
82 static_cast<int>(std::errc::invalid_argument),
83 "Trigger id exceeds maximum length");
84 }
85}
86
Szymon Dompkee28aa532021-10-27 12:33:12 +020087std::string TriggerManager::generateId(const std::string& prefix,
88 const std::string& triggerName) const
89{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010090 const auto existingTriggerIds = utils::transform(
91 triggers, [](const auto& trigger) { return trigger->getId(); });
Szymon Dompkee28aa532021-10-27 12:33:12 +020092
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010093 return utils::generateId(prefix, triggerName, existingTriggerIds,
94 maxTriggerIdLength);
Szymon Dompkee28aa532021-10-27 12:33:12 +020095}
96
Cezary Zwolak4416fce2021-03-17 03:21:06 +010097interfaces::Trigger& TriggerManager::addTrigger(
Szymon Dompkee28aa532021-10-27 12:33:12 +020098 const std::string& triggerIdIn, const std::string& triggerNameIn,
Szymon Dompke20013012021-07-23 09:54:20 +020099 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100100 const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100101 const std::vector<std::string>& reportIds,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100102 const LabeledTriggerThresholdParams& labeledThresholdParams)
103{
Szymon Dompkee28aa532021-10-27 12:33:12 +0200104 std::string triggerName = triggerNameIn;
105 if (triggerName.empty())
106 {
107 triggerName = triggerNameDefault;
108 }
109
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100110 std::string triggerId = generateId(triggerIdIn, triggerName);
Szymon Dompkee28aa532021-10-27 12:33:12 +0200111
112 verifyAddTrigger(triggerId, triggerName);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100113
114 triggers.emplace_back(triggerFactory->make(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100115 triggerId, triggerName, triggerActions, reportIds, *this,
Szymon Dompkee28aa532021-10-27 12:33:12 +0200116 *triggerStorage, labeledThresholdParams, labeledSensorsInfo));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100117
118 return *triggers.back();
119}
120
121void TriggerManager::loadFromPersistent()
122{
123 std::vector<interfaces::JsonStorage::FilePath> paths =
124 triggerStorage->list();
125
126 for (const auto& path : paths)
127 {
128 std::optional<nlohmann::json> data = triggerStorage->load(path);
129 try
130 {
131 if (!data.has_value())
132 {
133 throw std::runtime_error("Empty storage");
134 }
135 size_t version = data->at("Version").get<size_t>();
136 if (version != Trigger::triggerVersion)
137 {
138 throw std::runtime_error("Invalid version");
139 }
Szymon Dompkee28aa532021-10-27 12:33:12 +0200140 const std::string& id = data->at("Id").get_ref<std::string&>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100141 const std::string& name = data->at("Name").get_ref<std::string&>();
142 int thresholdParamsDiscriminator =
143 data->at("ThresholdParamsDiscriminator").get<int>();
Szymon Dompke20013012021-07-23 09:54:20 +0200144 const std::vector<std::string> triggerActions =
145 data->at("TriggerActions").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100146
147 LabeledTriggerThresholdParams labeledThresholdParams;
148 if (0 == thresholdParamsDiscriminator)
149 {
150 labeledThresholdParams =
151 data->at("ThresholdParams")
152 .get<std::vector<numeric::LabeledThresholdParam>>();
153 }
154 else
155 {
156 labeledThresholdParams =
157 data->at("ThresholdParams")
158 .get<std::vector<discrete::LabeledThresholdParam>>();
159 }
160
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100161 auto reportIds =
162 data->at("ReportIds").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100163
164 auto labeledSensorsInfo =
165 data->at("Sensors").get<std::vector<LabeledSensorInfo>>();
166
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100167 addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds,
168 labeledThresholdParams);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100169 }
170 catch (const std::exception& e)
171 {
172 phosphor::logging::log<phosphor::logging::level::ERR>(
173 "Failed to load trigger from storage",
174 phosphor::logging::entry(
175 "FILENAME=%s",
176 static_cast<std::filesystem::path>(path).c_str()),
177 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
178 triggerStorage->remove(path);
179 }
180 }
181}