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 sdbusplus::exception::SdBusError( 141 static_cast<int>(std::errc::invalid_argument), 142 "Name is too long"); 143 } 144 name = oldVal = newVal; 145 return 1; 146 }, 147 [this](const auto&) { return name; }); 148 149 dbusIface.register_property_r( 150 "TriggerActions", std::vector<std::string>(), 151 sdbusplus::vtable::property_::const_, [this](const auto&) { 152 return utils::transform(triggerActions, 153 [](const auto& action) { 154 return actionToString(action); 155 }); 156 }); 157 }); 158 159 for (const auto& threshold : thresholds) 160 { 161 threshold->initialize(); 162 } 163 164 messanger.on_receive<messages::CollectTriggerIdReq>( 165 [this](const auto& msg) { 166 if (utils::contains(*reportIds, msg.reportId)) 167 { 168 messanger.send(messages::CollectTriggerIdResp{*id}); 169 } 170 }); 171 172 messanger.send(messages::TriggerPresenceChangedInd{ 173 messages::Presence::Exist, *id, *reportIds}); 174 } 175 176 bool Trigger::storeConfiguration() const 177 { 178 try 179 { 180 nlohmann::json data; 181 182 auto labeledThresholdParams = 183 std::visit(utils::ToLabeledThresholdParamConversion(), 184 fromLabeledThresholdParam(getLabeledThresholds())); 185 186 data["Version"] = triggerVersion; 187 data["Id"] = *id; 188 data["Name"] = name; 189 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); 190 data["TriggerActions"] = 191 utils::transform(triggerActions, [](const auto& action) { 192 return actionToString(action); 193 }); 194 data["ThresholdParams"] = 195 utils::labeledThresholdParamsToJson(labeledThresholdParams); 196 data["ReportIds"] = *reportIds; 197 data["Sensors"] = getLabeledSensorInfo(); 198 199 triggerStorage.store(fileName, data); 200 } 201 catch (const std::exception& e) 202 { 203 phosphor::logging::log<phosphor::logging::level::ERR>( 204 "Failed to store a trigger in storage", 205 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 206 return false; 207 } 208 return true; 209 } 210 211 std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const 212 { 213 return utils::transform(sensors, [](const auto& sensor) { 214 return sensor->getLabeledSensorInfo(); 215 }); 216 } 217 218 std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const 219 { 220 return utils::transform(thresholds, [](const auto& threshold) { 221 return threshold->getThresholdParam(); 222 }); 223 } 224 225 bool Trigger::isDiscreate() const 226 { 227 const auto labeledThresholds = getLabeledThresholds(); 228 229 return utils::isFirstElementOfType<std::monostate>(labeledThresholds) || 230 utils::isFirstElementOfType<discrete::LabeledThresholdParam>( 231 labeledThresholds); 232 } 233