blob: 497908a3498646746446b2492a01c30c7d2be51d [file] [log] [blame]
Andrew Geissler36529022016-11-29 15:23:54 -06001#include <iostream>
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -06002#include <map>
3#include <string>
Andrew Geissleref3c1842016-12-01 12:33:09 -06004#include <systemd/sd-bus.h>
Andrew Geissler1e3bf942016-12-13 15:32:22 -06005#include <log.hpp>
Andrew Geissler36529022016-11-29 15:23:54 -06006#include "host_state_manager.hpp"
7
8namespace phosphor
9{
10namespace state
11{
12namespace manager
13{
14
Andrew Geissler3e3b84b2016-12-02 15:46:17 -060015// When you see server:: you know we're referencing our base class
16namespace server = sdbusplus::xyz::openbmc_project::State::server;
17
Andrew Geissler1e3bf942016-12-13 15:32:22 -060018using namespace phosphor::logging;
19
Andrew Geissler4da7e002017-01-24 15:21:40 -060020constexpr auto HOST_STATE_POWEROFF_TGT = "obmc-chassis-stop@0.target";
21constexpr auto HOST_STATE_POWERON_TGT = "obmc-chassis-start@0.target";
22
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060023/* Map a transition to it's systemd target */
24const std::map<server::Host::Transition,std::string> SYSTEMD_TARGET_TABLE =
25{
Andrew Geissler4da7e002017-01-24 15:21:40 -060026 {server::Host::Transition::Off, HOST_STATE_POWEROFF_TGT},
27 {server::Host::Transition::On, HOST_STATE_POWERON_TGT}
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -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
34constexpr auto SYSTEM_SERVICE = "org.openbmc.managers.System";
35constexpr auto SYSTEM_OBJ_PATH = "/org/openbmc/managers/System";
36constexpr auto SYSTEM_INTERFACE = SYSTEM_SERVICE;
37
Andrew Geissleref621162016-12-08 12:56:21 -060038/* Map a system state to the HostState */
Andrew Geissleref621162016-12-08 12:56:21 -060039const std::map<std::string, server::Host::HostState> SYS_HOST_STATE_TABLE = {
40 {"HOST_BOOTING", server::Host::HostState::Running},
41 {"HOST_POWERED_OFF", server::Host::HostState::Off}
42};
43
Andrew Geissler4da7e002017-01-24 15:21:40 -060044void Host::subscribeToSystemdSignals()
45{
46 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
47 SYSTEMD_OBJ_PATH,
48 SYSTEMD_INTERFACE,
49 "Subscribe");
50 this->bus.call_noreply(method);
51
52 return;
53}
54
Andrew Geissleref3c1842016-12-01 12:33:09 -060055// TODO - Will be rewritten once sdbusplus client bindings are in place
56// and persistent storage design is in place
57void Host::determineInitialState()
58{
59 std::string sysState;
60
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060061 auto method = this->bus.new_method_call(SYSTEM_SERVICE,
62 SYSTEM_OBJ_PATH,
63 SYSTEM_INTERFACE,
Andrew Geissleref3c1842016-12-01 12:33:09 -060064 "getSystemState");
65
66 auto reply = this->bus.call(method);
67
68 reply.read(sysState);
69
70 if(sysState == "HOST_BOOTED")
71 {
Andrew Geissler1e3bf942016-12-13 15:32:22 -060072 log<level::INFO>("Initial Host State will be Running",
73 entry("CURRENT_HOST_STATE=%s",
74 convertForMessage(HostState::Running).c_str()));
Andrew Geissler97924142017-01-24 16:10:18 -060075 server::Host::currentHostState(HostState::Running);
76 server::Host::requestedHostTransition(Transition::On);
Andrew Geissleref3c1842016-12-01 12:33:09 -060077 }
78 else
79 {
Andrew Geissler1e3bf942016-12-13 15:32:22 -060080 log<level::INFO>("Initial Host State will be Off",
81 entry("CURRENT_HOST_STATE=%s",
82 convertForMessage(HostState::Off).c_str()));
Andrew Geissler97924142017-01-24 16:10:18 -060083 server::Host::currentHostState(HostState::Off);
84 server::Host::requestedHostTransition(Transition::Off);
Andrew Geissleref3c1842016-12-01 12:33:09 -060085 }
86
87 // Set transition initially to Off
88 // TODO - Eventually need to restore this from persistent storage
Andrew Geissler3e3b84b2016-12-02 15:46:17 -060089 server::Host::requestedHostTransition(Transition::Off);
Andrew Geissleref3c1842016-12-01 12:33:09 -060090
91 return;
92}
93
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060094void Host::executeTransition(Transition tranReq)
95{
96 auto sysdUnit = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
97
98 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
99 SYSTEMD_OBJ_PATH,
100 SYSTEMD_INTERFACE,
101 "StartUnit");
102
103 method.append(sysdUnit);
104 method.append("replace");
105
Andrew Geissler4da7e002017-01-24 15:21:40 -0600106 this->bus.call_noreply(method);
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600107
108 return;
109}
110
Andrew Geissler4da7e002017-01-24 15:21:40 -0600111int Host::sysStateChangeSignal(sd_bus_message *msg, void *userData,
112 sd_bus_error *retError)
Andrew Geissleref621162016-12-08 12:56:21 -0600113{
Andrew Geissler4da7e002017-01-24 15:21:40 -0600114 return static_cast<Host*>(userData)->sysStateChange(msg, retError);
115}
Andrew Geissleref621162016-12-08 12:56:21 -0600116
Andrew Geissler4da7e002017-01-24 15:21:40 -0600117int Host::sysStateChange(sd_bus_message* msg,
118 sd_bus_error* retError)
119{
120 uint32_t newStateID {};
121 sdbusplus::message::object_path newStateObjPath;
122 std::string newStateUnit{};
123 std::string newStateResult{};
124
125 auto sdPlusMsg = sdbusplus::message::message(msg);
126 //Read the msg and populate each variable
127 sdPlusMsg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
128
129 if((newStateUnit == HOST_STATE_POWEROFF_TGT) &&
130 (newStateResult == "done"))
Andrew Geissleref621162016-12-08 12:56:21 -0600131 {
Andrew Geissler4da7e002017-01-24 15:21:40 -0600132 log<level::INFO>("Recieved signal that host is off");
133 this->currentHostState(server::Host::HostState::Off);
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600134
135 // Check if we need to start a new transition (i.e. a Reboot)
Andrew Geissler4da7e002017-01-24 15:21:40 -0600136 if(this->server::Host::requestedHostTransition() ==
137 Transition::Reboot)
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600138 {
Andrew Geissler1e3bf942016-12-13 15:32:22 -0600139 log<level::DEBUG>("Reached intermediate state, going to next");
Andrew Geissler4da7e002017-01-24 15:21:40 -0600140 this->executeTransition(server::Host::Transition::On);
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600141 }
Andrew Geissleref621162016-12-08 12:56:21 -0600142 }
Andrew Geissler4da7e002017-01-24 15:21:40 -0600143 else if((newStateUnit == HOST_STATE_POWERON_TGT) &&
144 (newStateResult == "done"))
145 {
146 log<level::INFO>("Recieved signal that host is running");
147 this->currentHostState(server::Host::HostState::Running);
148 }
Andrew Geissleref621162016-12-08 12:56:21 -0600149
150 return 0;
151}
152
Andrew Geissleref3c1842016-12-01 12:33:09 -0600153Host::Transition Host::requestedHostTransition(Transition value)
154{
Andrew Geissler1e3bf942016-12-13 15:32:22 -0600155 log<level::INFO>(
156 "Host State transaction request",
157 entry("REQUESTED_HOST_TRANSITION=%s",
158 convertForMessage(value).c_str()));
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600159
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600160 Transition tranReq = value;
161 if(value == server::Host::Transition::Reboot)
162 {
163 // On reboot requests we just need to do a off if we're on and
164 // vice versa. The handleSysStateChange() code above handles the
165 // second part of the reboot
166 if(this->server::Host::currentHostState() ==
167 server::Host::HostState::Off)
168 {
169 tranReq = server::Host::Transition::On;
170 }
171 else
172 {
173 tranReq = server::Host::Transition::Off;
174 }
175 }
176
177 executeTransition(tranReq);
Andrew Geissler3e3b84b2016-12-02 15:46:17 -0600178 return server::Host::requestedHostTransition(value);
Andrew Geissleref3c1842016-12-01 12:33:09 -0600179}
180
Andrew Geissleref3c1842016-12-01 12:33:09 -0600181Host::HostState Host::currentHostState(HostState value)
182{
Andrew Geissler1e3bf942016-12-13 15:32:22 -0600183 log<level::INFO>("Change to Host State",
184 entry("CURRENT_HOST_STATE=%s",
185 convertForMessage(value).c_str()));
Andrew Geissleref621162016-12-08 12:56:21 -0600186 return server::Host::currentHostState(value);
Andrew Geissleref3c1842016-12-01 12:33:09 -0600187}
188
Andrew Geissler36529022016-11-29 15:23:54 -0600189} // namespace manager
190} // namespace state
191} // namepsace phosphor