1 #include "trigger_manager.hpp" 2 3 #include "trigger.hpp" 4 #include "types/trigger_types.hpp" 5 #include "utils/conversion_trigger.hpp" 6 #include "utils/transform.hpp" 7 8 #include <phosphor-logging/log.hpp> 9 10 TriggerManager::TriggerManager( 11 std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn, 12 std::unique_ptr<interfaces::JsonStorage> triggerStorageIn, 13 const std::shared_ptr<sdbusplus::asio::object_server>& objServer) : 14 triggerFactory(std::move(triggerFactoryIn)), 15 triggerStorage(std::move(triggerStorageIn)) 16 { 17 loadFromPersistent(); 18 19 managerIface = objServer->add_unique_interface( 20 triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) { 21 iface.register_method( 22 "AddTrigger", 23 [this](boost::asio::yield_context& yield, 24 const std::string& name, 25 const std::vector<std::string>& triggerActions, 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); 33 34 std::vector<LabeledSensorInfo> labeledSensorsInfo = 35 triggerFactory->getLabeledSensorsInfo(yield, sensors); 36 37 return addTrigger(name, triggerActions, labeledSensorsInfo, 38 reportNames, 39 labeledTriggerThresholdParams) 40 .getPath(); 41 }); 42 }); 43 } 44 45 void 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 } 52 53 void TriggerManager::verifyAddTrigger(const std::string& triggerName) 54 { 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 72 interfaces::Trigger& TriggerManager::addTrigger( 73 const std::string& triggerName, 74 const std::vector<std::string>& triggerActions, 75 const std::vector<LabeledSensorInfo>& labeledSensorsInfo, 76 const std::vector<std::string>& reportNames, 77 const LabeledTriggerThresholdParams& labeledThresholdParams) 78 { 79 verifyAddTrigger(triggerName); 80 81 triggers.emplace_back(triggerFactory->make( 82 triggerName, triggerActions, reportNames, *this, *triggerStorage, 83 labeledThresholdParams, labeledSensorsInfo)); 84 85 return *triggers.back(); 86 } 87 88 void 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>(); 110 const std::vector<std::string> triggerActions = 111 data->at("TriggerActions").get<std::vector<std::string>>(); 112 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 133 addTrigger(name, triggerActions, labeledSensorsInfo, reportNames, 134 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 } 148