hypervisor: monitor boot progress
The BootProgress property will be tracked to set the hypervisor state as
appropriate
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I5aa5d95893222169bc5abed6b851e795f2ad5ff0
diff --git a/hypervisor_state_manager.cpp b/hypervisor_state_manager.cpp
index acfbb83..afd496a 100644
--- a/hypervisor_state_manager.cpp
+++ b/hypervisor_state_manager.cpp
@@ -46,9 +46,6 @@
return server::Host::requestedHostTransition(value);
}
-// TODO - Monitor BootProgress and update hypervisor state to Running if
-// OS is started
-
server::Host::HostState Hypervisor::currentHostState(HostState value)
{
log<level::INFO>(
@@ -57,6 +54,54 @@
return server::Host::currentHostState(value);
}
+server::Host::HostState Hypervisor::currentHostState()
+{
+ return server::Host::currentHostState();
+}
+
+void Hypervisor::updateCurrentHostState(std::string& bootProgress)
+{
+ log<level::DEBUG>(
+ fmt::format("New BootProgress: {}", bootProgress).c_str());
+
+ if (bootProgress == "xyz.openbmc_project.State.Boot.Progress."
+ "ProgressStages.SystemInitComplete")
+ {
+ currentHostState(server::Host::HostState::Standby);
+ }
+ else if (bootProgress == "xyz.openbmc_project.State.Boot.Progress."
+ "ProgressStages.OSStart")
+ {
+ currentHostState(server::Host::HostState::TransitioningToRunning);
+ }
+ else if (bootProgress == "xyz.openbmc_project.State.Boot.Progress."
+ "ProgressStages.OSRunning")
+ {
+ currentHostState(server::Host::HostState::Running);
+ }
+ else
+ {
+ // BootProgress changed and it is not one of the above so
+ // set hypervisor state to off
+ currentHostState(server::Host::HostState::Off);
+ }
+}
+
+void Hypervisor::bootProgressChangeEvent(sdbusplus::message::message& msg)
+{
+ std::string statusInterface;
+ std::map<std::string, std::variant<std::string>> msgData;
+ msg.read(statusInterface, msgData);
+
+ auto propertyMap = msgData.find("BootProgress");
+ if (propertyMap != msgData.end())
+ {
+ // Extract the BootProgress
+ auto& bootProgress = std::get<std::string>(propertyMap->second);
+ updateCurrentHostState(bootProgress);
+ }
+}
+
} // namespace manager
} // namespace state
} // namespace phosphor
diff --git a/hypervisor_state_manager.hpp b/hypervisor_state_manager.hpp
index b0ce297..9bb3cb2 100644
--- a/hypervisor_state_manager.hpp
+++ b/hypervisor_state_manager.hpp
@@ -18,6 +18,7 @@
sdbusplus::xyz::openbmc_project::State::server::Host>;
namespace server = sdbusplus::xyz::openbmc_project::State::server;
+namespace sdbusRule = sdbusplus::bus::match::rules;
/** @class Host
* @brief OpenBMC host state management implementation.
@@ -40,7 +41,14 @@
* @param[in] objPath - The Dbus object path
*/
Hypervisor(sdbusplus::bus::bus& bus, const char* objPath) :
- HypervisorInherit(bus, objPath, false), bus(bus)
+ HypervisorInherit(bus, objPath, false), bus(bus),
+ bootProgressChangeSignal(
+ bus,
+ sdbusRule::propertiesChanged(
+ "/xyz/openbmc_project/state/host0",
+ "xyz.openbmc_project.State.Boot.Progress"),
+ std::bind(std::mem_fn(&Hypervisor::bootProgressChangeEvent), this,
+ std::placeholders::_1))
{}
/** @brief Set value of HostTransition */
@@ -51,9 +59,32 @@
server::Host::HostState
currentHostState(server::Host::HostState value) override;
+ /** @brief Return value of CurrentHostState */
+ server::Host::HostState currentHostState();
+
+ /** @brief Check if BootProgress change affects hypervisor state
+ *
+ * @param[in] bootProgress - BootProgress value to check
+ *
+ */
+ void updateCurrentHostState(std::string& bootProgress);
+
private:
+ /** @brief Process BootProgress property changes
+ *
+ * Instance specific interface to monitor for changes to the BootProgress
+ * property which may impact Hypervisor state.
+ *
+ * @param[in] msg - Data associated with subscribed signal
+ *
+ */
+ void bootProgressChangeEvent(sdbusplus::message::message& msg);
+
/** @brief Persistent sdbusplus DBus bus connection. */
sdbusplus::bus::bus& bus;
+
+ /** @brief Watch BootProgress changes to know hypervisor state **/
+ sdbusplus::bus::match_t bootProgressChangeSignal;
};
} // namespace manager
diff --git a/meson.build b/meson.build
index 170971a..53df188 100644
--- a/meson.build
+++ b/meson.build
@@ -208,4 +208,17 @@
include_directories: '../'
)
)
+
+ test(
+ 'test_hypervisor_state',
+ executable('test_hypervisor_state',
+ './test/hypervisor_state.cpp',
+ 'hypervisor_state_manager.cpp',
+ dependencies: [
+ gtest, sdbusplus, sdeventplus, phosphorlogging,
+ ],
+ implicit_include_directories: true,
+ include_directories: '../'
+ )
+ )
endif
diff --git a/test/hypervisor_state.cpp b/test/hypervisor_state.cpp
new file mode 100644
index 0000000..a6ee783
--- /dev/null
+++ b/test/hypervisor_state.cpp
@@ -0,0 +1,39 @@
+#include "config.h"
+
+#include <hypervisor_state_manager.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdeventplus/event.hpp>
+
+#include <gtest/gtest.h>
+
+namespace server = sdbusplus::xyz::openbmc_project::State::server;
+
+TEST(updateCurrentHostState, BasicPaths)
+{
+ auto bus = sdbusplus::bus::new_default();
+ auto event = sdeventplus::Event::get_default();
+ bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
+ auto objPathInst = std::string{HYPERVISOR_OBJPATH} + '0';
+
+ phosphor::state::manager::Hypervisor hypObj(bus, objPathInst.c_str());
+
+ std::string bootProgress = "Invalid.Boot.Progress";
+ hypObj.updateCurrentHostState(bootProgress);
+ EXPECT_EQ(hypObj.currentHostState(), server::Host::HostState::Off);
+
+ bootProgress = "xyz.openbmc_project.State.Boot.Progress."
+ "ProgressStages.SystemInitComplete";
+ hypObj.updateCurrentHostState(bootProgress);
+ EXPECT_EQ(hypObj.currentHostState(), server::Host::HostState::Standby);
+
+ bootProgress = "xyz.openbmc_project.State.Boot.Progress."
+ "ProgressStages.OSStart";
+ hypObj.updateCurrentHostState(bootProgress);
+ EXPECT_EQ(hypObj.currentHostState(),
+ server::Host::HostState::TransitioningToRunning);
+
+ bootProgress = "xyz.openbmc_project.State.Boot.Progress."
+ "ProgressStages.OSRunning";
+ hypObj.updateCurrentHostState(bootProgress);
+ EXPECT_EQ(hypObj.currentHostState(), server::Host::HostState::Running);
+}