Utilization of power restore delay for APR
There was an issue where APR would start too early in the boot
process causing conflicts between the BMC and host firmware on
the i2c buses. Waiting to run APR ensures the BMC reaches a
READY state and that the vpd collection has completed.
This commit adds a delay based off of the value of
'PowerRestoreDelay' a Dbus property hosted by the RestorePolicy
interface. The system owners may override this value which is
initially defaulted to 0 via an override in their meta layer.
Tested:
- Ran an AC cycle of the system and restarted phosphor-discover-
system-state@0.service.
- Ensure that the bmc reboot was delayed by the value
specified by PowerRestoreDelay.
- Verified through on real hardware. Simulation environment
has system noise that create unpredictable delay results
with delays over 15 seconds. The delays in simulation always
adhere to the property, but take additional time to boot.
- PowerRestoreDelay at 30 seconds (ran 5 separate times)
systemctl stop phosphor-discover-system-state@0.service
Jul 22 17:47:23 p10bmc phosphor-discover-system-state[2224]:
power_policy=Restore, powering host on (30s delay)
Jul 22 17:47:53 p10bmc systemd[1]: Finished Reboot If Enabled
5/5 tests were delayed exactly 30 seconds.
- PowerRestoreDelay at 100 seconds
Jul 22 17:52:45 p10bmc phosphor-discover-system-state[2224]:
power_policy=Restore, powering host on (100s delay)
Jul 22 17:54:25 p10bmc systemd[1]: Finished Reboot If Enabled.
1/1 test(s) were delayed exactly 100 seconds.
- PowerRestoreDelay at 0 seconds
Jul 22 18:02:51 p10bmc phosphor-discover-system-state[2271]:
power_policy=Restore, powering host on (30s delay)
Jul 22 18:02:51 p10bmc systemd[1]: Finished Reboot If Enabled.
Signed-off-by: Corey Hardesty <corey.hardesty@icloud.com>
Change-Id: I69f7f9f3a9e638defcbee2bbb8dda6d9c4b7f0ae
diff --git a/discover_system_state.cpp b/discover_system_state.cpp
index 0e56144..1623922 100644
--- a/discover_system_state.cpp
+++ b/discover_system_state.cpp
@@ -17,6 +17,7 @@
#include <iostream>
#include <map>
#include <string>
+#include <thread>
namespace phosphor
{
@@ -134,13 +135,34 @@
convertForMessage(RestorePolicy::Policy::None));
}
+ auto methodUserSettingDelay = bus.new_method_call(
+ settings.service(settings.powerRestorePolicy, powerRestoreIntf)
+ .c_str(),
+ settings.powerRestorePolicy.c_str(),
+ "org.freedesktop.DBus.Properties", "Get");
+
+ methodUserSettingDelay.append(powerRestoreIntf, "PowerRestoreDelay");
+
+ std::variant<uint64_t> restoreDelay;
+
+ auto delayResult = bus.call(methodUserSettingDelay);
+ delayResult.read(restoreDelay);
+ auto powerRestoreDelayUsec =
+ std::chrono::microseconds(std::get<uint64_t>(restoreDelay));
+ auto powerRestoreDelaySec =
+ std::chrono::duration_cast<std::chrono::seconds>(
+ powerRestoreDelayUsec);
+
info("Host power is off, processing power policy {POWER_POLICY}",
"POWER_POLICY", powerPolicy);
if (RestorePolicy::Policy::AlwaysOn ==
RestorePolicy::convertPolicyFromString(powerPolicy))
{
- info("power_policy=ALWAYS_POWER_ON, powering host on");
+ info(
+ "power_policy=ALWAYS_POWER_ON, powering host on ({DELAY}s delay)",
+ "DELAY", powerRestoreDelaySec.count());
+ std::this_thread::sleep_for(powerRestoreDelayUsec);
phosphor::state::manager::utils::setProperty(
bus, hostPath, HOST_BUSNAME, "RestartCause",
convertForMessage(
@@ -152,7 +174,10 @@
else if (RestorePolicy::Policy::AlwaysOff ==
RestorePolicy::convertPolicyFromString(powerPolicy))
{
- info("power_policy=ALWAYS_POWER_OFF, set requested state to off");
+ info(
+ "power_policy=ALWAYS_POWER_OFF, set requested state to off ({DELAY}s delay)",
+ "DELAY", powerRestoreDelaySec.count());
+ std::this_thread::sleep_for(powerRestoreDelayUsec);
// Read last requested state and re-request it to execute it
auto hostReqState = phosphor::state::manager::utils::getProperty(
bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
@@ -167,7 +192,9 @@
else if (RestorePolicy::Policy::Restore ==
RestorePolicy::convertPolicyFromString(powerPolicy))
{
- info("power_policy=RESTORE, restoring last state");
+ info("power_policy=RESTORE, restoring last state ({DELAY}s delay)",
+ "DELAY", powerRestoreDelaySec.count());
+ std::this_thread::sleep_for(powerRestoreDelayUsec);
// Read last requested state and re-request it to execute it
auto hostReqState = phosphor::state::manager::utils::getProperty(
bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");