blob: f21d1b5e10816cd15859130eb83bb301c6573197 [file] [log] [blame]
#include "LeakGPIODetector.hpp"
#include "LeakEvents.hpp"
#include "SystemdInterface.hpp"
#include <sdbusplus/async.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <array>
#include <functional>
#include <string>
#include <string_view>
#include <utility>
namespace leak
{
namespace config
{
/** @brief Leak level to systemd target service map */
static constexpr std::array<std::pair<config::DetectorLevel, std::string_view>,
2>
leakActionTargets = {{{config::DetectorLevel::warning,
"xyz.openbmc_project.leakdetector.warning@"},
{config::DetectorLevel::critical,
"xyz.openbmc_project.leakdetector.critical@"}}};
} // namespace config
static auto getObjectPath(const std::string& detectorName)
-> sdbusplus::message::object_path
{
return (
sdbusplus::message::object_path(DetectorIntf::namespace_path::value) /
DetectorIntf::namespace_path::detector / detectorName);
}
GPIODetector::GPIODetector(sdbusplus::async::context& ctx, Events& leakEvents,
const config::DetectorConfig& config) :
DetectorIntf(ctx, getObjectPath(config.name).str.c_str()), ctx(ctx),
leakEvents(leakEvents), config(config),
gpioInterface(ctx, config.name, config.pinName,
(config.polarity == config::PinPolarity::activeLow),
std::bind_front(&GPIODetector::updateGPIOStateAsync, this))
{
pretty_name<false>(config.name);
type<false>(config.type);
ctx.spawn(gpioInterface.start());
debug("Created leak detector {NAME}", "NAME", config.name);
}
auto GPIODetector::updateGPIOStateAsync(bool gpioState)
-> sdbusplus::async::task<>
{
auto newState = gpioState ? DetectorIntf::DetectorState::Abnormal
: DetectorIntf::DetectorState::Normal;
debug("Updating detector {DETECTOR} state to {STATE}", "DETECTOR",
config.name, "STATE", newState);
if (newState != state_)
{
state(newState);
co_await leakEvents.generateLeakEvent(getObjectPath(config.name),
state_, config.level);
if (state_ != DetectorIntf::DetectorState::Normal)
{
for (const auto& [level, serviceSuffix] : config::leakActionTargets)
{
if (config.level == level)
{
auto target = std::string(serviceSuffix) + config.name +
".service";
debug("Starting systemd target {TARGET}", "TARGET", target);
co_await systemd::SystemdInterface::startUnit(ctx, target);
break;
}
}
}
}
co_return;
}
} // namespace leak