blob: 3be873323eae349d67a16870e29fc89ad88b2505 [file] [log] [blame]
Andrew Geissler769a62f2019-12-06 13:36:08 -06001#include "config.h"
Andrew Geisslere426b582020-05-28 12:40:55 -05002
Michael Tritz3ed10082017-03-20 23:28:09 -05003#include "host_state_manager.hpp"
Deepak Kodihalli55f132b2017-07-25 07:36:06 -05004#include "settings.hpp"
Andrew Geissler49e67132022-01-26 14:27:52 -06005#include "utils.hpp"
Deepak Kodihalli55f132b2017-07-25 07:36:06 -05006#include "xyz/openbmc_project/Common/error.hpp"
7#include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
Michael Tritz3ed10082017-03-20 23:28:09 -05008
Andrew Geisslere426b582020-05-28 12:40:55 -05009#include <getopt.h>
10#include <systemd/sd-bus.h>
11
12#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler8ffdb262021-09-20 15:25:19 -050013#include <phosphor-logging/lg2.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -050014#include <sdbusplus/exception.hpp>
15#include <sdbusplus/server.hpp>
Patrick Williams9a286db2024-01-17 06:29:47 -060016#include <xyz/openbmc_project/State/BMC/client.hpp>
17#include <xyz/openbmc_project/State/Host/client.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -050018
NodeMan97bcbee4a2022-05-27 15:28:45 -050019#include <filesystem>
Andrew Geisslere426b582020-05-28 12:40:55 -050020#include <iostream>
21#include <map>
22#include <string>
NodeMan97358de952022-07-20 08:31:36 -050023#include <thread>
Andrew Geisslere426b582020-05-28 12:40:55 -050024
Michael Tritz3ed10082017-03-20 23:28:09 -050025namespace phosphor
26{
27namespace state
28{
29namespace manager
30{
31
Andrew Geissler8ffdb262021-09-20 15:25:19 -050032PHOSPHOR_LOG2_USING;
33
Michael Tritz3ed10082017-03-20 23:28:09 -050034using namespace phosphor::logging;
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050035using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Patrick Williams7e969cb2023-08-23 16:24:23 -050036using namespace sdbusplus::server::xyz::openbmc_project::control::power;
Amithash Prasasdf566c962024-07-22 20:28:42 -070037using HostState = sdbusplus::client::xyz::openbmc_project::state::Host<>;
38using BMCState = sdbusplus::client::xyz::openbmc_project::state::BMC<>;
Michael Tritz3ed10082017-03-20 23:28:09 -050039
Michael Tritz3ed10082017-03-20 23:28:09 -050040} // namespace manager
41} // namespace state
Andrew Geisslera965cf02018-08-31 08:37:05 -070042} // namespace phosphor
Michael Tritz3ed10082017-03-20 23:28:09 -050043
Michael Tritzd50f6572017-09-05 16:38:11 -050044int main(int argc, char** argv)
Michael Tritz3ed10082017-03-20 23:28:09 -050045{
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050046 using namespace phosphor::logging;
47
Ramya Sivakumarc4b6f032026-01-27 16:03:23 +053048 constexpr auto dbusPropertiesInterface = "org.freedesktop.DBus.Properties";
49
Potin Laic328a4c2022-03-18 23:49:37 +080050 size_t hostId = 0;
Michael Tritzd50f6572017-09-05 16:38:11 -050051 int arg;
52 int optIndex = 0;
53
Pavithra Barithayaf15b9542024-06-21 08:18:48 -050054 static struct option longOpts[] = {
55 {"host", required_argument, nullptr, 'h'}, {nullptr, 0, nullptr, 0}};
Michael Tritzd50f6572017-09-05 16:38:11 -050056
Andrew Geissler58a18012018-01-19 19:36:05 -080057 while ((arg = getopt_long(argc, argv, "h:", longOpts, &optIndex)) != -1)
Michael Tritzd50f6572017-09-05 16:38:11 -050058 {
59 switch (arg)
60 {
61 case 'h':
Potin Laic328a4c2022-03-18 23:49:37 +080062 hostId = std::stoul(optarg);
Michael Tritzd50f6572017-09-05 16:38:11 -050063 break;
64 default:
65 break;
66 }
67 }
68
Patrick Williams9a286db2024-01-17 06:29:47 -060069 using Host = sdbusplus::client::xyz::openbmc_project::state::Host<>;
Patrick Williams1b2c3c02024-08-16 15:20:29 -040070 std::string hostPath =
71 std::string(Host::namespace_path::value) + "/" +
72 std::string(Host::namespace_path::host) + std::to_string(hostId);
Patrick Williams9a286db2024-01-17 06:29:47 -060073
Michael Tritz3ed10082017-03-20 23:28:09 -050074 auto bus = sdbusplus::bus::new_default();
75
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050076 using namespace settings;
Potin Laic328a4c2022-03-18 23:49:37 +080077 HostObjects settings(bus, hostId);
Deepak Kodihalli55f132b2017-07-25 07:36:06 -050078
Michael Tritz3ed10082017-03-20 23:28:09 -050079 using namespace phosphor::state::manager;
Patrick Williams7e969cb2023-08-23 16:24:23 -050080 namespace server = sdbusplus::server::xyz::openbmc_project::state;
Michael Tritz3ed10082017-03-20 23:28:09 -050081
Andrew Geissler033fc3b2017-08-30 15:11:44 -050082 // This application is only run if chassis power is off
Michael Tritz3ed10082017-03-20 23:28:09 -050083
Andrew Geisslerb2b3d9c2022-01-26 14:45:10 -060084 // If the BMC was rebooted due to a user initiated pinhole reset, do not
85 // implement any power restore policies
Patrick Williams9a286db2024-01-17 06:29:47 -060086 using BMC = sdbusplus::client::xyz::openbmc_project::state::BMC<>;
87 auto bmcPath = sdbusplus::message::object_path(BMC::namespace_path::value) /
88 BMC::namespace_path::bmc;
89
Thang Tranff85df62025-05-07 13:40:43 +070090#if !(RUN_APR_ON_PINHOLE_RESET && RUN_APR_ON_WATCHDOG_RESET && \
91 RUN_APR_ON_SOFTWARE_RESET)
Patrick Williams9a286db2024-01-17 06:29:47 -060092 auto bmcRebootCause =
93 sdbusplus::message::convert_from_string<BMC::RebootCause>(
94 phosphor::state::manager::utils::getProperty(
Alexander Hansen0e38d192025-10-22 16:04:01 +020095 bus, bmcPath.str, BMCState::interface,
96 BMCState::property_names::last_reboot_cause));
Patrick Williams9a286db2024-01-17 06:29:47 -060097
Thang Tranff85df62025-05-07 13:40:43 +070098#if !RUN_APR_ON_PINHOLE_RESET
Patrick Williams9a286db2024-01-17 06:29:47 -060099 if (bmcRebootCause == BMC::RebootCause::PinholeReset)
Andrew Geisslerb2b3d9c2022-01-26 14:45:10 -0600100 {
101 info(
102 "BMC was reset due to pinhole reset, no power restore policy will be run");
103 return 0;
104 }
Thang Tranff85df62025-05-07 13:40:43 +0700105#endif // RUN_APR_ON_PINHOLE_RESET
106
107#if !RUN_APR_ON_WATCHDOG_RESET
108 if (bmcRebootCause == BMC::RebootCause::Watchdog)
109 {
110 info(
111 "BMC was reset due to watchdog, no power restore policy will be run");
112 return 0;
113 }
114#endif // RUN_APR_ON_WATCHDOG_RESET
115
116#if !RUN_APR_ON_SOFTWARE_RESET
117 if (bmcRebootCause == BMC::RebootCause::Software)
Thang Q. Nguyenb669ea32022-02-22 07:15:15 +0000118 {
119 info(
120 "BMC was reset due to cold reset, no power restore policy will be run");
121 return 0;
122 }
Thang Tranff85df62025-05-07 13:40:43 +0700123#endif // RUN_APR_ON_SOFTWARE_RESET
124#endif
Andrew Geisslerb2b3d9c2022-01-26 14:45:10 -0600125
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600126 /* The logic here is to first check the one-time PowerRestorePolicy setting.
127 * If this property is not the default then look at the persistent
128 * user setting in the non one-time object, otherwise honor the one-time
129 * setting.
130 */
131 auto methodOneTime = bus.new_method_call(
132 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(),
Ramya Sivakumarc4b6f032026-01-27 16:03:23 +0530133 settings.powerRestorePolicyOneTime.c_str(), dbusPropertiesInterface,
134 "Get");
Alexander Hansen0e38d192025-10-22 16:04:01 +0200135 methodOneTime.append(
136 powerRestoreIntf,
137 PowerRestorePolicy::property_names::power_restore_policy);
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600138
139 auto methodUserSetting = bus.new_method_call(
Andrew Geissler58a18012018-01-19 19:36:05 -0800140 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(),
Ramya Sivakumarc4b6f032026-01-27 16:03:23 +0530141 settings.powerRestorePolicy.c_str(), dbusPropertiesInterface, "Get");
Alexander Hansen0e38d192025-10-22 16:04:01 +0200142 methodUserSetting.append(
143 powerRestoreIntf,
144 PowerRestorePolicy::property_names::power_restore_policy);
Anthony Wilson32c532e2018-10-25 21:56:07 -0500145
Patrick Williams2975e262020-05-13 18:01:09 -0500146 std::variant<std::string> result;
Anthony Wilson32c532e2018-10-25 21:56:07 -0500147 try
Michael Tritz3ed10082017-03-20 23:28:09 -0500148 {
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600149 auto reply = bus.call(methodOneTime);
Anthony Wilson32c532e2018-10-25 21:56:07 -0500150 reply.read(result);
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600151 auto powerPolicy = std::get<std::string>(result);
152
153 if (RestorePolicy::Policy::None ==
154 RestorePolicy::convertPolicyFromString(powerPolicy))
155 {
156 // one_time is set to None so use the customer setting
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500157 info("One time not set, check user setting of power policy");
NodeMan97bcbee4a2022-05-27 15:28:45 -0500158
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600159 auto reply = bus.call(methodUserSetting);
160 reply.read(result);
161 powerPolicy = std::get<std::string>(result);
162 }
163 else
164 {
165 // one_time setting was set so we're going to use it. Reset it
166 // to default for next time.
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500167 info("One time set, use it and reset to default");
Andrew Geissler49e67132022-01-26 14:27:52 -0600168 phosphor::state::manager::utils::setProperty(
Pavithra Barithaya695888d2024-06-21 12:01:30 -0500169 bus, settings.powerRestorePolicyOneTime, powerRestoreIntf,
Alexander Hansen0e38d192025-10-22 16:04:01 +0200170 PowerRestorePolicy::property_names::power_restore_policy,
Andrew Geissler49e67132022-01-26 14:27:52 -0600171 convertForMessage(RestorePolicy::Policy::None));
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600172 }
173
NodeMan97358de952022-07-20 08:31:36 -0500174 auto methodUserSettingDelay = bus.new_method_call(
175 settings.service(settings.powerRestorePolicy, powerRestoreIntf)
176 .c_str(),
Ramya Sivakumarc4b6f032026-01-27 16:03:23 +0530177 settings.powerRestorePolicy.c_str(), dbusPropertiesInterface,
178 "Get");
NodeMan97358de952022-07-20 08:31:36 -0500179
Alexander Hansen0e38d192025-10-22 16:04:01 +0200180 methodUserSettingDelay.append(
181 powerRestoreIntf,
182 PowerRestorePolicy::property_names::power_restore_delay);
NodeMan97358de952022-07-20 08:31:36 -0500183
184 std::variant<uint64_t> restoreDelay;
185
186 auto delayResult = bus.call(methodUserSettingDelay);
187 delayResult.read(restoreDelay);
188 auto powerRestoreDelayUsec =
189 std::chrono::microseconds(std::get<uint64_t>(restoreDelay));
190 auto powerRestoreDelaySec =
191 std::chrono::duration_cast<std::chrono::seconds>(
192 powerRestoreDelayUsec);
193
Zoey YJ Chung840ac402025-08-29 13:09:01 +0800194 info(
195 "Host{HOST_ID} power is off, processing power policy {POWER_POLICY}",
196 "HOST_ID", hostId, "POWER_POLICY", powerPolicy);
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600197
198 if (RestorePolicy::Policy::AlwaysOn ==
199 RestorePolicy::convertPolicyFromString(powerPolicy))
200 {
NodeMan97358de952022-07-20 08:31:36 -0500201 info(
Zoey YJ Chung840ac402025-08-29 13:09:01 +0800202 "power_policy=ALWAYS_POWER_ON, powering host{HOST_ID} on ({DELAY}s delay)",
203 "HOST_ID", hostId, "DELAY", powerRestoreDelaySec.count());
Prithvi Pai3d506282025-02-01 12:31:01 +0530204#ifdef APPLY_POWER_POLICY_WHEN_BMC_READY
Potin Lai08865452023-11-07 23:28:11 +0800205 utils::waitBmcReady(bus, powerRestoreDelaySec);
Prithvi Pai3d506282025-02-01 12:31:01 +0530206#else
207 std::this_thread::sleep_for(powerRestoreDelayUsec);
208#endif
Andrew Geissler49e67132022-01-26 14:27:52 -0600209 phosphor::state::manager::utils::setProperty(
Alexander Hansen0e38d192025-10-22 16:04:01 +0200210 bus, hostPath, HostState::interface,
211 HostState::property_names::restart_cause,
Andrew Geissler49e67132022-01-26 14:27:52 -0600212 convertForMessage(
213 server::Host::RestartCause::PowerPolicyAlwaysOn));
214 phosphor::state::manager::utils::setProperty(
Alexander Hansen0e38d192025-10-22 16:04:01 +0200215 bus, hostPath, HostState::interface,
216 HostState::property_names::requested_host_transition,
Andrew Geissler49e67132022-01-26 14:27:52 -0600217 convertForMessage(server::Host::Transition::On));
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600218 }
Andrew Geissler70b48f32022-08-18 11:48:24 -0400219 // Always execute power on if AlwaysOn is set, otherwise check config
220 // option (and AC loss status) on whether to execute other policy
221 // settings
Potin Laie9601842023-03-03 17:23:28 +0800222#if ONLY_RUN_APR_ON_POWER_LOSS
Andrew Geissler70b48f32022-08-18 11:48:24 -0400223 else if (!phosphor::state::manager::utils::checkACLoss(hostId))
224 {
225 info(
226 "Chassis power was not on prior to BMC reboot so do not run any further power policy");
227 return 0;
228 }
229#endif
Thang Tran1fc48452022-02-08 16:04:11 +0700230 else if (RestorePolicy::Policy::AlwaysOff ==
231 RestorePolicy::convertPolicyFromString(powerPolicy))
232 {
NodeMan97358de952022-07-20 08:31:36 -0500233 info(
234 "power_policy=ALWAYS_POWER_OFF, set requested state to off ({DELAY}s delay)",
235 "DELAY", powerRestoreDelaySec.count());
Prithvi Pai3d506282025-02-01 12:31:01 +0530236#ifdef APPLY_POWER_POLICY_WHEN_BMC_READY
Potin Lai08865452023-11-07 23:28:11 +0800237 utils::waitBmcReady(bus, powerRestoreDelaySec);
Prithvi Pai3d506282025-02-01 12:31:01 +0530238#else
239 std::this_thread::sleep_for(powerRestoreDelayUsec);
240#endif
Thang Tran6810ad52022-02-24 09:36:57 +0700241 // Read last requested state and re-request it to execute it
242 auto hostReqState = phosphor::state::manager::utils::getProperty(
Alexander Hansen0e38d192025-10-22 16:04:01 +0200243 bus, hostPath, HostState::interface,
244 HostState::property_names::requested_host_transition);
NodeMan97744fe622022-07-21 17:14:23 -0500245 if (hostReqState !=
246 convertForMessage(server::Host::Transition::Off))
Thang Tran6810ad52022-02-24 09:36:57 +0700247 {
248 phosphor::state::manager::utils::setProperty(
Amithash Prasasdf566c962024-07-22 20:28:42 -0700249 bus, hostPath, HostState::interface,
Alexander Hansen0e38d192025-10-22 16:04:01 +0200250 HostState::property_names::requested_host_transition,
Thang Tran6810ad52022-02-24 09:36:57 +0700251 convertForMessage(server::Host::Transition::Off));
252 }
Thang Tran1fc48452022-02-08 16:04:11 +0700253 }
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600254 else if (RestorePolicy::Policy::Restore ==
255 RestorePolicy::convertPolicyFromString(powerPolicy))
256 {
NodeMan97358de952022-07-20 08:31:36 -0500257 info("power_policy=RESTORE, restoring last state ({DELAY}s delay)",
258 "DELAY", powerRestoreDelaySec.count());
Prithvi Pai3d506282025-02-01 12:31:01 +0530259#ifdef APPLY_POWER_POLICY_WHEN_BMC_READY
Potin Lai08865452023-11-07 23:28:11 +0800260 utils::waitBmcReady(bus, powerRestoreDelaySec);
Prithvi Pai3d506282025-02-01 12:31:01 +0530261#else
262 std::this_thread::sleep_for(powerRestoreDelayUsec);
263#endif
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600264 // Read last requested state and re-request it to execute it
Andrew Geissler49e67132022-01-26 14:27:52 -0600265 auto hostReqState = phosphor::state::manager::utils::getProperty(
Alexander Hansen0e38d192025-10-22 16:04:01 +0200266 bus, hostPath, HostState::interface,
267 HostState::property_names::requested_host_transition);
NodeMan97744fe622022-07-21 17:14:23 -0500268
269 // As long as the host transition is not 'Off' power on host state.
270 if (hostReqState !=
271 convertForMessage(server::Host::Transition::Off))
Thang Tran6810ad52022-02-24 09:36:57 +0700272 {
273 phosphor::state::manager::utils::setProperty(
Alexander Hansen0e38d192025-10-22 16:04:01 +0200274 bus, hostPath, HostState::interface,
275 HostState::property_names::restart_cause,
Thang Tran6810ad52022-02-24 09:36:57 +0700276 convertForMessage(
277 server::Host::RestartCause::PowerPolicyPreviousState));
278 phosphor::state::manager::utils::setProperty(
Amithash Prasasdf566c962024-07-22 20:28:42 -0700279 bus, hostPath, HostState::interface,
Alexander Hansen0e38d192025-10-22 16:04:01 +0200280 HostState::property_names::requested_host_transition,
NodeMan97744fe622022-07-21 17:14:23 -0500281 convertForMessage(server::Host::Transition::On));
Thang Tran6810ad52022-02-24 09:36:57 +0700282 }
Andrew Geissler35ca2e32021-02-09 13:54:26 -0600283 }
Anthony Wilson32c532e2018-10-25 21:56:07 -0500284 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500285 catch (const sdbusplus::exception_t& e)
Anthony Wilson32c532e2018-10-25 21:56:07 -0500286 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500287 error("Error in PowerRestorePolicy Get: {ERROR}", "ERROR", e);
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500288 elog<InternalFailure>();
289 }
Deepak Kodihalli55f132b2017-07-25 07:36:06 -0500290
Michael Tritz3ed10082017-03-20 23:28:09 -0500291 return 0;
292}