blob: fd3a4671454b2d985abb5ed106df7dd00eefcaf0 [file] [log] [blame]
#pragma once
#include "device.hpp"
#include "sdbusplus/async/proxy.hpp"
#include <boost/asio/steady_timer.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/async/context.hpp>
#include <sdbusplus/timer.hpp>
#include <string>
// This is the base class for the code updater
// Every code updater can inherit from this
class SoftwareManager
{
public:
SoftwareManager(sdbusplus::async::context& ctx,
const std::string& busNameSuffix, bool dryRun);
// @param state desired powerstate (true means on)
// @returns true on success
sdbusplus::async::task<bool> setHostPowerstate(bool state);
// @returns true when powered
// @returns std::nullopt on failure to query power state
sdbusplus::async::task<std::optional<bool>> getHostPowerstate();
// Fetches initial configuration from dbus.
// This should be called once by a code updater at startup.
// It will call 'getInitialConfigurationSingleDevice' for each device
// configured
// @param configurationInterfaces the dbus interfaces from which to fetch
// configuration
sdbusplus::async::task<> getInitialConfiguration(
const std::vector<std::string>& configurationInterfaces);
// request the bus name on dbus after all configuration has been parsed
// and the devices have been initialized
// @returns the name on dbus
std::string setupBusName();
// set of devices found through configuration and probing
std::set<std::unique_ptr<Device>> devices;
protected:
const bool dryRun;
template <typename T>
sdbusplus::async::task<std::optional<T>>
dbusGetRequiredConfigurationProperty(
const std::string& service, const std::string& path,
const std::string& property, DeviceConfig& config)
{
std::string configIface =
"xyz.openbmc_project.Configuration." + config.configType;
std::optional<T> res = co_await dbusGetRequiredProperty<T>(
service, path, configIface, property);
co_return res;
}
// this variant also logs the error
template <typename T>
sdbusplus::async::task<std::optional<T>> dbusGetRequiredProperty(
const std::string& service, const std::string& path,
const std::string& intf, const std::string& property)
{
std::optional<T> opt =
co_await dbusGetProperty<T>(service, path, intf, property);
if (!opt.has_value())
{
lg2::error(
"[config] missing property {PROPERTY} on path {PATH}, interface {INTF}",
"PROPERTY", property, "PATH", path, "INTF", intf);
}
co_return opt;
}
template <typename T>
sdbusplus::async::task<std::optional<T>>
dbusGetProperty(const std::string& service, const std::string& path,
const std::string& intf, const std::string& property)
{
auto client =
sdbusplus::async::proxy().service(service).path(path).interface(
"org.freedesktop.DBus.Properties");
try
{
std::variant<T> result = co_await client.call<std::variant<T>>(
ctx, "Get", intf, property);
T res = std::get<T>(result);
co_return res;
}
catch (std::exception& e)
{
co_return std::nullopt;
}
}
// This function receives a dbus name and object path for a single device,
// which was configured.
// The component code updater overrides this function and may create a
// device instance internally, or reject the configuration as invalid.
// @param service The dbus name where our configuration is
// @param config The common configuration properties which are shared
// by all devices.
// Also includes the object path to fetch other
// configuration properties.
virtual sdbusplus::async::task<> getInitialConfigurationSingleDevice(
const std::string& service, const std::string& path,
DeviceConfig& config) = 0;
sdbusplus::async::context& ctx;
private:
// this is appended to the common prefix to construct the dbus name
std::string busNameSuffix;
sdbusplus::server::manager_t manager;
friend Software;
friend Device;
};