bmc_state: Update last update time after timesync
Currently the lastRebootTime is updated at service boot up and reuses
the values on future requests. This can cause incorrect values like
```
$ busctl get-property xyz.openbmc_project.State.BMC /xyz/openbmc_project/state/bmc0 xyz.openbmc_project.State.BMC LastRebootTime
t 1680555476000
$ uptime
11:23:05 up 1 day, 24 min, load average: 3.08, 2.89, 2.84
```
1680555476000 -> Mon Apr 03 2023 20:57:56 GMT+0000
which is more than 1 day and 24 minutes ago.
The change will detect property changes to `time-sync.target` which
would be activated after timesync happens. It will then deactivate the
matcher after update the lastReboot time once.
Tested:
After bootup and timesync, the lastReboot time is now correct.
Change-Id: Iee8a0bc9f0c5b22d5010f1a677011e44b5d425d3
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/bmc_state_manager.hpp b/bmc_state_manager.hpp
index d50d4f3..7ffa67b 100644
--- a/bmc_state_manager.hpp
+++ b/bmc_state_manager.hpp
@@ -43,23 +43,35 @@
sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
sdbusRule::path("/org/freedesktop/systemd1") +
sdbusRule::interface("org.freedesktop.systemd1.Manager"),
- [this](sdbusplus::message_t& m) { bmcStateChange(m); }))
+ [this](sdbusplus::message_t& m) { bmcStateChange(m); })),
+
+ timeSyncSignal(std::make_unique<decltype(timeSyncSignal)::element_type>(
+ bus,
+ sdbusRule::propertiesChanged(
+ "/org/freedesktop/systemd1/unit/time_2dsync_2etarget",
+ "org.freedesktop.systemd1.Unit"),
+ [this](sdbusplus::message_t& m) {
+ std::string interface;
+ std::unordered_map<std::string, std::variant<std::string>>
+ propertyChanged;
+ m.read(interface, propertyChanged);
+
+ for (const auto& [key, value] : propertyChanged)
+ {
+ if (key == "ActiveState" &&
+ std::holds_alternative<std::string>(value) &&
+ std::get<std::string>(value) == "active")
+ {
+ updateLastRebootTime();
+ timeSyncSignal.reset();
+ }
+ }
+ }))
{
utils::subscribeToSystemdSignals(bus);
discoverInitialState();
discoverLastRebootCause();
-
- using namespace std::chrono;
- struct sysinfo info;
-
- auto rc = sysinfo(&info);
- assert(rc == 0);
- // Since uptime is in seconds, also get the current time in seconds.
- auto now = time_point_cast<seconds>(system_clock::now());
- auto rebootTimeTs = now - seconds(info.uptime);
- rebootTime =
- duration_cast<milliseconds>(rebootTimeTs.time_since_epoch())
- .count();
+ updateLastRebootTime();
this->emit_object_added();
};
@@ -115,12 +127,20 @@
/** @brief Used to subscribe to dbus system state changes **/
std::unique_ptr<sdbusplus::bus::match_t> stateSignal;
+ /** @brief Used to subscribe to timesync **/
+ std::unique_ptr<sdbusplus::bus::match_t> timeSyncSignal;
+
/**
* @brief discover the last reboot cause of the bmc
**/
void discoverLastRebootCause();
/**
+ * @brief update the last reboot time of the bmc
+ **/
+ void updateLastRebootTime();
+
+ /**
* @brief the lastRebootTime calcuated at startup.
**/
uint64_t rebootTime;