host-condition: implement property read
This is the implementation of the new PDI interface for checking if the
host is running.
Tested:
- Verified when host was not running that expected response was
provided:
busctl get-property xyz.openbmc_project.Control.Host /xyz/openbmc_project/control/host0 xyz.openbmc_project.Condition.HostFirmware CurrentFirmwareCondition
s "xyz.openbmc_project.Condition.HostFirmware.FirmwareCondition.Off"
- Verified when host was running, that expected response was provided:
busctl get-property xyz.openbmc_project.Control.Host /xyz/openbmc_project/control/host0 xyz.openbmc_project.Condition.HostFirmware CurrentFirmwareCondition
s "xyz.openbmc_project.Condition.HostFirmware.FirmwareCondition.Running"
- Verified that if hostAckCallback is not called within allotted time
that hostAckTimer expires and successfully sets the hostCondition
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I07bc3b3eac4fdfde2a8a1798c2a29f5f2a34a832
diff --git a/host-interface.cpp b/host-interface.cpp
index 7836b40..ffd1aaf 100644
--- a/host-interface.cpp
+++ b/host-interface.cpp
@@ -1,3 +1,4 @@
+
#include "config.h"
#include "host-interface.hpp"
@@ -7,7 +8,10 @@
#include <functional>
#include <ipmid-host/cmd-utils.hpp>
#include <ipmid-host/cmd.hpp>
+#include <ipmid/api.hpp>
#include <ipmid/utils.hpp>
+#include <memory>
+#include <optional>
#include <phosphor-logging/log.hpp>
namespace phosphor
@@ -17,6 +21,8 @@
namespace command
{
+using namespace phosphor::logging;
+
// When you see Base:: you know we're referencing our base class
namespace Base = sdbusplus::xyz::openbmc_project::Control::server;
@@ -43,8 +49,6 @@
// Called at user request
void Host::execute(Base::Host::Command command)
{
- using namespace phosphor::logging;
-
log<level::DEBUG>(
"Pushing cmd on to queue",
entry("CONTROL_HOST_CMD=%s", convertForMessage(command).c_str()));
@@ -69,8 +73,50 @@
Host::FirmwareCondition Host::currentFirmwareCondition() const
{
- // TODO: Implement function
- return FirmwareCondition::Unknown;
+ // shared object used to wait for host response
+ auto hostCondition =
+ std::make_shared<std::optional<Host::FirmwareCondition>>();
+
+ // callback for command to host
+ auto hostAckCallback = [hostCondition](IpmiCmdData cmd, bool status) {
+ auto value = status ? Host::FirmwareCondition::Running
+ : Host::FirmwareCondition::Off;
+
+ log<level::DEBUG>("currentFirmwareCondition:hostAckCallback fired",
+ entry("CONTROL_HOST_CMD=%i", value));
+
+ *(hostCondition.get()) = value;
+ return;
+ };
+
+ auto cmd = phosphor::host::command::CommandHandler(
+ ipmiCommand.at(Base::Host::Command::Heartbeat),
+ std::move(hostAckCallback));
+
+ ipmid_send_cmd_to_host(std::move(cmd));
+
+ // Timer to ensure this function returns something within a reasonable time
+ phosphor::Timer hostAckTimer([hostCondition]() {
+ log<level::DEBUG>("currentFirmwareCondition: timer expired!");
+ *(hostCondition.get()) = Host::FirmwareCondition::Off;
+ });
+
+ // Wait 1 second past the ATN_ACK timeout to ensure we wait for as
+ // long as the timeout
+ hostAckTimer.start(std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS + 1));
+
+ auto io = getIoContext();
+
+ while (!hostCondition.get()->has_value())
+ {
+ log<level::DEBUG>(
+ "currentFirmwareCondition: waiting for host response");
+ io->run_for(std::chrono::milliseconds(100));
+ }
+ hostAckTimer.stop();
+
+ log<level::DEBUG>("currentFirmwareCondition: hostCondition is ready!");
+ return hostCondition.get()->value();
}
} // namespace command