#include "trigger_manager.hpp" #include "trigger.hpp" #include "types/trigger_types.hpp" #include "utils/conversion_trigger.hpp" #include "utils/dbus_path_utils.hpp" #include "utils/make_id_name.hpp" #include "utils/transform.hpp" #include "utils/tstring.hpp" #include #include TriggerManager::TriggerManager( std::unique_ptr triggerFactoryIn, std::unique_ptr triggerStorageIn, const std::shared_ptr& objServer) : triggerFactory(std::move(triggerFactoryIn)), triggerStorage(std::move(triggerStorageIn)) { loadFromPersistent(); managerIface = objServer->add_unique_interface( triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) { iface.register_method( "AddTrigger", [this](boost::asio::yield_context& yield, const std::string& id, const std::string& name, const std::vector& triggerActions, const SensorsInfo& sensors, const std::vector& reports, const TriggerThresholdParamsExt& thresholds) { LabeledTriggerThresholdParams labeledTriggerThresholdParams = std::visit(utils::ToLabeledThresholdParamConversion(), thresholds); std::vector labeledSensorsInfo = triggerFactory->getLabeledSensorsInfo(yield, sensors); auto reportIds = utils::transform( reports, [](const auto& item) { return utils::reportPathToId(item); }); return addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds, labeledTriggerThresholdParams) .getPath(); }); }); } void TriggerManager::removeTrigger(const interfaces::Trigger* trigger) { triggers.erase( std::remove_if(triggers.begin(), triggers.end(), [trigger](const auto& x) { return trigger == x.get(); }), triggers.end()); } void TriggerManager::verifyReportIds( const std::vector& newReportIds) { if (std::unordered_set(newReportIds.begin(), newReportIds.end()).size() != newReportIds.size()) { throw sdbusplus::exception::SdBusError( static_cast(std::errc::invalid_argument), "Duplicate element in ReportIds"); } } void TriggerManager::verifyThresholdParams( const LabeledTriggerThresholdParams& thresholdParams) { namespace ts = utils::tstring; if (auto discreteParams = std::get_if>( &thresholdParams); discreteParams != nullptr) { for (auto discreteParam : *discreteParams) { if (discreteParam.at_label().length() > utils::constants::maxIdNameLength) { throw errors::InvalidArgument("ThresholdParams.Id", "UserId too long."); } } } } void TriggerManager::verifyAddTrigger( const std::vector& reportIds, const LabeledTriggerThresholdParams& thresholdParams) const { if (triggers.size() >= maxTriggers) { throw sdbusplus::exception::SdBusError( static_cast(std::errc::too_many_files_open), "Reached maximal trigger count"); } verifyReportIds(reportIds); verifyThresholdParams(thresholdParams); } interfaces::Trigger& TriggerManager::addTrigger( const std::string& triggerIdIn, const std::string& triggerNameIn, const std::vector& triggerActions, const std::vector& labeledSensorsInfo, const std::vector& reportIds, const LabeledTriggerThresholdParams& labeledThresholdParams) { const auto existingTriggerIds = utils::transform( triggers, [](const auto& trigger) { return trigger->getId(); }); auto [id, name] = utils::makeIdName(triggerIdIn, triggerNameIn, triggerNameDefault, existingTriggerIds); verifyAddTrigger(reportIds, labeledThresholdParams); triggers.emplace_back(triggerFactory->make( id, name, triggerActions, reportIds, *this, *triggerStorage, labeledThresholdParams, labeledSensorsInfo)); return *triggers.back(); } void TriggerManager::loadFromPersistent() { std::vector paths = triggerStorage->list(); for (const auto& path : paths) { std::optional data = triggerStorage->load(path); try { if (!data.has_value()) { throw std::runtime_error("Empty storage"); } size_t version = data->at("Version").get(); if (version != Trigger::triggerVersion) { throw std::runtime_error("Invalid version"); } const std::string& id = data->at("Id").get_ref(); const std::string& name = data->at("Name").get_ref(); int thresholdParamsDiscriminator = data->at("ThresholdParamsDiscriminator").get(); const std::vector triggerActions = data->at("TriggerActions").get>(); LabeledTriggerThresholdParams labeledThresholdParams; if (0 == thresholdParamsDiscriminator) { labeledThresholdParams = data->at("ThresholdParams") .get>(); } else { labeledThresholdParams = data->at("ThresholdParams") .get>(); } auto reportIds = data->at("ReportIds").get>(); auto labeledSensorsInfo = data->at("Sensors").get>(); addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds, labeledThresholdParams); } catch (const std::exception& e) { phosphor::logging::log( "Failed to load trigger from storage", phosphor::logging::entry( "FILENAME=%s", static_cast(path).c_str()), phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); triggerStorage->remove(path); } } }