-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathbmc_state_manager.hpp
151 lines (127 loc) · 4.46 KB
/
bmc_state_manager.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#pragma once
#include "utils.hpp"
#include "xyz/openbmc_project/State/BMC/server.hpp"
#include <linux/watchdog.h>
#include <sys/sysinfo.h>
#include <sdbusplus/bus.hpp>
#include <cassert>
#include <chrono>
namespace phosphor
{
namespace state
{
namespace manager
{
using BMCInherit = sdbusplus::server::object_t<
sdbusplus::server::xyz::openbmc_project::state::BMC>;
namespace sdbusRule = sdbusplus::bus::match::rules;
/** @class BMC
* @brief OpenBMC BMC state management implementation.
* @details A concrete implementation for xyz.openbmc_project.State.BMC
* DBus API.
*/
class BMC : public BMCInherit
{
public:
/** @brief Constructs BMC State Manager
*
* @param[in] bus - The Dbus bus object
* @param[in] busName - The Dbus name to own
* @param[in] objPath - The Dbus object path
*/
BMC(sdbusplus::bus_t& bus, const char* objPath) :
BMCInherit(bus, objPath, BMCInherit::action::defer_emit), bus(bus),
stateSignal(std::make_unique<decltype(stateSignal)::element_type>(
bus,
sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
sdbusRule::path("/org/freedesktop/systemd1") +
sdbusRule::interface("org.freedesktop.systemd1.Manager"),
[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();
updateLastRebootTime();
this->emit_object_added();
};
/** @brief Set value of BMCTransition **/
Transition requestedBMCTransition(Transition value) override;
/** @brief Set value of CurrentBMCState **/
BMCState currentBMCState(BMCState value) override;
/** @brief Returns the last time the BMC was rebooted
*
* @details Uses uptime information to determine when
* the BMC was last rebooted.
*
* @return uint64_t - Epoch time, in milliseconds, of the
* last reboot.
*/
uint64_t lastRebootTime() const override;
/** @brief Set value of LastRebootCause **/
RebootCause lastRebootCause(RebootCause value) override;
private:
/**
* @brief Retrieve input systemd unit state
**/
std::string getUnitState(const std::string& unitToCheck);
/**
* @brief discover the state of the bmc
**/
void discoverInitialState();
/** @brief Execute the transition request
*
* @param[in] tranReq - Transition requested
*/
void executeTransition(Transition tranReq);
/** @brief Callback function on bmc state change
*
* Check if the state is relevant to the BMC and if so, update
* corresponding BMC object's state
*
* @param[in] msg - Data associated with subscribed signal
*
*/
int bmcStateChange(sdbusplus::message_t& msg);
/** @brief Persistent sdbusplus DBus bus connection. **/
sdbusplus::bus_t& bus;
/** @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 calculated at startup.
**/
uint64_t rebootTime;
};
} // namespace manager
} // namespace state
} // namespace phosphor