blob: 303b4a432a10123bc178b96eb41fce5c7236b5ad [file] [log] [blame]
Michael Tritz3ed10082017-03-20 23:28:09 -05001#include <iostream>
2#include <map>
3#include <string>
4#include <config.h>
5#include <systemd/sd-bus.h>
6#include <sdbusplus/server.hpp>
7#include <phosphor-logging/log.hpp>
Deepak Kodihalli55f132b2017-07-25 07:36:06 -05008#include <phosphor-logging/elog-errors.hpp>
Michael Tritz3ed10082017-03-20 23:28:09 -05009#include "host_state_manager.hpp"
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050010#include "settings.hpp"
11#include "xyz/openbmc_project/Common/error.hpp"
12#include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
Michael Tritz3ed10082017-03-20 23:28:09 -050013
14namespace phosphor
15{
16namespace state
17{
18namespace manager
19{
20
21using namespace phosphor::logging;
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050022using namespace sdbusplus::xyz::openbmc_project::Common::Error;
23using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
Michael Tritz3ed10082017-03-20 23:28:09 -050024
25constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
26constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
27constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
28
29constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
30
31constexpr auto HOST_PATH = "/xyz/openbmc_project/state/host0";
32
Michael Tritz3ed10082017-03-20 23:28:09 -050033std::string getService(sdbusplus::bus::bus& bus, std::string path,
34 std::string interface)
35{
36 auto mapper = bus.new_method_call(MAPPER_BUSNAME,
37 MAPPER_PATH,
38 MAPPER_INTERFACE,
39 "GetObject");
40
41 mapper.append(path, std::vector<std::string>({interface}));
42 auto mapperResponseMsg = bus.call(mapper);
43
44 if (mapperResponseMsg.is_method_error())
45 {
46 log<level::ERR>("Error in mapper call",
47 entry("PATH=%s", path.c_str()),
48 entry("INTERFACE=%s", interface.c_str()));
49 throw std::runtime_error("Error in mapper call");
50 }
51
52 std::map<std::string, std::vector<std::string>> mapperResponse;
53 mapperResponseMsg.read(mapperResponse);
54 if (mapperResponse.empty())
55 {
56 log<level::ERR>("Error reading mapper response",
57 entry("PATH=%s", path.c_str()),
58 entry("INTERFACE=%s", interface.c_str()));
59 throw std::runtime_error("Error reading mapper response");
60 }
61
62 return mapperResponse.begin()->first;
63}
64
65std::string getProperty(sdbusplus::bus::bus& bus, std::string path,
66 std::string interface, std::string propertyName)
67{
68 sdbusplus::message::variant<std::string> property;
69 std::string service = getService(bus, path, interface);
70
71 auto method = bus.new_method_call(service.c_str(),
72 path.c_str(),
73 PROPERTY_INTERFACE,
74 "Get");
75
76 method.append(interface, propertyName);
77 auto reply = bus.call(method);
78
79 if (reply.is_method_error())
80 {
81 log<level::ERR>("Error in property Get",
82 entry("PROPERTY=%s", propertyName.c_str()));
83 throw std::runtime_error("Error in property Get");
84 }
85
86 reply.read(property);
87
88 if (sdbusplus::message::variant_ns::get<std::string>(property).empty())
89 {
90 log<level::ERR>("Error reading property response",
91 entry("PROPERTY=%s", propertyName.c_str()));
92 throw std::runtime_error("Error reading property response");
93 }
94
95 return sdbusplus::message::variant_ns::get<std::string>(property);
96}
97
98void setProperty(sdbusplus::bus::bus& bus, std::string path,
99 std::string interface, std::string property, std::string value)
100{
101 sdbusplus::message::variant<std::string> variantValue = value;
102 std::string service = getService(bus, path, interface);
103
104 auto method = bus.new_method_call(service.c_str(),
105 path.c_str(),
106 PROPERTY_INTERFACE,
107 "Set");
108
109 method.append(interface, property, variantValue);
110 bus.call_noreply(method);
111
112 return;
113}
114
115} // namespace manager
116} // namespace state
117} // namepsace phosphor
118
119int main()
120{
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500121 using namespace phosphor::logging;
122
Michael Tritz3ed10082017-03-20 23:28:09 -0500123 auto bus = sdbusplus::bus::new_default();
124
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500125 using namespace settings;
126 Objects settings(bus);
127
Michael Tritz3ed10082017-03-20 23:28:09 -0500128 using namespace phosphor::state::manager;
129 namespace server = sdbusplus::xyz::openbmc_project::State::server;
130
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500131 // This application is only run if chassis power is off
Michael Tritz3ed10082017-03-20 23:28:09 -0500132
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500133 auto method =
134 bus.new_method_call(
135 settings.service(settings.powerRestorePolicy,
136 powerRestoreIntf).c_str(),
137 settings.powerRestorePolicy.c_str(),
138 "org.freedesktop.DBus.Properties",
139 "Get");
140 method.append(powerRestoreIntf, "PowerRestorePolicy");
141 auto reply = bus.call(method);
142 if (reply.is_method_error())
Michael Tritz3ed10082017-03-20 23:28:09 -0500143 {
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500144 log<level::ERR>("Error in PowerRestorePolicy Get");
145 elog<InternalFailure>();
146 }
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500147
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500148 sdbusplus::message::variant<std::string> result;
149 reply.read(result);
150 auto powerPolicy = result.get<std::string>();
Michael Tritz3ed10082017-03-20 23:28:09 -0500151
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500152 log<level::INFO>("Host power is off, checking power policy",
153 entry("POWER_POLICY=%s", powerPolicy.c_str()));
Michael Tritz3ed10082017-03-20 23:28:09 -0500154
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500155 if (RestorePolicy::Policy::AlwaysOn ==
156 RestorePolicy::convertPolicyFromString(powerPolicy))
157 {
158 log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
159 setProperty(bus, HOST_PATH, HOST_BUSNAME,
160 "RequestedHostTransition",
161 convertForMessage(server::Host::Transition::On));
162 }
163 else if(RestorePolicy::Policy::Restore ==
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500164 RestorePolicy::convertPolicyFromString(powerPolicy))
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500165 {
166 log<level::INFO>("power_policy=RESTORE, restoring last state");
Michael Tritz3ed10082017-03-20 23:28:09 -0500167
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500168 // Read last requested state and re-request it to execute it
169 auto hostReqState = getProperty(bus, HOST_PATH,
170 HOST_BUSNAME,
171 "RequestedHostTransition");
172 setProperty(bus, HOST_PATH, HOST_BUSNAME,
173 "RequestedHostTransition",
174 hostReqState);
Michael Tritz3ed10082017-03-20 23:28:09 -0500175 }
176
177 return 0;
178}