1 #include "trigger.hpp" 2 3 #include "messages/collect_trigger_id.hpp" 4 #include "messages/trigger_presence_changed_ind.hpp" 5 #include "trigger_manager.hpp" 6 #include "types/report_types.hpp" 7 #include "types/trigger_types.hpp" 8 #include "utils/contains.hpp" 9 #include "utils/conversion_trigger.hpp" 10 #include "utils/dbus_path_utils.hpp" 11 #include "utils/transform.hpp" 12 13 #include <phosphor-logging/log.hpp> 14 15 Trigger::Trigger( 16 boost::asio::io_context& ioc, 17 const std::shared_ptr<sdbusplus::asio::object_server>& objServer, 18 TriggerId&& idIn, const std::string& nameIn, 19 const std::vector<TriggerAction>& triggerActionsIn, 20 const std::shared_ptr<std::vector<std::string>> reportIdsIn, 21 std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn, 22 interfaces::TriggerManager& triggerManager, 23 interfaces::JsonStorage& triggerStorageIn, 24 const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) : 25 id(std::move(idIn)), 26 path(utils::pathAppend(utils::constants::triggerDirPath, *id)), 27 name(nameIn), triggerActions(std::move(triggerActionsIn)), 28 reportIds(std::move(reportIdsIn)), thresholds(std::move(thresholdsIn)), 29 fileName(std::to_string(std::hash<std::string>{}(*id))), 30 triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)), 31 messanger(ioc) 32 { 33 deleteIface = objServer->add_unique_interface( 34 path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) { 35 dbusIface.register_method("Delete", [this, &ioc, &triggerManager] { 36 if (persistent) 37 { 38 triggerStorage.remove(fileName); 39 } 40 messanger.send(messages::TriggerPresenceChangedInd{ 41 messages::Presence::Removed, *id, {}}); 42 boost::asio::post(ioc, [this, &triggerManager] { 43 triggerManager.removeTrigger(this); 44 }); 45 }); 46 }); 47 48 triggerIface = objServer->add_unique_interface( 49 path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) { 50 persistent = storeConfiguration(); 51 dbusIface.register_property_rw( 52 "Persistent", persistent, 53 sdbusplus::vtable::property_::emits_change, 54 [this](bool newVal, const auto&) { 55 if (newVal == persistent) 56 { 57 return 1; 58 } 59 if (newVal) 60 { 61 persistent = storeConfiguration(); 62 } 63 else 64 { 65 triggerStorage.remove(fileName); 66 persistent = false; 67 } 68 return 1; 69 }, [this](const auto&) { return persistent; }); 70 71 dbusIface.register_property_rw( 72 "Thresholds", TriggerThresholdParams{}, 73 sdbusplus::vtable::property_::emits_change, 74 [this, &triggerFactory](auto newVal, auto& oldVal) { 75 auto newThresholdParams = 76 std::visit(utils::ToLabeledThresholdParamConversion(), newVal); 77 TriggerManager::verifyThresholdParams(newThresholdParams); 78 triggerFactory.updateThresholds(thresholds, *id, triggerActions, 79 reportIds, sensors, 80 newThresholdParams); 81 oldVal = std::move(newVal); 82 return 1; 83 }, [this](const auto&) { 84 return fromLabeledThresholdParam(getLabeledThresholds()); 85 }); 86 87 dbusIface.register_property_rw( 88 "Sensors", SensorsInfo{}, 89 sdbusplus::vtable::property_::emits_change, 90 [this, &triggerFactory](auto newVal, auto& oldVal) { 91 auto labeledSensorInfo = 92 triggerFactory.getLabeledSensorsInfo(newVal); 93 triggerFactory.updateSensors(sensors, labeledSensorInfo); 94 for (const auto& threshold : thresholds) 95 { 96 threshold->updateSensors(sensors); 97 } 98 oldVal = std::move(newVal); 99 return 1; 100 }, [this](const auto&) { 101 return utils::fromLabeledSensorsInfo(getLabeledSensorInfo()); 102 }); 103 104 dbusIface.register_property_rw( 105 "Reports", std::vector<sdbusplus::message::object_path>(), 106 sdbusplus::vtable::property_::emits_change, 107 [this](auto newVal, auto& oldVal) { 108 auto newReportIds = utils::transform<std::vector>( 109 newVal, 110 [](const auto& path) { return utils::reportPathToId(path); }); 111 TriggerManager::verifyReportIds(newReportIds); 112 *reportIds = newReportIds; 113 messanger.send(messages::TriggerPresenceChangedInd{ 114 messages::Presence::Exist, *id, *reportIds}); 115 oldVal = std::move(newVal); 116 return 1; 117 }, [this](const auto&) { 118 return utils::transform<std::vector>(*reportIds, 119 [](const auto& id) { 120 return utils::pathAppend(utils::constants::reportDirPath, id); 121 }); 122 }); 123 124 dbusIface.register_property_r( 125 "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_, 126 [this](const auto& x) { return isDiscreate(); }); 127 128 dbusIface.register_property_rw( 129 "Name", name, sdbusplus::vtable::property_::emits_change, 130 [this](auto newVal, auto& oldVal) { 131 if (newVal.length() > utils::constants::maxIdNameLength) 132 { 133 throw errors::InvalidArgument("Name", "Name is too long."); 134 } 135 name = oldVal = newVal; 136 return 1; 137 }, [this](const auto&) { return name; }); 138 139 dbusIface.register_property_r( 140 "TriggerActions", std::vector<std::string>(), 141 sdbusplus::vtable::property_::const_, [this](const auto&) { 142 return utils::transform(triggerActions, [](const auto& action) { 143 return actionToString(action); 144 }); 145 }); 146 }); 147 148 for (const auto& threshold : thresholds) 149 { 150 threshold->initialize(); 151 } 152 153 messanger.on_receive<messages::CollectTriggerIdReq>( 154 [this](const auto& msg) { 155 if (utils::contains(*reportIds, msg.reportId)) 156 { 157 messanger.send(messages::CollectTriggerIdResp{*id}); 158 } 159 }); 160 161 messanger.send(messages::TriggerPresenceChangedInd{ 162 messages::Presence::Exist, *id, *reportIds}); 163 } 164 165 bool Trigger::storeConfiguration() const 166 { 167 try 168 { 169 nlohmann::json data; 170 171 auto labeledThresholdParams = 172 std::visit(utils::ToLabeledThresholdParamConversion(), 173 fromLabeledThresholdParam(getLabeledThresholds())); 174 175 data["Version"] = triggerVersion; 176 data["Id"] = *id; 177 data["Name"] = name; 178 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); 179 data["TriggerActions"] = utils::transform( 180 triggerActions, 181 [](const auto& action) { return actionToString(action); }); 182 data["ThresholdParams"] = 183 utils::labeledThresholdParamsToJson(labeledThresholdParams); 184 data["ReportIds"] = *reportIds; 185 data["Sensors"] = getLabeledSensorInfo(); 186 187 triggerStorage.store(fileName, data); 188 } 189 catch (const std::exception& e) 190 { 191 phosphor::logging::log<phosphor::logging::level::ERR>( 192 "Failed to store a trigger in storage", 193 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 194 return false; 195 } 196 return true; 197 } 198 199 std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const 200 { 201 return utils::transform(sensors, [](const auto& sensor) { 202 return sensor->getLabeledSensorInfo(); 203 }); 204 } 205 206 std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const 207 { 208 return utils::transform(thresholds, [](const auto& threshold) { 209 return threshold->getThresholdParam(); 210 }); 211 } 212 213 bool Trigger::isDiscreate() const 214 { 215 const auto labeledThresholds = getLabeledThresholds(); 216 217 return utils::isFirstElementOfType<std::monostate>(labeledThresholds) || 218 utils::isFirstElementOfType<discrete::LabeledThresholdParam>( 219 labeledThresholds); 220 } 221