blob: 6356de105feee859ba6035423e6e32e50ed0fd9a [file] [log] [blame]
Jayanth Othayoth21a889f2021-10-07 06:53:40 -05001#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
12namespace openpower::phal::dump
13{
14
15using 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 */
25uint32_t dumpStatusChanged(sdbusplus::message::message& msg,
26 const std::string& path, 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 */
62void 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
101void 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::message 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::exception& 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