xref: /openbmc/telemetry/src/trigger_manager.cpp (revision c7935fa1)
176833cb5SWludzik, Jozef #include "trigger_manager.hpp"
276833cb5SWludzik, Jozef 
34416fce6SCezary Zwolak #include "trigger.hpp"
4dcc4e193SKrzysztof Grobelny #include "types/trigger_types.hpp"
54416fce6SCezary Zwolak #include "utils/conversion_trigger.hpp"
61cdd7e4fSSzymon Dompke #include "utils/dbus_path_utils.hpp"
732305f14SSzymon Dompke #include "utils/make_id_name.hpp"
84416fce6SCezary Zwolak #include "utils/transform.hpp"
932305f14SSzymon Dompke #include "utils/tstring.hpp"
104416fce6SCezary Zwolak 
114416fce6SCezary Zwolak #include <phosphor-logging/log.hpp>
124416fce6SCezary Zwolak 
13b4ef22e4SSzymon Dompke #include <unordered_set>
14b4ef22e4SSzymon Dompke 
TriggerManager(std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,const std::shared_ptr<sdbusplus::asio::object_server> & objServer)1576833cb5SWludzik, Jozef TriggerManager::TriggerManager(
1676833cb5SWludzik, Jozef     std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn,
17a4e67616SCezary Zwolak     std::unique_ptr<interfaces::JsonStorage> triggerStorageIn,
1876833cb5SWludzik, Jozef     const std::shared_ptr<sdbusplus::asio::object_server>& objServer) :
19a4e67616SCezary Zwolak     triggerFactory(std::move(triggerFactoryIn)),
20a4e67616SCezary Zwolak     triggerStorage(std::move(triggerStorageIn))
2176833cb5SWludzik, Jozef {
224416fce6SCezary Zwolak     loadFromPersistent();
234416fce6SCezary Zwolak 
24*c7935fa1SPatrick Williams     managerIface = objServer->add_unique_interface(
25*c7935fa1SPatrick Williams         triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) {
2676833cb5SWludzik, Jozef         iface.register_method(
2776833cb5SWludzik, Jozef             "AddTrigger",
283a1c297aSPatrick Williams             [this](boost::asio::yield_context& yield, const std::string& id,
292001301aSSzymon Dompke                    const std::string& name,
302001301aSSzymon Dompke                    const std::vector<std::string>& triggerActions,
314416fce6SCezary Zwolak                    const SensorsInfo& sensors,
321cdd7e4fSSzymon Dompke                    const std::vector<sdbusplus::message::object_path>& reports,
334416fce6SCezary Zwolak                    const TriggerThresholdParamsExt& thresholds) {
343a1c297aSPatrick Williams             LabeledTriggerThresholdParams labeledTriggerThresholdParams =
353a1c297aSPatrick Williams                 std::visit(utils::ToLabeledThresholdParamConversion(),
364416fce6SCezary Zwolak                            thresholds);
3776833cb5SWludzik, Jozef 
384416fce6SCezary Zwolak             std::vector<LabeledSensorInfo> labeledSensorsInfo =
394416fce6SCezary Zwolak                 triggerFactory->getLabeledSensorsInfo(yield, sensors);
4076833cb5SWludzik, Jozef 
411cdd7e4fSSzymon Dompke             auto reportIds = utils::transform<std::vector>(
423a1c297aSPatrick Williams                 reports,
433a1c297aSPatrick Williams                 [](const auto& item) { return utils::reportPathToId(item); });
441cdd7e4fSSzymon Dompke 
453a1c297aSPatrick Williams             return addTrigger(id, name, triggerActions, labeledSensorsInfo,
463a1c297aSPatrick Williams                               reportIds, labeledTriggerThresholdParams)
474416fce6SCezary Zwolak                 .getPath();
4876833cb5SWludzik, Jozef         });
4976833cb5SWludzik, Jozef     });
5076833cb5SWludzik, Jozef }
5176833cb5SWludzik, Jozef 
removeTrigger(const interfaces::Trigger * trigger)5276833cb5SWludzik, Jozef void TriggerManager::removeTrigger(const interfaces::Trigger* trigger)
5376833cb5SWludzik, Jozef {
5476833cb5SWludzik, Jozef     triggers.erase(
5576833cb5SWludzik, Jozef         std::remove_if(triggers.begin(), triggers.end(),
5676833cb5SWludzik, Jozef                        [trigger](const auto& x) { return trigger == x.get(); }),
5776833cb5SWludzik, Jozef         triggers.end());
5876833cb5SWludzik, Jozef }
594416fce6SCezary Zwolak 
verifyReportIds(const std::vector<std::string> & newReportIds)60b4ef22e4SSzymon Dompke void TriggerManager::verifyReportIds(
61b4ef22e4SSzymon Dompke     const std::vector<std::string>& newReportIds)
62b4ef22e4SSzymon Dompke {
63b4ef22e4SSzymon Dompke     if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() !=
64b4ef22e4SSzymon Dompke         newReportIds.size())
65b4ef22e4SSzymon Dompke     {
66b4ef22e4SSzymon Dompke         throw sdbusplus::exception::SdBusError(
67b4ef22e4SSzymon Dompke             static_cast<int>(std::errc::invalid_argument),
68b4ef22e4SSzymon Dompke             "Duplicate element in ReportIds");
69b4ef22e4SSzymon Dompke     }
70b4ef22e4SSzymon Dompke }
71b4ef22e4SSzymon Dompke 
verifyThresholdParams(const LabeledTriggerThresholdParams & thresholdParams)7232305f14SSzymon Dompke void TriggerManager::verifyThresholdParams(
7332305f14SSzymon Dompke     const LabeledTriggerThresholdParams& thresholdParams)
7432305f14SSzymon Dompke {
7532305f14SSzymon Dompke     namespace ts = utils::tstring;
7632305f14SSzymon Dompke 
7732305f14SSzymon Dompke     if (auto discreteParams =
7832305f14SSzymon Dompke             std::get_if<std::vector<discrete::LabeledThresholdParam>>(
7932305f14SSzymon Dompke                 &thresholdParams);
8032305f14SSzymon Dompke         discreteParams != nullptr)
8132305f14SSzymon Dompke     {
8232305f14SSzymon Dompke         for (auto discreteParam : *discreteParams)
8332305f14SSzymon Dompke         {
8432305f14SSzymon Dompke             if (discreteParam.at_label<ts::UserId>().length() >
8532305f14SSzymon Dompke                 utils::constants::maxIdNameLength)
8632305f14SSzymon Dompke             {
8762c08e9bSKrzysztof Grobelny                 throw errors::InvalidArgument("ThresholdParams.Id",
8862c08e9bSKrzysztof Grobelny                                               "UserId too long.");
8932305f14SSzymon Dompke             }
9032305f14SSzymon Dompke         }
9132305f14SSzymon Dompke     }
9232305f14SSzymon Dompke }
9332305f14SSzymon Dompke 
verifyAddTrigger(const std::vector<std::string> & reportIds,const LabeledTriggerThresholdParams & thresholdParams) const94b4ef22e4SSzymon Dompke void TriggerManager::verifyAddTrigger(
9532305f14SSzymon Dompke     const std::vector<std::string>& reportIds,
9632305f14SSzymon Dompke     const LabeledTriggerThresholdParams& thresholdParams) const
974416fce6SCezary Zwolak {
984416fce6SCezary Zwolak     if (triggers.size() >= maxTriggers)
994416fce6SCezary Zwolak     {
1004416fce6SCezary Zwolak         throw sdbusplus::exception::SdBusError(
1014416fce6SCezary Zwolak             static_cast<int>(std::errc::too_many_files_open),
1024416fce6SCezary Zwolak             "Reached maximal trigger count");
1034416fce6SCezary Zwolak     }
1044416fce6SCezary Zwolak 
10532305f14SSzymon Dompke     verifyReportIds(reportIds);
10632305f14SSzymon Dompke     verifyThresholdParams(thresholdParams);
1074416fce6SCezary Zwolak }
1084416fce6SCezary Zwolak 
addTrigger(const std::string & triggerIdIn,const std::string & triggerNameIn,const std::vector<std::string> & triggerActions,const std::vector<LabeledSensorInfo> & labeledSensorsInfo,const std::vector<std::string> & reportIds,const LabeledTriggerThresholdParams & labeledThresholdParams)1094416fce6SCezary Zwolak interfaces::Trigger& TriggerManager::addTrigger(
110e28aa53dSSzymon Dompke     const std::string& triggerIdIn, const std::string& triggerNameIn,
1112001301aSSzymon Dompke     const std::vector<std::string>& triggerActions,
1124416fce6SCezary Zwolak     const std::vector<LabeledSensorInfo>& labeledSensorsInfo,
113b8cc78ddSKrzysztof Grobelny     const std::vector<std::string>& reportIds,
1144416fce6SCezary Zwolak     const LabeledTriggerThresholdParams& labeledThresholdParams)
1154416fce6SCezary Zwolak {
116a950e42bSKrzysztof Grobelny     const auto existingTriggerIds = utils::transform(
117a950e42bSKrzysztof Grobelny         triggers, [](const auto& trigger) { return trigger->getId(); });
118e28aa53dSSzymon Dompke 
11932305f14SSzymon Dompke     auto [id, name] = utils::makeIdName(triggerIdIn, triggerNameIn,
12032305f14SSzymon Dompke                                         triggerNameDefault, existingTriggerIds);
121e28aa53dSSzymon Dompke 
12232305f14SSzymon Dompke     verifyAddTrigger(reportIds, labeledThresholdParams);
1234416fce6SCezary Zwolak 
1244416fce6SCezary Zwolak     triggers.emplace_back(triggerFactory->make(
125a950e42bSKrzysztof Grobelny         id, name, triggerActions, reportIds, *this, *triggerStorage,
126a950e42bSKrzysztof Grobelny         labeledThresholdParams, labeledSensorsInfo));
1274416fce6SCezary Zwolak 
1284416fce6SCezary Zwolak     return *triggers.back();
1294416fce6SCezary Zwolak }
1304416fce6SCezary Zwolak 
loadFromPersistent()1314416fce6SCezary Zwolak void TriggerManager::loadFromPersistent()
1324416fce6SCezary Zwolak {
1334416fce6SCezary Zwolak     std::vector<interfaces::JsonStorage::FilePath> paths =
1344416fce6SCezary Zwolak         triggerStorage->list();
1354416fce6SCezary Zwolak 
1364416fce6SCezary Zwolak     for (const auto& path : paths)
1374416fce6SCezary Zwolak     {
1384416fce6SCezary Zwolak         std::optional<nlohmann::json> data = triggerStorage->load(path);
1394416fce6SCezary Zwolak         try
1404416fce6SCezary Zwolak         {
1414416fce6SCezary Zwolak             if (!data.has_value())
1424416fce6SCezary Zwolak             {
1434416fce6SCezary Zwolak                 throw std::runtime_error("Empty storage");
1444416fce6SCezary Zwolak             }
1454416fce6SCezary Zwolak             size_t version = data->at("Version").get<size_t>();
1464416fce6SCezary Zwolak             if (version != Trigger::triggerVersion)
1474416fce6SCezary Zwolak             {
1484416fce6SCezary Zwolak                 throw std::runtime_error("Invalid version");
1494416fce6SCezary Zwolak             }
150e28aa53dSSzymon Dompke             const std::string& id = data->at("Id").get_ref<std::string&>();
1514416fce6SCezary Zwolak             const std::string& name = data->at("Name").get_ref<std::string&>();
1524416fce6SCezary Zwolak             int thresholdParamsDiscriminator =
1534416fce6SCezary Zwolak                 data->at("ThresholdParamsDiscriminator").get<int>();
1542001301aSSzymon Dompke             const std::vector<std::string> triggerActions =
1552001301aSSzymon Dompke                 data->at("TriggerActions").get<std::vector<std::string>>();
1564416fce6SCezary Zwolak 
1574416fce6SCezary Zwolak             LabeledTriggerThresholdParams labeledThresholdParams;
1584416fce6SCezary Zwolak             if (0 == thresholdParamsDiscriminator)
1594416fce6SCezary Zwolak             {
1604416fce6SCezary Zwolak                 labeledThresholdParams =
1614416fce6SCezary Zwolak                     data->at("ThresholdParams")
1624416fce6SCezary Zwolak                         .get<std::vector<numeric::LabeledThresholdParam>>();
1634416fce6SCezary Zwolak             }
1644416fce6SCezary Zwolak             else
1654416fce6SCezary Zwolak             {
1664416fce6SCezary Zwolak                 labeledThresholdParams =
1674416fce6SCezary Zwolak                     data->at("ThresholdParams")
1684416fce6SCezary Zwolak                         .get<std::vector<discrete::LabeledThresholdParam>>();
1694416fce6SCezary Zwolak             }
1704416fce6SCezary Zwolak 
171b8cc78ddSKrzysztof Grobelny             auto reportIds =
172b8cc78ddSKrzysztof Grobelny                 data->at("ReportIds").get<std::vector<std::string>>();
1734416fce6SCezary Zwolak 
1744416fce6SCezary Zwolak             auto labeledSensorsInfo =
1754416fce6SCezary Zwolak                 data->at("Sensors").get<std::vector<LabeledSensorInfo>>();
1764416fce6SCezary Zwolak 
177b8cc78ddSKrzysztof Grobelny             addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds,
178b8cc78ddSKrzysztof Grobelny                        labeledThresholdParams);
1794416fce6SCezary Zwolak         }
1804416fce6SCezary Zwolak         catch (const std::exception& e)
1814416fce6SCezary Zwolak         {
1824416fce6SCezary Zwolak             phosphor::logging::log<phosphor::logging::level::ERR>(
1834416fce6SCezary Zwolak                 "Failed to load trigger from storage",
1844416fce6SCezary Zwolak                 phosphor::logging::entry(
1854416fce6SCezary Zwolak                     "FILENAME=%s",
1864416fce6SCezary Zwolak                     static_cast<std::filesystem::path>(path).c_str()),
1874416fce6SCezary Zwolak                 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
1884416fce6SCezary Zwolak             triggerStorage->remove(path);
1894416fce6SCezary Zwolak         }
1904416fce6SCezary Zwolak     }
1914416fce6SCezary Zwolak }
192