summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host-cmd-manager.cpp42
-rw-r--r--host-cmd-manager.hpp29
2 files changed, 70 insertions, 1 deletions
diff --git a/host-cmd-manager.cpp b/host-cmd-manager.cpp
index 799f9bf..4316451 100644
--- a/host-cmd-manager.cpp
+++ b/host-cmd-manager.cpp
@@ -2,6 +2,7 @@
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
+#include <xyz/openbmc_project/State/Host/server.hpp>
#include <systemintfcmds.h>
#include <utils.hpp>
#include <config.h>
@@ -18,15 +19,26 @@ namespace command
constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
+constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0";
+constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host";
+constexpr auto HOST_TRANS_PROP = "RequestedHostTransition";
// For throwing exceptions
using namespace phosphor::logging;
using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
Error::InternalFailure;
+namespace sdbusRule = sdbusplus::bus::match::rules;
+
Manager::Manager(sdbusplus::bus::bus& bus, sd_event* event) :
bus(bus),
- timer(event, std::bind(&Manager::hostTimeout, this))
+ timer(event, std::bind(&Manager::hostTimeout, this)),
+ hostTransitionMatch(bus,
+ sdbusRule::propertiesChanged(
+ HOST_STATE_PATH,
+ HOST_STATE_INTERFACE),
+ std::bind(&Manager::clearQueueOnPowerOn, this,
+ std::placeholders::_1))
{
// Nothing to do here.
}
@@ -75,6 +87,11 @@ void Manager::hostTimeout()
{
log<level::ERR>("Host control timeout hit!");
+ clearQueue();
+}
+
+void Manager::clearQueue()
+{
// Dequeue all entries and send fail signal
while(!this->workQueue.empty())
{
@@ -150,6 +167,29 @@ void Manager::execute(CommandHandler command)
return;
}
+void Manager::clearQueueOnPowerOn(sdbusplus::message::message& msg)
+{
+ namespace server = sdbusplus::xyz::openbmc_project::State::server;
+
+ ::ipmi::DbusInterface interface;
+ ::ipmi::PropertyMap properties;
+
+ msg.read(interface, properties);
+
+ if (properties.find(HOST_TRANS_PROP) == properties.end())
+ {
+ return;
+ }
+
+ auto& requestedState = properties.at(HOST_TRANS_PROP).get<std::string>();
+
+ if (server::Host::convertTransitionFromString(requestedState) ==
+ server::Host::Transition::On)
+ {
+ clearQueue();
+ }
+}
+
} // namespace command
} // namespace host
} // namepsace phosphor
diff --git a/host-cmd-manager.hpp b/host-cmd-manager.hpp
index 06ac5fa..c25706c 100644
--- a/host-cmd-manager.hpp
+++ b/host-cmd-manager.hpp
@@ -3,6 +3,7 @@
#include <tuple>
#include <queue>
#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
#include <timer.hpp>
#include <host-ipmid/ipmid-host-cmd-utils.hpp>
@@ -68,6 +69,31 @@ class Manager
*/
void hostTimeout();
+ /** @brief Clears the command queue
+ *
+ * @detail Clears the command queue and calls all callbacks
+ * specifying the command wasn't successful.
+ */
+ void clearQueue();
+
+ /** @brief Clears the command queue on a power on
+ *
+ * @detail The properties changed handler for the
+ * RequestedHostTransition property. When this property
+ * changes to 'On', this function will purge the command
+ * queue.
+ *
+ * This is done to avoid having commands that were issued
+ * before the host powers on from getting sent to the host,
+ * either due to race conditions around state transitions
+ * or from a user doing something like requesting an already
+ * powered off system to power off again and then immediately
+ * requesting a power on.
+ *
+ * @param[in] msg - the sdbusplus message containing the property
+ */
+ void clearQueueOnPowerOn(sdbusplus::message::message& msg);
+
/** @brief Reference to the dbus handler */
sdbusplus::bus::bus& bus;
@@ -76,6 +102,9 @@ class Manager
/** @brief Timer for commands to host */
phosphor::ipmi::Timer timer;
+
+ /** @brief Match handler for the requested host state */
+ sdbusplus::bus::match_t hostTransitionMatch;
};
} // namespace command
OpenPOWER on IntegriCloud