1e426b589SAndrew Geissler #include "systemd_target_signal.hpp" 2e426b589SAndrew Geissler 3234a3179SAndrew Geissler #include <phosphor-logging/elog-errors.hpp> 4e426b589SAndrew Geissler #include <phosphor-logging/log.hpp> 5e426b589SAndrew Geissler #include <sdbusplus/exception.hpp> 6234a3179SAndrew Geissler #include <sdbusplus/server/manager.hpp> 7234a3179SAndrew Geissler #include <sdeventplus/event.hpp> 8234a3179SAndrew Geissler #include <xyz/openbmc_project/Common/error.hpp> 9234a3179SAndrew Geissler 10234a3179SAndrew Geissler namespace phosphor 11234a3179SAndrew Geissler { 12234a3179SAndrew Geissler namespace state 13234a3179SAndrew Geissler { 14234a3179SAndrew Geissler namespace manager 15234a3179SAndrew Geissler { 16234a3179SAndrew Geissler 17234a3179SAndrew Geissler using phosphor::logging::elog; 18234a3179SAndrew Geissler using phosphor::logging::entry; 19234a3179SAndrew Geissler using phosphor::logging::level; 20234a3179SAndrew Geissler using phosphor::logging::log; 21234a3179SAndrew Geissler using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 22234a3179SAndrew Geissler 23234a3179SAndrew Geissler void SystemdTargetLogging::logError(const std::string& error, 24234a3179SAndrew Geissler const std::string& result) 25234a3179SAndrew Geissler { 26234a3179SAndrew Geissler auto method = this->bus.new_method_call( 27234a3179SAndrew Geissler "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", 28234a3179SAndrew Geissler "xyz.openbmc_project.Logging.Create", "Create"); 29234a3179SAndrew Geissler // Signature is ssa{ss} 30234a3179SAndrew Geissler method.append(error); 31234a3179SAndrew Geissler method.append("xyz.openbmc_project.Logging.Entry.Level.Critical"); 32234a3179SAndrew Geissler method.append(std::array<std::pair<std::string, std::string>, 1>( 33234a3179SAndrew Geissler {std::pair<std::string, std::string>({"SYSTEMD_RESULT", result})})); 34234a3179SAndrew Geissler try 35234a3179SAndrew Geissler { 36234a3179SAndrew Geissler this->bus.call_noreply(method); 37234a3179SAndrew Geissler } 38*0a675215SPatrick Williams catch (const sdbusplus::exception::exception& e) 39234a3179SAndrew Geissler { 40234a3179SAndrew Geissler log<level::ERR>("Failed to create systemd target error", 41234a3179SAndrew Geissler entry("ERROR=%s", error.c_str()), 42234a3179SAndrew Geissler entry("RESULT=%s", result.c_str()), 43234a3179SAndrew Geissler entry("SDBUSERR=%s", e.what())); 44234a3179SAndrew Geissler } 45234a3179SAndrew Geissler } 46234a3179SAndrew Geissler 47234a3179SAndrew Geissler const std::string* SystemdTargetLogging::processError(const std::string& unit, 48234a3179SAndrew Geissler const std::string& result) 49234a3179SAndrew Geissler { 50234a3179SAndrew Geissler auto targetEntry = this->targetData.find(unit); 51234a3179SAndrew Geissler if (targetEntry != this->targetData.end()) 52234a3179SAndrew Geissler { 53234a3179SAndrew Geissler // Check if its result matches any of our monitored errors 54234a3179SAndrew Geissler if (std::find(targetEntry->second.errorsToMonitor.begin(), 55234a3179SAndrew Geissler targetEntry->second.errorsToMonitor.end(), 56234a3179SAndrew Geissler result) != targetEntry->second.errorsToMonitor.end()) 57234a3179SAndrew Geissler { 58234a3179SAndrew Geissler log<level::INFO>("Monitored systemd unit has hit an error", 59234a3179SAndrew Geissler entry("UNIT=%s", unit.c_str()), 60234a3179SAndrew Geissler entry("RESULT=%s", result.c_str())); 61234a3179SAndrew Geissler return (&targetEntry->second.errorToLog); 62234a3179SAndrew Geissler } 63234a3179SAndrew Geissler } 64b154fa9cSAndrew Geissler return nullptr; 65234a3179SAndrew Geissler } 66234a3179SAndrew Geissler 67234a3179SAndrew Geissler void SystemdTargetLogging::systemdUnitChange(sdbusplus::message::message& msg) 68234a3179SAndrew Geissler { 69234a3179SAndrew Geissler uint32_t id; 70234a3179SAndrew Geissler sdbusplus::message::object_path objPath; 71234a3179SAndrew Geissler std::string unit{}; 72234a3179SAndrew Geissler std::string result{}; 73234a3179SAndrew Geissler 74234a3179SAndrew Geissler msg.read(id, objPath, unit, result); 75234a3179SAndrew Geissler 76234a3179SAndrew Geissler // In most cases it will just be success, in which case just return 77234a3179SAndrew Geissler if (result != "done") 78234a3179SAndrew Geissler { 79234a3179SAndrew Geissler const std::string* error = processError(unit, result); 80234a3179SAndrew Geissler 81234a3179SAndrew Geissler // If this is a monitored error then log it 82234a3179SAndrew Geissler if (error) 83234a3179SAndrew Geissler { 84234a3179SAndrew Geissler logError(*error, result); 85234a3179SAndrew Geissler } 86234a3179SAndrew Geissler } 87234a3179SAndrew Geissler return; 88234a3179SAndrew Geissler } 89234a3179SAndrew Geissler 9038605ee2SAndrew Geissler void SystemdTargetLogging::processNameChangeSignal( 9138605ee2SAndrew Geissler sdbusplus::message::message& msg) 9238605ee2SAndrew Geissler { 9338605ee2SAndrew Geissler std::string name; // well-known 9438605ee2SAndrew Geissler std::string old_owner; // unique-name 9538605ee2SAndrew Geissler std::string new_owner; // unique-name 9638605ee2SAndrew Geissler 9738605ee2SAndrew Geissler msg.read(name, old_owner, new_owner); 9838605ee2SAndrew Geissler 9938605ee2SAndrew Geissler // Looking for systemd to be on dbus so we can call it 10038605ee2SAndrew Geissler if (name == "org.freedesktop.systemd1") 10138605ee2SAndrew Geissler { 10238605ee2SAndrew Geissler log<level::INFO>("org.freedesktop.systemd1 is now on dbus"); 10338605ee2SAndrew Geissler subscribeToSystemdSignals(); 10438605ee2SAndrew Geissler } 10538605ee2SAndrew Geissler return; 10638605ee2SAndrew Geissler } 10738605ee2SAndrew Geissler 108234a3179SAndrew Geissler void SystemdTargetLogging::subscribeToSystemdSignals() 109234a3179SAndrew Geissler { 110234a3179SAndrew Geissler auto method = this->bus.new_method_call( 111234a3179SAndrew Geissler "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 112234a3179SAndrew Geissler "org.freedesktop.systemd1.Manager", "Subscribe"); 113234a3179SAndrew Geissler 114234a3179SAndrew Geissler try 115234a3179SAndrew Geissler { 116234a3179SAndrew Geissler this->bus.call(method); 117234a3179SAndrew Geissler } 118*0a675215SPatrick Williams catch (const sdbusplus::exception::exception& e) 119234a3179SAndrew Geissler { 12038605ee2SAndrew Geissler // If error indicates systemd is not on dbus yet then do nothing. 12138605ee2SAndrew Geissler // The systemdNameChangeSignals callback will detect when it is on 12238605ee2SAndrew Geissler // dbus and then call this function again 12338605ee2SAndrew Geissler const std::string noDbus("org.freedesktop.DBus.Error.ServiceUnknown"); 12438605ee2SAndrew Geissler if (noDbus == e.name()) 12538605ee2SAndrew Geissler { 12638605ee2SAndrew Geissler log<level::INFO>("org.freedesktop.systemd1 not on dbus yet"); 12738605ee2SAndrew Geissler } 12838605ee2SAndrew Geissler else 12938605ee2SAndrew Geissler { 130234a3179SAndrew Geissler log<level::ERR>("Failed to subscribe to systemd signals", 131234a3179SAndrew Geissler entry("SDBUSERR=%s", e.what())); 132234a3179SAndrew Geissler elog<InternalFailure>(); 133234a3179SAndrew Geissler } 13438605ee2SAndrew Geissler return; 13538605ee2SAndrew Geissler } 13638605ee2SAndrew Geissler 13738605ee2SAndrew Geissler // Call destructor on match callback since application is now subscribed to 13838605ee2SAndrew Geissler // systemd signals 13938605ee2SAndrew Geissler this->systemdNameOwnedChangedSignal.~match(); 140234a3179SAndrew Geissler 141234a3179SAndrew Geissler return; 142234a3179SAndrew Geissler } 143234a3179SAndrew Geissler 144234a3179SAndrew Geissler } // namespace manager 145234a3179SAndrew Geissler } // namespace state 146234a3179SAndrew Geissler } // namespace phosphor 147