1 #include "trigger.hpp" 2 3 #include "trigger_manager.hpp" 4 #include "types/report_types.hpp" 5 #include "types/trigger_types.hpp" 6 #include "utils/conversion_trigger.hpp" 7 #include "utils/transform.hpp" 8 9 #include <phosphor-logging/log.hpp> 10 11 Trigger::Trigger( 12 boost::asio::io_context& ioc, 13 const std::shared_ptr<sdbusplus::asio::object_server>& objServer, 14 const std::string& idIn, const std::string& nameIn, 15 const std::vector<TriggerAction>& triggerActionsIn, 16 const std::shared_ptr<std::vector<std::string>> reportIdsIn, 17 std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn, 18 interfaces::TriggerManager& triggerManager, 19 interfaces::JsonStorage& triggerStorageIn, 20 const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) : 21 id(idIn), 22 name(nameIn), triggerActions(std::move(triggerActionsIn)), 23 path(triggerDir + id), reportIds(std::move(reportIdsIn)), 24 thresholds(std::move(thresholdsIn)), 25 fileName(std::to_string(std::hash<std::string>{}(id))), 26 triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)) 27 { 28 deleteIface = objServer->add_unique_interface( 29 path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) { 30 dbusIface.register_method("Delete", [this, &ioc, &triggerManager] { 31 if (persistent) 32 { 33 triggerStorage.remove(fileName); 34 } 35 boost::asio::post(ioc, [this, &triggerManager] { 36 triggerManager.removeTrigger(this); 37 }); 38 }); 39 }); 40 41 triggerIface = objServer->add_unique_interface( 42 path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) { 43 persistent = storeConfiguration(); 44 dbusIface.register_property_rw( 45 "Persistent", persistent, 46 sdbusplus::vtable::property_::emits_change, 47 [this](bool newVal, const auto&) { 48 if (newVal == persistent) 49 { 50 return 1; 51 } 52 if (newVal) 53 { 54 persistent = storeConfiguration(); 55 } 56 else 57 { 58 triggerStorage.remove(fileName); 59 persistent = false; 60 } 61 return 1; 62 }, 63 [this](const auto&) { return persistent; }); 64 65 dbusIface.register_property_rw( 66 "Thresholds", TriggerThresholdParams{}, 67 sdbusplus::vtable::property_::emits_change, 68 [this, &triggerFactory](auto newVal, auto& oldVal) { 69 auto newThresholdParams = std::visit( 70 utils::ToLabeledThresholdParamConversion(), newVal); 71 triggerFactory.updateThresholds(thresholds, triggerActions, 72 reportIds, sensors, 73 newThresholdParams); 74 oldVal = std::move(newVal); 75 return 1; 76 }, 77 [this](const auto&) { 78 return fromLabeledThresholdParam( 79 utils::transform(thresholds, [](const auto& threshold) { 80 return threshold->getThresholdParam(); 81 })); 82 }); 83 84 dbusIface.register_property_rw( 85 "Sensors", SensorsInfo{}, 86 sdbusplus::vtable::property_::emits_change, 87 [this, &triggerFactory](auto newVal, auto& oldVal) { 88 auto labeledSensorInfo = 89 triggerFactory.getLabeledSensorsInfo(newVal); 90 triggerFactory.updateSensors(sensors, labeledSensorInfo); 91 for (const auto& threshold : thresholds) 92 { 93 threshold->updateSensors(sensors); 94 } 95 oldVal = std::move(newVal); 96 return 1; 97 }, 98 [this](const auto&) { 99 return utils::fromLabeledSensorsInfo( 100 utils::transform(sensors, [](const auto& sensor) { 101 return sensor->getLabeledSensorInfo(); 102 })); 103 }); 104 105 dbusIface.register_property_rw( 106 "ReportNames", std::vector<std::string>{}, 107 sdbusplus::vtable::property_::emits_change, 108 [this](auto newVal, auto& oldVal) { 109 reportIds->clear(); 110 std::copy(newVal.begin(), newVal.end(), 111 std::back_inserter(*reportIds)); 112 oldVal = std::move(newVal); 113 return 1; 114 }, 115 [this](const auto&) { return *reportIds; }); 116 117 dbusIface.register_property_r( 118 "Discrete", false, sdbusplus::vtable::property_::const_, 119 [this](const auto& x) { 120 return !std::holds_alternative< 121 numeric::LabeledThresholdParam>( 122 thresholds.back()->getThresholdParam()); 123 }); 124 125 dbusIface.register_property_rw( 126 "Name", std::string(), 127 sdbusplus::vtable::property_::emits_change, 128 [this](auto newVal, auto& oldVal) { 129 name = oldVal = newVal; 130 return 1; 131 }, 132 [this](const auto&) { return name; }); 133 134 dbusIface.register_property_r( 135 "TriggerActions", std::vector<std::string>(), 136 sdbusplus::vtable::property_::const_, [this](const auto&) { 137 return utils::transform(triggerActions, 138 [](const auto& action) { 139 return actionToString(action); 140 }); 141 }); 142 }); 143 144 for (const auto& threshold : thresholds) 145 { 146 threshold->initialize(); 147 } 148 } 149 150 bool Trigger::storeConfiguration() const 151 { 152 try 153 { 154 nlohmann::json data; 155 156 auto labeledThresholdParams = 157 std::visit(utils::ToLabeledThresholdParamConversion(), 158 fromLabeledThresholdParam(utils::transform( 159 thresholds, [](const auto& threshold) { 160 return threshold->getThresholdParam(); 161 }))); 162 163 data["Version"] = triggerVersion; 164 data["Id"] = id; 165 data["Name"] = name; 166 data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index(); 167 data["TriggerActions"] = 168 utils::transform(triggerActions, [](const auto& action) { 169 return actionToString(action); 170 }); 171 data["ThresholdParams"] = 172 utils::labeledThresholdParamsToJson(labeledThresholdParams); 173 data["ReportIds"] = *reportIds; 174 data["Sensors"] = utils::transform(sensors, [](const auto& sensor) { 175 return sensor->getLabeledSensorInfo(); 176 }); 177 178 triggerStorage.store(fileName, data); 179 } 180 catch (const std::exception& e) 181 { 182 phosphor::logging::log<phosphor::logging::level::ERR>( 183 "Failed to store a trigger in storage", 184 phosphor::logging::entry("EXCEPTION_MSG=%s", e.what())); 185 return false; 186 } 187 return true; 188 } 189