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, 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); 33 34 std::vector<LabeledSensorInfo> labeledSensorsInfo = 35 triggerFactory->getLabeledSensorsInfo(yield, sensors); 36 37 return addTrigger(name, isDiscrete, logToJournal, 38 logToRedfish, updateReport, 39 labeledSensorsInfo, reportNames, 40 labeledTriggerThresholdParams) 41 .getPath(); 42 }); 43 }); 44 } 45 46 void 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 } 53 54 void 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 75 interfaces::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 92 void 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 } 155