blob: 487f63e3cced24a27a2dd92e25c2c6a979350674 [file] [log] [blame]
#include "software_manager.hpp"
#include "sdbusplus/async/timer.hpp"
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/async.hpp>
#include <sdbusplus/async/context.hpp>
#include <sdbusplus/bus.hpp>
#include <xyz/openbmc_project/Association/Definitions/server.hpp>
#include <xyz/openbmc_project/ObjectMapper/client.hpp>
#include <xyz/openbmc_project/State/Host/client.hpp>
SoftwareManager::SoftwareManager(sdbusplus::async::context& ctx,
const std::string& busNameSuffix,
bool isDryRun) :
dryRun(isDryRun), ctx(ctx), busNameSuffix(busNameSuffix), manager(ctx, "/")
{
lg2::debug("initialized SoftwareManager");
}
std::string SoftwareManager::setupBusName()
{
const std::string serviceNameFull =
"xyz.openbmc_project.Software." + this->busNameSuffix;
lg2::debug("requesting dbus name {BUSNAME}", "BUSNAME", serviceNameFull);
ctx.get_bus().request_name(serviceNameFull.c_str());
return serviceNameFull;
}
// NOLINTBEGIN
sdbusplus::async::task<bool> SoftwareManager::setHostPowerstate(bool state)
// NOLINTEND
{
auto proxy = sdbusplus::async::proxy()
.service("xyz.openbmc_project.State.Host")
.path("/xyz/openbmc_project/state/host0")
.interface("xyz.openbmc_project.State.Host");
lg2::info("[PWR] changing host power state to {STATE}", "STATE",
(state) ? "ON" : "OFF");
std::string voff = "xyz.openbmc_project.State.Host.Transition.Off";
std::string von = "xyz.openbmc_project.State.Host.Transition.On";
std::string targetState;
if (state)
{
co_await proxy.set_property(ctx, "RequestedHostTransition", von);
targetState = "xyz.openbmc_project.State.Host.HostState.Running";
}
else
{
co_await proxy.set_property(ctx, "RequestedHostTransition", voff);
targetState = "xyz.openbmc_project.State.Host.HostState.Off";
}
lg2::debug("[PWR] requested host transition to {STATE}", "STATE",
targetState);
lg2::debug("[PWR] async sleep to wait for state transition");
co_await sdbusplus::async::sleep_for(ctx, std::chrono::seconds(10));
auto actualOpt = co_await getHostPowerstate();
if (actualOpt == std::nullopt)
{
co_return false;
}
const bool actual = actualOpt.value();
if (actual == state)
{
lg2::debug("[PWR] successfully achieved state {STATE}", "STATE",
targetState);
co_return true;
}
else
{
lg2::debug("[PWR] failed to achieve state {STATE}", "STATE",
targetState);
co_return false;
}
}
// NOLINTBEGIN
sdbusplus::async::task<std::optional<bool>> SoftwareManager::getHostPowerstate()
// NOLINTEND
{
auto proxy = sdbusplus::async::proxy()
.service("xyz.openbmc_project.State.Host")
.path("/xyz/openbmc_project/state/host0")
.interface("xyz.openbmc_project.State.Host");
std::string stateOn = "xyz.openbmc_project.State.Host.HostState.Running";
std::string stateOff = "xyz.openbmc_project.State.Host.HostState.Off";
std::string res =
co_await proxy.get_property<std::string>(ctx, "CurrentHostState");
if (res == stateOn)
{
co_return true;
}
else if (res == stateOff)
{
co_return false;
}
lg2::error("[PWR] unexpected power state: {STATE}", "STATE", res);
co_return true;
}
// NOLINTBEGIN
sdbusplus::async::task<> SoftwareManager::getInitialConfiguration(
const std::vector<std::string>& configurationInterfaces)
// NOLINTEND
{
auto client = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>(ctx)
.service("xyz.openbmc_project.ObjectMapper")
.path("/xyz/openbmc_project/object_mapper");
auto res =
co_await client.get_sub_tree("/xyz/openbmc_project/inventory", 0, {});
for (auto& iface : configurationInterfaces)
{
lg2::debug("[config] looking for dbus interface {INTF}", "INTF", iface);
}
for (auto& [path, v] : res)
{
for (auto& [service, interfaceNames] : v)
{
std::string interfaceFound;
for (std::string& interfaceName : interfaceNames)
{
for (auto& iface : configurationInterfaces)
{
if (interfaceName == iface)
{
interfaceFound = interfaceName;
}
}
}
if (interfaceFound.empty())
{
continue;
}
lg2::debug(
"[config] found configuration interface at {SERVICE}, {OBJPATH}",
"SERVICE", service, "OBJPATH", path);
std::optional<uint64_t> optVendorIANA =
co_await SoftwareManager::dbusGetRequiredProperty<uint64_t>(
service, path, interfaceFound, "VendorIANA");
std::optional<std::string> optCompatible =
co_await SoftwareManager::dbusGetRequiredProperty<std::string>(
service, path, interfaceFound, "Compatible");
std::optional<std::string> optEMConfigType =
co_await SoftwareManager::dbusGetRequiredProperty<std::string>(
service, path, interfaceFound, "Type");
std::optional<std::string> optEMConfigName =
co_await SoftwareManager::dbusGetRequiredProperty<std::string>(
service, path, interfaceFound, "Name");
if (!optVendorIANA.has_value() || !optCompatible.has_value() ||
!optEMConfigType.has_value() || !optEMConfigName.has_value())
{
continue;
}
DeviceConfig config(optVendorIANA.value(), optCompatible.value(),
optEMConfigType.value(),
optEMConfigName.value());
co_await getInitialConfigurationSingleDevice(service, path, config);
}
}
lg2::debug("[config] done with initial configuration");
setupBusName();
}