blob: 3a38152ccbeadfb315e91deebc09bf6bf5e12bf8 [file] [log] [blame]
Michael Tritzd50f6572017-09-05 16:38:11 -05001#include <getopt.h>
Michael Tritz3ed10082017-03-20 23:28:09 -05002#include <iostream>
3#include <map>
4#include <string>
5#include <config.h>
6#include <systemd/sd-bus.h>
Anthony Wilson32c532e2018-10-25 21:56:07 -05007#include <sdbusplus/exception.hpp>
Michael Tritz3ed10082017-03-20 23:28:09 -05008#include <sdbusplus/server.hpp>
9#include <phosphor-logging/log.hpp>
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050010#include <phosphor-logging/elog-errors.hpp>
Michael Tritz3ed10082017-03-20 23:28:09 -050011#include "host_state_manager.hpp"
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050012#include "settings.hpp"
13#include "xyz/openbmc_project/Common/error.hpp"
14#include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
Michael Tritz3ed10082017-03-20 23:28:09 -050015
16namespace phosphor
17{
18namespace state
19{
20namespace manager
21{
22
23using namespace phosphor::logging;
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050024using namespace sdbusplus::xyz::openbmc_project::Common::Error;
25using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
Anthony Wilson32c532e2018-10-25 21:56:07 -050026using sdbusplus::exception::SdBusError;
Michael Tritz3ed10082017-03-20 23:28:09 -050027
28constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
29constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
30constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
31
32constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
33
Michael Tritz3ed10082017-03-20 23:28:09 -050034std::string getService(sdbusplus::bus::bus& bus, std::string path,
35 std::string interface)
36{
Andrew Geissler58a18012018-01-19 19:36:05 -080037 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
38 MAPPER_INTERFACE, "GetObject");
Michael Tritz3ed10082017-03-20 23:28:09 -050039
40 mapper.append(path, std::vector<std::string>({interface}));
Michael Tritz3ed10082017-03-20 23:28:09 -050041
42 std::map<std::string, std::vector<std::string>> mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050043 try
Michael Tritz3ed10082017-03-20 23:28:09 -050044 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050045 auto mapperResponseMsg = bus.call(mapper);
46
47 mapperResponseMsg.read(mapperResponse);
48 if (mapperResponse.empty())
49 {
50 log<level::ERR>("Error reading mapper response",
51 entry("PATH=%s", path.c_str()),
52 entry("INTERFACE=%s", interface.c_str()));
53 throw std::runtime_error("Error reading mapper response");
54 }
55 }
56 catch (const SdBusError& e)
57 {
58 log<level::ERR>("Error in mapper call", entry("ERROR=%s", e.what()),
Michael Tritz3ed10082017-03-20 23:28:09 -050059 entry("PATH=%s", path.c_str()),
60 entry("INTERFACE=%s", interface.c_str()));
Anthony Wilson32c532e2018-10-25 21:56:07 -050061 throw;
Michael Tritz3ed10082017-03-20 23:28:09 -050062 }
63
64 return mapperResponse.begin()->first;
65}
66
67std::string getProperty(sdbusplus::bus::bus& bus, std::string path,
68 std::string interface, std::string propertyName)
69{
70 sdbusplus::message::variant<std::string> property;
71 std::string service = getService(bus, path, interface);
72
Andrew Geissler58a18012018-01-19 19:36:05 -080073 auto method = bus.new_method_call(service.c_str(), path.c_str(),
74 PROPERTY_INTERFACE, "Get");
Michael Tritz3ed10082017-03-20 23:28:09 -050075
76 method.append(interface, propertyName);
Michael Tritz3ed10082017-03-20 23:28:09 -050077
Anthony Wilson32c532e2018-10-25 21:56:07 -050078 try
Michael Tritz3ed10082017-03-20 23:28:09 -050079 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050080 auto reply = bus.call(method);
81 reply.read(property);
Michael Tritz3ed10082017-03-20 23:28:09 -050082 }
Anthony Wilson32c532e2018-10-25 21:56:07 -050083 catch (const SdBusError& e)
84 {
85 log<level::ERR>("Error in property Get", entry("ERROR=%s", e.what()),
86 entry("PROPERTY=%s", propertyName.c_str()));
87 throw;
88 }
Michael Tritz3ed10082017-03-20 23:28:09 -050089
90 if (sdbusplus::message::variant_ns::get<std::string>(property).empty())
91 {
92 log<level::ERR>("Error reading property response",
93 entry("PROPERTY=%s", propertyName.c_str()));
94 throw std::runtime_error("Error reading property response");
95 }
96
97 return sdbusplus::message::variant_ns::get<std::string>(property);
98}
99
Patrick Venturef2870592018-10-14 14:11:30 -0700100void setProperty(sdbusplus::bus::bus& bus, const std::string& path,
101 const std::string& interface, const std::string& property,
102 const std::string& value)
Michael Tritz3ed10082017-03-20 23:28:09 -0500103{
104 sdbusplus::message::variant<std::string> variantValue = value;
105 std::string service = getService(bus, path, interface);
106
Andrew Geissler58a18012018-01-19 19:36:05 -0800107 auto method = bus.new_method_call(service.c_str(), path.c_str(),
108 PROPERTY_INTERFACE, "Set");
Michael Tritz3ed10082017-03-20 23:28:09 -0500109
110 method.append(interface, property, variantValue);
111 bus.call_noreply(method);
112
113 return;
114}
115
116} // namespace manager
117} // namespace state
Andrew Geisslera965cf02018-08-31 08:37:05 -0700118} // namespace phosphor
Michael Tritz3ed10082017-03-20 23:28:09 -0500119
Michael Tritzd50f6572017-09-05 16:38:11 -0500120int main(int argc, char** argv)
Michael Tritz3ed10082017-03-20 23:28:09 -0500121{
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500122 using namespace phosphor::logging;
123
Michael Tritzd50f6572017-09-05 16:38:11 -0500124 std::string hostPath = "/xyz/openbmc_project/state/host0";
125 int arg;
126 int optIndex = 0;
127
Andrew Geissler58a18012018-01-19 19:36:05 -0800128 static struct option longOpts[] = {{"host", required_argument, 0, 'h'},
129 {0, 0, 0, 0}};
Michael Tritzd50f6572017-09-05 16:38:11 -0500130
Andrew Geissler58a18012018-01-19 19:36:05 -0800131 while ((arg = getopt_long(argc, argv, "h:", longOpts, &optIndex)) != -1)
Michael Tritzd50f6572017-09-05 16:38:11 -0500132 {
133 switch (arg)
134 {
135 case 'h':
Andrew Geissler58a18012018-01-19 19:36:05 -0800136 hostPath =
137 std::string("/xyz/openbmc_project/state/host") + optarg;
Michael Tritzd50f6572017-09-05 16:38:11 -0500138 break;
139 default:
140 break;
141 }
142 }
143
Michael Tritz3ed10082017-03-20 23:28:09 -0500144 auto bus = sdbusplus::bus::new_default();
145
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500146 using namespace settings;
147 Objects settings(bus);
148
Michael Tritz3ed10082017-03-20 23:28:09 -0500149 using namespace phosphor::state::manager;
150 namespace server = sdbusplus::xyz::openbmc_project::State::server;
151
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500152 // This application is only run if chassis power is off
Michael Tritz3ed10082017-03-20 23:28:09 -0500153
Andrew Geissler58a18012018-01-19 19:36:05 -0800154 auto method = bus.new_method_call(
155 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(),
156 settings.powerRestorePolicy.c_str(), "org.freedesktop.DBus.Properties",
157 "Get");
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500158 method.append(powerRestoreIntf, "PowerRestorePolicy");
Anthony Wilson32c532e2018-10-25 21:56:07 -0500159
160 sdbusplus::message::variant<std::string> result;
161 try
Michael Tritz3ed10082017-03-20 23:28:09 -0500162 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500163 auto reply = bus.call(method);
164 reply.read(result);
165 }
166 catch (const SdBusError& e)
167 {
168 log<level::ERR>("Error in PowerRestorePolicy Get",
169 entry("ERROR=%s", e.what()));
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500170 elog<InternalFailure>();
171 }
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500172
William A. Kennington III7a0689a2018-11-12 17:19:33 -0800173 auto powerPolicy = sdbusplus::message::variant_ns::get<std::string>(result);
Michael Tritz3ed10082017-03-20 23:28:09 -0500174
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500175 log<level::INFO>("Host power is off, checking power policy",
176 entry("POWER_POLICY=%s", powerPolicy.c_str()));
Michael Tritz3ed10082017-03-20 23:28:09 -0500177
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500178 if (RestorePolicy::Policy::AlwaysOn ==
179 RestorePolicy::convertPolicyFromString(powerPolicy))
180 {
181 log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
Andrew Geissler58a18012018-01-19 19:36:05 -0800182 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500183 convertForMessage(server::Host::Transition::On));
184 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800185 else if (RestorePolicy::Policy::Restore ==
186 RestorePolicy::convertPolicyFromString(powerPolicy))
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500187 {
188 log<level::INFO>("power_policy=RESTORE, restoring last state");
Michael Tritz3ed10082017-03-20 23:28:09 -0500189
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500190 // Read last requested state and re-request it to execute it
Andrew Geissler58a18012018-01-19 19:36:05 -0800191 auto hostReqState =
192 getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
193 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500194 hostReqState);
Michael Tritz3ed10082017-03-20 23:28:09 -0500195 }
196
197 return 0;
198}