blob: 7de33a66483e196c0c73089dbb688fb16a726006 [file] [log] [blame] [edit]
#include "bmc/remote_state_ping.h"
#include <iterator>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "bmc/daemon_context_bmc.h"
#include "bmc/remote_state_monitor.h"
#include "safepower_agent.pb.h"
#include "safepower_agent_config.pb.h"
#include "state_updater.h"
#include "absl/functional/bind_front.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
// NOLINTBEGIN(readability/boost) // Runs on BMC.
#include "absl/time/time.h"
#include "boost/process.hpp"
#include "boost/process/args.hpp"
// NOLINTEND(readability/boost)
namespace safepower_agent {
PingStateMonitor::PingStateMonitor(
std::string entity_tag, std::string hostname,
safepower_agent_config::PingConfig ping_config,
std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>>
system_state_updater)
: RemoteStateMonitor(std::move(entity_tag),
absl::Milliseconds(ping_config.interval_ms()),
std::move(system_state_updater)),
hostname_(std::move(hostname)),
command_({std::move(*ping_config.mutable_command())}),
args_(std::make_move_iterator(ping_config.mutable_extra_args()->begin()),
std::make_move_iterator(ping_config.mutable_extra_args()->end())) {
args_.push_back("-c");
args_.push_back(absl::StrCat(ping_config.count_per_check()));
args_.push_back(hostname_);
LOG(INFO) << "Ping command: " << command_ << " " << absl::StrJoin(args_, " ");
}
// TODO(jebr): b/450140775 - occasionally log the ping command output
void PingStateMonitor::Check() {
boost::process::async_system(
DaemonContextBMC::Get().get_io_context(),
absl::bind_front(&PingStateMonitor::ProcessPingResult, this),
boost::process::exe = command_, boost::process::args = args_,
(boost::process::std_out & boost::process::std_err) >
boost::process::null);
}
void PingStateMonitor::ProcessPingResult(boost::system::error_code ec,
int exit_code) {
if (ec) {
LOG(ERROR) << "Failed to ping " << hostname_ << ": " << ec.message();
return;
}
ReachableState new_reachable_state = exit_code == 0
? ReachableState::kReachable
: ReachableState::kUnreachable;
UpdateReachableState(new_reachable_state);
}
void PingStateMonitor::UpdateNodeState(
safepower_agent_proto::NodeState& node_state,
ReachableState reachable_state) const {
safepower_agent_proto::BootStateSpecifier state;
switch (reachable_state) {
case ReachableState::kUnknown:
LOG(INFO) << node_entity_tag() << " is reachability state is unknown";
state = safepower_agent_proto::BOOT_STATE_UNSPECIFIED;
break;
case ReachableState::kReachable:
state = safepower_agent_proto::BOOT_STATE_BOOTING;
break;
case ReachableState::kUnreachable:
state = safepower_agent_proto::BOOT_STATE_NOT_BOOTED;
break;
default:
LOG(DFATAL) << "Unknown reachable state: "
<< static_cast<int>(reachable_state);
return;
}
node_state.mutable_boot_state()->set_state(state);
}
} // namespace safepower_agent