blob: 5348f5f4214ab8ecbb9e8b1276f46c2a6cf47f64 [file] [log] [blame]
#include "LeakDetectionManager.hpp"
#include "LeakGPIODetector.hpp"
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/async.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <sdbusplus/server/manager.hpp>
#include <exception>
#include <functional>
#include <memory>
#include <optional>
#include <string>
PHOSPHOR_LOG2_USING;
namespace leak
{
DetectionManager::DetectionManager(sdbusplus::async::context& ctx) :
ctx(ctx), leakEvents(ctx),
entityManager(
ctx, {GPIODetectorConfigIntf::interface},
std::bind_front(&DetectionManager::processInventoryAdded, this),
std::bind_front(&DetectionManager::processInventoryRemoved, this))
{
ctx.spawn(entityManager.handleInventoryGet());
}
auto DetectionManager::processInventoryAdded(
const sdbusplus::message::object_path& objectPath,
const std::string& /*unused*/) -> void
{
ctx.spawn(processConfigAddedAsync(objectPath));
}
auto DetectionManager::processInventoryRemoved(
const sdbusplus::message::object_path& objectPath,
const std::string& /*unused*/) -> void
{
if (!detectors.contains(objectPath.str))
{
return;
}
debug("Removed detector {DETECTOR}", "DETECTOR", objectPath);
detectors.erase(objectPath.str);
}
auto DetectionManager::processConfigAddedAsync(
sdbusplus::message::object_path objectPath) -> sdbusplus::async::task<>
{
auto res = co_await getDetectorConfig(objectPath);
if (!res)
{
co_return;
}
auto config = res.value();
if (detectors.contains(objectPath.str))
{
warning("Detector {DETECTOR} already exist", "DETECTOR", config.name);
co_return;
}
try
{
detectors[objectPath.str] =
std::make_unique<GPIODetector>(ctx, leakEvents, config);
}
catch (std::exception& e)
{
error("Failed to create detector {DETECTOR}: {ERROR}", "DETECTOR",
config.name, "ERROR", e.what());
}
co_return;
}
auto DetectionManager::getDetectorConfig(
sdbusplus::message::object_path objectPath)
-> sdbusplus::async::task<std::optional<config::DetectorConfig>>
{
config::DetectorConfig config = {};
auto properties =
co_await GPIODetectorConfigIntf(ctx)
.service(entity_manager::EntityManagerInterface::serviceName)
.path(objectPath.str)
.properties();
config.name = properties.name;
for (const auto& [key, value] : config::validDetectorTypes)
{
if (properties.type == key)
{
config.type = value;
break;
}
}
config.pinName = properties.pin_name;
for (const auto& [key, value] : config::validPinPolarity)
{
if (properties.polarity == key)
{
config.polarity = value;
break;
}
}
if (config.polarity == config::PinPolarity::unknown)
{
error("Invalid polarity {POLARITY} for {NAME}", "POLARITY",
properties.polarity, "NAME", config.name);
co_return std::nullopt;
}
for (const auto& [key, value] : config::validDetectorLevel)
{
if (properties.level == key)
{
config.level = value;
break;
}
}
if (config.level == config::DetectorLevel::unknown)
{
error("Invalid level {LEVEL} for {NAME}", "LEVEL", properties.level,
"NAME", config.name);
co_return std::nullopt;
}
debug("Detector config: {NAME} {PIN_NAME} {POLARITY} {LEVEL}", "NAME",
config.name, "PIN_NAME", config.pinName, "POLARITY", config.polarity,
"LEVEL", config.level);
co_return config;
}
} // namespace leak
int main()
{
constexpr auto path = leak::DetectorIntf::namespace_path::value;
constexpr auto serviceName = "xyz.openbmc_project.leakdetector";
sdbusplus::async::context ctx;
sdbusplus::server::manager_t manager{ctx, path};
info("Creating leak detection manager at {PATH}", "PATH", path);
leak::DetectionManager leakDetectionManager{ctx};
ctx.request_name(serviceName);
ctx.run();
return 0;
}