xref: /openbmc/openpower-hw-diags/util/dbus.cpp (revision 8018391d)
1 #include <util/dbus.hpp>
2 #include <util/trace.hpp>
3 #include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
4 
5 namespace util
6 {
7 
8 namespace dbus
9 {
10 
11 //------------------------------------------------------------------------------
12 
13 constexpr auto objectMapperService   = "xyz.openbmc_project.ObjectMapper";
14 constexpr auto objectMapperPath      = "/xyz/openbmc_project/object_mapper";
15 constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper";
16 
17 /** @brief Find the path and service that implements the given interface */
18 int find(const std::string& i_interface, std::string& o_path,
19          std::string& o_service)
20 {
21     int rc = 1; // assume not success
22 
23     auto bus = sdbusplus::bus::new_default();
24 
25     try
26     {
27         constexpr auto function = "GetSubTree";
28 
29         auto method = bus.new_method_call(objectMapperService, objectMapperPath,
30                                           objectMapperInterface, function);
31 
32         // Search the entire dbus tree for the specified interface
33         method.append(std::string{"/"}, 0,
34                       std::vector<std::string>{i_interface});
35 
36         auto reply = bus.call(method);
37 
38         DBusSubTree response;
39         reply.read(response);
40 
41         if (!response.empty())
42         {
43             // Response is a map of object paths to a map of service, interfaces
44             auto object = *(response.begin());
45             o_path      = object.first;                 // return path
46             o_service   = object.second.begin()->first; // return service
47 
48             rc = 0; // success
49         }
50     }
51     catch (const sdbusplus::exception::SdBusError& e)
52     {
53         trace::err("util::dbus::find exception");
54         std::string traceMsg = std::string(e.what());
55         trace::err(traceMsg.c_str());
56     }
57 
58     return rc;
59 }
60 
61 /** @brief Find the service that implements the given object and interface */
62 int findService(const std::string& i_interface, const std::string& i_path,
63                 std::string& o_service)
64 {
65     int rc = 1; // assume not success
66 
67     auto bus = sdbusplus::bus::new_default();
68 
69     try
70     {
71         constexpr auto function = "GetObject";
72 
73         auto method = bus.new_method_call(objectMapperService, objectMapperPath,
74                                           objectMapperInterface, function);
75 
76         // Find services that implement the object path, constrain the search
77         // to the given interface.
78         method.append(i_path, std::vector<std::string>{i_interface});
79 
80         auto reply = bus.call(method);
81 
82         // response is a map of service names to their interfaces
83         std::map<DBusService, DBusInterfaceList> response;
84         reply.read(response);
85 
86         if (!response.empty())
87         {
88             // return the service
89             o_service = response.begin()->first;
90 
91             rc = 0; // success
92         }
93     }
94     catch (const sdbusplus::exception::SdBusError& e)
95     {
96         trace::err("util::dbus::map exception");
97         std::string traceMsg = std::string(e.what());
98         trace::err(traceMsg.c_str());
99     }
100 
101     return rc;
102 }
103 
104 /** @brief Read a property from a dbus object interface */
105 int getProperty(const std::string& i_interface, const std::string& i_path,
106                 const std::string& i_service, const std::string& i_property,
107                 DBusValue& o_response)
108 {
109     int rc = 1; // assume not success
110 
111     auto bus = sdbusplus::bus::new_default();
112 
113     try
114     {
115         constexpr auto interface = "org.freedesktop.DBus.Properties";
116         constexpr auto function  = "Get";
117 
118         // calling the get property method
119         auto method = bus.new_method_call(i_service.c_str(), i_path.c_str(),
120                                           interface, function);
121 
122         method.append(i_interface, i_property);
123         auto reply = bus.call(method);
124 
125         // returning the property value
126         reply.read(o_response);
127 
128         rc = 0; // success
129     }
130     catch (const sdbusplus::exception::SdBusError& e)
131     {
132         trace::err("util::dbus::getProperty exception");
133         std::string traceMsg = std::string(e.what());
134         trace::err(traceMsg.c_str());
135     }
136 
137     return rc;
138 }
139 
140 /** @brief Get the IBM compatible names defined for this system */
141 std::vector<std::string> systemNames()
142 {
143     std::vector<std::string> names;
144 
145     constexpr auto interface =
146         "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
147 
148     DBusService service;
149     DBusPath path;
150 
151     // find a dbus object and path that implements the interface
152     if (0 == find(interface, path, service))
153     {
154         DBusValue value;
155 
156         // compatible system names are implemented as a property
157         constexpr auto property = "Names";
158 
159         if (0 == getProperty(interface, path, service, property, value))
160         {
161             // return value is a variant, names are in the vector
162             names = std::get<std::vector<std::string>>(value);
163         }
164     }
165 
166     return names;
167 }
168 
169 /** @brief Transition the host state */
170 void transitionHost(const HostState i_hostState)
171 {
172     try
173     {
174         // We will be transitioning host by starting appropriate dbus target
175         std::string target = "obmc-host-quiesce@0.target"; // quiesce is default
176 
177         // crash (mpipl) mode state requested
178         if (HostState::Crash == i_hostState)
179         {
180             target = "obmc-host-crash@0.target";
181         }
182 
183         auto bus    = sdbusplus::bus::new_system();
184         auto method = bus.new_method_call(
185             "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
186             "org.freedesktop.systemd1.Manager", "StartUnit");
187 
188         method.append(target);    // target unit to start
189         method.append("replace"); // mode = replace conflicting queued jobs
190 
191         bus.call_noreply(method); // start the service
192     }
193     catch (const sdbusplus::exception::SdBusError& e)
194     {
195         trace::err("util::dbus::transitionHost exception");
196         std::string traceMsg = std::string(e.what());
197         trace::err(traceMsg.c_str());
198     }
199 }
200 
201 /** @brief Read state of autoRebootEnabled property via dbus */
202 bool autoRebootEnabled()
203 {
204     // Assume true in case autoRebootEnbabled property is not available
205     bool autoReboot = true;
206 
207     constexpr auto interface = "xyz.openbmc_project.Control.Boot.RebootPolicy";
208 
209     DBusService service; // will find this
210     DBusPath path;       // will find this
211 
212     // find a dbus object and path that implements the interface
213     if (0 == find(interface, path, service))
214     {
215         DBusValue value;
216 
217         // autoreboot policy is implemented as a property
218         constexpr auto property = "AutoReboot";
219 
220         if (0 == getProperty(interface, path, service, property, value))
221         {
222             // return value is a variant, autoreboot policy is boolean
223             autoReboot = std::get<bool>(value);
224         }
225     }
226 
227     return autoReboot;
228 }
229 
230 /** @brief Get the running state of the host */
231 HostRunningState hostRunningState()
232 {
233     // assume not able to get host running state
234     HostRunningState host = HostRunningState::Unknown;
235 
236     constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
237 
238     DBusService service;
239     DBusPath path;
240 
241     // find a dbus object and path that implements the interface
242     if (0 == find(interface, path, service))
243     {
244         DBusValue value;
245 
246         // boot progress is implemented as a property
247         constexpr auto property = "BootProgress";
248 
249         if (0 == getProperty(interface, path, service, property, value))
250         {
251             // return value is a variant, progress is in the vector of strings
252             std::string bootProgress(std::get<std::string>(value));
253 
254             // convert boot progress to host state
255             using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
256                 server::Progress::ProgressStages;
257 
258             BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
259                 server::Progress::convertProgressStagesFromString(bootProgress);
260 
261             if ((stage == BootProgress::SystemInitComplete) ||
262                 (stage == BootProgress::OSStart) ||
263                 (stage == BootProgress::OSRunning))
264             {
265                 host = HostRunningState::Started;
266             }
267             else
268             {
269                 host = HostRunningState::NotStarted;
270             }
271         }
272     }
273 
274     return host;
275 }
276 
277 /** @brief Read state of dumpPolicyEnabled property via dbus */
278 bool dumpPolicyEnabled()
279 {
280     // Assume true In case dumpPolicyEnabled property is not available
281     bool dumpPolicyEnabled = true;
282 
283     constexpr auto interface = "xyz.openbmc_project.Object.Enable";
284     constexpr auto path      = "/xyz/openbmc_project/dump/system_dump_policy";
285 
286     DBusService service; // will find this
287 
288     // find a dbus object and path that implements the interface
289     if (0 == findService(interface, path, service))
290     {
291         DBusValue value;
292 
293         // autoreboot policy is implemented as a property
294         constexpr auto property = "Enabled";
295 
296         if (0 == getProperty(interface, path, service, property, value))
297         {
298             // return value is a variant, dump policy enabled is a boolean
299             dumpPolicyEnabled = std::get<bool>(value);
300         }
301     }
302 
303     return dumpPolicyEnabled;
304 }
305 
306 } // namespace dbus
307 
308 } // namespace util
309