blob: d403671995a745a6ffc091790f402638171913b9 [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{
35 auto mapper = bus.new_method_call(MAPPER_BUSNAME,
36 MAPPER_PATH,
37 MAPPER_INTERFACE,
38 "GetObject");
39
40 mapper.append(path, std::vector<std::string>({interface}));
41 auto mapperResponseMsg = bus.call(mapper);
42
43 if (mapperResponseMsg.is_method_error())
44 {
45 log<level::ERR>("Error in mapper call",
46 entry("PATH=%s", path.c_str()),
47 entry("INTERFACE=%s", interface.c_str()));
48 throw std::runtime_error("Error in mapper call");
49 }
50
51 std::map<std::string, std::vector<std::string>> mapperResponse;
52 mapperResponseMsg.read(mapperResponse);
53 if (mapperResponse.empty())
54 {
55 log<level::ERR>("Error reading mapper response",
56 entry("PATH=%s", path.c_str()),
57 entry("INTERFACE=%s", interface.c_str()));
58 throw std::runtime_error("Error reading mapper response");
59 }
60
61 return mapperResponse.begin()->first;
62}
63
64std::string getProperty(sdbusplus::bus::bus& bus, std::string path,
65 std::string interface, std::string propertyName)
66{
67 sdbusplus::message::variant<std::string> property;
68 std::string service = getService(bus, path, interface);
69
70 auto method = bus.new_method_call(service.c_str(),
71 path.c_str(),
72 PROPERTY_INTERFACE,
73 "Get");
74
75 method.append(interface, propertyName);
76 auto reply = bus.call(method);
77
78 if (reply.is_method_error())
79 {
80 log<level::ERR>("Error in property Get",
81 entry("PROPERTY=%s", propertyName.c_str()));
82 throw std::runtime_error("Error in property Get");
83 }
84
85 reply.read(property);
86
87 if (sdbusplus::message::variant_ns::get<std::string>(property).empty())
88 {
89 log<level::ERR>("Error reading property response",
90 entry("PROPERTY=%s", propertyName.c_str()));
91 throw std::runtime_error("Error reading property response");
92 }
93
94 return sdbusplus::message::variant_ns::get<std::string>(property);
95}
96
97void setProperty(sdbusplus::bus::bus& bus, std::string path,
98 std::string interface, std::string property, std::string value)
99{
100 sdbusplus::message::variant<std::string> variantValue = value;
101 std::string service = getService(bus, path, interface);
102
103 auto method = bus.new_method_call(service.c_str(),
104 path.c_str(),
105 PROPERTY_INTERFACE,
106 "Set");
107
108 method.append(interface, property, variantValue);
109 bus.call_noreply(method);
110
111 return;
112}
113
114} // namespace manager
115} // namespace state
116} // namepsace phosphor
117
Michael Tritzd50f6572017-09-05 16:38:11 -0500118int main(int argc, char** argv)
Michael Tritz3ed10082017-03-20 23:28:09 -0500119{
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500120 using namespace phosphor::logging;
121
Michael Tritzd50f6572017-09-05 16:38:11 -0500122 std::string hostPath = "/xyz/openbmc_project/state/host0";
123 int arg;
124 int optIndex = 0;
125
126 static struct option longOpts[] =
127 {
128 {"host", required_argument, 0, 'h'},
129 {0, 0, 0, 0}
130 };
131
132 while((arg = getopt_long(argc, argv, "h:", longOpts, &optIndex)) != -1)
133 {
134 switch (arg)
135 {
136 case 'h':
137 hostPath = std::string("/xyz/openbmc_project/state/host") +
138 optarg;
139 break;
140 default:
141 break;
142 }
143 }
144
Michael Tritz3ed10082017-03-20 23:28:09 -0500145 auto bus = sdbusplus::bus::new_default();
146
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500147 using namespace settings;
148 Objects settings(bus);
149
Michael Tritz3ed10082017-03-20 23:28:09 -0500150 using namespace phosphor::state::manager;
151 namespace server = sdbusplus::xyz::openbmc_project::State::server;
152
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500153 // This application is only run if chassis power is off
Michael Tritz3ed10082017-03-20 23:28:09 -0500154
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500155 auto method =
156 bus.new_method_call(
157 settings.service(settings.powerRestorePolicy,
158 powerRestoreIntf).c_str(),
159 settings.powerRestorePolicy.c_str(),
160 "org.freedesktop.DBus.Properties",
161 "Get");
162 method.append(powerRestoreIntf, "PowerRestorePolicy");
163 auto reply = bus.call(method);
164 if (reply.is_method_error())
Michael Tritz3ed10082017-03-20 23:28:09 -0500165 {
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500166 log<level::ERR>("Error in PowerRestorePolicy Get");
167 elog<InternalFailure>();
168 }
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500169
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500170 sdbusplus::message::variant<std::string> result;
171 reply.read(result);
172 auto powerPolicy = result.get<std::string>();
Michael Tritz3ed10082017-03-20 23:28:09 -0500173
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500174 log<level::INFO>("Host power is off, checking power policy",
175 entry("POWER_POLICY=%s", powerPolicy.c_str()));
Michael Tritz3ed10082017-03-20 23:28:09 -0500176
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500177 if (RestorePolicy::Policy::AlwaysOn ==
178 RestorePolicy::convertPolicyFromString(powerPolicy))
179 {
180 log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
Michael Tritzd50f6572017-09-05 16:38:11 -0500181 setProperty(bus, hostPath, HOST_BUSNAME,
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500182 "RequestedHostTransition",
183 convertForMessage(server::Host::Transition::On));
184 }
185 else if(RestorePolicy::Policy::Restore ==
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500186 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
Michael Tritzd50f6572017-09-05 16:38:11 -0500191 auto hostReqState = getProperty(bus, hostPath,
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500192 HOST_BUSNAME,
193 "RequestedHostTransition");
Michael Tritzd50f6572017-09-05 16:38:11 -0500194 setProperty(bus, hostPath, HOST_BUSNAME,
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500195 "RequestedHostTransition",
196 hostReqState);
Michael Tritz3ed10082017-03-20 23:28:09 -0500197 }
198
199 return 0;
200}