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/generate_id.hpp" 7 #include "utils/transform.hpp" 8 9 #include <phosphor-logging/log.hpp> 10 11 TriggerManager::TriggerManager( 12 std::unique_ptr<interfaces::TriggerFactory> triggerFactoryIn, 13 std::unique_ptr<interfaces::JsonStorage> triggerStorageIn, 14 const std::shared_ptr<sdbusplus::asio::object_server>& objServer) : 15 triggerFactory(std::move(triggerFactoryIn)), 16 triggerStorage(std::move(triggerStorageIn)) 17 { 18 loadFromPersistent(); 19 20 managerIface = objServer->add_unique_interface( 21 triggerManagerPath, triggerManagerIfaceName, [this](auto& iface) { 22 iface.register_method( 23 "AddTrigger", 24 [this](boost::asio::yield_context& yield, const std::string& id, 25 const std::string& name, 26 const std::vector<std::string>& triggerActions, 27 const SensorsInfo& sensors, 28 const std::vector<std::string>& reportIds, 29 const TriggerThresholdParamsExt& thresholds) { 30 LabeledTriggerThresholdParams 31 labeledTriggerThresholdParams = std::visit( 32 utils::ToLabeledThresholdParamConversion(), 33 thresholds); 34 35 std::vector<LabeledSensorInfo> labeledSensorsInfo = 36 triggerFactory->getLabeledSensorsInfo(yield, sensors); 37 38 return addTrigger(id, name, triggerActions, 39 labeledSensorsInfo, reportIds, 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(const std::string& triggerId, 55 const std::string& triggerName) const 56 { 57 if (triggers.size() >= maxTriggers) 58 { 59 throw sdbusplus::exception::SdBusError( 60 static_cast<int>(std::errc::too_many_files_open), 61 "Reached maximal trigger count"); 62 } 63 64 utils::verifyIdCharacters(triggerId); 65 66 for (const auto& trigger : triggers) 67 { 68 if (trigger->getId() == triggerId) 69 { 70 throw sdbusplus::exception::SdBusError( 71 static_cast<int>(std::errc::file_exists), "Duplicate trigger"); 72 } 73 } 74 } 75 76 interfaces::Trigger& TriggerManager::addTrigger( 77 const std::string& triggerIdIn, const std::string& triggerNameIn, 78 const std::vector<std::string>& triggerActions, 79 const std::vector<LabeledSensorInfo>& labeledSensorsInfo, 80 const std::vector<std::string>& reportIds, 81 const LabeledTriggerThresholdParams& labeledThresholdParams) 82 { 83 const auto existingTriggerIds = utils::transform( 84 triggers, [](const auto& trigger) { return trigger->getId(); }); 85 86 auto [id, name] = 87 utils::generateId(triggerIdIn, triggerNameIn, triggerNameDefault, 88 existingTriggerIds, maxTriggerIdLength); 89 90 verifyAddTrigger(id, name); 91 92 triggers.emplace_back(triggerFactory->make( 93 id, name, triggerActions, reportIds, *this, *triggerStorage, 94 labeledThresholdParams, labeledSensorsInfo)); 95 96 return *triggers.back(); 97 } 98 99 void TriggerManager::loadFromPersistent() 100 { 101 std::vector<interfaces::JsonStorage::FilePath> paths = 102 triggerStorage->list(); 103 104 for (const auto& path : paths) 105 { 106 std::optional<nlohmann::json> data = triggerStorage->load(path); 107 try 108 { 109 if (!data.has_value()) 110 { 111 throw std::runtime_error("Empty storage"); 112 } 113 size_t version = data->at("Version").get<size_t>(); 114 if (version != Trigger::triggerVersion) 115 { 116 throw std::runtime_error("Invalid version"); 117 } 118 const std::string& id = data->at("Id").get_ref<std::string&>(); 119 const std::string& name = data->at("Name").get_ref<std::string&>(); 120 int thresholdParamsDiscriminator = 121 data->at("ThresholdParamsDiscriminator").get<int>(); 122 const std::vector<std::string> triggerActions = 123 data->at("TriggerActions").get<std::vector<std::string>>(); 124 125 LabeledTriggerThresholdParams labeledThresholdParams; 126 if (0 == thresholdParamsDiscriminator) 127 { 128 labeledThresholdParams = 129 data->at("ThresholdParams") 130 .get<std::vector<numeric::LabeledThresholdParam>>(); 131 } 132 else 133 { 134 labeledThresholdParams = 135 data->at("ThresholdParams") 136 .get<std::vector<discrete::LabeledThresholdParam>>(); 137 } 138 139 auto reportIds = 140 data->at("ReportIds").get<std::vector<std::string>>(); 141 142 auto labeledSensorsInfo = 143 data->at("Sensors").get<std::vector<LabeledSensorInfo>>(); 144 145 addTrigger(id, name, triggerActions, labeledSensorsInfo, reportIds, 146 labeledThresholdParams); 147 } 148 catch (const std::exception& e) 149 { 150 phosphor::logging::log<phosphor::logging::level::ERR>( 151 "Failed to load trigger from storage", 152 phosphor::logging::entry( 153 "FILENAME=%s", 154 static_cast<std::filesystem::path>(path).c_str()), 155 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 156 triggerStorage->remove(path); 157 } 158 } 159 } 160