blob: e1a2e0f0f99724dbf7288486a74df0f55d52fe0e [file] [log] [blame]
Andrew Geissler0029a5d2017-01-24 14:48:35 -06001#include <sdbusplus/bus.hpp>
Saqib Khana8006a22017-02-14 11:37:08 -06002#include <phosphor-logging/log.hpp>
Andrew Geisslera90a31a2016-12-13 16:16:28 -06003#include "chassis_state_manager.hpp"
4
5namespace phosphor
6{
7namespace state
8{
9namespace manager
10{
11
12// When you see server:: you know we're referencing our base class
13namespace server = sdbusplus::xyz::openbmc_project::State::server;
14
15using namespace phosphor::logging;
16
Josh D. King6838ea92017-04-11 13:39:18 -050017constexpr auto CHASSIS_STATE_POWEROFF_TGT = "obmc-chassis-poweroff@0.target";
18constexpr auto CHASSIS_STATE_POWERON_TGT = "obmc-chassis-poweron@0.target";
Andrew Geissler0029a5d2017-01-24 14:48:35 -060019
Josh D. King697474c2017-03-02 11:15:55 -060020constexpr auto ACTIVE_STATE = "active";
21constexpr auto ACTIVATING_STATE = "activating";
22
Andrew Geisslerce80f242017-01-24 13:25:33 -060023/* Map a transition to it's systemd target */
24const std::map<server::Chassis::Transition,std::string> SYSTEMD_TARGET_TABLE =
25{
Andrew Geissler0029a5d2017-01-24 14:48:35 -060026 {server::Chassis::Transition::Off, CHASSIS_STATE_POWEROFF_TGT},
27 {server::Chassis::Transition::On, CHASSIS_STATE_POWERON_TGT}
Andrew Geisslerce80f242017-01-24 13:25:33 -060028};
29
30constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
31constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
32constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
33
Josh D. King697474c2017-03-02 11:15:55 -060034constexpr auto SYSTEMD_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
35constexpr auto SYSTEMD_INTERFACE_UNIT = "org.freedesktop.systemd1.Unit";
36
Andrew Geissler0029a5d2017-01-24 14:48:35 -060037void Chassis::subscribeToSystemdSignals()
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060038{
Andrew Geissler0029a5d2017-01-24 14:48:35 -060039 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
40 SYSTEMD_OBJ_PATH,
41 SYSTEMD_INTERFACE,
42 "Subscribe");
43 this->bus.call_noreply(method);
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060044
Andrew Geissler0029a5d2017-01-24 14:48:35 -060045 return;
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060046}
47
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060048// TODO - Will be rewritten once sdbusplus client bindings are in place
49// and persistent storage design is in place and sdbusplus
50// has read property function
51void Chassis::determineInitialState()
52{
53 sdbusplus::message::variant<int> pgood = -1;
54 auto method = this->bus.new_method_call("org.openbmc.control.Power",
55 "/org/openbmc/control/power0",
56 "org.freedesktop.DBus.Properties",
57 "Get");
58
59 method.append("org.openbmc.control.Power", "pgood");
60 auto reply = this->bus.call(method);
61 reply.read(pgood);
62
63 if(pgood == 1)
64 {
65 log<level::INFO>("Initial Chassis State will be On",
66 entry("CHASSIS_CURRENT_POWER_STATE=%s",
67 convertForMessage(PowerState::On).c_str()));
68 server::Chassis::currentPowerState(PowerState::On);
69 server::Chassis::requestedPowerTransition(Transition::On);
70 }
71 else
72 {
73 log<level::INFO>("Initial Chassis State will be Off",
74 entry("CHASSIS_CURRENT_POWER_STATE=%s",
75 convertForMessage(PowerState::Off).c_str()));
76 server::Chassis::currentPowerState(PowerState::Off);
77 server::Chassis::requestedPowerTransition(Transition::Off);
78 }
79
80 return;
81}
82
Andrew Geisslerce80f242017-01-24 13:25:33 -060083void Chassis::executeTransition(Transition tranReq)
84{
85 auto sysdTarget = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
86
87 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
88 SYSTEMD_OBJ_PATH,
89 SYSTEMD_INTERFACE,
90 "StartUnit");
91
92 method.append(sysdTarget);
93 method.append("replace");
94
95 this->bus.call_noreply(method);
96
97 return;
98}
99
Josh D. King697474c2017-03-02 11:15:55 -0600100bool Chassis::stateActive(const std::string& target)
101{
102 sdbusplus::message::variant<std::string> currentState;
103 sdbusplus::message::object_path unitTargetPath;
104
105 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
106 SYSTEMD_OBJ_PATH,
107 SYSTEMD_INTERFACE,
108 "GetUnit");
109
110 method.append(target);
111 auto result = this->bus.call(method);
112
113 //Check that the bus call didn't result in an error
114 if(result.is_method_error())
115 {
116 log<level::ERR>("Error in bus call - could not resolve GetUnit for:",
117 entry(" %s", SYSTEMD_INTERFACE));
118 return false;
119 }
120
121 result.read(unitTargetPath);
122
123 method = this->bus.new_method_call(SYSTEMD_SERVICE,
124 static_cast<const std::string&>
125 (unitTargetPath).c_str(),
126 SYSTEMD_PROPERTY_IFACE,
127 "Get");
128
129 method.append(SYSTEMD_INTERFACE_UNIT, "ActiveState");
130 result = this->bus.call(method);
131
132 //Check that the bus call didn't result in an error
133 if(result.is_method_error())
134 {
135 log<level::ERR>("Error in bus call - could not resolve Get for:",
136 entry(" %s", SYSTEMD_PROPERTY_IFACE));
137 return false;
138 }
139
140 result.read(currentState);
141
142 if(currentState != ACTIVE_STATE && currentState != ACTIVATING_STATE)
143 {
144 //False - not active
145 return false;
146 }
147 //True - active
148 return true;
149
150}
151
Patrick Williams8f8ba392017-05-05 15:47:39 -0500152int Chassis::sysStateChange(sdbusplus::message::message& msg)
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600153{
154 uint32_t newStateID {};
155 sdbusplus::message::object_path newStateObjPath;
156 std::string newStateUnit{};
157 std::string newStateResult{};
158
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600159 //Read the msg and populate each variable
Patrick Williams8f8ba392017-05-05 15:47:39 -0500160 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600161
162 if((newStateUnit == CHASSIS_STATE_POWEROFF_TGT) &&
Josh D. King697474c2017-03-02 11:15:55 -0600163 (newStateResult == "done") &&
164 (!stateActive(CHASSIS_STATE_POWERON_TGT)))
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600165 {
Andrew Jeffery55b983e2017-04-19 11:11:26 +0930166 log<level::INFO>("Received signal that power OFF is complete");
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600167 this->currentPowerState(server::Chassis::PowerState::Off);
168 }
169 else if((newStateUnit == CHASSIS_STATE_POWERON_TGT) &&
Josh D. King697474c2017-03-02 11:15:55 -0600170 (newStateResult == "done") &&
171 (stateActive(CHASSIS_STATE_POWERON_TGT)))
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600172 {
Andrew Jeffery55b983e2017-04-19 11:11:26 +0930173 log<level::INFO>("Received signal that power ON is complete");
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600174 this->currentPowerState(server::Chassis::PowerState::On);
175 }
176
177 return 0;
178}
179
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600180Chassis::Transition Chassis::requestedPowerTransition(Transition value)
181{
182
183 log<level::INFO>("Change to Chassis Requested Power State",
184 entry("CHASSIS_REQUESTED_POWER_STATE=%s",
185 convertForMessage(value).c_str()));
Andrew Geisslerce80f242017-01-24 13:25:33 -0600186 executeTransition(value);
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600187 return server::Chassis::requestedPowerTransition(value);
188}
189
190Chassis::PowerState Chassis::currentPowerState(PowerState value)
191{
192 log<level::INFO>("Change to Chassis Power State",
193 entry("CHASSIS_CURRENT_POWER_STATE=%s",
194 convertForMessage(value).c_str()));
195 return server::Chassis::currentPowerState(value);
196}
197
198} // namespace manager
199} // namespace state
200} // namepsace phosphor