blob: 25089efed754408b794a97109e9a779da381bf47 [file] [log] [blame]
Andrew Geisslere426b582020-05-28 12:40:55 -05001#include "systemd_target_signal.hpp"
2
Andrew Geissler234a3172019-08-09 14:30:02 -05003#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler8ffdb262021-09-20 15:25:19 -05004#include <phosphor-logging/lg2.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -05005#include <sdbusplus/exception.hpp>
Andrew Geissler234a3172019-08-09 14:30:02 -05006#include <sdbusplus/server/manager.hpp>
7#include <sdeventplus/event.hpp>
Andrew Geissler234a3172019-08-09 14:30:02 -05008#include <xyz/openbmc_project/Common/error.hpp>
9
10namespace phosphor
11{
12namespace state
13{
14namespace manager
15{
16
17using phosphor::logging::elog;
Andrew Geissler8ffdb262021-09-20 15:25:19 -050018PHOSPHOR_LOG2_USING;
19
Andrew Geissler234a3172019-08-09 14:30:02 -050020using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
21
Andrew Geissler8ffdb262021-09-20 15:25:19 -050022void SystemdTargetLogging::logError(const std::string& errorLog,
Andrew Geissler234a3172019-08-09 14:30:02 -050023 const std::string& result)
24{
25 auto method = this->bus.new_method_call(
26 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
27 "xyz.openbmc_project.Logging.Create", "Create");
28 // Signature is ssa{ss}
Andrew Geissler8ffdb262021-09-20 15:25:19 -050029 method.append(errorLog);
Andrew Geissler234a3172019-08-09 14:30:02 -050030 method.append("xyz.openbmc_project.Logging.Entry.Level.Critical");
31 method.append(std::array<std::pair<std::string, std::string>, 1>(
32 {std::pair<std::string, std::string>({"SYSTEMD_RESULT", result})}));
33 try
34 {
35 this->bus.call_noreply(method);
36 }
Patrick Williams0a675212021-09-02 09:49:43 -050037 catch (const sdbusplus::exception::exception& e)
Andrew Geissler234a3172019-08-09 14:30:02 -050038 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050039 error("Failed to create systemd target error, error:{ERROR_MSG}, "
40 "result:{RESULT}, exception:{ERROR}",
41 "ERROR_MSG", errorLog, "RESULT", result, "ERROR", e);
Andrew Geissler234a3172019-08-09 14:30:02 -050042 }
43}
44
45const std::string* SystemdTargetLogging::processError(const std::string& unit,
46 const std::string& result)
47{
48 auto targetEntry = this->targetData.find(unit);
49 if (targetEntry != this->targetData.end())
50 {
51 // Check if its result matches any of our monitored errors
52 if (std::find(targetEntry->second.errorsToMonitor.begin(),
53 targetEntry->second.errorsToMonitor.end(),
54 result) != targetEntry->second.errorsToMonitor.end())
55 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050056 info(
57 "Monitored systemd unit has hit an error, unit:{UNIT}, result:{RESULT}",
58 "UNIT", unit, "RESULT", result);
Andrew Geissler234a3172019-08-09 14:30:02 -050059 return (&targetEntry->second.errorToLog);
60 }
61 }
Andrew Geisslerb154fa92019-12-10 15:18:10 -060062 return nullptr;
Andrew Geissler234a3172019-08-09 14:30:02 -050063}
64
65void SystemdTargetLogging::systemdUnitChange(sdbusplus::message::message& msg)
66{
67 uint32_t id;
68 sdbusplus::message::object_path objPath;
69 std::string unit{};
70 std::string result{};
71
72 msg.read(id, objPath, unit, result);
73
74 // In most cases it will just be success, in which case just return
75 if (result != "done")
76 {
77 const std::string* error = processError(unit, result);
78
79 // If this is a monitored error then log it
80 if (error)
81 {
82 logError(*error, result);
83 }
84 }
85 return;
86}
87
Andrew Geissler38605ee2019-11-11 16:01:56 -060088void SystemdTargetLogging::processNameChangeSignal(
89 sdbusplus::message::message& msg)
90{
91 std::string name; // well-known
92 std::string old_owner; // unique-name
93 std::string new_owner; // unique-name
94
95 msg.read(name, old_owner, new_owner);
96
97 // Looking for systemd to be on dbus so we can call it
98 if (name == "org.freedesktop.systemd1")
99 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500100 info("org.freedesktop.systemd1 is now on dbus");
Andrew Geissler38605ee2019-11-11 16:01:56 -0600101 subscribeToSystemdSignals();
102 }
103 return;
104}
105
Andrew Geissler234a3172019-08-09 14:30:02 -0500106void SystemdTargetLogging::subscribeToSystemdSignals()
107{
108 auto method = this->bus.new_method_call(
109 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
110 "org.freedesktop.systemd1.Manager", "Subscribe");
111
112 try
113 {
114 this->bus.call(method);
115 }
Patrick Williams0a675212021-09-02 09:49:43 -0500116 catch (const sdbusplus::exception::exception& e)
Andrew Geissler234a3172019-08-09 14:30:02 -0500117 {
Andrew Geissler38605ee2019-11-11 16:01:56 -0600118 // If error indicates systemd is not on dbus yet then do nothing.
119 // The systemdNameChangeSignals callback will detect when it is on
120 // dbus and then call this function again
121 const std::string noDbus("org.freedesktop.DBus.Error.ServiceUnknown");
122 if (noDbus == e.name())
123 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500124 info("org.freedesktop.systemd1 not on dbus yet");
Andrew Geissler38605ee2019-11-11 16:01:56 -0600125 }
126 else
127 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500128 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR",
129 e);
Andrew Geissler38605ee2019-11-11 16:01:56 -0600130 elog<InternalFailure>();
131 }
132 return;
Andrew Geissler234a3172019-08-09 14:30:02 -0500133 }
134
Andrew Geissler38605ee2019-11-11 16:01:56 -0600135 // Call destructor on match callback since application is now subscribed to
136 // systemd signals
137 this->systemdNameOwnedChangedSignal.~match();
138
Andrew Geissler234a3172019-08-09 14:30:02 -0500139 return;
140}
141
142} // namespace manager
143} // namespace state
144} // namespace phosphor