From cb781fe1b8750712b9f8c6e534e794d27204c5ef Mon Sep 17 00:00:00 2001 From: Nagaraju Goruganti Date: Fri, 6 Apr 2018 13:41:01 -0500 Subject: Add Chassis POH Counter Added 32-bit counter, which shows how many hours the system has been running. The value is a cumulative one and includes all working hours since production. If the chassis state is Powered-on, This will be incremented by one for every hour. It won't get updated when the chassis state is powered-off. Resolves openbmc/openbmc#2979 Change-Id: I18e9bb571d1a6e401b25450168249f70891be665 Signed-off-by: Nagaraju Goruganti --- chassis_state_manager.cpp | 128 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) (limited to 'chassis_state_manager.cpp') diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp index ece0b1c..d78a6f7 100644 --- a/chassis_state_manager.cpp +++ b/chassis_state_manager.cpp @@ -1,6 +1,15 @@ #include #include +#include +#include "xyz/openbmc_project/Common/error.hpp" #include "chassis_state_manager.hpp" +#include +#include +#include "config.h" +#include + +// Register class version with Cereal +CEREAL_CLASS_VERSION(phosphor::state::manager::Chassis, CLASS_VERSION); namespace phosphor { @@ -181,10 +190,127 @@ Chassis::Transition Chassis::requestedPowerTransition(Transition value) Chassis::PowerState Chassis::currentPowerState(PowerState value) { + PowerState chassisPowerState; log("Change to Chassis Power State", entry("CHASSIS_CURRENT_POWER_STATE=%s", convertForMessage(value).c_str())); - return server::Chassis::currentPowerState(value); + + chassisPowerState = server::Chassis::currentPowerState(value); + if (chassisPowerState == PowerState::On) + { + timer->state(timer::ON); + } + else + { + timer->state(timer::OFF); + } + return chassisPowerState; +} + +uint32_t Chassis::pOHCounter(uint32_t value) +{ + if (value != pOHCounter()) + { + ChassisInherit::pOHCounter(value); + serialize(); + } + return pOHCounter(); +} + +void Chassis::restorePOHCounter() +{ + uint32_t counter; + if (!deserialize(POH_COUNTER_PERSIST_PATH, counter)) + { + // set to default value + pOHCounter(0); + } + else + { + pOHCounter(counter); + } +} + +fs::path Chassis::serialize(const fs::path& path) +{ + std::ofstream os(path.c_str(), std::ios::binary); + cereal::JSONOutputArchive oarchive(os); + oarchive(pOHCounter()); + return path; +} + +bool Chassis::deserialize(const fs::path& path, uint32_t& pOHCounter) +{ + try + { + if (fs::exists(path)) + { + std::ifstream is(path.c_str(), std::ios::in | std::ios::binary); + cereal::JSONInputArchive iarchive(is); + iarchive(pOHCounter); + return true; + } + return false; + } + catch (cereal::Exception& e) + { + log(e.what()); + fs::remove(path); + return false; + } + catch (const fs::filesystem_error& e) + { + return false; + } + + return false; +} + +void Chassis::startPOHCounter() +{ + using namespace std::chrono_literals; + using namespace phosphor::logging; + using namespace sdbusplus::xyz::openbmc_project::Common::Error; + + auto dir = fs::path(POH_COUNTER_PERSIST_PATH).parent_path(); + fs::create_directories(dir); + + sd_event* event = nullptr; + auto r = sd_event_default(&event); + if (r < 0) + { + log("Error creating a default sd_event handler"); + throw; + } + + phosphor::state::manager::EventPtr eventP{event}; + event = nullptr; + + auto callback = [&]() { + if (ChassisInherit::currentPowerState() == PowerState::On) + { + pOHCounter(pOHCounter() + 1); + } + }; + + try + { + timer = std::make_unique( + eventP, callback, std::chrono::seconds(POH::hour), + phosphor::state::manager::timer::ON); + bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL); + r = sd_event_loop(eventP.get()); + if (r < 0) + { + log("Error occurred during the sd_event_loop", + entry("RC=%d", r)); + elog(); + } + } + catch (InternalFailure& e) + { + phosphor::logging::commit(); + } } } // namespace manager -- cgit v1.2.1