blob: c055f9fe6125517e066989e37a090cc89ce4db5d [file] [log] [blame]
#include <iostream>
#include <map>
#include <string>
#include <config.h>
#include <systemd/sd-bus.h>
#include <sdbusplus/server.hpp>
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include "chassis_state_manager.hpp"
#include "host_state_manager.hpp"
#include "settings.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
#include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
namespace phosphor
{
namespace state
{
namespace manager
{
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
constexpr auto HOST_PATH = "/xyz/openbmc_project/state/host0";
constexpr auto CHASSIS_PATH = "/xyz/openbmc_project/state/chassis0";
std::string getService(sdbusplus::bus::bus& bus, std::string path,
std::string interface)
{
auto mapper = bus.new_method_call(MAPPER_BUSNAME,
MAPPER_PATH,
MAPPER_INTERFACE,
"GetObject");
mapper.append(path, std::vector<std::string>({interface}));
auto mapperResponseMsg = bus.call(mapper);
if (mapperResponseMsg.is_method_error())
{
log<level::ERR>("Error in mapper call",
entry("PATH=%s", path.c_str()),
entry("INTERFACE=%s", interface.c_str()));
throw std::runtime_error("Error in mapper call");
}
std::map<std::string, std::vector<std::string>> mapperResponse;
mapperResponseMsg.read(mapperResponse);
if (mapperResponse.empty())
{
log<level::ERR>("Error reading mapper response",
entry("PATH=%s", path.c_str()),
entry("INTERFACE=%s", interface.c_str()));
throw std::runtime_error("Error reading mapper response");
}
return mapperResponse.begin()->first;
}
std::string getProperty(sdbusplus::bus::bus& bus, std::string path,
std::string interface, std::string propertyName)
{
sdbusplus::message::variant<std::string> property;
std::string service = getService(bus, path, interface);
auto method = bus.new_method_call(service.c_str(),
path.c_str(),
PROPERTY_INTERFACE,
"Get");
method.append(interface, propertyName);
auto reply = bus.call(method);
if (reply.is_method_error())
{
log<level::ERR>("Error in property Get",
entry("PROPERTY=%s", propertyName.c_str()));
throw std::runtime_error("Error in property Get");
}
reply.read(property);
if (sdbusplus::message::variant_ns::get<std::string>(property).empty())
{
log<level::ERR>("Error reading property response",
entry("PROPERTY=%s", propertyName.c_str()));
throw std::runtime_error("Error reading property response");
}
return sdbusplus::message::variant_ns::get<std::string>(property);
}
void setProperty(sdbusplus::bus::bus& bus, std::string path,
std::string interface, std::string property, std::string value)
{
sdbusplus::message::variant<std::string> variantValue = value;
std::string service = getService(bus, path, interface);
auto method = bus.new_method_call(service.c_str(),
path.c_str(),
PROPERTY_INTERFACE,
"Set");
method.append(interface, property, variantValue);
bus.call_noreply(method);
return;
}
} // namespace manager
} // namespace state
} // namepsace phosphor
int main()
{
using namespace phosphor::logging;
auto bus = sdbusplus::bus::new_default();
using namespace settings;
Objects settings(bus);
using namespace phosphor::state::manager;
namespace server = sdbusplus::xyz::openbmc_project::State::server;
std::string currentPowerState = getProperty(bus, CHASSIS_PATH,
CHASSIS_BUSNAME,
"CurrentPowerState");
if(currentPowerState == convertForMessage(server::Chassis::PowerState::Off))
{
auto method =
bus.new_method_call(
settings.service(settings.powerRestorePolicy,
powerRestoreIntf).c_str(),
settings.powerRestorePolicy.c_str(),
"org.freedesktop.DBus.Properties",
"Get");
method.append(powerRestoreIntf, "PowerRestorePolicy");
auto reply = bus.call(method);
if (reply.is_method_error())
{
log<level::ERR>("Error in PowerRestorePolicy Get");
elog<InternalFailure>();
}
sdbusplus::message::variant<std::string> result;
reply.read(result);
auto powerPolicy = result.get<std::string>();
log<level::INFO>("Host power is off, checking power policy",
entry("POWER_POLICY=%s", powerPolicy.c_str()));
if (RestorePolicy::Policy::AlwaysOn ==
RestorePolicy::convertPolicyFromString(powerPolicy))
{
log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
setProperty(bus, HOST_PATH, HOST_BUSNAME,
"RequestedHostTransition",
convertForMessage(server::Host::Transition::On));
}
}
return 0;
}