blob: da4797fbf420e78e7a967445184d0528c9ff8e9e [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"
6#include "utils/transform.hpp"
7
8#include <phosphor-logging/log.hpp>
9
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010010TriggerManager::TriggerManager(
11 std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
Cezary Zwolaka4e67612021-02-18 13:16:16 +010012 std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010013 const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
Cezary Zwolaka4e67612021-02-18 13:16:16 +010014 triggerFactory(std::move(triggerFactoryIn)),
15 triggerStorage(std::move(triggerStorageIn))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010016{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010017 loadFromPersistent();
18
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010019 managerIface = objServer->add_unique_interface(
20 triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) {
21 iface.register_method(
22 "AddTrigger",
Cezary Zwolak4416fce2021-03-17 03:21:06 +010023 [this](boost::asio::yield_context& yield,
Szymon Dompke20013012021-07-23 09:54:20 +020024 const std::string& name,
25 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010026 const SensorsInfo& sensors,
27 const std::vector<std::string>& reportNames,
28 const TriggerThresholdParamsExt& thresholds) {
29 LabeledTriggerThresholdParams
30 labeledTriggerThresholdParams = std::visit(
31 utils::ToLabeledThresholdParamConversion(),
32 thresholds);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010033
Cezary Zwolak4416fce2021-03-17 03:21:06 +010034 std::vector<LabeledSensorInfo> labeledSensorsInfo =
35 triggerFactory->getLabeledSensorsInfo(yield, sensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010036
Szymon Dompke20013012021-07-23 09:54:20 +020037 return addTrigger(name, triggerActions, labeledSensorsInfo,
38 reportNames,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010039 labeledTriggerThresholdParams)
40 .getPath();
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010041 });
42 });
43}
44
45void TriggerManager::removeTrigger(const interfaces::Trigger* trigger)
46{
47 triggers.erase(
48 std::remove_if(triggers.begin(), triggers.end(),
49 [trigger](const auto& x) { return trigger == x.get(); }),
50 triggers.end());
51}
Cezary Zwolak4416fce2021-03-17 03:21:06 +010052
Szymon Dompke20013012021-07-23 09:54:20 +020053void TriggerManager::verifyAddTrigger(const std::string& triggerName)
Cezary Zwolak4416fce2021-03-17 03:21:06 +010054{
55 if (triggers.size() >= maxTriggers)
56 {
57 throw sdbusplus::exception::SdBusError(
58 static_cast<int>(std::errc::too_many_files_open),
59 "Reached maximal trigger count");
60 }
61
62 for (const auto& trigger : triggers)
63 {
64 if (trigger->getName() == triggerName)
65 {
66 throw sdbusplus::exception::SdBusError(
67 static_cast<int>(std::errc::file_exists), "Duplicate trigger");
68 }
69 }
70}
71
72interfaces::Trigger& TriggerManager::addTrigger(
Szymon Dompke20013012021-07-23 09:54:20 +020073 const std::string& triggerName,
74 const std::vector<std::string>& triggerActions,
Cezary Zwolak4416fce2021-03-17 03:21:06 +010075 const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
76 const std::vector<std::string>& reportNames,
77 const LabeledTriggerThresholdParams& labeledThresholdParams)
78{
Szymon Dompke20013012021-07-23 09:54:20 +020079 verifyAddTrigger(triggerName);
Cezary Zwolak4416fce2021-03-17 03:21:06 +010080
81 triggers.emplace_back(triggerFactory->make(
Szymon Dompke20013012021-07-23 09:54:20 +020082 triggerName, triggerActions, reportNames, *this, *triggerStorage,
83 labeledThresholdParams, labeledSensorsInfo));
Cezary Zwolak4416fce2021-03-17 03:21:06 +010084
85 return *triggers.back();
86}
87
88void TriggerManager::loadFromPersistent()
89{
90 std::vector<interfaces::JsonStorage::FilePath> paths =
91 triggerStorage->list();
92
93 for (const auto& path : paths)
94 {
95 std::optional<nlohmann::json> data = triggerStorage->load(path);
96 try
97 {
98 if (!data.has_value())
99 {
100 throw std::runtime_error("Empty storage");
101 }
102 size_t version = data->at("Version").get<size_t>();
103 if (version != Trigger::triggerVersion)
104 {
105 throw std::runtime_error("Invalid version");
106 }
107 const std::string& name = data->at("Name").get_ref<std::string&>();
108 int thresholdParamsDiscriminator =
109 data->at("ThresholdParamsDiscriminator").get<int>();
Szymon Dompke20013012021-07-23 09:54:20 +0200110 const std::vector<std::string> triggerActions =
111 data->at("TriggerActions").get<std::vector<std::string>>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100112
113 LabeledTriggerThresholdParams labeledThresholdParams;
114 if (0 == thresholdParamsDiscriminator)
115 {
116 labeledThresholdParams =
117 data->at("ThresholdParams")
118 .get<std::vector<numeric::LabeledThresholdParam>>();
119 }
120 else
121 {
122 labeledThresholdParams =
123 data->at("ThresholdParams")
124 .get<std::vector<discrete::LabeledThresholdParam>>();
125 }
126
127 auto reportNames =
128 data->at("ReportNames").get<std::vector<std::string>>();
129
130 auto labeledSensorsInfo =
131 data->at("Sensors").get<std::vector<LabeledSensorInfo>>();
132
Szymon Dompke20013012021-07-23 09:54:20 +0200133 addTrigger(name, triggerActions, labeledSensorsInfo, reportNames,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100134 labeledThresholdParams);
135 }
136 catch (const std::exception& e)
137 {
138 phosphor::logging::log<phosphor::logging::level::ERR>(
139 "Failed to load trigger from storage",
140 phosphor::logging::entry(
141 "FILENAME=%s",
142 static_cast<std::filesystem::path>(path).c_str()),
143 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
144 triggerStorage->remove(path);
145 }
146 }
147}