blob: da0d856f37c30570b65883a8083bd0632ca4a472 [file] [log] [blame]
#include "bmc/state_monitor_bmc.h"
#include <cstdint>
#include <memory>
#include <string>
#include "bmc/daemon_context_bmc.h"
#include "bmc/redfish.h"
#include "safepower_agent.pb.h"
#include "safepower_agent_config.pb.h"
#include "state_updater.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"
namespace safepower_agent {
using safepower_agent_config::GpowerdConfig;
using safepower_agent_config::StateGatheringInfo;
StateMonitorBMC::StateMonitorBMC(
std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> reactor)
: reactor_(reactor) {}
absl::Status StateMonitorBMC::BuildFromConfig(const GpowerdConfig& config) {
for (auto& resource_to_monitor : config.state_monitor_config()) {
if (resource_to_monitor.state_gathering_info().info_case() ==
StateGatheringInfo::kRedfish) {
std::string state_name = resource_to_monitor.state_name();
std::string uri =
resource_to_monitor.state_gathering_info().redfish().uri();
std::string json_key =
resource_to_monitor.state_gathering_info().redfish().json_key();
std::string node_entity_tag =
resource_to_monitor.system_component().node_entity_tag();
std::string component_name =
resource_to_monitor.system_component().name();
uint64_t collection_interval_ms =
resource_to_monitor.state_gathering_info().collection_interval_ms();
auto prototype = resource_to_monitor.state_gathering_info().prototype();
if (prototype.has_power_state() &&
(prototype.power_state().has_state())) {
// create bmcweb state monitor for power state
if (!CreateRedfishUpdatePowerState(state_name, uri, json_key,
collection_interval_ms,
node_entity_tag, component_name)
.ok()) {
LOG(ERROR) << "failed to create bmcweb state monitor for: "
<< state_name;
return absl::InvalidArgumentError(
"failed to create bmcweb state monitor for: " + state_name);
}
} else {
LOG(ERROR) << "update function is not supported TODO b/372971177";
return absl::UnimplementedError("update function is not supported ");
}
} else if (resource_to_monitor.state_gathering_info().info_case() ==
StateGatheringInfo::kDbus) {
(void)CreateDbusStateMonitor("", "", "", "", "", 1000);
} else {
LOG(ERROR) << "state monitor type is not supported; "
<< resource_to_monitor.state_gathering_info().info_case();
return absl::InvalidArgumentError(
absl::StrCat("state monitor type is not supported: ",
resource_to_monitor.state_gathering_info().info_case()));
}
}
return absl::OkStatus();
}
absl::Status StateMonitorBMC::CreateRedfishUpdatePowerState(
std::string state_name, std::string uri, std::string json_key,
int collection_interval_ms, std::string node_entity_tag,
std::string component_name) {
LOG(INFO) << "creating bmcweb state monitor for:" << state_name;
LOG(INFO) << "uri: " << uri;
LOG(INFO) << "json_key: " << json_key;
LOG(INFO) << "collection_interval_ms: " << collection_interval_ms;
return DaemonContextBMC::Get().scheduler().PeriodicCall(
[state_name, uri, json_key, this, node_entity_tag, component_name] {
Redfish::Get(uri, [state_name, uri, json_key, this, node_entity_tag,
component_name](absl::StatusOr<nlohmann::json> js) {
if (!js.ok()) {
LOG(ERROR) << "Failed to get " << uri
<< " from BMC: " << js.status();
return;
}
auto js_value = js->find(json_key);
std::string state_str = js_value != js->end() ? *js_value : "";
safepower_agent_proto::PowerStateSpecifier temp_power_state =
ConvertStatePowerStringToEnum(state_str);
const safepower_agent_proto::SystemState current_state =
this->reactor_->state();
safepower_agent_proto::PowerStateSpecifier last_ps =
safepower_agent_proto::POWER_STATE_UNSPECIFIED;
auto node_it = current_state.node_state().find(node_entity_tag);
if (node_it != current_state.node_state().end()) {
auto component_it =
node_it->second.component_state().find(component_name);
if (component_it != node_it->second.component_state().end()) {
last_ps = component_it->second.power_state().state();
}
}
if (last_ps == temp_power_state) return;
absl::string_view last_ps_str = PowerStateSpecifier_Name(last_ps);
absl::string_view temp_ps_str =
PowerStateSpecifier_Name(temp_power_state);
LOG(INFO) << absl::StrFormat(
"state changed from: %d (%s) to: %d (%s)", last_ps, last_ps_str,
temp_power_state, temp_ps_str);
// add new state power state to a new system proto
safepower_agent_proto::SystemState new_state;
safepower_agent_proto::PowerState ps;
ps.set_state(temp_power_state);
safepower_agent_proto::ComponentState cs;
*(cs.mutable_power_state()) = ps;
safepower_agent_proto::NodeState ns;
ns.mutable_component_state()->insert({component_name, cs});
new_state.mutable_node_state()->insert({node_entity_tag, ns});
reactor_->UpdateState(new_state);
});
},
absl::Milliseconds(collection_interval_ms), state_name);
}
safepower_agent_proto::PowerStateSpecifier
StateMonitorBMC::ConvertStatePowerStringToEnum(absl::string_view state_str) {
if (state_str == "On") {
return safepower_agent_proto::POWER_STATE_ON;
} else if (state_str == "Off") {
return safepower_agent_proto::POWER_STATE_OFF;
} else if (state_str == "Paused") { // not in bmcweb
return safepower_agent_proto::POWER_STATE_PAUSED;
} else if (state_str == "PoweringOn") {
return safepower_agent_proto::POWER_STATE_POWERING_ON;
} else if (state_str == "PoweringOff") {
return safepower_agent_proto::POWER_STATE_POWERING_OFF;
} else {
LOG(ERROR) << "failed to map power state string to enum: " << state_str;
return safepower_agent_proto::POWER_STATE_UNSPECIFIED;
}
}
absl::Status StateMonitorBMC::CreateDbusStateMonitor(
std::string state_name, std::string dbus_path, std::string dbus_method,
std::string dbus_interface, std::string dbus_value,
int collection_interval_ms) {
LOG(INFO) << "creating dbus state monitor for:" << state_name;
LOG(INFO) << "dbus_path: " << dbus_path;
LOG(INFO) << "dbus_method: " << dbus_method;
LOG(INFO) << "dbus_interface: " << dbus_interface;
LOG(INFO) << "dbus_value: " << dbus_value;
LOG(INFO) << "collection_interval_ms: " << collection_interval_ms;
return absl::UnimplementedError("CreateDbusStateMonitor is not implemented");
}
} // namespace safepower_agent