| #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 |