| #include "psm_handler.hpp" |
| |
| #include "log.hpp" |
| |
| #include <fmt/printf.h> |
| |
| #include <variant> |
| |
| namespace boot_time_monitor |
| { |
| namespace psm |
| { |
| |
| namespace btm = boot_time_monitor; |
| |
| using BasicVariantType = |
| std::variant<std::vector<std::string>, std::string, int64_t, uint64_t, |
| double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>; |
| |
| std::string inline translateHostStateName(std::string_view state) |
| { |
| std::size_t found = state.find_last_of('.'); |
| return std::string("HostState:") + std::string(state.substr(found + 1)); |
| } |
| |
| std::string inline translateOSStatus(std::string_view status) |
| { |
| std::size_t found = status.find_last_of('.'); |
| return std::string("OSStatus:") + std::string(status.substr(found + 1)); |
| } |
| |
| Handler::Handler(sdbusplus::bus::bus& bus, const btm::NodeConfig& nodeConfig, |
| const btm::psm::PSMConfig& psmConfig, |
| std::shared_ptr<btm::api::IBoottimeApi> api) : |
| mNodeConfig(nodeConfig), mApi(std::move(api)) |
| { |
| // Initialize mPreHostState |
| auto method = |
| bus.new_method_call(psmConfig.hostStateDbusService.c_str(), // Service |
| psmConfig.hostStateDbusObjPath.c_str(), // Path |
| "org.freedesktop.DBus.Properties", // Iface |
| "Get"); // Function |
| method.append("xyz.openbmc_project.State.Host", "CurrentHostState"); |
| BasicVariantType result; |
| try |
| { |
| bus.call(method).read(result); |
| mPreHostState = std::get<std::string>(result); |
| fmt::print("{} `CurrentHostState` is `{}`\n", mNodeConfig.node_name, |
| mPreHostState); |
| } |
| catch (const sdbusplus::exception::SdBusError& e) |
| { |
| fmt::print( |
| stderr, |
| "Failed to query `CurrentHostState` with busctl get-property {} {} " |
| "xyz.openbmc_project.State.Host CurrentHostState" |
| ". Got error: {}\n", |
| psmConfig.hostStateDbusService, psmConfig.hostStateDbusObjPath, |
| e.what()); |
| } |
| |
| hostStateWatcher = std::make_unique<sdbusplus::bus::match::match>( |
| bus, |
| sdbusplus::bus::match::rules::propertiesChanged( |
| psmConfig.hostStateDbusObjPath, "xyz.openbmc_project.State.Host"), |
| [this](sdbusplus::message::message& message) { |
| std::string objectName; |
| boost::container::flat_map< |
| std::string, |
| std::variant<std::string, bool, int64_t, uint64_t, double>> |
| values; |
| message.read(objectName, values); |
| |
| auto findState = values.find("CurrentHostState"); |
| if (findState != values.end()) |
| { |
| const std::string curHostState = |
| std::get<std::string>(findState->second); |
| fmt::print( |
| stderr, |
| "[hostStateWatcher] {} `CurrentHostState` has changed from {} to {}\n", |
| mNodeConfig.node_name, mPreHostState, curHostState); |
| absl::Status status = mApi->SetNodeCheckpoint( |
| mNodeConfig, translateHostStateName(curHostState), 0, 0); |
| btm::log::LogIfError(status); |
| mPreHostState = curHostState; |
| } |
| }); |
| |
| // Initialize mPreOSState |
| method = |
| bus.new_method_call(psmConfig.osStateDbusService.c_str(), // Service |
| psmConfig.osStateDbusObjPath.c_str(), // Path |
| "org.freedesktop.DBus.Properties", // Iface |
| "Get"); // Function |
| method.append("xyz.openbmc_project.State.OperatingSystem.Status", |
| "OperatingSystemState"); |
| try |
| { |
| bus.call(method).read(result); |
| mPreOSState = std::get<std::string>(result); |
| fmt::print("{} `OperatingSystemState` is `{}`\n", mNodeConfig.node_name, |
| mPreOSState); |
| } |
| catch (const sdbusplus::exception::SdBusError& e) |
| { |
| fmt::print( |
| stderr, |
| "Failed to query OperatingSystemState with busctl get-property {} {} " |
| "xyz.openbmc_project.State.OperatingSystem.Status OperatingSystemState." |
| "Got error: {}\n", |
| psmConfig.hostStateDbusService, psmConfig.hostStateDbusObjPath, |
| e.what()); |
| } |
| |
| osStatusWatcher = std::make_unique<sdbusplus::bus::match::match>( |
| bus, |
| sdbusplus::bus::match::rules::propertiesChanged( |
| psmConfig.osStateDbusObjPath, |
| "xyz.openbmc_project.State.OperatingSystem.Status"), |
| [this](sdbusplus::message::message& message) { |
| std::string objectName; |
| boost::container::flat_map< |
| std::string, |
| std::variant<std::string, bool, int64_t, uint64_t, double>> |
| values; |
| message.read(objectName, values); |
| |
| auto findState = values.find("OperatingSystemState"); |
| if (findState != values.end()) |
| { |
| const std::string curOSStatus = |
| std::get<std::string>(findState->second); |
| |
| fmt::print( |
| stderr, |
| "[osStatusWatcher] {} `OperatingSystemState` has changed from {} to {}\n", |
| mNodeConfig.node_name, mPreOSState, curOSStatus); |
| absl::Status status = mApi->SetNodeCheckpoint( |
| mNodeConfig, translateOSStatus(curOSStatus), 0, 0); |
| btm::log::LogIfError(status); |
| mPreOSState = curOSStatus; |
| } |
| }); |
| } |
| } // namespace psm |
| } // namespace boot_time_monitor |