| Andrew Geissler | e426b58 | 2020-05-28 12:40:55 -0500 | [diff] [blame] | 1 | #include "systemd_target_signal.hpp" | 
|  | 2 |  | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 3 | #include <phosphor-logging/elog-errors.hpp> | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 4 | #include <phosphor-logging/lg2.hpp> | 
| Andrew Geissler | e426b58 | 2020-05-28 12:40:55 -0500 | [diff] [blame] | 5 | #include <sdbusplus/exception.hpp> | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 6 | #include <sdbusplus/server/manager.hpp> | 
|  | 7 | #include <sdeventplus/event.hpp> | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 8 | #include <xyz/openbmc_project/Common/error.hpp> | 
|  | 9 |  | 
|  | 10 | namespace phosphor | 
|  | 11 | { | 
|  | 12 | namespace state | 
|  | 13 | { | 
|  | 14 | namespace manager | 
|  | 15 | { | 
|  | 16 |  | 
|  | 17 | using phosphor::logging::elog; | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 18 | PHOSPHOR_LOG2_USING; | 
|  | 19 |  | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 20 | using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; | 
|  | 21 |  | 
| Andrew Geissler | 21d305e | 2022-02-11 16:49:51 -0600 | [diff] [blame^] | 22 | void SystemdTargetLogging::createBmcDump() | 
|  | 23 | { | 
|  | 24 | auto method = this->bus.new_method_call( | 
|  | 25 | "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc", | 
|  | 26 | "xyz.openbmc_project.Dump.Create", "CreateDump"); | 
|  | 27 | method.append( | 
|  | 28 | std::vector< | 
|  | 29 | std::pair<std::string, std::variant<std::string, uint64_t>>>()); | 
|  | 30 | try | 
|  | 31 | { | 
|  | 32 | this->bus.call_noreply(method); | 
|  | 33 | } | 
|  | 34 | catch (const sdbusplus::exception::exception& e) | 
|  | 35 | { | 
|  | 36 | error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e); | 
|  | 37 | // just continue, this is error path anyway so we're just collecting | 
|  | 38 | // what we can | 
|  | 39 | } | 
|  | 40 | } | 
|  | 41 |  | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 42 | void SystemdTargetLogging::logError(const std::string& errorLog, | 
| Andrew Geissler | e684103 | 2022-02-11 10:31:50 -0600 | [diff] [blame] | 43 | const std::string& result, | 
|  | 44 | const std::string& unit) | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 45 | { | 
|  | 46 | auto method = this->bus.new_method_call( | 
|  | 47 | "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", | 
|  | 48 | "xyz.openbmc_project.Logging.Create", "Create"); | 
|  | 49 | // Signature is ssa{ss} | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 50 | method.append(errorLog); | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 51 | method.append("xyz.openbmc_project.Logging.Entry.Level.Critical"); | 
| Andrew Geissler | e684103 | 2022-02-11 10:31:50 -0600 | [diff] [blame] | 52 | method.append(std::array<std::pair<std::string, std::string>, 2>( | 
|  | 53 | {std::pair<std::string, std::string>({"SYSTEMD_RESULT", result}), | 
|  | 54 | std::pair<std::string, std::string>({"SYSTEMD_UNIT", unit})})); | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 55 | try | 
|  | 56 | { | 
|  | 57 | this->bus.call_noreply(method); | 
|  | 58 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 59 | catch (const sdbusplus::exception::exception& e) | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 60 | { | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 61 | error("Failed to create systemd target error, error:{ERROR_MSG}, " | 
|  | 62 | "result:{RESULT}, exception:{ERROR}", | 
|  | 63 | "ERROR_MSG", errorLog, "RESULT", result, "ERROR", e); | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 64 | } | 
|  | 65 | } | 
|  | 66 |  | 
| Andrew Geissler | f3870c6 | 2022-02-10 16:15:28 -0600 | [diff] [blame] | 67 | const std::string SystemdTargetLogging::processError(const std::string& unit, | 
|  | 68 | const std::string& result) | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 69 | { | 
|  | 70 | auto targetEntry = this->targetData.find(unit); | 
|  | 71 | if (targetEntry != this->targetData.end()) | 
|  | 72 | { | 
|  | 73 | // Check if its result matches any of our monitored errors | 
|  | 74 | if (std::find(targetEntry->second.errorsToMonitor.begin(), | 
|  | 75 | targetEntry->second.errorsToMonitor.end(), | 
|  | 76 | result) != targetEntry->second.errorsToMonitor.end()) | 
|  | 77 | { | 
| Andrew Geissler | ad65b2d | 2021-09-21 12:53:29 -0500 | [diff] [blame] | 78 | info( | 
|  | 79 | "Monitored systemd unit has hit an error, unit:{UNIT}, result:{RESULT}", | 
|  | 80 | "UNIT", unit, "RESULT", result); | 
| Andrew Geissler | f3870c6 | 2022-02-10 16:15:28 -0600 | [diff] [blame] | 81 | return (targetEntry->second.errorToLog); | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 82 | } | 
|  | 83 | } | 
| Andrew Geissler | f3870c6 | 2022-02-10 16:15:28 -0600 | [diff] [blame] | 84 |  | 
|  | 85 | // Check if it's in our list of services to monitor | 
|  | 86 | if (std::find(this->serviceData.begin(), this->serviceData.end(), unit) != | 
|  | 87 | this->serviceData.end()) | 
|  | 88 | { | 
|  | 89 | if (result == "failed") | 
|  | 90 | { | 
|  | 91 | info( | 
|  | 92 | "Monitored systemd service has hit an error, unit:{UNIT}, result:{RESULT}", | 
|  | 93 | "UNIT", unit, "RESULT", result); | 
| Andrew Geissler | 21d305e | 2022-02-11 16:49:51 -0600 | [diff] [blame^] | 94 |  | 
|  | 95 | // Generate a BMC dump when a critical service fails | 
|  | 96 | createBmcDump(); | 
| Andrew Geissler | f3870c6 | 2022-02-10 16:15:28 -0600 | [diff] [blame] | 97 | return (std::string{ | 
|  | 98 | "xyz.openbmc_project.State.Error.CriticalServiceFailure"}); | 
|  | 99 | } | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | return (std::string{}); | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 103 | } | 
|  | 104 |  | 
|  | 105 | void SystemdTargetLogging::systemdUnitChange(sdbusplus::message::message& msg) | 
|  | 106 | { | 
|  | 107 | uint32_t id; | 
|  | 108 | sdbusplus::message::object_path objPath; | 
|  | 109 | std::string unit{}; | 
|  | 110 | std::string result{}; | 
|  | 111 |  | 
|  | 112 | msg.read(id, objPath, unit, result); | 
|  | 113 |  | 
|  | 114 | // In most cases it will just be success, in which case just return | 
|  | 115 | if (result != "done") | 
|  | 116 | { | 
| Andrew Geissler | f3870c6 | 2022-02-10 16:15:28 -0600 | [diff] [blame] | 117 | const std::string error = processError(unit, result); | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 118 |  | 
|  | 119 | // If this is a monitored error then log it | 
| Andrew Geissler | f3870c6 | 2022-02-10 16:15:28 -0600 | [diff] [blame] | 120 | if (!error.empty()) | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 121 | { | 
| Andrew Geissler | e684103 | 2022-02-11 10:31:50 -0600 | [diff] [blame] | 122 | logError(error, result, unit); | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 123 | } | 
|  | 124 | } | 
|  | 125 | return; | 
|  | 126 | } | 
|  | 127 |  | 
| Andrew Geissler | 38605ee | 2019-11-11 16:01:56 -0600 | [diff] [blame] | 128 | void SystemdTargetLogging::processNameChangeSignal( | 
|  | 129 | sdbusplus::message::message& msg) | 
|  | 130 | { | 
|  | 131 | std::string name;      // well-known | 
|  | 132 | std::string old_owner; // unique-name | 
|  | 133 | std::string new_owner; // unique-name | 
|  | 134 |  | 
|  | 135 | msg.read(name, old_owner, new_owner); | 
|  | 136 |  | 
|  | 137 | // Looking for systemd to be on dbus so we can call it | 
|  | 138 | if (name == "org.freedesktop.systemd1") | 
|  | 139 | { | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 140 | info("org.freedesktop.systemd1 is now on dbus"); | 
| Andrew Geissler | 38605ee | 2019-11-11 16:01:56 -0600 | [diff] [blame] | 141 | subscribeToSystemdSignals(); | 
|  | 142 | } | 
|  | 143 | return; | 
|  | 144 | } | 
|  | 145 |  | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 146 | void SystemdTargetLogging::subscribeToSystemdSignals() | 
|  | 147 | { | 
|  | 148 | auto method = this->bus.new_method_call( | 
|  | 149 | "org.freedesktop.systemd1", "/org/freedesktop/systemd1", | 
|  | 150 | "org.freedesktop.systemd1.Manager", "Subscribe"); | 
|  | 151 |  | 
|  | 152 | try | 
|  | 153 | { | 
|  | 154 | this->bus.call(method); | 
|  | 155 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 156 | catch (const sdbusplus::exception::exception& e) | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 157 | { | 
| Andrew Geissler | 38605ee | 2019-11-11 16:01:56 -0600 | [diff] [blame] | 158 | // If error indicates systemd is not on dbus yet then do nothing. | 
|  | 159 | // The systemdNameChangeSignals callback will detect when it is on | 
|  | 160 | // dbus and then call this function again | 
|  | 161 | const std::string noDbus("org.freedesktop.DBus.Error.ServiceUnknown"); | 
|  | 162 | if (noDbus == e.name()) | 
|  | 163 | { | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 164 | info("org.freedesktop.systemd1 not on dbus yet"); | 
| Andrew Geissler | 38605ee | 2019-11-11 16:01:56 -0600 | [diff] [blame] | 165 | } | 
|  | 166 | else | 
|  | 167 | { | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 168 | error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", | 
|  | 169 | e); | 
| Andrew Geissler | 38605ee | 2019-11-11 16:01:56 -0600 | [diff] [blame] | 170 | elog<InternalFailure>(); | 
|  | 171 | } | 
|  | 172 | return; | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 173 | } | 
|  | 174 |  | 
| Andrew Geissler | 38605ee | 2019-11-11 16:01:56 -0600 | [diff] [blame] | 175 | // Call destructor on match callback since application is now subscribed to | 
|  | 176 | // systemd signals | 
|  | 177 | this->systemdNameOwnedChangedSignal.~match(); | 
|  | 178 |  | 
| Andrew Geissler | 234a317 | 2019-08-09 14:30:02 -0500 | [diff] [blame] | 179 | return; | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | } // namespace manager | 
|  | 183 | } // namespace state | 
|  | 184 | } // namespace phosphor |