blob: d9d04d2a7cccc8e79d7ae10be0e1fa3b97f93772 [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 "interfaces/trigger_types.hpp"
4#include "trigger.hpp"
5#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,
24 const std::string& name, bool isDiscrete,
25 bool logToJournal, bool logToRedfish, bool updateReport,
26 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
Cezary Zwolak4416fce2021-03-17 03:21:06 +010037 return addTrigger(name, isDiscrete, logToJournal,
38 logToRedfish, updateReport,
39 labeledSensorsInfo, reportNames,
40 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
54void TriggerManager::verifyAddTrigger(
55 const std::string& triggerName, bool isDiscrete,
56 const LabeledTriggerThresholdParams& thresholdParams)
57{
58 if (triggers.size() >= maxTriggers)
59 {
60 throw sdbusplus::exception::SdBusError(
61 static_cast<int>(std::errc::too_many_files_open),
62 "Reached maximal trigger count");
63 }
64
65 for (const auto& trigger : triggers)
66 {
67 if (trigger->getName() == triggerName)
68 {
69 throw sdbusplus::exception::SdBusError(
70 static_cast<int>(std::errc::file_exists), "Duplicate trigger");
71 }
72 }
73}
74
75interfaces::Trigger& TriggerManager::addTrigger(
76 const std::string& triggerName, bool isDiscrete, bool logToJournal,
77 bool logToRedfish, bool updateReport,
78 const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
79 const std::vector<std::string>& reportNames,
80 const LabeledTriggerThresholdParams& labeledThresholdParams)
81{
82 verifyAddTrigger(triggerName, isDiscrete, labeledThresholdParams);
83
84 triggers.emplace_back(triggerFactory->make(
85 triggerName, isDiscrete, logToJournal, logToRedfish, updateReport,
86 reportNames, *this, *triggerStorage, labeledThresholdParams,
87 labeledSensorsInfo));
88
89 return *triggers.back();
90}
91
92void TriggerManager::loadFromPersistent()
93{
94 std::vector<interfaces::JsonStorage::FilePath> paths =
95 triggerStorage->list();
96
97 for (const auto& path : paths)
98 {
99 std::optional<nlohmann::json> data = triggerStorage->load(path);
100 try
101 {
102 if (!data.has_value())
103 {
104 throw std::runtime_error("Empty storage");
105 }
106 size_t version = data->at("Version").get<size_t>();
107 if (version != Trigger::triggerVersion)
108 {
109 throw std::runtime_error("Invalid version");
110 }
111 const std::string& name = data->at("Name").get_ref<std::string&>();
112 int thresholdParamsDiscriminator =
113 data->at("ThresholdParamsDiscriminator").get<int>();
114 bool isDiscrete = data->at("IsDiscrete").get<bool>();
115 bool logToJournal = data->at("LogToJournal").get<bool>();
116 bool logToRedfish = data->at("LogToRedfish").get<bool>();
117 bool updateReport = data->at("UpdateReport").get<bool>();
118
119 LabeledTriggerThresholdParams labeledThresholdParams;
120 if (0 == thresholdParamsDiscriminator)
121 {
122 labeledThresholdParams =
123 data->at("ThresholdParams")
124 .get<std::vector<numeric::LabeledThresholdParam>>();
125 }
126 else
127 {
128 labeledThresholdParams =
129 data->at("ThresholdParams")
130 .get<std::vector<discrete::LabeledThresholdParam>>();
131 }
132
133 auto reportNames =
134 data->at("ReportNames").get<std::vector<std::string>>();
135
136 auto labeledSensorsInfo =
137 data->at("Sensors").get<std::vector<LabeledSensorInfo>>();
138
139 addTrigger(name, isDiscrete, logToJournal, logToRedfish,
140 updateReport, labeledSensorsInfo, reportNames,
141 labeledThresholdParams);
142 }
143 catch (const std::exception& e)
144 {
145 phosphor::logging::log<phosphor::logging::level::ERR>(
146 "Failed to load trigger from storage",
147 phosphor::logging::entry(
148 "FILENAME=%s",
149 static_cast<std::filesystem::path>(path).c_str()),
150 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
151 triggerStorage->remove(path);
152 }
153 }
154}