summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNagaraju Goruganti <ngorugan@in.ibm.com>2018-04-06 13:41:01 -0500
committerNagaraju Goruganti <ngorugan@in.ibm.com>2018-05-12 04:57:37 +0000
commitcb781fe1b8750712b9f8c6e534e794d27204c5ef (patch)
tree48428765acf75b0a66eedbcdbd4ff2f40046ca1c
parent41a774efacb3f3a9593aeaa971468e770d205e13 (diff)
downloadphosphor-state-manager-cb781fe1b8750712b9f8c6e534e794d27204c5ef.tar.gz
phosphor-state-manager-cb781fe1b8750712b9f8c6e534e794d27204c5ef.zip
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 <ngorugan@in.ibm.com>
-rw-r--r--Makefile.am4
-rw-r--r--chassis_state_manager.cpp128
-rw-r--r--chassis_state_manager.hpp81
-rw-r--r--chassis_state_manager_main.cpp7
-rw-r--r--configure.ac6
5 files changed, 216 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index dbd84f9..5aff810 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,14 +37,14 @@ generic_cxxflags = \
generic_ldflags = \
$(SYSTEMD_LIBS) \
$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
- $(SDBUSPLUS_LIBS)
+ $(SDBUSPLUS_LIBS) \
$(PHOSPHOR_LOGGING_LIBS)
phosphor_host_state_manager_CXXFLAGS = $(generic_cxxflags)
phosphor_host_state_manager_LDFLAGS = $(generic_ldflags) -lstdc++fs
phosphor_chassis_state_manager_CXXFLAGS = $(generic_cxxflags)
-phosphor_chassis_state_manager_LDFLAGS = $(generic_ldflags)
+phosphor_chassis_state_manager_LDFLAGS = $(generic_ldflags) -lstdc++fs
phosphor_bmc_state_manager_CXXFLAGS = $(generic_cxxflags)
phosphor_bmc_state_manager_LDFLAGS = $(generic_ldflags)
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 <sdbusplus/bus.hpp>
#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include "xyz/openbmc_project/Common/error.hpp"
#include "chassis_state_manager.hpp"
+#include <cereal/archives/json.hpp>
+#include <fstream>
+#include "config.h"
+#include <experimental/filesystem>
+
+// 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<level::INFO>("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<level::ERR>(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<level::ERR>("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<phosphor::state::manager::Timer>(
+ 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<level::ERR>("Error occurred during the sd_event_loop",
+ entry("RC=%d", r));
+ elog<InternalFailure>();
+ }
+ }
+ catch (InternalFailure& e)
+ {
+ phosphor::logging::commit<InternalFailure>();
+ }
}
} // namespace manager
diff --git a/chassis_state_manager.hpp b/chassis_state_manager.hpp
index 54f0afd..a1fcb04 100644
--- a/chassis_state_manager.hpp
+++ b/chassis_state_manager.hpp
@@ -1,8 +1,13 @@
#pragma once
#include <functional>
+#include <experimental/filesystem>
+#include <cereal/cereal.hpp>
#include <sdbusplus/bus.hpp>
#include "xyz/openbmc_project/State/Chassis/server.hpp"
+#include "xyz/openbmc_project/State/PowerOnHours/server.hpp"
+#include "config.h"
+#include "timer.hpp"
namespace phosphor
{
@@ -10,10 +15,19 @@ namespace state
{
namespace manager
{
+namespace POH
+{
+
+using namespace std::chrono_literals;
+constexpr auto hour = 3600s; // seconds Per Hour
+
+} // namespace POH
using ChassisInherit = sdbusplus::server::object::object<
- sdbusplus::xyz::openbmc_project::State::server::Chassis>;
+ sdbusplus::xyz::openbmc_project::State::server::Chassis,
+ sdbusplus::xyz::openbmc_project::State::server::PowerOnHours>;
namespace sdbusRule = sdbusplus::bus::match::rules;
+namespace fs = std::experimental::filesystem;
/** @class Chassis
* @brief OpenBMC chassis state management implementation.
@@ -49,6 +63,8 @@ class Chassis : public ChassisInherit
determineInitialState();
+ restorePOHCounter(); // restore POHCounter from persisted file
+
// We deferred this until we could get our property correct
this->emit_object_added();
}
@@ -59,6 +75,12 @@ class Chassis : public ChassisInherit
/** @brief Set value of CurrentPowerState */
PowerState currentPowerState(PowerState value) override;
+ /** @brief Get value of POHCounter */
+ using ChassisInherit::pOHCounter;
+
+ /** @brief Increment POHCounter if Chassis Power state is ON */
+ void startPOHCounter();
+
private:
/** @brief Determine initial chassis state and set internally */
void determineInitialState();
@@ -108,6 +130,63 @@ class Chassis : public ChassisInherit
/** @brief Used to subscribe to dbus systemd signals **/
sdbusplus::bus::match_t systemdSignals;
+
+ /** @brief Used to Set value of POHCounter */
+ uint32_t pOHCounter(uint32_t value) override;
+
+ /** @brief Used to restore POHCounter value from persisted file */
+ void restorePOHCounter();
+
+ /** @brief Function required by Cereal to perform serialization.
+ *
+ * @tparam Archive - Cereal archive type (json in our case).
+ * @param[in] archive - reference to Cereal archive.
+ * @param[in] version - Class version that enables handling
+ * a serialized data across code levels
+ */
+ template <class Archive>
+ inline void save(Archive& archive, const std::uint32_t version) const
+ {
+ archive(pOHCounter());
+ }
+
+ /** @brief Function required by Cereal to perform deserialization.
+ *
+ * @tparam Archive - Cereal archive type (json in our case).
+ * @param[in] archive - reference to Cereal archive.
+ * @param[in] version - Class version that enables handling
+ * a serialized data across code levels
+ */
+ template <class Archive>
+ inline void load(Archive& archive, const std::uint32_t version)
+ {
+ uint32_t value;
+ archive(value);
+ pOHCounter(value);
+ }
+
+ /** @brief Serialize and persist requested POH counter.
+ *
+ * @param[in] dir - pathname of file where the serialized POH counter will
+ * be placed.
+ *
+ * @return fs::path - pathname of persisted requested POH counter.
+ */
+ fs::path
+ serialize(const fs::path& dir = fs::path(POH_COUNTER_PERSIST_PATH));
+
+ /** @brief Deserialze a persisted requested POH counter.
+ *
+ * @param[in] path - pathname of persisted POH counter file
+ * @param[in] retCounter - deserialized POH counter value
+ *
+ * @return bool - true if the deserialization was successful, false
+ * otherwise.
+ */
+ bool deserialize(const fs::path& path, uint32_t& retCounter);
+
+ /** @brief Timer */
+ std::unique_ptr<phosphor::state::manager::Timer> timer;
};
} // namespace manager
diff --git a/chassis_state_manager_main.cpp b/chassis_state_manager_main.cpp
index ce3a0d8..1870890 100644
--- a/chassis_state_manager_main.cpp
+++ b/chassis_state_manager_main.cpp
@@ -19,12 +19,7 @@ int main(int argc, char *argv[])
objPathInst.c_str());
bus.request_name(CHASSIS_BUSNAME);
-
- while (true)
- {
- bus.process_discard();
- bus.wait();
- }
+ manager.startPOHCounter();
return 0;
}
diff --git a/configure.ac b/configure.ac
index 8c02dc8..838aaf2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,6 +60,12 @@ AS_IF([test "x$HOST_STATE_PERSIST_PATH" == "x"], \
AC_DEFINE_UNQUOTED([HOST_STATE_PERSIST_PATH], ["$HOST_STATE_PERSIST_PATH"], \
[Path of file for storing requested host state.])
+AC_ARG_VAR(POH_COUNTER_PERSIST_PATH, [Path of file for storing POH counter.])
+AS_IF([test "x$POH_COUNTER_PERSIST_PATH" == "x"], \
+ [POH_COUNTER_PERSIST_PATH="/var/lib/phosphor-state-manager/POHCounter"])
+AC_DEFINE_UNQUOTED([POH_COUNTER_PERSIST_PATH], ["$POH_COUNTER_PERSIST_PATH"], \
+ [Path of file for storing POH counter.])
+
AC_ARG_VAR(BOOT_COUNT_MAX_ALLOWED, [The maximum allowed reboot count])
AS_IF([test "x$BOOT_COUNT_MAX_ALLOWED" == "x"], [BOOT_COUNT_MAX_ALLOWED=3])
AC_DEFINE_UNQUOTED([BOOT_COUNT_MAX_ALLOWED], [$BOOT_COUNT_MAX_ALLOWED], [The maximum allowed reboot count])
OpenPOWER on IntegriCloud