1 #include "dump_utils.hpp" 2 3 #include "util.hpp" 4 5 #include <fmt/format.h> 6 7 #include <phosphor-logging/log.hpp> 8 #include <sdbusplus/bus.hpp> 9 #include <sdbusplus/exception.hpp> 10 #include <sdbusplus/server.hpp> 11 12 namespace openpower::phal::dump 13 { 14 15 using namespace phosphor::logging; 16 17 /** 18 * Callback for dump request properties change signal monitor 19 * 20 * @param[in] msg Dbus message from the dbus match infrastructure 21 * @param[in] path The object path we are monitoring 22 * @param[out] inProgress Used to break out of our dbus wait loop 23 * @reutn Always non-zero indicating no error, no cascading callbacks 24 */ 25 uint32_t dumpStatusChanged(sdbusplus::message_t& msg, const std::string& path, 26 bool& inProgress) 27 { 28 // reply (msg) will be a property change message 29 std::string interface; 30 std::map<std::string, std::variant<std::string, uint8_t>> property; 31 msg.read(interface, property); 32 33 // looking for property Status changes 34 std::string propertyType = "Status"; 35 auto dumpStatus = property.find(propertyType); 36 37 if (dumpStatus != property.end()) 38 { 39 const std::string* status = 40 std::get_if<std::string>(&(dumpStatus->second)); 41 42 if ((nullptr != status) && ("xyz.openbmc_project.Common.Progress." 43 "OperationStatus.InProgress" != *status)) 44 { 45 // dump is done, trace some info and change in progress flag 46 log<level::INFO>(fmt::format("Dump status({}) : path={}", 47 status->c_str(), path.c_str()) 48 .c_str()); 49 inProgress = false; 50 } 51 } 52 53 return 1; // non-negative return code for successful callback 54 } 55 56 /** 57 * Register a callback for dump progress status changes 58 * 59 * @param[in] path The object path of the dump to monitor 60 * @param timeout - timeout - timeout interval in seconds 61 */ 62 void monitorDump(const std::string& path, const uint32_t timeout) 63 { 64 bool inProgress = true; // callback will update this 65 66 // setup the signal match rules and callback 67 std::string matchInterface = "xyz.openbmc_project.Common.Progress"; 68 auto bus = sdbusplus::bus::new_system(); 69 70 std::unique_ptr<sdbusplus::bus::match_t> match = 71 std::make_unique<sdbusplus::bus::match_t>( 72 bus, 73 sdbusplus::bus::match::rules::propertiesChanged( 74 path.c_str(), matchInterface.c_str()), 75 [&](auto& msg) { 76 return dumpStatusChanged(msg, path, inProgress); 77 }); 78 79 // wait for dump status to be completed (complete == true) 80 // or until timeout interval 81 log<level::INFO>("dump requested (waiting)"); 82 bool timedOut = false; 83 uint32_t secondsCount = 0; 84 while ((true == inProgress) && !timedOut) 85 { 86 bus.wait(std::chrono::seconds(1)); 87 bus.process_discard(); 88 89 if (++secondsCount == timeout) 90 { 91 timedOut = true; 92 } 93 } 94 if (timedOut) 95 { 96 log<level::ERR>("Dump progress status did not change to " 97 "complete within the timeout interval, exiting..."); 98 } 99 } 100 101 void requestDump(const DumpParameters& dumpParameters) 102 { 103 log<level::INFO>(fmt::format("Requesting Dump PEL({}) Index({})", 104 dumpParameters.logId, dumpParameters.unitId) 105 .c_str()); 106 107 constexpr auto path = "/org/openpower/dump"; 108 constexpr auto interface = "xyz.openbmc_project.Dump.Create"; 109 constexpr auto function = "CreateDump"; 110 111 sdbusplus::message_t method; 112 113 auto bus = sdbusplus::bus::new_default(); 114 115 try 116 { 117 std::string service = util::getService(bus, path, interface); 118 auto method = 119 bus.new_method_call(service.c_str(), path, interface, function); 120 121 // dbus call arguments 122 std::map<std::string, std::variant<std::string, uint64_t>> createParams; 123 createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] = 124 uint64_t(dumpParameters.logId); 125 if (DumpType::SBE == dumpParameters.dumpType) 126 { 127 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] = 128 "com.ibm.Dump.Create.DumpType.SBE"; 129 createParams["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] = 130 dumpParameters.unitId; 131 } 132 method.append(createParams); 133 134 auto response = bus.call(method); 135 136 // reply will be type dbus::ObjectPath 137 sdbusplus::message::object_path reply; 138 response.read(reply); 139 140 // monitor dump progress 141 monitorDump(reply, dumpParameters.timeout); 142 } 143 catch (const sdbusplus::exception_t& e) 144 { 145 log<level::ERR>(fmt::format("D-Bus call createDump exception", 146 "OBJPATH={}, INTERFACE={}, EXCEPTION={}", 147 path, interface, e.what()) 148 .c_str()); 149 constexpr auto ERROR_DUMP_DISABLED = 150 "xyz.openbmc_project.Dump.Create.Error.Disabled"; 151 if (e.name() == ERROR_DUMP_DISABLED) 152 { 153 // Dump is disabled, Skip the dump collection. 154 log<level::INFO>( 155 fmt::format("Dump is disabled on({}), skipping dump collection", 156 dumpParameters.unitId) 157 .c_str()); 158 } 159 else 160 { 161 throw std::runtime_error( 162 "Error in invoking D-Bus createDump interface"); 163 } 164 } 165 catch (const std::exception& e) 166 { 167 throw e; 168 } 169 } 170 171 } // namespace openpower::phal::dump 172