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