Save persistent triggers to storage
Create json storage file for persistent triggers.
Handle persistent dbus property.
Save/remove persistent triggers on add/delete.
Cover code with UTs.
Tested:
- Passed unit tests
- Tested on QEMU
* adding new valid and invalid trigger from cli
* verifying if valid trigger is properly stored
* deleting existed trigger from storage
Change-Id: I243326e84833a8cb22075fbf565573b62b205b4a
Signed-off-by: Cezary Zwolak <cezary.zwolak@intel.com>
Signed-off-by: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
diff --git a/src/trigger.cpp b/src/trigger.cpp
index 471ad10..2bba3ea 100644
--- a/src/trigger.cpp
+++ b/src/trigger.cpp
@@ -1,26 +1,44 @@
#include "trigger.hpp"
#include "interfaces/types.hpp"
+#include "utils/transform.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+template <class... Ts>
+struct overloaded : Ts...
+{
+ using Ts::operator()...;
+};
+template <class... Ts>
+overloaded(Ts...) -> overloaded<Ts...>;
Trigger::Trigger(
boost::asio::io_context& ioc,
const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
- const std::string& nameIn, const bool isDiscrete, const bool logToJournal,
- const bool logToRedfish, const bool updateReport,
- const std::vector<std::pair<sdbusplus::message::object_path, std::string>>&
- sensorsIn,
+ const std::string& nameIn, const bool isDiscreteIn,
+ const bool logToJournalIn, const bool logToRedfishIn,
+ const bool updateReportIn, const TriggerSensors& sensorsIn,
const std::vector<std::string>& reportNamesIn,
const TriggerThresholdParams& thresholdParamsIn,
std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn,
- interfaces::TriggerManager& triggerManager) :
+ interfaces::TriggerManager& triggerManager,
+ interfaces::JsonStorage& triggerStorageIn) :
name(nameIn),
- path(triggerDir + name), persistent(false), sensors(sensorsIn),
- reportNames(reportNamesIn), thresholdParams(thresholdParamsIn),
- thresholds(std::move(thresholdsIn))
+ isDiscrete(isDiscreteIn), logToJournal(logToJournalIn),
+ logToRedfish(logToRedfishIn), updateReport(updateReportIn),
+ path(triggerDir + name), sensors(sensorsIn), reportNames(reportNamesIn),
+ thresholdParams(thresholdParamsIn), thresholds(std::move(thresholdsIn)),
+ fileName(std::to_string(std::hash<std::string>{}(name))),
+ triggerStorage(triggerStorageIn)
{
deleteIface = objServer->add_unique_interface(
path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) {
dbusIface.register_method("Delete", [this, &ioc, &triggerManager] {
+ if (persistent)
+ {
+ triggerStorage.remove(fileName);
+ }
boost::asio::post(ioc, [this, &triggerManager] {
triggerManager.removeTrigger(this);
});
@@ -29,12 +47,30 @@
triggerIface = objServer->add_unique_interface(
path, triggerIfaceName,
- [this, isDiscrete, logToJournal, logToRedfish,
- updateReport](auto& dbusIface) {
- dbusIface.register_property_r(
+ [this, isDiscreteIn, logToJournalIn, logToRedfishIn,
+ updateReportIn](auto& dbusIface) {
+ persistent = storeConfiguration();
+ dbusIface.register_property_rw(
"Persistent", persistent,
sdbusplus::vtable::property_::emits_change,
- [](const auto& x) { return x; });
+ [this](bool newVal, const auto&) {
+ if (newVal == persistent)
+ {
+ return true;
+ }
+ if (newVal)
+ {
+ persistent = storeConfiguration();
+ }
+ else
+ {
+ triggerStorage.remove(fileName);
+ persistent = false;
+ }
+ return true;
+ },
+ [this](const auto&) { return persistent; });
+
dbusIface.register_property_r(
"Thresholds", thresholdParams,
sdbusplus::vtable::property_::emits_change,
@@ -65,3 +101,62 @@
threshold->initialize();
}
}
+
+bool Trigger::storeConfiguration() const
+{
+ try
+ {
+ nlohmann::json data;
+
+ data["Version"] = triggerVersion;
+ data["Name"] = name;
+ data["ThresholdParamsDiscriminator"] = thresholdParams.index();
+ data["IsDiscrete"] = isDiscrete;
+ data["LogToJournal"] = logToJournal;
+ data["LogToRedfish"] = logToRedfish;
+ data["UpdateReport"] = updateReport;
+
+ std::visit(
+ overloaded{
+ [&](const std::vector<numeric::ThresholdParam>& arg) {
+ data["ThresholdParams"] =
+ utils::transform(arg, [](const auto& thresholdParam) {
+ const auto& [type, dwellTime, direction,
+ thresholdValue] = thresholdParam;
+ return numeric::LabeledThresholdParam(
+ numeric::stringToType(type), dwellTime,
+ numeric::stringToDirection(direction),
+ thresholdValue);
+ });
+ },
+ [&](const std::vector<discrete::ThresholdParam>& arg) {
+ data["ThresholdParams"] =
+ utils::transform(arg, [](const auto& thresholdParam) {
+ const auto& [userId, severity, dwellTime,
+ thresholdValue] = thresholdParam;
+ return discrete::LabeledThresholdParam(
+ userId, discrete::stringToSeverity(severity),
+ dwellTime, thresholdValue);
+ });
+ },
+ },
+ thresholdParams);
+
+ data["ReportNames"] = reportNames;
+
+ data["Sensors"] = utils::transform(sensors, [](const auto& sensor) {
+ const auto& [sensorPath, sensorMetadata] = sensor;
+ return LabeledTriggerSensor(sensorPath, sensorMetadata);
+ });
+
+ triggerStorage.store(fileName, data);
+ }
+ catch (const std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Failed to store a trigger in storage",
+ phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
+ return false;
+ }
+ return true;
+}
\ No newline at end of file