blob: 8c76b97c29f91034b0e0af0461af834eb88d45e8 [file] [log] [blame]
Andrew Geisslere426b582020-05-28 12:40:55 -05001#include "systemd_target_signal.hpp"
2
Andrew Geissler55e96ac2022-04-19 11:44:53 -04003#include "utils.hpp"
4
Andrew Geissler234a3172019-08-09 14:30:02 -05005#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler8ffdb262021-09-20 15:25:19 -05006#include <phosphor-logging/lg2.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -05007#include <sdbusplus/exception.hpp>
Andrew Geissler234a3172019-08-09 14:30:02 -05008#include <sdbusplus/server/manager.hpp>
9#include <sdeventplus/event.hpp>
Andrew Geissler234a3172019-08-09 14:30:02 -050010#include <xyz/openbmc_project/Common/error.hpp>
11
12namespace phosphor
13{
14namespace state
15{
16namespace manager
17{
18
19using phosphor::logging::elog;
Andrew Geissler8ffdb262021-09-20 15:25:19 -050020PHOSPHOR_LOG2_USING;
21
Andrew Geissler234a3172019-08-09 14:30:02 -050022using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
23
Andrew Geissler73d2ac92022-02-17 16:55:50 -060024void SystemdTargetLogging::startBmcQuiesceTarget()
25{
26 auto method = this->bus.new_method_call(
27 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
28 "org.freedesktop.systemd1.Manager", "StartUnit");
29
30 // TODO: Enhance when needed to support multiple-bmc instance systems
31 method.append("obmc-bmc-service-quiesce@0.target");
32 method.append("replace");
33 try
34 {
35 this->bus.call_noreply(method);
36 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050037 catch (const sdbusplus::exception_t& e)
Andrew Geissler73d2ac92022-02-17 16:55:50 -060038 {
39 error("Failed to start BMC quiesce target, exception:{ERROR}", "ERROR",
40 e);
41 // just continue, this is error path anyway so we're just doing what
42 // we can
43 }
44
45 return;
46}
47
Andrew Geissler8ffdb262021-09-20 15:25:19 -050048void SystemdTargetLogging::logError(const std::string& errorLog,
Andrew Geisslere6841032022-02-11 10:31:50 -060049 const std::string& result,
50 const std::string& unit)
Andrew Geissler234a3172019-08-09 14:30:02 -050051{
52 auto method = this->bus.new_method_call(
53 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
54 "xyz.openbmc_project.Logging.Create", "Create");
55 // Signature is ssa{ss}
Andrew Geissler8ffdb262021-09-20 15:25:19 -050056 method.append(errorLog);
Andrew Geissler234a3172019-08-09 14:30:02 -050057 method.append("xyz.openbmc_project.Logging.Entry.Level.Critical");
Andrew Geisslere6841032022-02-11 10:31:50 -060058 method.append(std::array<std::pair<std::string, std::string>, 2>(
59 {std::pair<std::string, std::string>({"SYSTEMD_RESULT", result}),
60 std::pair<std::string, std::string>({"SYSTEMD_UNIT", unit})}));
Andrew Geissler234a3172019-08-09 14:30:02 -050061 try
62 {
63 this->bus.call_noreply(method);
64 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050065 catch (const sdbusplus::exception_t& e)
Andrew Geissler234a3172019-08-09 14:30:02 -050066 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050067 error("Failed to create systemd target error, error:{ERROR_MSG}, "
68 "result:{RESULT}, exception:{ERROR}",
69 "ERROR_MSG", errorLog, "RESULT", result, "ERROR", e);
Andrew Geissler234a3172019-08-09 14:30:02 -050070 }
71}
72
Andrew Geisslerf3870c62022-02-10 16:15:28 -060073const std::string SystemdTargetLogging::processError(const std::string& unit,
74 const std::string& result)
Andrew Geissler234a3172019-08-09 14:30:02 -050075{
76 auto targetEntry = this->targetData.find(unit);
77 if (targetEntry != this->targetData.end())
78 {
79 // Check if its result matches any of our monitored errors
80 if (std::find(targetEntry->second.errorsToMonitor.begin(),
81 targetEntry->second.errorsToMonitor.end(),
82 result) != targetEntry->second.errorsToMonitor.end())
83 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050084 info(
85 "Monitored systemd unit has hit an error, unit:{UNIT}, result:{RESULT}",
86 "UNIT", unit, "RESULT", result);
Andrew Geisslerd59006a2022-03-21 14:25:08 -050087
88 // Generate a BMC dump when a monitored target fails
Andrew Geissler55e96ac2022-04-19 11:44:53 -040089 utils::createBmcDump(this->bus);
Andrew Geisslerf3870c62022-02-10 16:15:28 -060090 return (targetEntry->second.errorToLog);
Andrew Geissler234a3172019-08-09 14:30:02 -050091 }
92 }
Andrew Geisslerf3870c62022-02-10 16:15:28 -060093
94 // Check if it's in our list of services to monitor
95 if (std::find(this->serviceData.begin(), this->serviceData.end(), unit) !=
96 this->serviceData.end())
97 {
98 if (result == "failed")
99 {
100 info(
101 "Monitored systemd service has hit an error, unit:{UNIT}, result:{RESULT}",
102 "UNIT", unit, "RESULT", result);
Andrew Geissler21d305e2022-02-11 16:49:51 -0600103
104 // Generate a BMC dump when a critical service fails
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400105 utils::createBmcDump(this->bus);
Andrew Geissler73d2ac92022-02-17 16:55:50 -0600106 // Enter BMC Quiesce when a critical service fails
107 startBmcQuiesceTarget();
Andrew Geisslerf3870c62022-02-10 16:15:28 -0600108 return (std::string{
109 "xyz.openbmc_project.State.Error.CriticalServiceFailure"});
110 }
111 }
112
113 return (std::string{});
Andrew Geissler234a3172019-08-09 14:30:02 -0500114}
115
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500116void SystemdTargetLogging::systemdUnitChange(sdbusplus::message_t& msg)
Andrew Geissler234a3172019-08-09 14:30:02 -0500117{
118 uint32_t id;
119 sdbusplus::message::object_path objPath;
120 std::string unit{};
121 std::string result{};
122
123 msg.read(id, objPath, unit, result);
124
125 // In most cases it will just be success, in which case just return
126 if (result != "done")
127 {
Andrew Geisslerf3870c62022-02-10 16:15:28 -0600128 const std::string error = processError(unit, result);
Andrew Geissler234a3172019-08-09 14:30:02 -0500129
130 // If this is a monitored error then log it
Andrew Geisslerf3870c62022-02-10 16:15:28 -0600131 if (!error.empty())
Andrew Geissler234a3172019-08-09 14:30:02 -0500132 {
Andrew Geisslere6841032022-02-11 10:31:50 -0600133 logError(error, result, unit);
Andrew Geissler234a3172019-08-09 14:30:02 -0500134 }
135 }
136 return;
137}
138
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500139void SystemdTargetLogging::processNameChangeSignal(sdbusplus::message_t& msg)
Andrew Geissler38605ee2019-11-11 16:01:56 -0600140{
141 std::string name; // well-known
142 std::string old_owner; // unique-name
143 std::string new_owner; // unique-name
144
145 msg.read(name, old_owner, new_owner);
146
147 // Looking for systemd to be on dbus so we can call it
148 if (name == "org.freedesktop.systemd1")
149 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500150 info("org.freedesktop.systemd1 is now on dbus");
Andrew Geissler38605ee2019-11-11 16:01:56 -0600151 subscribeToSystemdSignals();
152 }
153 return;
154}
155
Andrew Geissler234a3172019-08-09 14:30:02 -0500156void SystemdTargetLogging::subscribeToSystemdSignals()
157{
158 auto method = this->bus.new_method_call(
159 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
160 "org.freedesktop.systemd1.Manager", "Subscribe");
161
162 try
163 {
164 this->bus.call(method);
165 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500166 catch (const sdbusplus::exception_t& e)
Andrew Geissler234a3172019-08-09 14:30:02 -0500167 {
Andrew Geissler38605ee2019-11-11 16:01:56 -0600168 // If error indicates systemd is not on dbus yet then do nothing.
169 // The systemdNameChangeSignals callback will detect when it is on
170 // dbus and then call this function again
171 const std::string noDbus("org.freedesktop.DBus.Error.ServiceUnknown");
172 if (noDbus == e.name())
173 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500174 info("org.freedesktop.systemd1 not on dbus yet");
Andrew Geissler38605ee2019-11-11 16:01:56 -0600175 }
176 else
177 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500178 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR",
179 e);
Andrew Geissler38605ee2019-11-11 16:01:56 -0600180 elog<InternalFailure>();
181 }
182 return;
Andrew Geissler234a3172019-08-09 14:30:02 -0500183 }
184
Andrew Geissler38605ee2019-11-11 16:01:56 -0600185 // Call destructor on match callback since application is now subscribed to
186 // systemd signals
187 this->systemdNameOwnedChangedSignal.~match();
188
Andrew Geissler234a3172019-08-09 14:30:02 -0500189 return;
190}
191
192} // namespace manager
193} // namespace state
194} // namespace phosphor