blob: c532b9db55fb4e0435d9f3a5dd6d17e3d2e8e8bb [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 Geissleref3c1842016-12-01 12:33:09 -060058 }
59 else
60 {
61 std::cout << "HOST is not BOOTED " << sysState << std::endl;
Andrew Geissleref621162016-12-08 12:56:21 -060062 currentHostState(HostState::Off);
Andrew Geissleref3c1842016-12-01 12:33:09 -060063 }
64
65 // Set transition initially to Off
66 // TODO - Eventually need to restore this from persistent storage
Andrew Geissler3e3b84b2016-12-02 15:46:17 -060067 server::Host::requestedHostTransition(Transition::Off);
Andrew Geissleref3c1842016-12-01 12:33:09 -060068
69 return;
70}
71
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -060072void Host::executeTransition(Transition tranReq)
73{
74 auto sysdUnit = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
75
76 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
77 SYSTEMD_OBJ_PATH,
78 SYSTEMD_INTERFACE,
79 "StartUnit");
80
81 method.append(sysdUnit);
82 method.append("replace");
83
84 this->bus.call(method);
85
86 return;
87}
88
Andrew Geissleref621162016-12-08 12:56:21 -060089int Host::handleSysStateChange(sd_bus_message *msg, void *usrData,
90 sd_bus_error *retError)
91{
92 const char *newState = nullptr;
93 auto sdPlusMsg = sdbusplus::message::message(msg);
94 sdPlusMsg.read(newState);
95
96 std::cout << "The System State has changed to " << newState << std::endl;
97
98 auto it = SYS_HOST_STATE_TABLE.find(newState);
99 if(it != SYS_HOST_STATE_TABLE.end())
100 {
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600101 // This is a state change we're interested in so process it
102 Host::HostState gotoState = it->second;
103 // Grab the host object instance from the userData
Andrew Geissleref621162016-12-08 12:56:21 -0600104 auto hostInst = static_cast<Host*>(usrData);
105 hostInst->currentHostState(gotoState);
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600106
107 // Check if we need to start a new transition (i.e. a Reboot)
108 if((gotoState == server::Host::HostState::Off) &&
109 (hostInst->server::Host::requestedHostTransition() ==
110 Transition::Reboot))
111 {
112 std::cout << "Reached intermediate state, going to next" <<
113 std::endl;
114 hostInst->executeTransition(server::Host::Transition::On);
115 }
116 else
117 {
118 std::cout << "Reached Final State " << newState << std::endl;
119 }
Andrew Geissleref621162016-12-08 12:56:21 -0600120 }
121 else
122 {
123 std::cout << "Not a relevant state change for host" << std::endl;
124 }
125
126 return 0;
127}
128
Andrew Geissleref3c1842016-12-01 12:33:09 -0600129Host::Transition Host::requestedHostTransition(Transition value)
130{
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600131 std::cout << "Someone is setting the RequestedHostTransition field"
132 << std::endl;
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600133
Andrew Geissler06dbc5b2016-12-13 11:46:16 -0600134 Transition tranReq = value;
135 if(value == server::Host::Transition::Reboot)
136 {
137 // On reboot requests we just need to do a off if we're on and
138 // vice versa. The handleSysStateChange() code above handles the
139 // second part of the reboot
140 if(this->server::Host::currentHostState() ==
141 server::Host::HostState::Off)
142 {
143 tranReq = server::Host::Transition::On;
144 }
145 else
146 {
147 tranReq = server::Host::Transition::Off;
148 }
149 }
150
151 executeTransition(tranReq);
152 std::cout << "Transition executed with success" << std::endl;
Andrew Geissler3e3b84b2016-12-02 15:46:17 -0600153 return server::Host::requestedHostTransition(value);
Andrew Geissleref3c1842016-12-01 12:33:09 -0600154}
155
Andrew Geissleref3c1842016-12-01 12:33:09 -0600156Host::HostState Host::currentHostState(HostState value)
157{
Andrew Geissleref621162016-12-08 12:56:21 -0600158 std::cout << "Changing HostState" << std::endl;
159 return server::Host::currentHostState(value);
Andrew Geissleref3c1842016-12-01 12:33:09 -0600160}
161
Andrew Geissler36529022016-11-29 15:23:54 -0600162} // namespace manager
163} // namespace state
164} // namepsace phosphor