xref: /openbmc/openpower-hw-diags/util/dbus.cpp (revision 9306716d)
1 #include <util/dbus.hpp>
2 #include <util/trace.hpp>
3 
4 namespace util
5 {
6 
7 namespace dbus
8 {
9 
10 //------------------------------------------------------------------------------
11 
12 constexpr auto objectMapperService   = "xyz.openbmc_project.ObjectMapper";
13 constexpr auto objectMapperPath      = "/xyz/openbmc_project/object_mapper";
14 constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper";
15 
16 /** @brief Find the path and service that implements the given interface */
17 int find(const std::string& i_interface, std::string& o_path,
18          std::string& o_service)
19 {
20     int rc = 1; // assume not success
21 
22     auto bus = sdbusplus::bus::new_default();
23 
24     try
25     {
26         constexpr auto function = "GetSubTree";
27 
28         auto method = bus.new_method_call(objectMapperService, objectMapperPath,
29                                           objectMapperInterface, function);
30 
31         // Search the entire dbus tree for the specified interface
32         method.append(std::string{"/"}, 0,
33                       std::vector<std::string>{i_interface});
34 
35         auto reply = bus.call(method);
36 
37         DBusSubTree response;
38         reply.read(response);
39 
40         if (!response.empty())
41         {
42             // Response is a map of object paths to a map of service, interfaces
43             auto object = *(response.begin());
44             o_path      = object.first;                 // return path
45             o_service   = object.second.begin()->first; // return service
46 
47             rc = 0; // success
48         }
49     }
50     catch (const sdbusplus::exception::SdBusError& e)
51     {
52         trace::err("util::dbus::find exception");
53         std::string traceMsg = std::string(e.what());
54         trace::err(traceMsg.c_str());
55     }
56 
57     return rc;
58 }
59 
60 /** @brief Find the service that implements the given object and interface */
61 int findService(const std::string& i_interface, const std::string& i_path,
62                 std::string& o_service)
63 {
64     int rc = 1; // assume not success
65 
66     auto bus = sdbusplus::bus::new_default();
67 
68     try
69     {
70         constexpr auto function = "GetObject";
71 
72         auto method = bus.new_method_call(objectMapperService, objectMapperPath,
73                                           objectMapperInterface, function);
74 
75         // Find services that implement the object path, constrain the search
76         // to the given interface.
77         method.append(i_path, std::vector<std::string>{i_interface});
78 
79         auto reply = bus.call(method);
80 
81         // response is a map of service names to their interfaces
82         std::map<DBusService, DBusInterfaceList> response;
83         reply.read(response);
84 
85         if (!response.empty())
86         {
87             // return the service
88             o_service = response.begin()->first;
89 
90             rc = 0; // success
91         }
92     }
93     catch (const sdbusplus::exception::SdBusError& e)
94     {
95         trace::err("util::dbus::map exception");
96         std::string traceMsg = std::string(e.what());
97         trace::err(traceMsg.c_str());
98     }
99 
100     return rc;
101 }
102 
103 /** @brief Read a property from a dbus object interface */
104 int getProperty(const std::string& i_interface, const std::string& i_path,
105                 const std::string& i_service, const std::string& i_property,
106                 DBusValue& o_response)
107 {
108     int rc = 1; // assume not success
109 
110     auto bus = sdbusplus::bus::new_default();
111 
112     try
113     {
114         constexpr auto interface = "org.freedesktop.DBus.Properties";
115         constexpr auto function  = "Get";
116 
117         // calling the get property method
118         auto method = bus.new_method_call(i_service.c_str(), i_path.c_str(),
119                                           interface, function);
120 
121         method.append(i_interface, i_property);
122         auto reply = bus.call(method);
123 
124         // returning the property value
125         reply.read(o_response);
126 
127         rc = 0; // success
128     }
129     catch (const sdbusplus::exception::SdBusError& e)
130     {
131         trace::err("util::dbus::getProperty exception");
132         std::string traceMsg = std::string(e.what());
133         trace::err(traceMsg.c_str());
134     }
135 
136     return rc;
137 }
138 
139 /** @brief Get the IBM compatible names defined for this system */
140 std::vector<std::string> systemNames()
141 {
142     std::vector<std::string> names;
143 
144     constexpr auto interface =
145         "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
146 
147     DBusService service;
148     DBusPath path;
149 
150     // find a dbus object and path that implements the interface
151     if (0 == find(interface, path, service))
152     {
153         DBusValue value;
154 
155         // compatible system names are implemented as a property
156         constexpr auto property = "Names";
157 
158         if (0 == getProperty(interface, path, service, property, value))
159         {
160             // return value is a variant, names are in the vector
161             names = std::get<std::vector<std::string>>(value);
162         }
163     }
164 
165     return names;
166 }
167 
168 /** @brief Transition the host state */
169 void transitionHost(const HostState i_hostState)
170 {
171     try
172     {
173         // We will be transitioning host by starting appropriate dbus target
174         std::string target = "obmc-host-quiesce@0.target"; // quiesce is default
175 
176         // crash (mpipl) mode state requested
177         if (HostState::Crash == i_hostState)
178         {
179             target = "obmc-host-crash@0.target";
180         }
181 
182         auto bus    = sdbusplus::bus::new_system();
183         auto method = bus.new_method_call(
184             "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
185             "org.freedesktop.systemd1.Manager", "StartUnit");
186 
187         method.append(target);    // target unit to start
188         method.append("replace"); // mode = replace conflicting queued jobs
189 
190         bus.call_noreply(method); // start the service
191     }
192     catch (const sdbusplus::exception::SdBusError& e)
193     {
194         trace::err("util::dbus::transitionHost exception");
195         std::string traceMsg = std::string(e.what());
196         trace::err(traceMsg.c_str());
197     }
198 }
199 
200 } // namespace dbus
201 
202 } // namespace util
203