blob: d440c001813e5f523fb94d4e47d790d9d3b8c379 [file] [log] [blame]
Andrew Geissler769a62f2019-12-06 13:36:08 -06001#include "config.h"
Andrew Geisslere426b582020-05-28 12:40:55 -05002
Michael Tritz3ed10082017-03-20 23:28:09 -05003#include "host_state_manager.hpp"
Deepak Kodihalli55f132b2017-07-25 07:36:06 -05004#include "settings.hpp"
5#include "xyz/openbmc_project/Common/error.hpp"
6#include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
Michael Tritz3ed10082017-03-20 23:28:09 -05007
Andrew Geisslere426b582020-05-28 12:40:55 -05008#include <getopt.h>
9#include <systemd/sd-bus.h>
10
11#include <phosphor-logging/elog-errors.hpp>
12#include <phosphor-logging/log.hpp>
13#include <sdbusplus/exception.hpp>
14#include <sdbusplus/server.hpp>
15
16#include <iostream>
17#include <map>
18#include <string>
19
Michael Tritz3ed10082017-03-20 23:28:09 -050020namespace phosphor
21{
22namespace state
23{
24namespace manager
25{
26
27using namespace phosphor::logging;
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050028using namespace sdbusplus::xyz::openbmc_project::Common::Error;
29using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
Michael Tritz3ed10082017-03-20 23:28:09 -050030
31constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
32constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
33constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
34
35constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
36
Michael Tritz3ed10082017-03-20 23:28:09 -050037std::string getService(sdbusplus::bus::bus& bus, std::string path,
38 std::string interface)
39{
Andrew Geissler58a18012018-01-19 19:36:05 -080040 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
41 MAPPER_INTERFACE, "GetObject");
Michael Tritz3ed10082017-03-20 23:28:09 -050042
43 mapper.append(path, std::vector<std::string>({interface}));
Michael Tritz3ed10082017-03-20 23:28:09 -050044
45 std::map<std::string, std::vector<std::string>> mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050046 try
Michael Tritz3ed10082017-03-20 23:28:09 -050047 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050048 auto mapperResponseMsg = bus.call(mapper);
49
50 mapperResponseMsg.read(mapperResponse);
51 if (mapperResponse.empty())
52 {
53 log<level::ERR>("Error reading mapper response",
54 entry("PATH=%s", path.c_str()),
55 entry("INTERFACE=%s", interface.c_str()));
56 throw std::runtime_error("Error reading mapper response");
57 }
58 }
Patrick Williams0a675212021-09-02 09:49:43 -050059 catch (const sdbusplus::exception::exception& e)
Anthony Wilson32c532e2018-10-25 21:56:07 -050060 {
61 log<level::ERR>("Error in mapper call", entry("ERROR=%s", e.what()),
Michael Tritz3ed10082017-03-20 23:28:09 -050062 entry("PATH=%s", path.c_str()),
63 entry("INTERFACE=%s", interface.c_str()));
Anthony Wilson32c532e2018-10-25 21:56:07 -050064 throw;
Michael Tritz3ed10082017-03-20 23:28:09 -050065 }
66
67 return mapperResponse.begin()->first;
68}
69
70std::string getProperty(sdbusplus::bus::bus& bus, std::string path,
71 std::string interface, std::string propertyName)
72{
Patrick Williams2975e262020-05-13 18:01:09 -050073 std::variant<std::string> property;
Michael Tritz3ed10082017-03-20 23:28:09 -050074 std::string service = getService(bus, path, interface);
75
Andrew Geissler58a18012018-01-19 19:36:05 -080076 auto method = bus.new_method_call(service.c_str(), path.c_str(),
77 PROPERTY_INTERFACE, "Get");
Michael Tritz3ed10082017-03-20 23:28:09 -050078
79 method.append(interface, propertyName);
Michael Tritz3ed10082017-03-20 23:28:09 -050080
Anthony Wilson32c532e2018-10-25 21:56:07 -050081 try
Michael Tritz3ed10082017-03-20 23:28:09 -050082 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050083 auto reply = bus.call(method);
84 reply.read(property);
Michael Tritz3ed10082017-03-20 23:28:09 -050085 }
Patrick Williams0a675212021-09-02 09:49:43 -050086 catch (const sdbusplus::exception::exception& e)
Anthony Wilson32c532e2018-10-25 21:56:07 -050087 {
88 log<level::ERR>("Error in property Get", entry("ERROR=%s", e.what()),
89 entry("PROPERTY=%s", propertyName.c_str()));
90 throw;
91 }
Michael Tritz3ed10082017-03-20 23:28:09 -050092
Patrick Williams37413dc2020-05-13 11:29:54 -050093 if (std::get<std::string>(property).empty())
Michael Tritz3ed10082017-03-20 23:28:09 -050094 {
95 log<level::ERR>("Error reading property response",
96 entry("PROPERTY=%s", propertyName.c_str()));
97 throw std::runtime_error("Error reading property response");
98 }
99
Patrick Williams37413dc2020-05-13 11:29:54 -0500100 return std::get<std::string>(property);
Michael Tritz3ed10082017-03-20 23:28:09 -0500101}
102
Patrick Venturef2870592018-10-14 14:11:30 -0700103void setProperty(sdbusplus::bus::bus& bus, const std::string& path,
104 const std::string& interface, const std::string& property,
105 const std::string& value)
Michael Tritz3ed10082017-03-20 23:28:09 -0500106{
Patrick Williams2975e262020-05-13 18:01:09 -0500107 std::variant<std::string> variantValue = value;
Michael Tritz3ed10082017-03-20 23:28:09 -0500108 std::string service = getService(bus, path, interface);
109
Andrew Geissler58a18012018-01-19 19:36:05 -0800110 auto method = bus.new_method_call(service.c_str(), path.c_str(),
111 PROPERTY_INTERFACE, "Set");
Michael Tritz3ed10082017-03-20 23:28:09 -0500112
113 method.append(interface, property, variantValue);
114 bus.call_noreply(method);
115
116 return;
117}
118
119} // namespace manager
120} // namespace state
Andrew Geisslera965cf02018-08-31 08:37:05 -0700121} // namespace phosphor
Michael Tritz3ed10082017-03-20 23:28:09 -0500122
Michael Tritzd50f6572017-09-05 16:38:11 -0500123int main(int argc, char** argv)
Michael Tritz3ed10082017-03-20 23:28:09 -0500124{
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500125 using namespace phosphor::logging;
126
Michael Tritzd50f6572017-09-05 16:38:11 -0500127 std::string hostPath = "/xyz/openbmc_project/state/host0";
128 int arg;
129 int optIndex = 0;
130
Andrew Geissler58a18012018-01-19 19:36:05 -0800131 static struct option longOpts[] = {{"host", required_argument, 0, 'h'},
132 {0, 0, 0, 0}};
Michael Tritzd50f6572017-09-05 16:38:11 -0500133
Andrew Geissler58a18012018-01-19 19:36:05 -0800134 while ((arg = getopt_long(argc, argv, "h:", longOpts, &optIndex)) != -1)
Michael Tritzd50f6572017-09-05 16:38:11 -0500135 {
136 switch (arg)
137 {
138 case 'h':
Andrew Geissler58a18012018-01-19 19:36:05 -0800139 hostPath =
140 std::string("/xyz/openbmc_project/state/host") + optarg;
Michael Tritzd50f6572017-09-05 16:38:11 -0500141 break;
142 default:
143 break;
144 }
145 }
146
Michael Tritz3ed10082017-03-20 23:28:09 -0500147 auto bus = sdbusplus::bus::new_default();
148
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500149 using namespace settings;
150 Objects settings(bus);
151
Michael Tritz3ed10082017-03-20 23:28:09 -0500152 using namespace phosphor::state::manager;
153 namespace server = sdbusplus::xyz::openbmc_project::State::server;
154
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500155 // This application is only run if chassis power is off
Michael Tritz3ed10082017-03-20 23:28:09 -0500156
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600157 /* The logic here is to first check the one-time PowerRestorePolicy setting.
158 * If this property is not the default then look at the persistent
159 * user setting in the non one-time object, otherwise honor the one-time
160 * setting.
161 */
162 auto methodOneTime = bus.new_method_call(
163 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(),
164 settings.powerRestorePolicyOneTime.c_str(),
165 "org.freedesktop.DBus.Properties", "Get");
166 methodOneTime.append(powerRestoreIntf, "PowerRestorePolicy");
167
168 auto methodUserSetting = bus.new_method_call(
Andrew Geissler58a18012018-01-19 19:36:05 -0800169 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(),
170 settings.powerRestorePolicy.c_str(), "org.freedesktop.DBus.Properties",
171 "Get");
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600172 methodUserSetting.append(powerRestoreIntf, "PowerRestorePolicy");
Anthony Wilson32c532e2018-10-25 21:56:07 -0500173
Patrick Williams2975e262020-05-13 18:01:09 -0500174 std::variant<std::string> result;
Anthony Wilson32c532e2018-10-25 21:56:07 -0500175 try
Michael Tritz3ed10082017-03-20 23:28:09 -0500176 {
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600177 auto reply = bus.call(methodOneTime);
Anthony Wilson32c532e2018-10-25 21:56:07 -0500178 reply.read(result);
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600179 auto powerPolicy = std::get<std::string>(result);
180
181 if (RestorePolicy::Policy::None ==
182 RestorePolicy::convertPolicyFromString(powerPolicy))
183 {
184 // one_time is set to None so use the customer setting
185 log<level::INFO>(
186 "One time not set, check user setting of power policy");
187 auto reply = bus.call(methodUserSetting);
188 reply.read(result);
189 powerPolicy = std::get<std::string>(result);
190 }
191 else
192 {
193 // one_time setting was set so we're going to use it. Reset it
194 // to default for next time.
195 log<level::INFO>("One time set, use it and reset to default");
196 setProperty(bus, settings.powerRestorePolicyOneTime.c_str(),
197 powerRestoreIntf, "PowerRestorePolicy",
198 convertForMessage(RestorePolicy::Policy::None));
199 }
200
201 log<level::INFO>("Host power is off, processing power policy",
202 entry("POWER_POLICY=%s", powerPolicy.c_str()));
203
204 if (RestorePolicy::Policy::AlwaysOn ==
205 RestorePolicy::convertPolicyFromString(powerPolicy))
206 {
207 log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
208 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
209 convertForMessage(server::Host::Transition::On));
210 }
211 else if (RestorePolicy::Policy::Restore ==
212 RestorePolicy::convertPolicyFromString(powerPolicy))
213 {
214 log<level::INFO>("power_policy=RESTORE, restoring last state");
215
216 // Read last requested state and re-request it to execute it
217 auto hostReqState = getProperty(bus, hostPath, HOST_BUSNAME,
218 "RequestedHostTransition");
219 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
220 hostReqState);
221 }
Anthony Wilson32c532e2018-10-25 21:56:07 -0500222 }
Patrick Williams0a675212021-09-02 09:49:43 -0500223 catch (const sdbusplus::exception::exception& e)
Anthony Wilson32c532e2018-10-25 21:56:07 -0500224 {
225 log<level::ERR>("Error in PowerRestorePolicy Get",
226 entry("ERROR=%s", e.what()));
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500227 elog<InternalFailure>();
228 }
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500229
Michael Tritz3ed10082017-03-20 23:28:09 -0500230 return 0;
231}