blob: 7add98575ce4437452334e4936f077c5f357f845 [file] [log] [blame]
Shantappa Teekappanavar1ac61622021-06-22 19:07:29 -05001#include <phosphor-logging/log.hpp>
2#include <sdbusplus/bus.hpp>
3#include <sdbusplus/bus/match.hpp>
4#include <watchdog_dbus.hpp>
5#include <watchdog_handler.hpp>
6#include <watchdog_logging.hpp>
7
8namespace watchdog
9{
10namespace dump
11{
12
13using namespace phosphor::logging;
14
15/**
16 * @brief Callback for dump request properties change signal monitor
17 *
18 * @param msg - dbus message from the dbus match infrastructure
19 * @param path - the object path we are monitoring
20 * @param inProgress - used to break out of our dbus wait loop
21 * @return Always non-zero indicating no error, no cascading callbacks
22 */
23uint dumpStatusChanged(sdbusplus::message::message& msg, std::string path,
24 bool& inProgress)
25{
26 // reply (msg) will be a property change message
27 std::string interface;
28 std::map<std::string, std::variant<std::string, uint8_t>> property;
29 msg.read(interface, property);
30
31 // looking for property Status changes
32 std::string propertyType = "Status";
33 auto dumpStatus = property.find(propertyType);
34
35 if (dumpStatus != property.end())
36 {
37 const std::string* status =
38 std::get_if<std::string>(&(dumpStatus->second));
39
40 if ((nullptr != status) && ("xyz.openbmc_project.Common.Progress."
41 "OperationStatus.InProgress" != *status))
42 {
43 // dump is done, trace some info and change in progress flag
44 log<level::INFO>(path.c_str());
45 log<level::INFO>((*status).c_str());
46 inProgress = false;
47 }
48 }
49
50 return 1; // non-negative return code for successful callback
51}
52
53/**
54 * @brief Register a callback for dump progress status changes
55 *
56 * @param path - the object path of the dump to monitor
57 * @param timeout - timeout - timeout interval in seconds
58 */
59void monitorDump(const std::string& path, const uint32_t timeout)
60{
61 bool inProgress = true; // callback will update this
62
63 // setup the signal match rules and callback
64 std::string matchInterface = "xyz.openbmc_project.Common.Progress";
65 auto bus = sdbusplus::bus::new_system();
66
67 std::unique_ptr<sdbusplus::bus::match_t> match =
68 std::make_unique<sdbusplus::bus::match_t>(
69 bus,
70 sdbusplus::bus::match::rules::propertiesChanged(
71 path.c_str(), matchInterface.c_str()),
72 [&](auto& msg) {
73 return dumpStatusChanged(msg, path, inProgress);
74 });
75
76 // wait for dump status to be completed (complete == true)
77 // or until timeout interval
78 log<level::INFO>("hbdump requested");
79 bool timedOut = false;
80 uint32_t secondsCount = 0;
81 while ((true == inProgress) && !timedOut)
82 {
83 bus.wait(std::chrono::seconds(1));
84 bus.process_discard();
85
86 if (++secondsCount == timeout)
87 {
88 timedOut = true;
89 }
90 }
91
92 if (timedOut)
93 {
94 log<level::ERR>("hbdump dump progress status did not change to "
95 "complete within the timeout interval, exiting...");
96 }
97 else
98 {
99 log<level::INFO>("hbdump completed");
100 }
101}
102
103void requestDump(const uint32_t logId, const uint32_t timeout)
104{
105 constexpr auto path = "/org/openpower/dump";
106 constexpr auto interface = "xyz.openbmc_project.Dump.Create";
107 constexpr auto function = "CreateDump";
108
109 sdbusplus::message::message method;
110
111 if (0 == dbusMethod(path, interface, function, method))
112 {
113 try
114 {
115 // dbus call arguments
116 std::map<std::string, std::variant<std::string, uint64_t>>
117 createParams;
118 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
119 "com.ibm.Dump.Create.DumpType.Hostboot";
120 createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] =
121 uint64_t(logId);
122 method.append(createParams);
123
124 // using system dbus
125 auto bus = sdbusplus::bus::new_system();
126 auto response = bus.call(method);
127
128 // reply will be type dbus::ObjectPath
129 sdbusplus::message::object_path reply;
130 response.read(reply);
131
132 // monitor dump progress
133 monitorDump(reply, timeout);
134 }
135 catch (const sdbusplus::exception::SdBusError& e)
136 {
137 log<level::ERR>("Error in requestDump",
138 entry("ERROR=%s", e.what()));
139 }
140 }
141}
142
143} // namespace dump
144} // namespace watchdog