blob: f21d1b5e10816cd15859130eb83bb301c6573197 [file] [log] [blame]
Jagpal Singh Gill15dde862024-10-16 09:42:54 -07001#include "LeakGPIODetector.hpp"
2
3#include "LeakEvents.hpp"
4#include "SystemdInterface.hpp"
5
6#include <sdbusplus/async.hpp>
7#include <sdbusplus/message/native_types.hpp>
8
9#include <array>
10#include <functional>
11#include <string>
12#include <string_view>
13#include <utility>
14
15namespace leak
16{
17
18namespace config
19{
20
21/** @brief Leak level to systemd target service map */
22static constexpr std::array<std::pair<config::DetectorLevel, std::string_view>,
23 2>
24 leakActionTargets = {{{config::DetectorLevel::warning,
25 "xyz.openbmc_project.leakdetector.warning@"},
26 {config::DetectorLevel::critical,
27 "xyz.openbmc_project.leakdetector.critical@"}}};
28
29} // namespace config
30
31static auto getObjectPath(const std::string& detectorName)
32 -> sdbusplus::message::object_path
33{
34 return (
35 sdbusplus::message::object_path(DetectorIntf::namespace_path::value) /
36 DetectorIntf::namespace_path::detector / detectorName);
37}
38
39GPIODetector::GPIODetector(sdbusplus::async::context& ctx, Events& leakEvents,
40 const config::DetectorConfig& config) :
41 DetectorIntf(ctx, getObjectPath(config.name).str.c_str()), ctx(ctx),
42 leakEvents(leakEvents), config(config),
43 gpioInterface(ctx, config.name, config.pinName,
44 (config.polarity == config::PinPolarity::activeLow),
45 std::bind_front(&GPIODetector::updateGPIOStateAsync, this))
46{
47 pretty_name<false>(config.name);
48 type<false>(config.type);
49
50 ctx.spawn(gpioInterface.start());
51
52 debug("Created leak detector {NAME}", "NAME", config.name);
53}
54
55auto GPIODetector::updateGPIOStateAsync(bool gpioState)
56 -> sdbusplus::async::task<>
57{
58 auto newState = gpioState ? DetectorIntf::DetectorState::Abnormal
59 : DetectorIntf::DetectorState::Normal;
60
61 debug("Updating detector {DETECTOR} state to {STATE}", "DETECTOR",
62 config.name, "STATE", newState);
63
64 if (newState != state_)
65 {
66 state(newState);
67
68 co_await leakEvents.generateLeakEvent(getObjectPath(config.name),
69 state_, config.level);
70 if (state_ != DetectorIntf::DetectorState::Normal)
71 {
72 for (const auto& [level, serviceSuffix] : config::leakActionTargets)
73 {
74 if (config.level == level)
75 {
76 auto target = std::string(serviceSuffix) + config.name +
77 ".service";
78 debug("Starting systemd target {TARGET}", "TARGET", target);
79 co_await systemd::SystemdInterface::startUnit(ctx, target);
80 break;
81 }
82 }
83 }
84 }
85
86 co_return;
87}
88
89} // namespace leak