blob: ece0b1cf9724364539354045e2dfac9ee1861483 [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";
Andrew Geissler58a18012018-01-19 19:36:05 -080018constexpr auto CHASSIS_STATE_HARD_POWEROFF_TGT =
19 "obmc-chassis-hard-poweroff@0.target";
Josh D. King6838ea92017-04-11 13:39:18 -050020constexpr auto CHASSIS_STATE_POWERON_TGT = "obmc-chassis-poweron@0.target";
Andrew Geissler0029a5d2017-01-24 14:48:35 -060021
Josh D. King697474c2017-03-02 11:15:55 -060022constexpr auto ACTIVE_STATE = "active";
23constexpr auto ACTIVATING_STATE = "activating";
24
Andrew Geisslerce80f242017-01-24 13:25:33 -060025/* Map a transition to it's systemd target */
Andrew Geissler58a18012018-01-19 19:36:05 -080026const std::map<server::Chassis::Transition, std::string> SYSTEMD_TARGET_TABLE =
27 {
Andrew Geissler8cf2f9a2017-07-21 11:58:04 -050028 // Use the hard off target to ensure we shutdown immediately
29 {server::Chassis::Transition::Off, CHASSIS_STATE_HARD_POWEROFF_TGT},
Andrew Geissler58a18012018-01-19 19:36:05 -080030 {server::Chassis::Transition::On, CHASSIS_STATE_POWERON_TGT}};
Andrew Geisslerce80f242017-01-24 13:25:33 -060031
Andrew Geissler58a18012018-01-19 19:36:05 -080032constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
33constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
Andrew Geisslerce80f242017-01-24 13:25:33 -060034constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
35
Josh D. King697474c2017-03-02 11:15:55 -060036constexpr auto SYSTEMD_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
37constexpr auto SYSTEMD_INTERFACE_UNIT = "org.freedesktop.systemd1.Unit";
38
Andrew Geissler0029a5d2017-01-24 14:48:35 -060039void Chassis::subscribeToSystemdSignals()
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060040{
Andrew Geissler58a18012018-01-19 19:36:05 -080041 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
42 SYSTEMD_INTERFACE, "Subscribe");
Andrew Geissler0029a5d2017-01-24 14:48:35 -060043 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;
Andrew Geissler58a18012018-01-19 19:36:05 -080054 auto method = this->bus.new_method_call(
55 "org.openbmc.control.Power", "/org/openbmc/control/power0",
56 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060057
58 method.append("org.openbmc.control.Power", "pgood");
59 auto reply = this->bus.call(method);
60 reply.read(pgood);
61
Andrew Geissler58a18012018-01-19 19:36:05 -080062 if (pgood == 1)
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060063 {
64 log<level::INFO>("Initial Chassis State will be On",
65 entry("CHASSIS_CURRENT_POWER_STATE=%s",
66 convertForMessage(PowerState::On).c_str()));
67 server::Chassis::currentPowerState(PowerState::On);
68 server::Chassis::requestedPowerTransition(Transition::On);
69 }
70 else
71 {
72 log<level::INFO>("Initial Chassis State will be Off",
73 entry("CHASSIS_CURRENT_POWER_STATE=%s",
74 convertForMessage(PowerState::Off).c_str()));
75 server::Chassis::currentPowerState(PowerState::Off);
76 server::Chassis::requestedPowerTransition(Transition::Off);
77 }
78
79 return;
80}
81
Andrew Geisslerce80f242017-01-24 13:25:33 -060082void Chassis::executeTransition(Transition tranReq)
83{
84 auto sysdTarget = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
85
Andrew Geissler58a18012018-01-19 19:36:05 -080086 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
87 SYSTEMD_INTERFACE, "StartUnit");
Andrew Geisslerce80f242017-01-24 13:25:33 -060088
89 method.append(sysdTarget);
90 method.append("replace");
91
92 this->bus.call_noreply(method);
93
94 return;
95}
96
Josh D. King697474c2017-03-02 11:15:55 -060097bool Chassis::stateActive(const std::string& target)
98{
99 sdbusplus::message::variant<std::string> currentState;
100 sdbusplus::message::object_path unitTargetPath;
101
Andrew Geissler58a18012018-01-19 19:36:05 -0800102 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
103 SYSTEMD_INTERFACE, "GetUnit");
Josh D. King697474c2017-03-02 11:15:55 -0600104
105 method.append(target);
106 auto result = this->bus.call(method);
107
Andrew Geissler58a18012018-01-19 19:36:05 -0800108 // Check that the bus call didn't result in an error
109 if (result.is_method_error())
Josh D. King697474c2017-03-02 11:15:55 -0600110 {
111 log<level::ERR>("Error in bus call - could not resolve GetUnit for:",
112 entry(" %s", SYSTEMD_INTERFACE));
113 return false;
114 }
115
116 result.read(unitTargetPath);
117
Andrew Geissler58a18012018-01-19 19:36:05 -0800118 method = this->bus.new_method_call(
119 SYSTEMD_SERVICE,
120 static_cast<const std::string&>(unitTargetPath).c_str(),
121 SYSTEMD_PROPERTY_IFACE, "Get");
Josh D. King697474c2017-03-02 11:15:55 -0600122
123 method.append(SYSTEMD_INTERFACE_UNIT, "ActiveState");
124 result = this->bus.call(method);
125
Andrew Geissler58a18012018-01-19 19:36:05 -0800126 // Check that the bus call didn't result in an error
127 if (result.is_method_error())
Josh D. King697474c2017-03-02 11:15:55 -0600128 {
129 log<level::ERR>("Error in bus call - could not resolve Get for:",
130 entry(" %s", SYSTEMD_PROPERTY_IFACE));
131 return false;
132 }
133
134 result.read(currentState);
135
Andrew Geissler58a18012018-01-19 19:36:05 -0800136 if (currentState != ACTIVE_STATE && currentState != ACTIVATING_STATE)
Josh D. King697474c2017-03-02 11:15:55 -0600137 {
Andrew Geissler58a18012018-01-19 19:36:05 -0800138 // False - not active
Josh D. King697474c2017-03-02 11:15:55 -0600139 return false;
140 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800141 // True - active
Josh D. King697474c2017-03-02 11:15:55 -0600142 return true;
Josh D. King697474c2017-03-02 11:15:55 -0600143}
144
Patrick Williams8f8ba392017-05-05 15:47:39 -0500145int Chassis::sysStateChange(sdbusplus::message::message& msg)
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600146{
Andrew Geissler58a18012018-01-19 19:36:05 -0800147 uint32_t newStateID{};
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600148 sdbusplus::message::object_path newStateObjPath;
149 std::string newStateUnit{};
150 std::string newStateResult{};
151
Andrew Geissler58a18012018-01-19 19:36:05 -0800152 // Read the msg and populate each variable
Patrick Williams8f8ba392017-05-05 15:47:39 -0500153 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600154
Andrew Geissler58a18012018-01-19 19:36:05 -0800155 if ((newStateUnit == CHASSIS_STATE_POWEROFF_TGT) &&
156 (newStateResult == "done") && (!stateActive(CHASSIS_STATE_POWERON_TGT)))
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600157 {
Andrew Jeffery55b983e2017-04-19 11:11:26 +0930158 log<level::INFO>("Received signal that power OFF is complete");
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600159 this->currentPowerState(server::Chassis::PowerState::Off);
160 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800161 else if ((newStateUnit == CHASSIS_STATE_POWERON_TGT) &&
162 (newStateResult == "done") &&
163 (stateActive(CHASSIS_STATE_POWERON_TGT)))
164 {
165 log<level::INFO>("Received signal that power ON is complete");
166 this->currentPowerState(server::Chassis::PowerState::On);
167 }
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600168
169 return 0;
170}
171
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600172Chassis::Transition Chassis::requestedPowerTransition(Transition value)
173{
174
175 log<level::INFO>("Change to Chassis Requested Power State",
176 entry("CHASSIS_REQUESTED_POWER_STATE=%s",
177 convertForMessage(value).c_str()));
Andrew Geisslerce80f242017-01-24 13:25:33 -0600178 executeTransition(value);
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600179 return server::Chassis::requestedPowerTransition(value);
180}
181
182Chassis::PowerState Chassis::currentPowerState(PowerState value)
183{
184 log<level::INFO>("Change to Chassis Power State",
185 entry("CHASSIS_CURRENT_POWER_STATE=%s",
186 convertForMessage(value).c_str()));
187 return server::Chassis::currentPowerState(value);
188}
189
190} // namespace manager
191} // namespace state
192} // namepsace phosphor