xref: /openbmc/phosphor-bmc-code-mgmt/common/src/host_power.cpp (revision 994a77ff25aeb28b2cce7142d081af767f9eb542)
1 #include "host_power.hpp"
2 
3 #include <phosphor-logging/lg2.hpp>
4 #include <sdbusplus/async.hpp>
5 #include <sdbusplus/async/context.hpp>
6 #include <sdbusplus/async/match.hpp>
7 #include <sdbusplus/async/proxy.hpp>
8 #include <sdbusplus/bus/match.hpp>
9 #include <sdbusplus/message/native_types.hpp>
10 #include <xyz/openbmc_project/ObjectMapper/client.hpp>
11 #include <xyz/openbmc_project/State/Host/client.hpp>
12 
13 PHOSPHOR_LOG2_USING;
14 
15 using namespace std::literals;
16 
17 namespace RulesIntf = sdbusplus::bus::match::rules;
18 
19 using StateIntf =
20     sdbusplus::client::xyz::openbmc_project::state::Host<void, void>;
21 
22 const auto transitionOn =
23     sdbusplus::client::xyz::openbmc_project::state::Host<>::Transition::On;
24 const auto transitionOff =
25     sdbusplus::client::xyz::openbmc_project::state::Host<>::Transition::Off;
26 
27 namespace phosphor::software::host_power
28 {
29 
30 const auto host0ObjectPath = sdbusplus::client::xyz::openbmc_project::state::
31                                  Host<>::namespace_path::value +
32                              std::string("/host0");
33 
34 constexpr const char* service = "xyz.openbmc_project.State.Host";
35 
36 HostPower::HostPower(sdbusplus::async::context& ctx) :
37     stateChangedMatch(ctx, RulesIntf::propertiesChanged(host0ObjectPath,
38                                                         StateIntf::interface))
39 {}
40 
41 // NOLINTBEGIN(readability-static-accessed-through-instance)
42 sdbusplus::async::task<bool> HostPower::setState(sdbusplus::async::context& ctx,
43                                                  HostState state)
44 // NOLINTEND(readability-static-accessed-through-instance)
45 {
46     if (state != stateOn && state != stateOff)
47     {
48         error("Invalid power state {STATE}", "STATE", state);
49         co_return false;
50     }
51 
52     auto client = sdbusplus::client::xyz::openbmc_project::state::Host(ctx)
53                       .service(service)
54                       .path(host0ObjectPath);
55 
56     co_await client.requested_host_transition(
57         (state == stateOn) ? transitionOn : transitionOff);
58 
59     debug("Requested host transition to {STATE}", "STATE", state);
60 
61     constexpr size_t retries = 4;
62     constexpr size_t retryTimeout = 3;
63 
64     for (size_t i = 0; i < retries; i++)
65     {
66         co_await sdbusplus::async::sleep_for(
67             ctx, std::chrono::seconds(retryTimeout));
68 
69         if ((co_await client.current_host_state()) == state)
70         {
71             debug("Successfully achieved state {STATE}", "STATE", state);
72             co_return true;
73         }
74     }
75 
76     error("Failed to achieve state {STATE} before the timeout of {TIMEOUT}s",
77           "STATE", state, "TIMEOUT", retries * retryTimeout);
78 
79     co_return false;
80 }
81 
82 // NOLINTBEGIN(readability-static-accessed-through-instance)
83 sdbusplus::async::task<HostState> HostPower::getState(
84     sdbusplus::async::context& ctx)
85 // NOLINTEND(readability-static-accessed-through-instance)
86 {
87     auto client = sdbusplus::client::xyz::openbmc_project::state::Host(ctx)
88                       .service(service)
89                       .path(host0ObjectPath);
90 
91     auto res = co_await client.current_host_state();
92 
93     if (res != stateOn && res != stateOff)
94     {
95         error("Unexpected power state: {STATE}", "STATE", res);
96     }
97 
98     co_return res;
99 }
100 
101 } // namespace phosphor::software::host_power
102