blob: 68933c0bfdc992c611c1dc44ab2540d249095ae0 [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>
Andrew Geissler234a3172019-08-09 14:30:02 -05009#include <xyz/openbmc_project/Common/error.hpp>
Patrick Williams9a286db2024-01-17 06:29:47 -060010#include <xyz/openbmc_project/Logging/Create/client.hpp>
11#include <xyz/openbmc_project/Logging/Entry/client.hpp>
Andrew Geissler234a3172019-08-09 14:30:02 -050012
13namespace phosphor
14{
15namespace state
16{
17namespace manager
18{
19
20using phosphor::logging::elog;
Andrew Geissler8ffdb262021-09-20 15:25:19 -050021PHOSPHOR_LOG2_USING;
22
Andrew Geissler234a3172019-08-09 14:30:02 -050023using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
24
Patrick Williams9a286db2024-01-17 06:29:47 -060025using LoggingCreate =
26 sdbusplus::client::xyz::openbmc_project::logging::Create<>;
27using LoggingEntry = sdbusplus::client::xyz::openbmc_project::logging::Entry<>;
28
Andrew Geissler73d2ac92022-02-17 16:55:50 -060029void SystemdTargetLogging::startBmcQuiesceTarget()
30{
31 auto method = this->bus.new_method_call(
32 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
33 "org.freedesktop.systemd1.Manager", "StartUnit");
34
35 // TODO: Enhance when needed to support multiple-bmc instance systems
36 method.append("obmc-bmc-service-quiesce@0.target");
37 method.append("replace");
38 try
39 {
40 this->bus.call_noreply(method);
41 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050042 catch (const sdbusplus::exception_t& e)
Andrew Geissler73d2ac92022-02-17 16:55:50 -060043 {
44 error("Failed to start BMC quiesce target, exception:{ERROR}", "ERROR",
45 e);
46 // just continue, this is error path anyway so we're just doing what
47 // we can
48 }
49
50 return;
51}
52
Andrew Geissler8ffdb262021-09-20 15:25:19 -050053void SystemdTargetLogging::logError(const std::string& errorLog,
Andrew Geisslere6841032022-02-11 10:31:50 -060054 const std::string& result,
55 const std::string& unit)
Andrew Geissler234a3172019-08-09 14:30:02 -050056{
Patrick Williams1b2c3c02024-08-16 15:20:29 -040057 auto method = this->bus.new_method_call(
58 LoggingCreate::default_service, LoggingCreate::instance_path,
59 LoggingCreate::interface, "Create");
Andrew Geissler234a3172019-08-09 14:30:02 -050060 // Signature is ssa{ss}
Patrick Williams9a286db2024-01-17 06:29:47 -060061 method.append(
62 errorLog, LoggingEntry::Level::Critical,
63 std::array<std::pair<std::string, std::string>, 2>(
64 {std::pair<std::string, std::string>({"SYSTEMD_RESULT", result}),
65 std::pair<std::string, std::string>({"SYSTEMD_UNIT", unit})}));
Andrew Geissler234a3172019-08-09 14:30:02 -050066 try
67 {
68 this->bus.call_noreply(method);
69 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050070 catch (const sdbusplus::exception_t& e)
Andrew Geissler234a3172019-08-09 14:30:02 -050071 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050072 error("Failed to create systemd target error, error:{ERROR_MSG}, "
73 "result:{RESULT}, exception:{ERROR}",
74 "ERROR_MSG", errorLog, "RESULT", result, "ERROR", e);
Andrew Geissler234a3172019-08-09 14:30:02 -050075 }
76}
77
Pavithra Barithayad7a15cb2024-06-21 11:24:46 -050078std::string SystemdTargetLogging::processError(const std::string& unit,
79 const std::string& result)
Andrew Geissler234a3172019-08-09 14:30:02 -050080{
81 auto targetEntry = this->targetData.find(unit);
82 if (targetEntry != this->targetData.end())
83 {
84 // Check if its result matches any of our monitored errors
85 if (std::find(targetEntry->second.errorsToMonitor.begin(),
Patrick Williams1b2c3c02024-08-16 15:20:29 -040086 targetEntry->second.errorsToMonitor.end(), result) !=
87 targetEntry->second.errorsToMonitor.end())
Andrew Geissler234a3172019-08-09 14:30:02 -050088 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050089 info(
90 "Monitored systemd unit has hit an error, unit:{UNIT}, result:{RESULT}",
91 "UNIT", unit, "RESULT", result);
Andrew Geisslerd59006a2022-03-21 14:25:08 -050092
93 // Generate a BMC dump when a monitored target fails
Andrew Geissler55e96ac2022-04-19 11:44:53 -040094 utils::createBmcDump(this->bus);
Andrew Geisslerf3870c62022-02-10 16:15:28 -060095 return (targetEntry->second.errorToLog);
Andrew Geissler234a3172019-08-09 14:30:02 -050096 }
97 }
Andrew Geisslerf3870c62022-02-10 16:15:28 -060098
99 // Check if it's in our list of services to monitor
100 if (std::find(this->serviceData.begin(), this->serviceData.end(), unit) !=
101 this->serviceData.end())
102 {
103 if (result == "failed")
104 {
105 info(
106 "Monitored systemd service has hit an error, unit:{UNIT}, result:{RESULT}",
107 "UNIT", unit, "RESULT", result);
Andrew Geissler21d305e2022-02-11 16:49:51 -0600108
109 // Generate a BMC dump when a critical service fails
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400110 utils::createBmcDump(this->bus);
Andrew Geissler73d2ac92022-02-17 16:55:50 -0600111 // Enter BMC Quiesce when a critical service fails
112 startBmcQuiesceTarget();
Andrew Geisslerf3870c62022-02-10 16:15:28 -0600113 return (std::string{
114 "xyz.openbmc_project.State.Error.CriticalServiceFailure"});
115 }
116 }
117
118 return (std::string{});
Andrew Geissler234a3172019-08-09 14:30:02 -0500119}
120
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500121void SystemdTargetLogging::systemdUnitChange(sdbusplus::message_t& msg)
Andrew Geissler234a3172019-08-09 14:30:02 -0500122{
123 uint32_t id;
124 sdbusplus::message::object_path objPath;
125 std::string unit{};
126 std::string result{};
127
128 msg.read(id, objPath, unit, result);
129
130 // In most cases it will just be success, in which case just return
131 if (result != "done")
132 {
Andrew Geisslerf3870c62022-02-10 16:15:28 -0600133 const std::string error = processError(unit, result);
Andrew Geissler234a3172019-08-09 14:30:02 -0500134
135 // If this is a monitored error then log it
Andrew Geisslerf3870c62022-02-10 16:15:28 -0600136 if (!error.empty())
Andrew Geissler234a3172019-08-09 14:30:02 -0500137 {
Andrew Geisslere6841032022-02-11 10:31:50 -0600138 logError(error, result, unit);
Andrew Geissler234a3172019-08-09 14:30:02 -0500139 }
140 }
141 return;
142}
143
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500144void SystemdTargetLogging::processNameChangeSignal(sdbusplus::message_t& msg)
Andrew Geissler38605ee2019-11-11 16:01:56 -0600145{
146 std::string name; // well-known
147 std::string old_owner; // unique-name
148 std::string new_owner; // unique-name
149
150 msg.read(name, old_owner, new_owner);
151
152 // Looking for systemd to be on dbus so we can call it
153 if (name == "org.freedesktop.systemd1")
154 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500155 info("org.freedesktop.systemd1 is now on dbus");
Andrew Geissler38605ee2019-11-11 16:01:56 -0600156 subscribeToSystemdSignals();
157 }
158 return;
159}
160
Andrew Geissler234a3172019-08-09 14:30:02 -0500161void SystemdTargetLogging::subscribeToSystemdSignals()
162{
163 auto method = this->bus.new_method_call(
164 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
165 "org.freedesktop.systemd1.Manager", "Subscribe");
166
167 try
168 {
169 this->bus.call(method);
170 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500171 catch (const sdbusplus::exception_t& e)
Andrew Geissler234a3172019-08-09 14:30:02 -0500172 {
Andrew Geissler38605ee2019-11-11 16:01:56 -0600173 // If error indicates systemd is not on dbus yet then do nothing.
174 // The systemdNameChangeSignals callback will detect when it is on
175 // dbus and then call this function again
176 const std::string noDbus("org.freedesktop.DBus.Error.ServiceUnknown");
177 if (noDbus == e.name())
178 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500179 info("org.freedesktop.systemd1 not on dbus yet");
Andrew Geissler38605ee2019-11-11 16:01:56 -0600180 }
181 else
182 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500183 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR",
184 e);
Andrew Geissler38605ee2019-11-11 16:01:56 -0600185 elog<InternalFailure>();
186 }
187 return;
Andrew Geissler234a3172019-08-09 14:30:02 -0500188 }
189
Andrew Geissler38605ee2019-11-11 16:01:56 -0600190 // Call destructor on match callback since application is now subscribed to
191 // systemd signals
192 this->systemdNameOwnedChangedSignal.~match();
193
Andrew Geissler234a3172019-08-09 14:30:02 -0500194 return;
195}
196
197} // namespace manager
198} // namespace state
199} // namespace phosphor