blob: 06a32c4369c241229d10abec22176271006ddbaf [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;
Anthony Wilson32c532e2018-10-25 21:56:07 -050030using sdbusplus::exception::SdBusError;
Michael Tritz3ed10082017-03-20 23:28:09 -050031
32constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
33constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
34constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
35
36constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
37
Michael Tritz3ed10082017-03-20 23:28:09 -050038std::string getService(sdbusplus::bus::bus& bus, std::string path,
39 std::string interface)
40{
Andrew Geissler58a18012018-01-19 19:36:05 -080041 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
42 MAPPER_INTERFACE, "GetObject");
Michael Tritz3ed10082017-03-20 23:28:09 -050043
44 mapper.append(path, std::vector<std::string>({interface}));
Michael Tritz3ed10082017-03-20 23:28:09 -050045
46 std::map<std::string, std::vector<std::string>> mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050047 try
Michael Tritz3ed10082017-03-20 23:28:09 -050048 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050049 auto mapperResponseMsg = bus.call(mapper);
50
51 mapperResponseMsg.read(mapperResponse);
52 if (mapperResponse.empty())
53 {
54 log<level::ERR>("Error reading mapper response",
55 entry("PATH=%s", path.c_str()),
56 entry("INTERFACE=%s", interface.c_str()));
57 throw std::runtime_error("Error reading mapper response");
58 }
59 }
60 catch (const SdBusError& e)
61 {
62 log<level::ERR>("Error in mapper call", entry("ERROR=%s", e.what()),
Michael Tritz3ed10082017-03-20 23:28:09 -050063 entry("PATH=%s", path.c_str()),
64 entry("INTERFACE=%s", interface.c_str()));
Anthony Wilson32c532e2018-10-25 21:56:07 -050065 throw;
Michael Tritz3ed10082017-03-20 23:28:09 -050066 }
67
68 return mapperResponse.begin()->first;
69}
70
71std::string getProperty(sdbusplus::bus::bus& bus, std::string path,
72 std::string interface, std::string propertyName)
73{
Patrick Williams2975e262020-05-13 18:01:09 -050074 std::variant<std::string> property;
Michael Tritz3ed10082017-03-20 23:28:09 -050075 std::string service = getService(bus, path, interface);
76
Andrew Geissler58a18012018-01-19 19:36:05 -080077 auto method = bus.new_method_call(service.c_str(), path.c_str(),
78 PROPERTY_INTERFACE, "Get");
Michael Tritz3ed10082017-03-20 23:28:09 -050079
80 method.append(interface, propertyName);
Michael Tritz3ed10082017-03-20 23:28:09 -050081
Anthony Wilson32c532e2018-10-25 21:56:07 -050082 try
Michael Tritz3ed10082017-03-20 23:28:09 -050083 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050084 auto reply = bus.call(method);
85 reply.read(property);
Michael Tritz3ed10082017-03-20 23:28:09 -050086 }
Anthony Wilson32c532e2018-10-25 21:56:07 -050087 catch (const SdBusError& e)
88 {
89 log<level::ERR>("Error in property Get", entry("ERROR=%s", e.what()),
90 entry("PROPERTY=%s", propertyName.c_str()));
91 throw;
92 }
Michael Tritz3ed10082017-03-20 23:28:09 -050093
Patrick Williams37413dc2020-05-13 11:29:54 -050094 if (std::get<std::string>(property).empty())
Michael Tritz3ed10082017-03-20 23:28:09 -050095 {
96 log<level::ERR>("Error reading property response",
97 entry("PROPERTY=%s", propertyName.c_str()));
98 throw std::runtime_error("Error reading property response");
99 }
100
Patrick Williams37413dc2020-05-13 11:29:54 -0500101 return std::get<std::string>(property);
Michael Tritz3ed10082017-03-20 23:28:09 -0500102}
103
Patrick Venturef2870592018-10-14 14:11:30 -0700104void setProperty(sdbusplus::bus::bus& bus, const std::string& path,
105 const std::string& interface, const std::string& property,
106 const std::string& value)
Michael Tritz3ed10082017-03-20 23:28:09 -0500107{
Patrick Williams2975e262020-05-13 18:01:09 -0500108 std::variant<std::string> variantValue = value;
Michael Tritz3ed10082017-03-20 23:28:09 -0500109 std::string service = getService(bus, path, interface);
110
Andrew Geissler58a18012018-01-19 19:36:05 -0800111 auto method = bus.new_method_call(service.c_str(), path.c_str(),
112 PROPERTY_INTERFACE, "Set");
Michael Tritz3ed10082017-03-20 23:28:09 -0500113
114 method.append(interface, property, variantValue);
115 bus.call_noreply(method);
116
117 return;
118}
119
120} // namespace manager
121} // namespace state
Andrew Geisslera965cf02018-08-31 08:37:05 -0700122} // namespace phosphor
Michael Tritz3ed10082017-03-20 23:28:09 -0500123
Michael Tritzd50f6572017-09-05 16:38:11 -0500124int main(int argc, char** argv)
Michael Tritz3ed10082017-03-20 23:28:09 -0500125{
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500126 using namespace phosphor::logging;
127
Michael Tritzd50f6572017-09-05 16:38:11 -0500128 std::string hostPath = "/xyz/openbmc_project/state/host0";
129 int arg;
130 int optIndex = 0;
131
Andrew Geissler58a18012018-01-19 19:36:05 -0800132 static struct option longOpts[] = {{"host", required_argument, 0, 'h'},
133 {0, 0, 0, 0}};
Michael Tritzd50f6572017-09-05 16:38:11 -0500134
Andrew Geissler58a18012018-01-19 19:36:05 -0800135 while ((arg = getopt_long(argc, argv, "h:", longOpts, &optIndex)) != -1)
Michael Tritzd50f6572017-09-05 16:38:11 -0500136 {
137 switch (arg)
138 {
139 case 'h':
Andrew Geissler58a18012018-01-19 19:36:05 -0800140 hostPath =
141 std::string("/xyz/openbmc_project/state/host") + optarg;
Michael Tritzd50f6572017-09-05 16:38:11 -0500142 break;
143 default:
144 break;
145 }
146 }
147
Michael Tritz3ed10082017-03-20 23:28:09 -0500148 auto bus = sdbusplus::bus::new_default();
149
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500150 using namespace settings;
151 Objects settings(bus);
152
Michael Tritz3ed10082017-03-20 23:28:09 -0500153 using namespace phosphor::state::manager;
154 namespace server = sdbusplus::xyz::openbmc_project::State::server;
155
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500156 // This application is only run if chassis power is off
Michael Tritz3ed10082017-03-20 23:28:09 -0500157
Andrew Geissler58a18012018-01-19 19:36:05 -0800158 auto method = bus.new_method_call(
159 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(),
160 settings.powerRestorePolicy.c_str(), "org.freedesktop.DBus.Properties",
161 "Get");
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500162 method.append(powerRestoreIntf, "PowerRestorePolicy");
Anthony Wilson32c532e2018-10-25 21:56:07 -0500163
Patrick Williams2975e262020-05-13 18:01:09 -0500164 std::variant<std::string> result;
Anthony Wilson32c532e2018-10-25 21:56:07 -0500165 try
Michael Tritz3ed10082017-03-20 23:28:09 -0500166 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500167 auto reply = bus.call(method);
168 reply.read(result);
169 }
170 catch (const SdBusError& e)
171 {
172 log<level::ERR>("Error in PowerRestorePolicy Get",
173 entry("ERROR=%s", e.what()));
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500174 elog<InternalFailure>();
175 }
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500176
Patrick Williams37413dc2020-05-13 11:29:54 -0500177 auto powerPolicy = std::get<std::string>(result);
Michael Tritz3ed10082017-03-20 23:28:09 -0500178
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500179 log<level::INFO>("Host power is off, checking power policy",
180 entry("POWER_POLICY=%s", powerPolicy.c_str()));
Michael Tritz3ed10082017-03-20 23:28:09 -0500181
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500182 if (RestorePolicy::Policy::AlwaysOn ==
183 RestorePolicy::convertPolicyFromString(powerPolicy))
184 {
185 log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
Andrew Geissler58a18012018-01-19 19:36:05 -0800186 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500187 convertForMessage(server::Host::Transition::On));
188 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800189 else if (RestorePolicy::Policy::Restore ==
190 RestorePolicy::convertPolicyFromString(powerPolicy))
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500191 {
192 log<level::INFO>("power_policy=RESTORE, restoring last state");
Michael Tritz3ed10082017-03-20 23:28:09 -0500193
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500194 // Read last requested state and re-request it to execute it
Andrew Geissler58a18012018-01-19 19:36:05 -0800195 auto hostReqState =
196 getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
197 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500198 hostReqState);
Michael Tritz3ed10082017-03-20 23:28:09 -0500199 }
200
201 return 0;
202}