side-switch: power off chassis in prep for update
When switching to a new level of firmware, ensure the host is off and
the chassis power is off before switching to the new firmware.
Tested:
- Verify power off works
<6> Checking for side switch reboot
<6> Running firmware version path is /xyz/openbmc_project/software/74575136
<6> Running firmware version priority is 1
<6> Running image is at priority 1, execute side switch
<see power off occur in journal>
<6> chassis power is off
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: Ifdb3e0c51fe66e55ebb1c3fca7097af49607bf35
diff --git a/side-switch/side_switch.cpp b/side-switch/side_switch.cpp
index fb558c4..4c13ed0 100644
--- a/side-switch/side_switch.cpp
+++ b/side-switch/side_switch.cpp
@@ -3,18 +3,18 @@
#include "utils.hpp"
#include <phosphor-logging/lg2.hpp>
-#include <sdbusplus/bus.hpp>
#include <exception>
#include <string>
+#include <thread>
#include <variant>
#include <vector>
PHOSPHOR_LOG2_USING;
-bool sideSwitchNeeded()
+bool sideSwitchNeeded(sdbusplus::bus::bus& bus)
{
- auto bus = sdbusplus::bus::new_default();
+
std::string fwRunningVersionPath;
uint8_t fwRunningPriority = 0;
@@ -124,15 +124,71 @@
return (false);
}
+bool powerOffSystem(sdbusplus::bus::bus& bus)
+{
+
+ try
+ {
+ utils::PropertyValue chassOff =
+ "xyz.openbmc_project.State.Chassis.Transition.Off";
+ utils::setProperty(bus, "/xyz/openbmc_project/state/chassis0",
+ "xyz.openbmc_project.State.Chassis",
+ "RequestedPowerTransition", chassOff);
+ }
+ catch (const std::exception& e)
+ {
+ error("chassis off request failed: {ERROR}", "ERROR", e);
+ return (false);
+ }
+
+ // Now just wait for power to turn off
+ // Worst case is a systemd service hangs in power off for 2 minutes so
+ // take that and double it to avoid any timing issues. The user has
+ // requested we switch to the other side, so a lengthy delay is warranted
+ // if needed. On most systems the power off takes 5-15 seconds.
+ for (int i = 0; i < 240; i++)
+ {
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ try
+ {
+ auto currentPwrState = utils::getProperty<std::string>(
+ bus, "/xyz/openbmc_project/state/chassis0",
+ "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
+
+ if (currentPwrState ==
+ "xyz.openbmc_project.State.Chassis.PowerState.Off")
+ {
+ info("chassis power is off");
+ return (true);
+ }
+ }
+ catch (const std::exception& e)
+ {
+ error("reading chassis power state failed: {ERROR}", "ERROR", e);
+ return (false);
+ }
+ }
+ error("timeout waiting for chassis power to turn off");
+ return (false);
+}
+
int main()
{
info("Checking for side switch reboot");
- if (!sideSwitchNeeded())
+ auto bus = sdbusplus::bus::new_default();
+
+ if (!sideSwitchNeeded(bus))
{
info("Side switch not needed");
return 0;
}
+ if (!powerOffSystem(bus))
+ {
+ error("unable to power off chassis");
+ return 0;
+ }
+
// TODO - Future commits in series to fill in rest of logic
}
diff --git a/side-switch/side_switch.hpp b/side-switch/side_switch.hpp
index 684cae9..4af52cb 100644
--- a/side-switch/side_switch.hpp
+++ b/side-switch/side_switch.hpp
@@ -1,7 +1,17 @@
#pragma once
+#include <sdbusplus/bus.hpp>
+
/** @brief Determine if a side switch is needed
*
+ * @param[in] bus - The Dbus bus object
* @return True if side switch needed, false otherwise
*/
-bool sideSwitchNeeded();
+bool sideSwitchNeeded(sdbusplus::bus::bus& bus);
+
+/** @brief Power off the system
+ *
+ * @param[in] bus - The Dbus bus object
+ * @return True if chassis off success, false otherwise
+ */
+bool powerOffSystem(sdbusplus::bus::bus& bus);