1 #include "config.h" 2 3 #include "host_state_manager.hpp" 4 #include "settings.hpp" 5 #include "utils.hpp" 6 #include "xyz/openbmc_project/Common/error.hpp" 7 #include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp" 8 9 #include <getopt.h> 10 #include <systemd/sd-bus.h> 11 12 #include <phosphor-logging/elog-errors.hpp> 13 #include <phosphor-logging/lg2.hpp> 14 #include <sdbusplus/exception.hpp> 15 #include <sdbusplus/server.hpp> 16 17 #include <iostream> 18 #include <map> 19 #include <string> 20 21 namespace phosphor 22 { 23 namespace state 24 { 25 namespace manager 26 { 27 28 PHOSPHOR_LOG2_USING; 29 30 using namespace phosphor::logging; 31 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 32 using namespace sdbusplus::xyz::openbmc_project::Control::Power::server; 33 34 } // namespace manager 35 } // namespace state 36 } // namespace phosphor 37 38 int main(int argc, char** argv) 39 { 40 using namespace phosphor::logging; 41 42 std::string hostPath = "/xyz/openbmc_project/state/host0"; 43 int arg; 44 int optIndex = 0; 45 46 static struct option longOpts[] = {{"host", required_argument, 0, 'h'}, 47 {0, 0, 0, 0}}; 48 49 while ((arg = getopt_long(argc, argv, "h:", longOpts, &optIndex)) != -1) 50 { 51 switch (arg) 52 { 53 case 'h': 54 hostPath = 55 std::string("/xyz/openbmc_project/state/host") + optarg; 56 break; 57 default: 58 break; 59 } 60 } 61 62 auto bus = sdbusplus::bus::new_default(); 63 64 using namespace settings; 65 Objects settings(bus); 66 67 using namespace phosphor::state::manager; 68 namespace server = sdbusplus::xyz::openbmc_project::State::server; 69 70 // This application is only run if chassis power is off 71 72 /* The logic here is to first check the one-time PowerRestorePolicy setting. 73 * If this property is not the default then look at the persistent 74 * user setting in the non one-time object, otherwise honor the one-time 75 * setting. 76 */ 77 auto methodOneTime = bus.new_method_call( 78 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(), 79 settings.powerRestorePolicyOneTime.c_str(), 80 "org.freedesktop.DBus.Properties", "Get"); 81 methodOneTime.append(powerRestoreIntf, "PowerRestorePolicy"); 82 83 auto methodUserSetting = bus.new_method_call( 84 settings.service(settings.powerRestorePolicy, powerRestoreIntf).c_str(), 85 settings.powerRestorePolicy.c_str(), "org.freedesktop.DBus.Properties", 86 "Get"); 87 methodUserSetting.append(powerRestoreIntf, "PowerRestorePolicy"); 88 89 std::variant<std::string> result; 90 try 91 { 92 auto reply = bus.call(methodOneTime); 93 reply.read(result); 94 auto powerPolicy = std::get<std::string>(result); 95 96 if (RestorePolicy::Policy::None == 97 RestorePolicy::convertPolicyFromString(powerPolicy)) 98 { 99 // one_time is set to None so use the customer setting 100 info("One time not set, check user setting of power policy"); 101 auto reply = bus.call(methodUserSetting); 102 reply.read(result); 103 powerPolicy = std::get<std::string>(result); 104 } 105 else 106 { 107 // one_time setting was set so we're going to use it. Reset it 108 // to default for next time. 109 info("One time set, use it and reset to default"); 110 phosphor::state::manager::utils::setProperty( 111 bus, settings.powerRestorePolicyOneTime.c_str(), 112 powerRestoreIntf, "PowerRestorePolicy", 113 convertForMessage(RestorePolicy::Policy::None)); 114 } 115 116 info("Host power is off, processing power policy {POWER_POLICY}", 117 "POWER_POLICY", powerPolicy); 118 119 if (RestorePolicy::Policy::AlwaysOn == 120 RestorePolicy::convertPolicyFromString(powerPolicy)) 121 { 122 info("power_policy=ALWAYS_POWER_ON, powering host on"); 123 phosphor::state::manager::utils::setProperty( 124 bus, hostPath, HOST_BUSNAME, "RestartCause", 125 convertForMessage( 126 server::Host::RestartCause::PowerPolicyAlwaysOn)); 127 phosphor::state::manager::utils::setProperty( 128 bus, hostPath, HOST_BUSNAME, "RequestedHostTransition", 129 convertForMessage(server::Host::Transition::On)); 130 } 131 else if (RestorePolicy::Policy::AlwaysOff == 132 RestorePolicy::convertPolicyFromString(powerPolicy)) 133 { 134 info("power_policy=ALWAYS_POWER_OFF, set requested state to off"); 135 setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition", 136 convertForMessage(server::Host::Transition::Off)); 137 } 138 else if (RestorePolicy::Policy::Restore == 139 RestorePolicy::convertPolicyFromString(powerPolicy)) 140 { 141 info("power_policy=RESTORE, restoring last state"); 142 phosphor::state::manager::utils::setProperty( 143 bus, hostPath, HOST_BUSNAME, "RestartCause", 144 convertForMessage( 145 server::Host::RestartCause::PowerPolicyPreviousState)); 146 // Read last requested state and re-request it to execute it 147 auto hostReqState = phosphor::state::manager::utils::getProperty( 148 bus, hostPath, HOST_BUSNAME, "RequestedHostTransition"); 149 phosphor::state::manager::utils::setProperty( 150 bus, hostPath, HOST_BUSNAME, "RequestedHostTransition", 151 hostReqState); 152 } 153 } 154 catch (const sdbusplus::exception::exception& e) 155 { 156 error("Error in PowerRestorePolicy Get: {ERROR}", "ERROR", e); 157 elog<InternalFailure>(); 158 } 159 160 return 0; 161 } 162