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 }, 70 [this](const auto&) { return persistent; }); 71 72 dbusIface.register_property_rw( 73 "Thresholds", TriggerThresholdParams{}, 74 sdbusplus::vtable::property_::emits_change, 75 [this, &triggerFactory](auto newVal, auto& oldVal) { 76 auto newThresholdParams = std::visit( 77 utils::ToLabeledThresholdParamConversion(), newVal); 78 TriggerManager::verifyThresholdParams(newThresholdParams); 79 triggerFactory.updateThresholds( 80 thresholds, *id, triggerActions, reportIds, sensors, 81 newThresholdParams); 82 oldVal = std::move(newVal); 83 return 1; 84 }, 85 [this](const auto&) { 86 return fromLabeledThresholdParam(getLabeledThresholds()); 87 }); 88 89 dbusIface.register_property_rw( 90 "Sensors", SensorsInfo{}, 91 sdbusplus::vtable::property_::emits_change, 92 [this, &triggerFactory](auto newVal, auto& oldVal) { 93 auto labeledSensorInfo = 94 triggerFactory.getLabeledSensorsInfo(newVal); 95 triggerFactory.updateSensors(sensors, labeledSensorInfo); 96 for (const auto& threshold : thresholds) 97 { 98 threshold->updateSensors(sensors); 99 } 100 oldVal = std::move(newVal); 101 return 1; 102 }, 103 [this](const auto&) { 104 return utils::fromLabeledSensorsInfo( 105 getLabeledSensorInfo()); 106 }); 107 108 dbusIface.register_property_rw( 109 "Reports", std::vector<sdbusplus::message::object_path>(), 110 sdbusplus::vtable::property_::emits_change, 111 [this](auto newVal, auto& oldVal) { 112 auto newReportIds = utils::transform<std::vector>( 113 newVal, [](const auto& path) { 114 return utils::reportPathToId(path); 115 }); 116 TriggerManager::verifyReportIds(newReportIds); 117 *reportIds = newReportIds; 118 messanger.send(messages::TriggerPresenceChangedInd{ 119 messages::Presence::Exist, *id, *reportIds}); 120 oldVal = std::move(newVal); 121 return 1; 122 }, 123 [this](const auto&) { 124 return utils::transform<std::vector>( 125 *reportIds, [](const auto& id) { 126 return utils::pathAppend( 127 utils::constants::reportDirPath, id); 128 }); 129 }); 130 131 dbusIface.register_property_r( 132 "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_, 133 [this](const auto& x) { return isDiscreate(); }); 134 135 dbusIface.register_property_rw( 136 "Name", name, sdbusplus::vtable::property_::emits_change, 137 [this](auto newVal, auto& oldVal) { 138 if (newVal.length() > utils::constants::maxIdNameLength) 139 { 140 throw errors::InvalidArgument("Name", 141 "Name is too long."); 142 } 143 name = oldVal = newVal; 144 return 1; 145 }, 146 [this](const auto&) { return name; }); 147 148 dbusIface.register_property_r( 149 "TriggerActions", std::vector<std::string>(), 150 sdbusplus::vtable::property_::const_, [this](const auto&) { 151 return utils::transform(triggerActions, 152 [](const auto& action) { 153 return actionToString(action); 154 }); 155 }); 156 }); 157 158 for (const auto& threshold : thresholds) 159 { 160 threshold->initialize(); 161 } 162 163 messanger.on_receive<messages::CollectTriggerIdReq>( 164 [this](const auto& msg) { 165 if (utils::contains(*reportIds, msg.reportId)) 166 { 167 messanger.send(messages::CollectTriggerIdResp{*id}); 168 } 169 }); 170 171 messanger.send(messages::TriggerPresenceChangedInd{ 172 messages::Presence::Exist, *id, *reportIds}); 173 } 174 175 bool Trigger::storeConfiguration() const 176 { 177 try 178 { 179 nlohmann::json data; 180 181 auto labeledThresholdParams = 182 std::visit(utils::ToLabeledThresholdParamConversion(), 183 fromLabeledThresholdParam(getLabeledThresholds())); 184 185 data["Version"] = triggerVersion; 186 data["Id"] = *id; 187 data["Name"] = name; 188 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); 189 data["TriggerActions"] = 190 utils::transform(triggerActions, [](const auto& action) { 191 return actionToString(action); 192 }); 193 data["ThresholdParams"] = 194 utils::labeledThresholdParamsToJson(labeledThresholdParams); 195 data["ReportIds"] = *reportIds; 196 data["Sensors"] = getLabeledSensorInfo(); 197 198 triggerStorage.store(fileName, data); 199 } 200 catch (const std::exception& e) 201 { 202 phosphor::logging::log<phosphor::logging::level::ERR>( 203 "Failed to store a trigger in storage", 204 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 205 return false; 206 } 207 return true; 208 } 209 210 std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const 211 { 212 return utils::transform(sensors, [](const auto& sensor) { 213 return sensor->getLabeledSensorInfo(); 214 }); 215 } 216 217 std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const 218 { 219 return utils::transform(thresholds, [](const auto& threshold) { 220 return threshold->getThresholdParam(); 221 }); 222 } 223 224 bool Trigger::isDiscreate() const 225 { 226 const auto labeledThresholds = getLabeledThresholds(); 227 228 return utils::isFirstElementOfType<std::monostate>(labeledThresholds) || 229 utils::isFirstElementOfType<discrete::LabeledThresholdParam>( 230 labeledThresholds); 231 } 232