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