blob: 9bf1c730c1a5b659b628455ea602e626d3c3a9a4 [file]
#include "tlbmc/store/store_impl.h"
#include <sys/sysinfo.h>
#include <cstddef>
#include <cstdint>
#include <filesystem> // NOLINT
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <system_error> // NOLINT
#include <utility>
#include <vector>
#include "owner_certificate/owner_verification_cert_configuration.pb.h"
#include "bus_topology.pb.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "g3/macros.h"
#include "thread/thread.h"
#include "time/clock.h"
#include <nlohmann/json.hpp>
#include "central_config.pb.h"
#include "tlbmc/central_config/config.h"
#include "tlbmc/collector/bulk_sensor_collector_base.h"
#include "tlbmc/collector/collector.h"
#include "tlbmc/collector/fru_collector.h"
#include "tlbmc/collector/gpio_collector.h"
#include "tlbmc/collector/led_collector.h"
#include "tlbmc/collector/metric_collector.h"
#include "tlbmc/collector/monitoring_change_base.h"
#include "tlbmc/collector/pcie_collector.h"
#include "tlbmc/collector/power_control_collector.h"
#include "tlbmc/collector/power_fault_log_collector.h"
#include "tlbmc/collector/sel_collector.h"
#include "tlbmc/collector/sensor_collector.h"
#include "tlbmc/collector/sensor_collector_aggregator.h"
#include "tlbmc/collector/thermal_collector.h"
#include "ad_hoc_fru_config.pb.h"
#include "tlbmc/configs/entity_config.h"
#include "gpio_config.pb.h"
#include "power_control.pb.h"
#include "software_metrics_config.pb.h"
#include "thermal_config.pb.h"
#include "topology_config.pb.h"
#include "tlbmc/credentials/credential_manager.h"
#include "tlbmc/hal/fru_scanner.h"
#include "tlbmc/hal/peci/peci_access_impl.h"
#include "tlbmc/hal/peci/peci_access_interface.h"
#include "tlbmc/hal/system_registry.h"
#include "tlbmc/host_state/power_control.h"
#include "fru.pb.h"
#include "power_fault_log_entry.pb.h"
#include "tlbmc/resource/reset_type.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "software_metrics.pb.h"
#include "tlbmc/scheduler/scheduler.h"
#include "tlbmc/sensors/sensor.h"
#include "tlbmc/store/store.h"
#include "tlbmc/thermal/controller/dff_controller.h"
#include "tlbmc/thermal/controller/eat_controller.h"
#include "tlbmc/thermal/controller/fan_pid_controller.h"
#include "tlbmc/thermal/controller/pid_controller.h"
#include "tlbmc/thermal/controller/stepwise_controller.h"
#include "tlbmc/thermal/zone_manager.h"
#include "tlbmc/trace/tracer.h"
#include "tlbmc/true_hitless_metrics.pb.h"
#include "router_interface.h"
namespace milotic_tlbmc {
using ::crow::RouterInterface;
namespace {
constexpr int kDefaultPeriodicDumpIntervalMs = 1000 * 60 * 60; // 1 hour
} // namespace
absl::Status StoreImpl::ConfigureDeterministicCollection(
const Collector::Config& config) const {
return all_collectors_.fru_collector->ConfigureDeterministicCollection(
config);
}
std::unique_ptr<MonitoringChangeBase> StoreImpl::CreateMonitoringChange() {
return all_collectors_.sensor_collector_aggregator->CreateMonitoringChange();
}
PowerControlCollector* StoreImpl::GetPowerControlCollector() const {
return all_collectors_.power_control_collector.get();
}
FruCollector* StoreImpl::GetFruCollector() const {
return all_collectors_.fru_collector.get();
}
GpioCollector* StoreImpl::GetGpioCollector() const {
return all_collectors_.gpio_collector.get();
}
LedCollector* StoreImpl::GetLedCollector() const {
return all_collectors_.led_collector.get();
}
PcieCollector* StoreImpl::GetPcieCollector() const {
return all_collectors_.pcie_collector.get();
}
std::vector<std::shared_ptr<const Sensor>> StoreImpl::GetAllSensors() const {
return all_collectors_.sensor_collector_aggregator->GetAllSensors();
}
std::vector<std::string> StoreImpl::GetAllSharedMemorySensorKeys() const {
return all_collectors_.sensor_collector_aggregator
->GetAllSharedMemorySensorKeys();
}
bool StoreImpl::IsConfigKeyOwningAllSensors(
absl::string_view config_key) const {
return entity_config_->IsConfigKeyOwningAllSensors(config_key);
}
std::shared_ptr<const Sensor> StoreImpl::GetSensorBySensorKey(
const std::string& sensor_key) const {
return all_collectors_.sensor_collector_aggregator->GetSensorBySensorKey(
sensor_key);
}
std::vector<std::string> StoreImpl::GetAllSensorKeysByConfigKey(
const std::string& board_config_key) const {
return all_collectors_.sensor_collector_aggregator
->GetAllSensorKeysByConfigKey(board_config_key);
}
std::shared_ptr<const Sensor> StoreImpl::GetSensorByConfigKeyAndSensorKey(
const std::string& board_config_key, const std::string& sensor_key) const {
return all_collectors_.sensor_collector_aggregator
->GetSensorByConfigKeyAndSensorKey(board_config_key, sensor_key);
}
absl::Status StoreImpl::WriteToSensor(const std::string& sensor_key,
const SensorValue& value) {
return all_collectors_.sensor_collector_aggregator->WriteToSensor(sensor_key,
value);
}
absl::Status StoreImpl::SetSensorOverride(const std::string& sensor_key,
const SensorValue& value) {
if (all_collectors_.sensor_collector_aggregator == nullptr) {
return absl::InternalError(
"Sensor collector aggregator is not initialized");
}
return all_collectors_.sensor_collector_aggregator->SetSensorOverride(
sensor_key, value);
}
absl::Status StoreImpl::ClearSensorOverride(const std::string& sensor_key) {
if (all_collectors_.sensor_collector_aggregator == nullptr) {
return absl::InternalError(
"Sensor collector aggregator is not initialized");
}
return all_collectors_.sensor_collector_aggregator->ClearSensorOverride(
sensor_key);
}
absl::Status StoreImpl::ClearAllSensorOverrides() {
if (all_collectors_.sensor_collector_aggregator == nullptr) {
return absl::InternalError(
"Sensor collector aggregator is not initialized");
}
return all_collectors_.sensor_collector_aggregator->ClearAllSensorOverrides();
}
std::vector<std::string> StoreImpl::GetOverriddenSensorKeys() const {
if (all_collectors_.sensor_collector_aggregator == nullptr) {
return {};
}
return all_collectors_.sensor_collector_aggregator->GetOverriddenSensorKeys();
}
absl::StatusOr<bool> StoreImpl::IsSensorOverridden(
const std::string& sensor_key) const {
if (all_collectors_.sensor_collector_aggregator == nullptr) {
return false;
}
return all_collectors_.sensor_collector_aggregator->IsSensorOverridden(
sensor_key);
}
absl::StatusOr<const std::string&> StoreImpl::GetDevpathFromSensor(
std::shared_ptr<const Sensor> sensor) const {
// Get devpath for the sensor.
// 1. Check if the sensor has valid GetDevpath method. If so, return the
// devpath. If not, go to the step 2.
// 2. Get the related item key from static attributes.
// 3. Get topology node from related item key.
// 4. Get devpath from topology node.
absl::StatusOr<const std::string&> devpath = sensor->GetDevpath();
if (devpath.ok() && !devpath.value().empty()) {
return devpath;
}
const SensorAttributesStatic& static_attributes =
sensor->GetSensorAttributesStatic();
absl::string_view related_item_key = static_attributes.related_item().id();
// For fans, there may be several sensors with same related item id, we must
// get the true related item key from the parent board.
if (static_attributes.related_item().type() == RESOURCE_TYPE_FAN) {
ECCLESIA_ASSIGN_OR_RETURN(
const TopologyConfigNode* parent_board,
GetFruTopology(
static_attributes.entity_common_config().board_config_key()));
// The fan id should always be present in the parent board's children
// fans map.
auto fan_it = parent_board->children_fans().find(related_item_key);
if (fan_it == parent_board->children_fans().end()) {
return absl::NotFoundError(absl::Substitute(
"Fan $0 not found in parent board $1", related_item_key,
parent_board->fru_info().fru_key()));
}
related_item_key = fan_it->second;
} else if (static_attributes.related_item().type() ==
RESOURCE_TYPE_PROCESSOR) {
ECCLESIA_ASSIGN_OR_RETURN(
const TopologyConfigNode* parent_board,
GetFruTopology(
static_attributes.entity_common_config().board_config_key()));
// related_item.id is the topology processor key (physical id).
auto processor_it =
parent_board->children_processors().find(related_item_key);
if (processor_it == parent_board->children_processors().end()) {
return absl::NotFoundError(absl::Substitute(
"Processor $0 not found in parent board $1", related_item_key,
parent_board->fru_info().fru_key()));
}
related_item_key = processor_it->second;
} else if (static_attributes.related_item().type() == RESOURCE_TYPE_DIMM) {
ECCLESIA_ASSIGN_OR_RETURN(
const TopologyConfigNode* parent_board,
GetFruTopology(
static_attributes.entity_common_config().board_config_key()));
// The dimm id should always be present in the parent board's children
// fans map.
auto dimm_it = parent_board->children_dimms().find(related_item_key);
if (dimm_it == parent_board->children_dimms().end()) {
return absl::NotFoundError(absl::Substitute(
"DIMM $0 not found in parent board $1", related_item_key,
parent_board->fru_info().fru_key()));
}
related_item_key = dimm_it->second;
}
ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfigNode* topology_node,
GetFruTopology(related_item_key));
return topology_node->location_context().devpath();
}
void StoreImpl::InitializeSensorDevpaths() const {
if (!all_collectors_.sensor_collector_aggregator) {
return;
}
std::vector<std::shared_ptr<const Sensor>> sensors =
all_collectors_.sensor_collector_aggregator->GetAllSensors();
for (const std::shared_ptr<const Sensor>& sensor : sensors) {
absl::StatusOr<const std::string&> devpath = GetDevpathFromSensor(sensor);
if (!devpath.ok()) {
LOG(WARNING) << "Failed to get devpath for sensor " << sensor->GetKey()
<< ": " << devpath.status();
continue;
}
absl::Status status =
all_collectors_.sensor_collector_aggregator->SetDevpathForSensor(
sensor->GetKey(), devpath.value());
if (!status.ok()) {
LOG(WARNING) << "Failed to set devpath for sensor " << sensor->GetKey()
<< ": " << status;
}
}
}
absl::StatusOr<const Fru*> StoreImpl::GetFru(absl::string_view key) const {
return entity_config_->GetFru(key);
}
absl::StatusOr<const FruTable*> StoreImpl::GetAllFrus() const {
return entity_config_->GetAllFrus();
}
SoftwareMetricsValue StoreImpl::GetMetricValues() const {
return all_collectors_.metric_collector->GetMetricValues();
}
SocketStatStates StoreImpl::GetMetricSocketStatValues() const {
return all_collectors_.metric_collector->GetSocketStatMetricsValues();
}
NetFilterStates StoreImpl::GetMetricNetFilterValues() const {
return all_collectors_.metric_collector->GetNetFilterValues();
}
TrueHitlessMetrics StoreImpl::GetTrueHitlessMetrics() const {
return all_collectors_.metric_collector->GetTrueHitlessMetrics();
}
absl::StatusOr<std::vector<const thermal::ZoneManager*>>
StoreImpl::GetAllThermalZones() const {
return all_collectors_.thermal_collector->GetAllThermalZones();
}
absl::StatusOr<std::vector<const thermal::PidController*>>
StoreImpl::GetAllPidControllers() const {
return all_collectors_.thermal_collector->GetAllPidControllers();
}
absl::StatusOr<std::vector<const thermal::StepwiseController*>>
StoreImpl::GetAllStepwiseControllers() const {
return all_collectors_.thermal_collector->GetAllStepwiseControllers();
}
absl::StatusOr<std::vector<const thermal::FanPidController*>>
StoreImpl::GetAllFanPidControllers() const {
return all_collectors_.thermal_collector->GetAllFanPidControllers();
}
absl::StatusOr<std::vector<const thermal::EatController*>>
StoreImpl::GetAllEatControllers() const {
return all_collectors_.thermal_collector->GetAllEatControllers();
}
absl::StatusOr<std::vector<const thermal::DffController*>>
StoreImpl::GetAllDffControllers() const {
return all_collectors_.thermal_collector->GetAllDffControllers();
}
std::string StoreImpl::GetBmcUuid() const {
return all_collectors_.metric_collector->GetBmcUuid();
}
std::string StoreImpl::GetBmcFirmwareVersion() const {
return all_collectors_.metric_collector->GetBmcFirmwareVersion();
}
std::string StoreImpl::GetBmcFirmwareVersionId() const {
return all_collectors_.metric_collector->GetBmcFirmwareVersionId();
}
absl::Status StoreImpl::SetGpio(absl::string_view gpio_name, bool value) {
return all_collectors_.gpio_collector->SetGpio(gpio_name, value);
}
absl::Status StoreImpl::SetGpioActive(absl::string_view gpio_name) {
return all_collectors_.gpio_collector->SetActive(gpio_name);
}
absl::Status StoreImpl::SetGpioActiveForDuration(absl::string_view gpio_name,
absl::Duration duration) {
return all_collectors_.gpio_collector->SetActiveForDuration(gpio_name,
duration);
}
absl::StatusOr<bool> StoreImpl::GetGpio(absl::string_view gpio_name) {
return all_collectors_.gpio_collector->GetValue(gpio_name);
}
absl::Status StoreImpl::SendSystemResetRequest(absl::string_view system_id,
ResetType reset_type,
absl::Duration delay) {
LOG(INFO) << "SendSystemResetRequest: " << system_id << " " << reset_type
<< " " << delay;
if (all_collectors_.power_control_collector == nullptr) {
return absl::NotFoundError(
absl::Substitute("System $0 not found", system_id));
}
return all_collectors_.power_control_collector->SendSystemResetRequest(
system_id, reset_type, delay);
}
absl::StatusOr<std::vector<ResetType>>
StoreImpl::GetSupportedCustomChassisResetTypes(
absl::string_view chassis_id) const {
ECCLESIA_ASSIGN_OR_RETURN(std::string fru_key,
entity_config_->GetFruKeyByConfigKey(chassis_id));
ECCLESIA_ASSIGN_OR_RETURN(const Fru* fru, entity_config_->GetFru(fru_key));
if (fru == nullptr) {
return absl::NotFoundError(
absl::StrCat("Fru not found for chassis: ", chassis_id));
}
std::vector<ResetType> supported_types;
const auto& chassis_reset =
fru->attributes().chassis_properties().chassis_reset();
if (!chassis_reset.enabled()) {
return supported_types;
}
supported_types.reserve(chassis_reset.actions_size());
for (const auto& action : chassis_reset.actions()) {
supported_types.push_back(action.type());
}
return supported_types;
}
absl::StatusOr<bool> StoreImpl::SupportsCustomChassisReset(
absl::string_view chassis_id) const {
ECCLESIA_ASSIGN_OR_RETURN(std::string fru_key,
entity_config_->GetFruKeyByConfigKey(chassis_id));
ECCLESIA_ASSIGN_OR_RETURN(const Fru* fru, entity_config_->GetFru(fru_key));
if (fru == nullptr) {
return absl::NotFoundError(
absl::StrCat("Fru not found for chassis: ", chassis_id));
}
return fru->attributes().chassis_properties().chassis_reset().enabled();
}
absl::Status StoreImpl::ExecuteCustomChassisReset(absl::string_view chassis_id,
ResetType reset_type) {
ECCLESIA_ASSIGN_OR_RETURN(std::string fru_key,
entity_config_->GetFruKeyByConfigKey(chassis_id));
ECCLESIA_ASSIGN_OR_RETURN(const Fru* fru, entity_config_->GetFru(fru_key));
if (fru == nullptr) {
return absl::NotFoundError(
absl::StrCat("Fru not found for chassis: ", chassis_id));
}
const auto& chassis_reset =
fru->attributes().chassis_properties().chassis_reset();
if (!chassis_reset.enabled()) {
return absl::FailedPreconditionError(absl::StrCat(
"Custom chassis reset is not enabled for chassis: ", chassis_id));
}
absl::string_view gpio_name;
for (const auto& action : chassis_reset.actions()) {
if (action.type() == reset_type) {
gpio_name = action.gpio();
break;
}
}
if (gpio_name.empty()) {
absl::StatusOr<absl::string_view> reset_type_string =
GetResetTypeString(reset_type);
return absl::NotFoundError(absl::Substitute(
"No custom reset action found for chassis $0 and reset type $1",
chassis_id,
reset_type_string.value_or(reset_type_string.status().message())));
}
ECCLESIA_ASSIGN_OR_RETURN(
bool current_value, all_collectors_.gpio_collector->GetValue(gpio_name));
ECCLESIA_RETURN_IF_ERROR(
all_collectors_.gpio_collector->SetGpio(gpio_name, !current_value));
return all_collectors_.gpio_collector->SetGpio(gpio_name, current_value);
}
absl::StatusOr<PsiMetrics> StoreImpl::GetPsiMetrics() const {
return all_collectors_.metric_collector->GetPsiMetrics();
}
absl::StatusOr<std::vector<std::string>> StoreImpl::GetAvailableServices()
const {
return all_collectors_.metric_collector->GetAvailableServices();
}
absl::StatusOr<PsiMetrics> StoreImpl::GetPsiMetricsForService(
const std::string& service_name) const {
return all_collectors_.metric_collector->GetPsiMetricsForService(
service_name);
}
nlohmann::json StoreImpl::ToJson() const {
nlohmann::json json;
all_collectors_.sensor_collector_aggregator->ToJson(json);
json["Fru"] = all_collectors_.fru_collector->ToJson();
json["Metric"] = all_collectors_.metric_collector->ToJson();
json["Gpio"] = all_collectors_.gpio_collector->ToJson();
json["Led"] = all_collectors_.led_collector->ToJson();
json["Fan"] = all_collectors_.thermal_collector->ToJson();
json["PowerFaultLog"] = all_collectors_.power_fault_log_collector->ToJson();
json["Sel"] = all_collectors_.sel_collector->ToJson();
json["Pcie"] = all_collectors_.pcie_collector->ToJson();
json["EntityConfig"] = entity_config_->ToJson();
json["PowerState"] = all_collectors_.power_control_collector->ToJson();
return json;
}
nlohmann::json StoreImpl::GetSchedulerStats() const {
nlohmann::json json;
json["SensorCollector"] =
all_collectors_.sensor_collector->GetSchedulerStats();
json["FruCollector"] = all_collectors_.fru_collector->GetSchedulerStats();
json["MetricCollector"] =
all_collectors_.metric_collector->GetSchedulerStats();
json["GpioCollector"] = all_collectors_.gpio_collector->GetSchedulerStats();
json["LedCollector"] = all_collectors_.led_collector->GetSchedulerStats();
json["Fan"] = all_collectors_.thermal_collector->GetSchedulerStats();
json["PowerFaultLogCollector"] =
all_collectors_.power_fault_log_collector->GetSchedulerStats();
json["SelCollector"] = all_collectors_.sel_collector->GetSchedulerStats();
json["PcieCollector"] = all_collectors_.pcie_collector->GetSchedulerStats();
json["PowerControlCollector"] =
all_collectors_.power_control_collector->GetSchedulerStats();
json["Store"] = task_scheduler_->ToJson();
return json;
}
Store::Metrics StoreImpl::GetMetrics() const { return metrics_; }
absl::StatusOr<const TopologyConfigNode*> StoreImpl::GetFruTopology(
absl::string_view config_key) const {
return entity_config_->GetFruTopologyByConfig(config_key);
}
absl::StatusOr<const TopologyConfig*> StoreImpl::GetTopologyConfig() const {
return entity_config_->GetTopologyConfig();
}
absl::StatusOr<std::vector<std::string>> StoreImpl::GetAllConfigKeys() const {
return entity_config_->GetAllConfigKeys();
}
absl::StatusOr<std::string> StoreImpl::GetConfigKeyByFruKey(
absl::string_view fru_key) const {
return entity_config_->GetConfigKeyByFruKey(fru_key);
}
absl::StatusOr<std::string> StoreImpl::GetFruKeyByConfigKey(
absl::string_view config_key) const {
return entity_config_->GetFruKeyByConfigKey(config_key);
}
absl::StatusOr<std::vector<std::pair<std::string, std::string>>>
StoreImpl::GetFanInfoByConfigKey(absl::string_view config_name) const {
return entity_config_->GetFanInfoByConfigKey(config_name);
}
absl::StatusOr<std::string> StoreImpl::GenerateCsr(
const CredentialManager::CsrParams& csr_params) const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Trust Bundle Install Module is not enabled");
}
return credential_manager_->GenerateCsr(csr_params);
}
absl::Status StoreImpl::InstallServerCert(
const std::string& certificate) const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Trust Bundle Install Module is not enabled");
}
return credential_manager_->InstallServerCert(certificate);
}
absl::Status StoreImpl::InstallTrustBundle(const std::string& trust_bundle,
const std::string& signature) const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Trust Bundle Install Module is not enabled");
}
return credential_manager_->InstallTrustBundle(trust_bundle, signature);
}
absl::Status StoreImpl::InstallOsVerificationCertificate(
const std::string& cert_string) const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Trust Bundle Install Module is not enabled");
}
return credential_manager_->InstallOsVerificationCertificate(cert_string);
}
absl::Status StoreImpl::InstallSerialConsoleTrustedUserCAKeys(
const std::string& trusted_user_ca_keys,
const std::string& signature) const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Trust Bundle Install Module is not enabled");
}
return credential_manager_->InstallSerialConsoleTrustedUserCAKeys(
trusted_user_ca_keys, signature);
}
absl::Status StoreImpl::InstallSyslogCert(const std::string& cert_string,
const std::string& target_ip,
int64_t target_port,
SyslogProtocol protocol,
SyslogTlsMode tls_mode) const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Trust Bundle Install Module is not enabled");
}
return credential_manager_->InstallSyslogCert(
cert_string, target_ip, target_port, protocol, tls_mode);
}
bool StoreImpl::IsFirmwareUpdateable() const {
if (credential_manager_ == nullptr) {
return true;
}
return credential_manager_->IsFirmwareUpdateable();
}
absl::StatusOr<std::optional<std::string>> StoreImpl::GetOwnerVerificationCert()
const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetOwnerVerificationCert();
}
absl::StatusOr<
std::optional<owner_certificate::OwnerVerificationCertConfiguration>>
StoreImpl::GetOwnerVerificationCertConfiguration() const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetOwnerVerificationCertConfiguration();
}
absl::StatusOr<std::optional<std::string>>
StoreImpl::GetBmcSshTrustedUserCAKeysSignature() const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetBmcSshTrustedUserCAKeysSignature();
}
absl::StatusOr<std::optional<std::string>> StoreImpl::GetTrustBundle() const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetTrustBundle();
}
absl::StatusOr<std::optional<std::string>> StoreImpl::GetTrustBundleSignature()
const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetTrustBundleSignature();
}
absl::StatusOr<std::optional<std::string>> StoreImpl::GetServerCert() const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetServerCert();
}
absl::StatusOr<std::optional<std::string>> StoreImpl::GetOsVerificationCert()
const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetOsVerificationCert();
}
absl::StatusOr<std::optional<std::string>>
StoreImpl::GetSerialConsoleTrustedUserCAKeys() const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetSerialConsoleTrustedUserCAKeys();
}
absl::StatusOr<std::optional<std::string>>
StoreImpl::GetSerialConsoleDetatchedSignature() const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetSerialConsoleDetatchedSignature();
}
absl::StatusOr<std::optional<SyslogTargetConfig>>
StoreImpl::GetSyslogClientConf() const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetSyslogClientConf();
}
absl::StatusOr<std::optional<std::string>> StoreImpl::GetSyslogRootCert()
const {
if (credential_manager_ == nullptr) {
return absl::InternalError("Credential manager is null");
}
return credential_manager_->GetSyslogRootCert();
}
absl::Time StoreImpl::GetCurrentTime() const { return absl::Now(); }
absl::Time StoreImpl::GetLastResetTime() const {
struct sysinfo info;
if (sysinfo(&info) != 0) {
return absl::UnixEpoch();
}
return absl::Now() - absl::Seconds(info.uptime);
}
absl::StatusOr<std::string> StoreImpl::GetHotswapGpioName() {
if (!GetTlbmcConfig()
.gpio_collector_module()
.power_control_sub_module()
.enabled()) {
return absl::InternalError("Power control module is not enabled.");
}
if (GetTlbmcConfig()
.gpio_collector_module()
.power_control_sub_module()
.power_control_type() != PowerControlType::POWER_CONTROL_TYPE_GPIO) {
return absl::InternalError("Power control type is not GPIO.");
}
if (!options_.proto_parser->GetPowerControlConfigs().has_hotswap_pin_name()) {
return absl::InternalError("Hotswap pin name is not set.");
}
return options_.proto_parser->GetPowerControlConfigs().hotswap_pin_name();
}
absl::StatusOr<std::unique_ptr<StoreImpl>> StoreImpl::Create(
Options&& options) {
Metrics metrics_at_bootup;
absl::Time create_start_time = absl::Now();
if (options.fru_scanners.empty()) {
return absl::InvalidArgumentError("FruScanners is empty");
}
if (options.i2c_sysfs == nullptr) {
return absl::InvalidArgumentError("I2cSysfs is null");
}
if (options.i3c_sysfs == nullptr) {
return absl::InvalidArgumentError("I3cSysfs is null");
}
if (options.peci_sysfs == nullptr) {
return absl::InvalidArgumentError("PeciSysfs is null");
}
if (options.proto_parser == nullptr) {
return absl::InvalidArgumentError("Proto config parser is null");
}
options.proto_parser->LoadProtoConfigs();
absl::Time parse_configs_start_time = absl::Now();
Tracer::GetInstance().AddOneOffDatapoint("Tlbmc-Parse-Configs-Begin",
parse_configs_start_time);
ECCLESIA_RETURN_IF_ERROR(options.entity_config_reader->LoadEntityConfig(
options.config_location, options.offline_node_entities_path));
std::vector<AdHocFruConfig> ad_hoc_fru_scanning_configs =
FruCollector::Options::ParseAdHocFruConfigs(
options.entity_config_reader->GetConfig());
absl::Time parse_configs_end_time = absl::Now();
metrics_at_bootup.config_parse_duration =
parse_configs_end_time - parse_configs_start_time;
Tracer::GetInstance().AddOneOffDatapoint("Tlbmc-Parse-Configs-End",
parse_configs_end_time);
size_t ad_hoc_fru_count = ad_hoc_fru_scanning_configs.size();
absl::flat_hash_map<AdHocScannerType, FruScanner*> fru_scanners_raw;
for (const auto& [type, scanner] : options.fru_scanners) {
fru_scanners_raw[type] = scanner.get();
}
absl::flat_hash_map<
uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::ProbePath,
FruScanner*>
deterministic_fru_scanners_raw;
for (const auto& [probe_path, scanner] : options.deterministic_fru_scanners) {
deterministic_fru_scanners_raw[probe_path] = scanner.get();
}
const auto power_control_configs =
options.proto_parser->GetPowerControlConfigs();
std::vector<RelatedStateConfig> host_power_related_state_configs;
std::vector<RelatedStateConfig> os_state_related_state_configs;
for (const auto& power_control_config :
power_control_configs.power_control_configs()) {
if (power_control_config.has_host_power_related_state_config()) {
LOG(INFO) << "Host power related state config: "
<< power_control_config.host_power_related_state_config();
host_power_related_state_configs.push_back(
power_control_config.host_power_related_state_config());
}
if (power_control_config.has_os_state_related_state_config()) {
os_state_related_state_configs.push_back(
power_control_config.os_state_related_state_config());
}
}
FruCollector::Options fru_collector_options = {
.fru_scanners = std::move(fru_scanners_raw),
.ad_hoc_fru_scanning_configs = std::move(ad_hoc_fru_scanning_configs),
.enable_deterministic_fru_scanning = options.enable_deterministic_bmc,
.strict_part_info_check =
GetTlbmcConfig().fru_collector_module().strict_part_info_check(),
.deterministic_fru_scanners = std::move(deterministic_fru_scanners_raw),
.enable_deterministic_periodic_fru_scanning =
options.enable_deterministic_periodic_fru_scanning,
.periodic_deterministic_fru_scan_interval_ms =
options.periodic_deterministic_fru_scan_interval_ms,
.host_power_related_state_configs =
std::move(host_power_related_state_configs),
.os_state_related_state_configs =
std::move(os_state_related_state_configs),
.smbios_inventory = options.smbios_inventory,
.smbios_single_host_file_path = options.smbios_single_host_file_path,
.smbios_multihost_host_file_path_prefix =
options.smbios_multihost_host_file_path_prefix,
.smbios_single_host_status_file_path =
options.smbios_single_host_status_file_path,
.smbios_multihost_host_status_file_path_prefix =
options.smbios_multihost_host_status_file_path_prefix,
.expected_smbios_components =
std::move(options.expected_smbios_components),
};
if (!options.cached_fru_table_path.empty()) {
fru_collector_options.cached_fru_table_path = options.cached_fru_table_path;
}
AllCollectors all_collectors = {
.sensor_collector_aggregator = nullptr,
.sensor_collector = EmptySensorCollector::Create(),
.bulk_sensor_collector = nullptr,
.fru_collector = EmptyFruCollector::Create(),
.metric_collector = EmptyMetricCollector::Create(),
.gpio_collector = EmptyGpioCollector::Create(),
.power_control_collector = EmptyPowerControlCollector::Create(),
.led_collector = EmptyLedCollector::Create(),
.power_fault_log_collector = EmptyPowerFaultLogCollector::Create(),
.sel_collector = EmptySelCollector::Create(),
.pcie_collector = EmptyPcieCollector::Create(),
.thermal_collector = EmptyThermalCollector::Create(),
};
std::shared_ptr<EntityConfig> entity_config_shared =
EmptyEntityConfigImpl::Create();
if (options.gpio_collector != nullptr) {
all_collectors.gpio_collector = std::move(options.gpio_collector);
}
// Initialize power control collector before FruCollector and SensorCollector
// to make sure some sensors in FruCollector and SensorCollector can register
// power control callbacks.
if (GetTlbmcConfig()
.gpio_collector_module()
.power_control_sub_module()
.enabled() ||
options.proto_parser->GetPowerControlConfigs().has_hotswap_pin_name()) {
absl::StatusOr<std::unique_ptr<PowerControlCollector>> collector =
options.collector_factory->CreatePowerControlCollector({
.power_control_configs =
options.proto_parser->GetPowerControlConfigs(),
.gpio_collector = all_collectors.gpio_collector.get(),
.root_path = options.root_path,
});
if (!collector.ok()) {
LOG(ERROR) << "Failed to create PowerControlCollector: "
<< collector.status();
return collector.status();
}
all_collectors.power_control_collector = *std::move(collector);
}
if (GetTlbmcConfig().led_collector_module().enabled()) {
ECCLESIA_ASSIGN_OR_RETURN(
std::unique_ptr<LedCollector> led_collector,
options.collector_factory->CreateLedCollector({
.led_configs = options.proto_parser->GetLedConfigs(),
.led_sysfs = *options.led_sysfs,
.power_control_collector =
all_collectors.power_control_collector.get(),
.gpio_collector = all_collectors.gpio_collector.get(),
}));
all_collectors.led_collector = std::move(led_collector);
}
if (GetTlbmcConfig().fru_collector_module().enabled()) {
absl::Time fru_scan_start_time = absl::Now();
Tracer::GetInstance().AddOneOffDatapoint("Tlbmc-Scan-FRUs-Begin",
fru_scan_start_time);
ECCLESIA_ASSIGN_OR_RETURN(
std::unique_ptr<FruCollector> fru_collector,
options.collector_factory->CreateFruCollector(fru_collector_options));
const RawFruTable fru_table = fru_collector->GetCopyOfCurrentScannedFrus();
absl::Time fru_scan_end_time = absl::Now();
metrics_at_bootup.fru_scan_and_collector_create_duration =
fru_scan_end_time - fru_scan_start_time;
Tracer::GetInstance().AddOneOffDatapoint("Tlbmc-Scan-FRUs-End",
fru_scan_end_time);
// Load Configs
absl::Time load_configs_start_time = absl::Now();
Tracer::GetInstance().AddOneOffDatapoint("Tlbmc-Load-Configs-Begin",
load_configs_start_time);
absl::StatusOr<std::unique_ptr<EntityConfig>> entity_config =
options.entity_config_reader->CreateEntityConfig(
fru_table, ad_hoc_fru_count, options.enable_deterministic_bmc,
all_collectors.gpio_collector.get(),
options.enable_hft_test_sensor);
if (!entity_config.ok()) {
LOG(ERROR) << "Failed to create entity config: "
<< entity_config.status();
LOG(ERROR) << "The cached FRU table will be deleted.";
// If Store is bad, then cache may be bad too. Let cache reload on next
// boot.
std::error_code ec;
if (!std::filesystem::remove(fru_collector_options.cached_fru_table_path,
ec) &&
ec) {
LOG(WARNING) << "Failed to remove cached FRU table: " << ec.message();
}
return entity_config.status();
}
absl::Time load_configs_end_time = absl::Now();
metrics_at_bootup.topology_config_load_duration =
load_configs_end_time - load_configs_start_time;
Tracer::GetInstance().AddOneOffDatapoint("Tlbmc-Load-Configs-End",
load_configs_end_time);
// EntityConfig must be shared as it is used by the FruCollector.
entity_config_shared = absl::ShareUniquePtr(std::move(*entity_config));
fru_collector->SetEntityConfig(entity_config_shared);
all_collectors.fru_collector = std::move(fru_collector);
if (GetTlbmcConfig().sensor_collector_module().enabled()) {
// Now create all the collectors one by one.
absl::Time sensor_collector_create_start_time = absl::Now();
Tracer::GetInstance().AddOneOffDatapoint(
"Tlbmc-Create-SensorCollector-Begin",
sensor_collector_create_start_time);
ECCLESIA_ASSIGN_OR_RETURN(SensorCollector::SensorConfigs sensor_configs,
entity_config_shared->GetAllSensorConfigs());
std::unique_ptr<PeciAccessInterface> peci_access =
std::make_unique<PeciAccessImpl>();
SensorCollector::Params sensor_collector_params = {
.sensor_configs = std::move(sensor_configs),
.iio_sysfs = *options.iio_sysfs,
.i2c_sysfs = *options.i2c_sysfs,
.i3c_sysfs = *options.i3c_sysfs,
.peci_sysfs = *options.peci_sysfs,
.peci_access = *options.peci_access,
.override_sensor_sampling_interval_ms =
options.override_sensor_sampling_interval_ms,
.gpio_collector = all_collectors.gpio_collector.get(),
.enable_threshold_monitoring = GetTlbmcConfig()
.sensor_collector_module()
.enable_threshold_monitoring(),
.power_control_collector =
all_collectors.power_control_collector.get(),
};
if (options.nic_accessor_factory) {
sensor_collector_params.nic_accessor_factory =
std::move(options.nic_accessor_factory);
}
absl::StatusOr<std::unique_ptr<SensorCollector>> sensor_collector =
options.collector_factory->CreateSensorCollector(
sensor_collector_params);
if (!sensor_collector.ok()) {
LOG(ERROR) << "Failed to create sensor collector: "
<< sensor_collector.status();
LOG(ERROR) << "The cached FRU table will be deleted.";
// If Store is bad, then cache may be bad too. Let cache reload on next
// boot.
std::error_code ec;
if (!std::filesystem::remove(
fru_collector_options.cached_fru_table_path, ec) &&
ec) {
LOG(WARNING) << "Failed to remove cached FRU table: " << ec.message();
}
return sensor_collector.status();
}
absl::Time sensor_collector_create_end_time = absl::Now();
metrics_at_bootup.sensor_collector_create_duration =
sensor_collector_create_end_time - sensor_collector_create_start_time;
Tracer::GetInstance().AddOneOffDatapoint(
"Tlbmc-Create-SensorCollector-End", sensor_collector_create_end_time);
all_collectors.sensor_collector = std::move(*sensor_collector);
}
if (GetTlbmcConfig().pcie_collector_module().enabled()) {
absl::StatusOr<std::unique_ptr<PcieCollector>> pcie_collector =
options.collector_factory->CreatePcieCollector({
.pcie_configs = options.proto_parser->GetPcieConfigs(),
.gpio_collector = all_collectors.gpio_collector.get(),
});
if (!pcie_collector.ok()) {
LOG(ERROR) << "Failed to create PCIe collector: "
<< pcie_collector.status();
return pcie_collector.status();
}
all_collectors.pcie_collector = std::move(*pcie_collector);
}
}
absl::StatusOr<std::shared_ptr<BulkSensorCollectorBase>>
bulk_sensor_collector_or = CreateBulkSensorCollector(
*entity_config_shared, ecclesia::GetDefaultThreadFactory(),
ecclesia::Clock::RealClock());
if (!bulk_sensor_collector_or.ok()) {
LOG(ERROR) << "Failed to create bulk sensor collector: "
<< bulk_sensor_collector_or.status();
return bulk_sensor_collector_or.status();
}
all_collectors.bulk_sensor_collector = std::move(*bulk_sensor_collector_or);
// Uses either EmptySensorCollector or SensorCollector from above.
all_collectors.sensor_collector_aggregator =
std::make_unique<SensorCollectorAggregator>(
all_collectors.sensor_collector.get(),
all_collectors.bulk_sensor_collector.get());
if (GetTlbmcConfig().sensor_collector_module().enabled()) {
entity_config_shared->SetSensorCollectorAggregator(
all_collectors.sensor_collector_aggregator.get());
}
if (all_collectors.power_control_collector != nullptr) {
for (const auto& [host_id, power_control_ptr] :
all_collectors.power_control_collector->GetAllPowerControls()) {
if (power_control_ptr == nullptr) {
continue;
}
power_control_ptr->RegisterHostPowerOnToOffCallback(
[&resource_state_managers =
all_collectors.fru_collector->GetResourceStateManagers(),
host_id]([[maybe_unused]] bool setup_run) {
auto it = resource_state_managers.find(RELATED_STATE_HOST_POWER);
if (it == resource_state_managers.end()) {
LOG(WARNING)
<< "No resource state managers found for host power.";
return;
}
for (const auto& [state, resource_state_manager] :
resource_state_managers) {
resource_state_manager->HandleStateOnToOff(host_id);
}
});
power_control_ptr->RegisterHostPowerOffToOnCallback(
[&resource_state_managers =
all_collectors.fru_collector->GetResourceStateManagers(),
host_id]([[maybe_unused]] bool setup_run) {
auto it = resource_state_managers.find(RELATED_STATE_HOST_POWER);
if (it == resource_state_managers.end()) {
LOG(WARNING)
<< "No resource state managers found for host power.";
return;
}
for (const auto& [state, resource_state_manager] :
resource_state_managers) {
resource_state_manager->HandleStateOffToOn(host_id);
}
});
power_control_ptr->RegisterHostPowerOffToOnCallback(
[sensor_collector = all_collectors.sensor_collector.get()](
bool setup_run) { sensor_collector->TriggerPeciScan(); });
power_control_ptr->RegisterHostOSInactiveToStandbyCallback(
[fru_collector_ptr = all_collectors.fru_collector.get(),
host_id = host_id](bool setup_run) {
LOG(INFO) << "Registering HostOSInactiveToStandbyCallback with "
"setup_run: "
<< setup_run << " for host_id: " << host_id;
fru_collector_ptr->HandleHostOsInactiveToStandby(host_id,
setup_run);
});
power_control_ptr->RegisterHostOSStandbyToInactiveCallback(
[fru_collector_ptr = all_collectors.fru_collector.get(),
host_id = host_id](bool setup_run) {
LOG(INFO) << "Registering HostOSStandbyToInactiveCallback with "
"setup_run: "
<< setup_run << " for host_id: " << host_id;
fru_collector_ptr->HandleHostOsStandbyToInactive(host_id,
setup_run);
});
// Start the power control. This is not a blocking call.
power_control_ptr->Start();
}
}
if (GetTlbmcConfig().metric_collector_module().enabled()) {
absl::StatusOr<std::unique_ptr<MetricCollector>> metric_collector;
MetricCollector::Params params = {
.metric_configs = options.proto_parser->GetSoftwareMetricsConfig(),
.root_path = options.root_path,
.psi_base_path =
(std::filesystem::path(options.root_path) / "sys/fs/cgroup")
.string()};
if (options.executor_command_map.empty()) {
metric_collector =
options.collector_factory->CreateMetricCollector(params);
} else {
params.executor_command_map = options.executor_command_map;
metric_collector = MetricCollector::CreateForUnitTest(params);
}
if (!metric_collector.ok()) {
LOG(ERROR) << "Failed to create metric collector: "
<< metric_collector.status();
return metric_collector.status();
}
all_collectors.metric_collector = std::move(*metric_collector);
}
if (GetTlbmcConfig()
.sensor_collector_module()
.thermal_control_sub_module()
.enabled()) {
absl::StatusOr<std::unique_ptr<ThermalCollector>> thermal_collector;
ThermalConfigs thermal_configs = options.proto_parser->GetThermalConfigs();
ThermalCollector::Params params = {
.zone_manager_configs = thermal_configs.zones(),
.first_order_adrc_controller_configs =
thermal_configs.first_order_adrc_controllers(),
.second_order_adrc_controller_configs =
thermal_configs.second_order_adrc_controllers(),
.dff_controller_configs = thermal_configs.dff_controllers(),
.pid_controller_configs = thermal_configs.pid_controllers(),
.stepwise_controller_configs = thermal_configs.stepwise_controllers(),
.fan_pid_controller_configs = thermal_configs.fan_pid_controllers(),
.failsafe_logger_config = thermal_configs.failsafe_logger_config(),
.tuning_enabled = thermal_configs.tuning_enabled(),
};
thermal_collector = options.collector_factory->CreateThermalCollector(
params, &*all_collectors.sensor_collector_aggregator,
all_collectors.fru_collector.get(), entity_config_shared.get());
if (!thermal_collector.ok()) {
LOG(ERROR) << "Failed to create thermal collector: "
<< thermal_collector.status();
return thermal_collector.status();
}
all_collectors.thermal_collector = std::move(*thermal_collector);
}
if (all_collectors.sensor_collector != nullptr &&
all_collectors.thermal_collector != nullptr) {
all_collectors.sensor_collector->SetManualPwmCallback(
[thermal_collector = all_collectors.thermal_collector.get()](
absl::string_view fan_name, double pwm) {
thermal_collector->SetManualPwm(fan_name, pwm);
});
}
if (GetTlbmcConfig().power_fault_log_collector_module().enabled()) {
// The PowerFaultLogCollector is responsible for loading its own config.
PowerFaultLogCollector::Params params;
params.config = options.proto_parser->GetPowerFaultLogConfig();
absl::StatusOr<std::unique_ptr<PowerFaultLogCollector>>
power_fault_log_collector =
options.collector_factory->CreatePowerFaultLogCollector(params);
if (!power_fault_log_collector.ok()) {
LOG(ERROR) << "Failed to create PowerFaultLogCollector: "
<< power_fault_log_collector.status();
return power_fault_log_collector.status();
}
if (absl::Status status = (*power_fault_log_collector)->StartCollection();
!status.ok()) {
LOG(ERROR) << "Failed to start PowerFaultLogCollector: " << status;
return status;
}
all_collectors.power_fault_log_collector =
std::move(*power_fault_log_collector);
// Register power fault detector callbacks with GPIO collector.
absl::flat_hash_map<std::string, absl::AnyInvocable<void(GpioEventType)>>
gpio_monitor_callback_bundle = all_collectors.power_fault_log_collector
->GetGpioMonitorCallbackBundle();
for (auto& [gpio_name, callback] : gpio_monitor_callback_bundle) {
if (absl::Status status = all_collectors.gpio_collector->RegisterCallback(
gpio_name, std::move(callback));
!status.ok()) {
LOG(ERROR)
<< "Failed to register power fault detector callback for GPIO "
<< gpio_name << ": " << status;
return status;
}
}
// Register PrePowerCycle callback with power_control_collector to disable
// power fault detection prior to AC cycles.
auto* raw_collector = all_collectors.power_fault_log_collector.get();
if (all_collectors.power_control_collector != nullptr) {
all_collectors.power_control_collector->RegisterPrePowerCycleCallback(
[raw_collector]() { raw_collector->DisableFaultDetection(); });
}
}
if (GetTlbmcConfig().sel_collector_module().enabled()) {
// The SelCollector is responsible for loading its own config.
SelCollector::Params params;
params.config = options.proto_parser->GetSelConfig();
absl::StatusOr<std::unique_ptr<SelCollector>> sel_collector =
options.collector_factory->CreateSelCollector(params);
if (!sel_collector.ok()) {
LOG(ERROR) << "Failed to create SelCollector: " << sel_collector.status();
return sel_collector.status();
}
ECCLESIA_RETURN_IF_ERROR((*sel_collector)->StartDefaultSubscriber());
all_collectors.sel_collector = std::move(*sel_collector);
}
// Create the store
int periodic_dump_interval_ms =
options.override_store_snapshot_interval_ms.value_or(
kDefaultPeriodicDumpIntervalMs);
metrics_at_bootup.time_to_ready = absl::Now() - create_start_time;
// Trigger AdHocFruScanning after every collector has been initialized to
// prevent race conditions
all_collectors.fru_collector->SetUpAdHocFruScanning();
std::shared_ptr<CredentialManager> credential_manager =
options.credential_manager;
if (credential_manager == nullptr &&
GetTlbmcConfig().trust_bundle_install_module().enabled()) {
return absl::InvalidArgumentError(
"CredentialManager cannot be null when trust bundle install module is "
"enabled.");
}
std::unique_ptr<StoreImpl> store = absl::WrapUnique(
new StoreImpl(std::move(options), std::move(all_collectors),
std::move(entity_config_shared),
absl::Milliseconds(periodic_dump_interval_ms),
std::move(credential_manager), metrics_at_bootup,
options.system_registry));
store->InitializeSensorDevpaths();
return store;
}
void StoreImpl::SetSmartRouter(RouterInterface* smart_router) {
entity_config_->SetSmartRouter(smart_router);
}
StoreImpl::StoreImpl(Options&& options, AllCollectors all_collectors,
std::shared_ptr<EntityConfig> entity_config,
absl::Duration store_snapshot_interval,
std::shared_ptr<CredentialManager> credential_manager,
Metrics metrics_at_bootup,
std::shared_ptr<SystemRegistry> system_registry)
: credential_manager_(std::move(credential_manager)),
options_(std::move(options)),
all_collectors_(std::move(all_collectors)),
entity_config_(std::move(entity_config)),
task_scheduler_(std::make_unique<TaskScheduler>()),
system_registry_(std::move(system_registry)),
metrics_(metrics_at_bootup) {
task_scheduler_->RunAndScheduleAsync(
[this](absl::AnyInvocable<void()> done) {
// Dump the store snapshot.
LOG(WARNING) << "=== Store snapshot ===";
LOG(WARNING) << ToJson().dump();
LOG(WARNING) << "=== END ===";
// Dump the collector scheduler stats.
LOG(WARNING) << "=== Collector Scheduler stats ===";
LOG(WARNING) << GetSchedulerStats().dump();
LOG(WARNING) << "=== END ===";
// Dump the central config.
LOG(WARNING) << "=== Central Config ===";
LOG(WARNING) << GetTlbmcConfig();
LOG(WARNING) << "=== END ===";
done();
},
store_snapshot_interval);
}
// Since the task scheduler is a member variable, we need to stop it before
// destructing since the store is running an async task that is accessing the
// task scheduler.
StoreImpl::~StoreImpl() {
if (all_collectors_.sensor_collector != nullptr) {
all_collectors_.sensor_collector->SetManualPwmCallback(std::nullopt);
}
if (all_collectors_.sel_collector != nullptr) {
all_collectors_.sel_collector->Stop();
}
if (task_scheduler_ != nullptr) {
task_scheduler_->Stop();
}
// Collectors with background threads or dependencies on sensor collectors
// and GPIO/state managers MUST be destroyed/stopped first.
all_collectors_.led_collector.reset();
all_collectors_.power_control_collector.reset();
all_collectors_.pcie_collector.reset();
all_collectors_.thermal_collector.reset();
all_collectors_.fru_collector.reset();
all_collectors_.metric_collector.reset();
all_collectors_.power_fault_log_collector.reset();
all_collectors_.sel_collector.reset();
all_collectors_.gpio_collector.reset();
if (entity_config_ != nullptr) {
entity_config_->SetSensorCollectorAggregator(nullptr);
}
all_collectors_.sensor_collector_aggregator.reset();
all_collectors_.bulk_sensor_collector.reset();
all_collectors_.sensor_collector.reset();
}
void StoreImpl::StartSensorCollection() const {
if (all_collectors_.sensor_collector_aggregator != nullptr) {
all_collectors_.sensor_collector_aggregator->StartSensorCollection();
}
}
void StoreImpl::StartThermalCollection() const {
if (all_collectors_.thermal_collector != nullptr) {
all_collectors_.thermal_collector->StartCollection();
}
}
void StoreImpl::SetManualMode(bool enable_manual_mode) {
if (all_collectors_.thermal_collector != nullptr) {
all_collectors_.thermal_collector->SetManualMode(enable_manual_mode);
}
}
void StoreImpl::SetManualPwm(absl::string_view fan_name, double pwm) {
if (all_collectors_.thermal_collector != nullptr) {
all_collectors_.thermal_collector->SetManualPwm(fan_name, pwm);
}
}
PowerFaultLogEntries StoreImpl::GetPowerFaultLogEntries() const {
return all_collectors_.power_fault_log_collector->GetCollectedEntries();
}
absl::StatusOr<std::string> StoreImpl::GetPowerFaultLogFileContent(
absl::string_view folder_name, absl::string_view file_name) const {
return all_collectors_.power_fault_log_collector->GetLogFileContent(
folder_name, file_name);
}
absl::Status StoreImpl::SetPidControllerCoefficients(
absl::string_view controller_id,
const thermal::PidController::PidControllerCoefficients& coefficients,
absl::Duration timeout) {
absl::Status status =
all_collectors_.thermal_collector->RequestPidControllerCoefficientsTuning(
controller_id, coefficients);
if (!status.ok()) {
return status;
}
absl::Time start_time = absl::Now();
while (all_collectors_.thermal_collector->HasPendingTuningRequest(
controller_id) &&
absl::Now() - start_time < timeout) {
absl::SleepFor(absl::Milliseconds(100));
}
return all_collectors_.thermal_collector->HasPendingTuningRequest(
controller_id)
? absl::DeadlineExceededError(absl::StrCat(
"Timeout ", timeout,
" exceeded and tuning request is still pending."))
: absl::OkStatus();
}
absl::Status StoreImpl::SetFanPidControllerCoefficients(
absl::string_view controller_id,
const thermal::FanPidController::FanPidControllerCoefficients& coefficients,
absl::Duration timeout) {
absl::Status status = all_collectors_.thermal_collector
->RequestFanPidControllerCoefficientsTuning(
controller_id, coefficients);
if (!status.ok()) {
return status;
}
absl::Time start_time = absl::Now();
while (all_collectors_.thermal_collector->HasPendingTuningRequest(
controller_id) &&
absl::Now() - start_time < timeout) {
absl::SleepFor(absl::Milliseconds(100));
}
return all_collectors_.thermal_collector->HasPendingTuningRequest(
controller_id)
? absl::DeadlineExceededError(absl::StrCat(
"Timeout ", timeout,
" exceeded and tuning request is still pending."))
: absl::OkStatus();
}
std::vector<nlohmann::json> StoreImpl::GetSelEntriesForward(
uint64_t start_id, size_t max_count) const {
return all_collectors_.sel_collector->GetSelEntriesForward(start_id,
max_count);
}
std::vector<nlohmann::json> StoreImpl::GetSelEntriesBackward(
uint64_t start_id, size_t max_count) const {
return all_collectors_.sel_collector->GetSelEntriesBackward(start_id,
max_count);
}
std::vector<nlohmann::json> StoreImpl::GetLatestSelEntries(
size_t max_count) const {
return all_collectors_.sel_collector->GetLatestSelEntries(max_count);
}
void StoreImpl::DumpSelEntriesRaw(uint64_t start_id, std::ostream& os) const {
if (all_collectors_.sel_collector != nullptr) {
all_collectors_.sel_collector->DumpSelEntriesRaw(start_id, os);
}
}
} // namespace milotic_tlbmc