1 #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>
8 #include "chassis_state_manager.hpp"
9 #include "host_state_manager.hpp"
10 
11 namespace phosphor
12 {
13 namespace state
14 {
15 namespace manager
16 {
17 
18 using namespace phosphor::logging;
19 
20 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
21 constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
22 constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
23 
24 constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
25 
26 constexpr auto HOST_PATH = "/xyz/openbmc_project/state/host0";
27 
28 constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
29 constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
30 
31 constexpr auto CHASSIS_PATH = "/xyz/openbmc_project/state/chassis0";
32 
33 std::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 
65 std::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 
98 void 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 
119 int main()
120 {
121     auto bus = sdbusplus::bus::new_default();
122 
123     using namespace phosphor::state::manager;
124     namespace server = sdbusplus::xyz::openbmc_project::State::server;
125 
126     std::string currentPowerState = getProperty(bus, CHASSIS_PATH,
127                                                 CHASSIS_BUSNAME,
128                                                 "CurrentPowerState");
129 
130     if(currentPowerState == convertForMessage(server::Chassis::PowerState::Off))
131     {
132         std::string power_policy = getProperty(bus, SETTINGS_PATH,
133                                                SETTINGS_INTERFACE,
134                                                "power_policy");
135 
136         log<level::INFO>("Host power is off, checking power policy",
137                          entry("POWER_POLICY=%s", power_policy.c_str()));
138 
139         if (power_policy == "ALWAYS_POWER_ON")
140         {
141             log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
142             setProperty(bus, HOST_PATH, HOST_BUSNAME,
143                         "RequestedHostTransition",
144                         convertForMessage(server::Host::Transition::On));
145         }
146 
147     }
148 
149     return 0;
150 }
151