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