blob: 968a44fe58f709372885f0bbe4a65849980e2150 [file] [log] [blame]
Ben Tyner324234b2021-06-28 17:01:17 -05001#include <util/dbus.hpp>
2#include <util/trace.hpp>
3
4namespace util
5{
6
7namespace dbus
8{
9
10//------------------------------------------------------------------------------
11
12constexpr auto objectMapperService = "xyz.openbmc_project.ObjectMapper";
13constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper";
14constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper";
15
16/** @brief Find the path and service that implements the given interface */
17int 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
Ben Tyner324234b2021-06-28 17:01:17 -050024 try
25 {
Ben Tyner659e65c2021-07-21 09:49:35 -050026 constexpr auto function = "GetSubTree";
27
Ben Tyner324234b2021-06-28 17:01:17 -050028 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 */
61int 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
Ben Tyner324234b2021-06-28 17:01:17 -050068 try
69 {
Ben Tyner659e65c2021-07-21 09:49:35 -050070 constexpr auto function = "GetObject";
71
Ben Tyner324234b2021-06-28 17:01:17 -050072 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 */
104int 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
Ben Tyner324234b2021-06-28 17:01:17 -0500112 try
113 {
Ben Tyner659e65c2021-07-21 09:49:35 -0500114 constexpr auto interface = "org.freedesktop.DBus.Properties";
115 constexpr auto function = "Get";
116
Ben Tyner324234b2021-06-28 17:01:17 -0500117 // 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 */
140std::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
Ben Tyner93067162021-07-23 10:39:30 -0500168/** @brief Transition the host state */
169void 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
Ben Tyner324234b2021-06-28 17:01:17 -0500200} // namespace dbus
201
202} // namespace util