use settings from persistent files if available
If persistent files are available for a service then utilize it for that
service. If the setting in the file does not match what system has
reported, then make the change to systemd to match the setting.
This commit officially moves service-config-manager over to utilizing
persistent files for the users service settings if the appropriate
compile feature is enabled (persist-settings-to-file).
One reason for doing this is to facilitate the redundant BMC design
point [1]. Backing the service settings in a persistent file allows an
easy mechanism to synchronize the service-config-manager settings from
an Active BMC to a Passive.
Backup and Restore could also make use of this. This feature seems to
come up every once in a while as a wanted function.
Having persistent files with clear true/false settings will be much
easier to manage then trying to synchronize the complex systemd
service/socket details from the filesystem.
[1]: https://gerrit.openbmc.org/c/openbmc/docs/+/70233
Tested:
- Verified the basics of enabling and disabling IPMI and SSH via dbus
and Redfish (curl)
- Verified if the settings in the persistent files do not match what
systemd reports on startup, the srvcfg-manager will apply the settings
from the files
- Verified that if there is an error loading the file then it is deleted
and a fresh one is created
- Verified that if the version in the file is not 1 then it is deleted
and a fresh one is created
- Verified that when the new feature is not enabled that no files are
created or loaded
Change-Id: Iccc29d99d88c1b0700106e70c9eacb40b93b2817
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/inc/srvcfg_manager.hpp b/inc/srvcfg_manager.hpp
index eec1aa1..4fc9ccd 100644
--- a/inc/srvcfg_manager.hpp
+++ b/inc/srvcfg_manager.hpp
@@ -122,6 +122,7 @@
std::string getSocketUnitName();
std::string getServiceUnitName();
void writeStateFile();
+ void loadStateFile();
};
} // namespace service
diff --git a/src/srvcfg_manager.cpp b/src/srvcfg_manager.cpp
index a7cb90c..62a1837 100644
--- a/src/srvcfg_manager.cpp
+++ b/src/srvcfg_manager.cpp
@@ -288,7 +288,7 @@
{
registerProperties();
}
- writeStateFile();
+ loadStateFile();
}
catch (const std::exception& e)
{
@@ -339,6 +339,86 @@
#endif
}
+void ServiceConfig::loadStateFile()
+{
+#ifdef PERSIST_SETTINGS
+ if (std::filesystem::exists(stateFile))
+ {
+ std::ifstream file(stateFile);
+ if (!file.good())
+ {
+ lg2::error("Error reading {FILEPATH}; delete it and continue",
+ "FILEPATH", stateFile);
+ std::filesystem::remove(stateFile);
+ // rewrite file with what was ready from systemd
+ writeStateFile();
+ return;
+ }
+
+ nlohmann::json stateMap =
+ nlohmann::json::parse(file, nullptr, false, true);
+ if (stateMap.is_discarded())
+ {
+ lg2::error("Error loading {FILEPATH}; delete it and continue",
+ "FILEPATH", stateFile);
+ std::filesystem::remove(stateFile);
+ // rewrite file with what was ready from systemd
+ writeStateFile();
+ return;
+ }
+ else if (stateMap[persistDataFileVersionStr] != persistDataFileVersion)
+ {
+ lg2::error(
+ "Error version:{VERSION} read from {FILEPATH} does not match expected {VERSION_EXP}; delete it and continue",
+ "VERSION", stateMap[persistDataFileVersionStr], "FILEPATH",
+ stateFile, "VERSION_EXP", persistDataFileVersion);
+ std::filesystem::remove(stateFile);
+ // rewrite file with what was ready from systemd
+ writeStateFile();
+ return;
+ }
+
+ // If there are any differences, the persistent config file wins so
+ // update the dbus properties and trigger a reload to apply the changes
+ if (stateMap[srvCfgPropMasked] != unitMaskedState)
+ {
+ lg2::info(
+ "Masked property for {FILEPATH} not equal. Setting to {SETTING}",
+ "FILEPATH", stateFile, "SETTING", stateMap[srvCfgPropMasked]);
+ unitMaskedState = stateMap[srvCfgPropMasked];
+ updatedFlag |=
+ (1 << static_cast<uint8_t>(UpdatedProp::maskedState));
+ startServiceRestartTimer();
+ }
+ if (stateMap[srvCfgPropEnabled] != unitEnabledState)
+ {
+ lg2::info(
+ "Enabled property for {FILEPATH} not equal. Setting to {SETTING}",
+ "FILEPATH", stateFile, "SETTING", stateMap[srvCfgPropEnabled]);
+ unitEnabledState = stateMap[srvCfgPropEnabled];
+ updatedFlag |=
+ (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
+ startServiceRestartTimer();
+ }
+ if (stateMap[srvCfgPropRunning] != unitRunningState)
+ {
+ lg2::info(
+ "Running property for {FILEPATH} not equal. Setting to {SETTING}",
+ "FILEPATH", stateFile, "SETTING", stateMap[srvCfgPropRunning]);
+ unitRunningState = stateMap[srvCfgPropRunning];
+ updatedFlag |=
+ (1 << static_cast<uint8_t>(UpdatedProp::runningState));
+ startServiceRestartTimer();
+ }
+ }
+ else
+ {
+ // Just write out what we got from systemd if no existing config file
+ writeStateFile();
+ }
+#endif
+}
+
ServiceConfig::ServiceConfig(
sdbusplus::asio::object_server& srv_,
std::shared_ptr<sdbusplus::asio::connection>& conn_,