blob: 1b09b1676518937578ab6beed2594b0175a040af [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 Geissler36529022016-11-29 15:23:54 -06005#include "host_state_manager.hpp"
6
7namespace phosphor
8{
9namespace state
10{
11namespace manager
12{
13
Andrew Geissler3e3b84b2016-12-02 15:46:17 -060014// When you see server:: you know we're referencing our base class
15namespace server = sdbusplus::xyz::openbmc_project::State::server;
16
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060017/* Map a transition to it's systemd target */
18const std::map<server::Host::Transition,std::string> SYSTEMD_TARGET_TABLE =
19{
Andrew Geissleref621162016-12-08 12:56:21 -060020 {server::Host::Transition::Off, "obmc-chassis-stop@0.target"},
21 {server::Host::Transition::On, "obmc-chassis-start@0.target"}
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060022};
23
24constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
25constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
26constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
27
28constexpr auto SYSTEM_SERVICE = "org.openbmc.managers.System";
29constexpr auto SYSTEM_OBJ_PATH = "/org/openbmc/managers/System";
30constexpr auto SYSTEM_INTERFACE = SYSTEM_SERVICE;
31
Andrew Geissleref621162016-12-08 12:56:21 -060032/* Map a system state to the HostState */
33/* TODO:Issue 774 - Use systemd target signals to control host states */
34const std::map<std::string, server::Host::HostState> SYS_HOST_STATE_TABLE = {
35 {"HOST_BOOTING", server::Host::HostState::Running},
36 {"HOST_POWERED_OFF", server::Host::HostState::Off}
37};
38
Andrew Geissleref3c1842016-12-01 12:33:09 -060039// TODO - Will be rewritten once sdbusplus client bindings are in place
40// and persistent storage design is in place
41void Host::determineInitialState()
42{
43 std::string sysState;
44
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060045 auto method = this->bus.new_method_call(SYSTEM_SERVICE,
46 SYSTEM_OBJ_PATH,
47 SYSTEM_INTERFACE,
Andrew Geissleref3c1842016-12-01 12:33:09 -060048 "getSystemState");
49
50 auto reply = this->bus.call(method);
51
52 reply.read(sysState);
53
54 if(sysState == "HOST_BOOTED")
55 {
56 std::cout << "HOST is BOOTED " << sysState << std::endl;
Andrew Geissleref621162016-12-08 12:56:21 -060057 currentHostState(HostState::Running);
Andrew Geissler359aaaf2016-12-13 13:23:53 -060058 requestedHostTransition(Transition::On);
Andrew Geissleref3c1842016-12-01 12:33:09 -060059 }
60 else
61 {
62 std::cout << "HOST is not BOOTED " << sysState << std::endl;
Andrew Geissleref621162016-12-08 12:56:21 -060063 currentHostState(HostState::Off);
Andrew Geissler359aaaf2016-12-13 13:23:53 -060064 requestedHostTransition(Transition::Off);
Andrew Geissleref3c1842016-12-01 12:33:09 -060065 }
66
67 // Set transition initially to Off
68 // TODO - Eventually need to restore this from persistent storage
Andrew Geissler3e3b84b2016-12-02 15:46:17 -060069 server::Host::requestedHostTransition(Transition::Off);
Andrew Geissleref3c1842016-12-01 12:33:09 -060070
71 return;
72}
73
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060074void Host::executeTransition(Transition tranReq)
75{
76 auto sysdUnit = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
77
78 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
79 SYSTEMD_OBJ_PATH,
80 SYSTEMD_INTERFACE,
81 "StartUnit");
82
83 method.append(sysdUnit);
84 method.append("replace");
85
86 this->bus.call(method);
87
88 return;
89}
90
Andrew Geissleref621162016-12-08 12:56:21 -060091int Host::handleSysStateChange(sd_bus_message *msg, void *usrData,
92 sd_bus_error *retError)
93{
94 const char *newState = nullptr;
95 auto sdPlusMsg = sdbusplus::message::message(msg);
96 sdPlusMsg.read(newState);
97
98 std::cout << "The System State has changed to " << newState << std::endl;
99
100 auto it = SYS_HOST_STATE_TABLE.find(newState);
101 if(it != SYS_HOST_STATE_TABLE.end())
102 {
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600103 // This is a state change we're interested in so process it
104 Host::HostState gotoState = it->second;
105 // Grab the host object instance from the userData
Andrew Geissleref621162016-12-08 12:56:21 -0600106 auto hostInst = static_cast<Host*>(usrData);
107 hostInst->currentHostState(gotoState);
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600108
109 // Check if we need to start a new transition (i.e. a Reboot)
110 if((gotoState == server::Host::HostState::Off) &&
111 (hostInst->server::Host::requestedHostTransition() ==
112 Transition::Reboot))
113 {
114 std::cout << "Reached intermediate state, going to next" <<
115 std::endl;
116 hostInst->executeTransition(server::Host::Transition::On);
117 }
118 else
119 {
120 std::cout << "Reached Final State " << newState << std::endl;
121 }
Andrew Geissleref621162016-12-08 12:56:21 -0600122 }
123 else
124 {
125 std::cout << "Not a relevant state change for host" << std::endl;
126 }
127
128 return 0;
129}
130
Andrew Geissleref3c1842016-12-01 12:33:09 -0600131Host::Transition Host::requestedHostTransition(Transition value)
132{
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600133 std::cout << "Someone is setting the RequestedHostTransition field"
134 << std::endl;
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600135
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600136 Transition tranReq = value;
137 if(value == server::Host::Transition::Reboot)
138 {
139 // On reboot requests we just need to do a off if we're on and
140 // vice versa. The handleSysStateChange() code above handles the
141 // second part of the reboot
142 if(this->server::Host::currentHostState() ==
143 server::Host::HostState::Off)
144 {
145 tranReq = server::Host::Transition::On;
146 }
147 else
148 {
149 tranReq = server::Host::Transition::Off;
150 }
151 }
152
153 executeTransition(tranReq);
154 std::cout << "Transition executed with success" << std::endl;
Andrew Geissler3e3b84b2016-12-02 15:46:17 -0600155 return server::Host::requestedHostTransition(value);
Andrew Geissleref3c1842016-12-01 12:33:09 -0600156}
157
Andrew Geissleref3c1842016-12-01 12:33:09 -0600158Host::HostState Host::currentHostState(HostState value)
159{
Andrew Geissleref621162016-12-08 12:56:21 -0600160 std::cout << "Changing HostState" << std::endl;
161 return server::Host::currentHostState(value);
Andrew Geissleref3c1842016-12-01 12:33:09 -0600162}
163
Andrew Geissler36529022016-11-29 15:23:54 -0600164} // namespace manager
165} // namespace state
166} // namepsace phosphor