blob: 5ce94b4e2835722674ed2b724c0abb3f77342eeb [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>
7#include <sdbusplus/server.hpp>
8#include <phosphor-logging/log.hpp>
Deepak Kodihalli55f132b2017-07-25 07:36:06 -05009#include <phosphor-logging/elog-errors.hpp>
Michael Tritz3ed10082017-03-20 23:28:09 -050010#include "host_state_manager.hpp"
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050011#include "settings.hpp"
12#include "xyz/openbmc_project/Common/error.hpp"
13#include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
Michael Tritz3ed10082017-03-20 23:28:09 -050014
15namespace phosphor
16{
17namespace state
18{
19namespace manager
20{
21
22using namespace phosphor::logging;
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050023using namespace sdbusplus::xyz::openbmc_project::Common::Error;
24using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
Michael Tritz3ed10082017-03-20 23:28:09 -050025
26constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
27constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
28constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
29
30constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
31
Michael Tritz3ed10082017-03-20 23:28:09 -050032std::string getService(sdbusplus::bus::bus& bus, std::string path,
33 std::string interface)
34{
Andrew Geissler58a18012018-01-19 19:36:05 -080035 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
36 MAPPER_INTERFACE, "GetObject");
Michael Tritz3ed10082017-03-20 23:28:09 -050037
38 mapper.append(path, std::vector<std::string>({interface}));
39 auto mapperResponseMsg = bus.call(mapper);
40
41 if (mapperResponseMsg.is_method_error())
42 {
Andrew Geissler58a18012018-01-19 19:36:05 -080043 log<level::ERR>("Error in mapper call", entry("PATH=%s", path.c_str()),
Michael Tritz3ed10082017-03-20 23:28:09 -050044 entry("INTERFACE=%s", interface.c_str()));
45 throw std::runtime_error("Error in mapper call");
46 }
47
48 std::map<std::string, std::vector<std::string>> mapperResponse;
49 mapperResponseMsg.read(mapperResponse);
50 if (mapperResponse.empty())
51 {
52 log<level::ERR>("Error reading mapper response",
53 entry("PATH=%s", path.c_str()),
54 entry("INTERFACE=%s", interface.c_str()));
55 throw std::runtime_error("Error reading mapper response");
56 }
57
58 return mapperResponse.begin()->first;
59}
60
61std::string getProperty(sdbusplus::bus::bus& bus, std::string path,
62 std::string interface, std::string propertyName)
63{
64 sdbusplus::message::variant<std::string> property;
65 std::string service = getService(bus, path, interface);
66
Andrew Geissler58a18012018-01-19 19:36:05 -080067 auto method = bus.new_method_call(service.c_str(), path.c_str(),
68 PROPERTY_INTERFACE, "Get");
Michael Tritz3ed10082017-03-20 23:28:09 -050069
70 method.append(interface, propertyName);
71 auto reply = bus.call(method);
72
73 if (reply.is_method_error())
74 {
75 log<level::ERR>("Error in property Get",
76 entry("PROPERTY=%s", propertyName.c_str()));
77 throw std::runtime_error("Error in property Get");
78 }
79
80 reply.read(property);
81
82 if (sdbusplus::message::variant_ns::get<std::string>(property).empty())
83 {
84 log<level::ERR>("Error reading property response",
85 entry("PROPERTY=%s", propertyName.c_str()));
86 throw std::runtime_error("Error reading property response");
87 }
88
89 return sdbusplus::message::variant_ns::get<std::string>(property);
90}
91
Patrick Venturef2870592018-10-14 14:11:30 -070092void setProperty(sdbusplus::bus::bus& bus, const std::string& path,
93 const std::string& interface, const std::string& property,
94 const std::string& value)
Michael Tritz3ed10082017-03-20 23:28:09 -050095{
96 sdbusplus::message::variant<std::string> variantValue = value;
97 std::string service = getService(bus, path, interface);
98
Andrew Geissler58a18012018-01-19 19:36:05 -080099 auto method = bus.new_method_call(service.c_str(), path.c_str(),
100 PROPERTY_INTERFACE, "Set");
Michael Tritz3ed10082017-03-20 23:28:09 -0500101
102 method.append(interface, property, variantValue);
103 bus.call_noreply(method);
104
105 return;
106}
107
108} // namespace manager
109} // namespace state
Andrew Geisslera965cf02018-08-31 08:37:05 -0700110} // namespace phosphor
Michael Tritz3ed10082017-03-20 23:28:09 -0500111
Michael Tritzd50f6572017-09-05 16:38:11 -0500112int main(int argc, char** argv)
Michael Tritz3ed10082017-03-20 23:28:09 -0500113{
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500114 using namespace phosphor::logging;
115
Michael Tritzd50f6572017-09-05 16:38:11 -0500116 std::string hostPath = "/xyz/openbmc_project/state/host0";
117 int arg;
118 int optIndex = 0;
119
Andrew Geissler58a18012018-01-19 19:36:05 -0800120 static struct option longOpts[] = {{"host", required_argument, 0, 'h'},
121 {0, 0, 0, 0}};
Michael Tritzd50f6572017-09-05 16:38:11 -0500122
Andrew Geissler58a18012018-01-19 19:36:05 -0800123 while ((arg = getopt_long(argc, argv, "h:", longOpts, &optIndex)) != -1)
Michael Tritzd50f6572017-09-05 16:38:11 -0500124 {
125 switch (arg)
126 {
127 case 'h':
Andrew Geissler58a18012018-01-19 19:36:05 -0800128 hostPath =
129 std::string("/xyz/openbmc_project/state/host") + optarg;
Michael Tritzd50f6572017-09-05 16:38:11 -0500130 break;
131 default:
132 break;
133 }
134 }
135
Michael Tritz3ed10082017-03-20 23:28:09 -0500136 auto bus = sdbusplus::bus::new_default();
137
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500138 using namespace settings;
139 Objects settings(bus);
140
Michael Tritz3ed10082017-03-20 23:28:09 -0500141 using namespace phosphor::state::manager;
142 namespace server = sdbusplus::xyz::openbmc_project::State::server;
143
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500144 // This application is only run if chassis power is off
Michael Tritz3ed10082017-03-20 23:28:09 -0500145
Andrew Geissler58a18012018-01-19 19:36:05 -0800146 auto method = bus.new_method_call(
147 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(),
148 settings.powerRestorePolicy.c_str(), "org.freedesktop.DBus.Properties",
149 "Get");
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500150 method.append(powerRestoreIntf, "PowerRestorePolicy");
151 auto reply = bus.call(method);
152 if (reply.is_method_error())
Michael Tritz3ed10082017-03-20 23:28:09 -0500153 {
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500154 log<level::ERR>("Error in PowerRestorePolicy Get");
155 elog<InternalFailure>();
156 }
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500157
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500158 sdbusplus::message::variant<std::string> result;
159 reply.read(result);
160 auto powerPolicy = result.get<std::string>();
Michael Tritz3ed10082017-03-20 23:28:09 -0500161
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500162 log<level::INFO>("Host power is off, checking power policy",
163 entry("POWER_POLICY=%s", powerPolicy.c_str()));
Michael Tritz3ed10082017-03-20 23:28:09 -0500164
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500165 if (RestorePolicy::Policy::AlwaysOn ==
166 RestorePolicy::convertPolicyFromString(powerPolicy))
167 {
168 log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
Andrew Geissler58a18012018-01-19 19:36:05 -0800169 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500170 convertForMessage(server::Host::Transition::On));
171 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800172 else if (RestorePolicy::Policy::Restore ==
173 RestorePolicy::convertPolicyFromString(powerPolicy))
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500174 {
175 log<level::INFO>("power_policy=RESTORE, restoring last state");
Michael Tritz3ed10082017-03-20 23:28:09 -0500176
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500177 // Read last requested state and re-request it to execute it
Andrew Geissler58a18012018-01-19 19:36:05 -0800178 auto hostReqState =
179 getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
180 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500181 hostReqState);
Michael Tritz3ed10082017-03-20 23:28:09 -0500182 }
183
184 return 0;
185}