blob: e79bc5a2330b5847638873209c3225ce92b9aad4 [file] [log] [blame]
George Liuf3b75142021-06-10 11:22:50 +08001#include "utils.hpp"
2
Chris Cain36f9cde2021-11-22 11:18:21 -06003#include <fmt/core.h>
4
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +05305#include <phosphor-logging/elog-errors.hpp>
Gunnar Mills94df8c92018-09-14 14:50:03 -05006#include <sdbusplus/bus.hpp>
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +05307#include <xyz/openbmc_project/Common/error.hpp>
George Liub5ca1012021-09-10 12:53:11 +08008
9#include <string>
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053010namespace open_power
11{
12namespace occ
13{
George Liuf3b75142021-06-10 11:22:50 +080014namespace utils
15{
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053016// For throwing exceptions
17using namespace phosphor::logging;
Gunnar Mills94df8c92018-09-14 14:50:03 -050018using InternalFailure =
19 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053020
George Liuf3b75142021-06-10 11:22:50 +080021const std::string getService(const std::string& path,
22 const std::string& interface)
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053023{
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053024
George Liuf3b75142021-06-10 11:22:50 +080025 using InterfaceList = std::vector<std::string>;
26 std::map<std::string, std::vector<std::string>> mapperResponse;
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053027
George Liuf3b75142021-06-10 11:22:50 +080028 auto& bus = getBus();
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053029
George Liuf3b75142021-06-10 11:22:50 +080030 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
31 MAPPER_IFACE, "GetObject");
32 mapper.append(path, InterfaceList({interface}));
33
34 auto mapperResponseMsg = bus.call(mapper);
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053035 mapperResponseMsg.read(mapperResponse);
George Liuf3b75142021-06-10 11:22:50 +080036 if (mapperResponse.empty())
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053037 {
38 log<level::ERR>("ERROR reading mapper response",
Gunnar Mills94df8c92018-09-14 14:50:03 -050039 entry("PATH=%s", path.c_str()),
George Liuf3b75142021-06-10 11:22:50 +080040 entry("INTERFACE=%s", interface.c_str()));
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053041
42 elog<InternalFailure>();
43 }
George Liuf3b75142021-06-10 11:22:50 +080044
45 // the value here will be the service name
46 return mapperResponse.cbegin()->first;
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053047}
48
George Liuf3b75142021-06-10 11:22:50 +080049const PropertyValue getProperty(const std::string& objectPath,
50 const std::string& interface,
51 const std::string& propertyName)
52{
53 PropertyValue value{};
54
55 auto& bus = getBus();
56 auto service = getService(objectPath, interface);
57 if (service.empty())
58 {
59 return value;
60 }
61
62 auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
63 DBUS_PROPERTY_IFACE, "Get");
64 method.append(interface, propertyName);
65
66 auto reply = bus.call(method);
67 reply.read(value);
68
69 return value;
70}
71
Chris Cain36f9cde2021-11-22 11:18:21 -060072/**
73 * @brief Sets a given object's property value
74 *
Chris Cain1be43372021-12-09 19:29:37 -060075 * @param[in] objectPath - Name of the object containing the property
Chris Cain36f9cde2021-11-22 11:18:21 -060076 * @param[in] interface - Interface name containing the property
Chris Cain1be43372021-12-09 19:29:37 -060077 * @param[in] propertyName - Property name
Chris Cain36f9cde2021-11-22 11:18:21 -060078 * @param[in] value - Property value
79 */
80void setProperty(const std::string& objectPath, const std::string& interface,
Chris Cain5d66a0a2022-02-09 08:52:10 -060081 const std::string& propertyName, PropertyValue&& value)
Chris Cain36f9cde2021-11-22 11:18:21 -060082{
83 using namespace std::literals::string_literals;
Chris Cain5d66a0a2022-02-09 08:52:10 -060084 PropertyValue varValue(std::forward<PropertyValue>(value));
Chris Cain36f9cde2021-11-22 11:18:21 -060085
Chris Cain1be43372021-12-09 19:29:37 -060086 try
Chris Cain36f9cde2021-11-22 11:18:21 -060087 {
Chris Cain1be43372021-12-09 19:29:37 -060088 auto& bus = getBus();
89 auto service = getService(objectPath, interface);
90 if (service.empty())
91 {
92 return;
93 }
94
95 auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
96 DBUS_PROPERTY_IFACE, "Set");
97 method.append(interface, propertyName, varValue);
98
99 auto reply = bus.call(method);
100 if (reply.is_method_error())
101 {
102 log<level::ERR>(
103 fmt::format("util::setProperty: Failed to set property {}",
104 propertyName)
105 .c_str());
106 }
Chris Cain36f9cde2021-11-22 11:18:21 -0600107 }
Chris Cain1be43372021-12-09 19:29:37 -0600108 catch (const std::exception& e)
Chris Cain36f9cde2021-11-22 11:18:21 -0600109 {
Chris Cain1be43372021-12-09 19:29:37 -0600110 auto error = errno;
Chris Cain36f9cde2021-11-22 11:18:21 -0600111 log<level::ERR>(
Chris Cain1be43372021-12-09 19:29:37 -0600112 fmt::format("setProperty: failed to Set {}, errno={}, what={}",
113 propertyName.c_str(), error, e.what())
Chris Cain36f9cde2021-11-22 11:18:21 -0600114 .c_str());
115 }
116}
117
Matt Spinler5901abd2021-09-23 13:50:03 -0500118std::vector<std::string>
119 getSubtreePaths(const std::vector<std::string>& interfaces,
120 const std::string& path)
121{
122 std::vector<std::string> paths;
123
124 auto& bus = getBus();
125 auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
126 MAPPER_IFACE, "GetSubTreePaths");
127 method.append(path, 0, interfaces);
128
129 auto reply = bus.call(method);
130 reply.read(paths);
131
132 return paths;
133}
Chris Cain1be43372021-12-09 19:29:37 -0600134
135// Get the service and object path for an interface
136std::string getServiceUsingSubTree(const std::string& interface,
137 std::string& path)
138{
139 using Path = std::string;
140 using Intf = std::string;
141 using Serv = std::string;
142 using Intfs = std::vector<Intf>;
143 using Objects = std::map<Path, std::map<Serv, Intfs>>;
144 Serv service;
145 Objects rspObjects;
146
147 auto& bus = getBus();
148 auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
149 MAPPER_IFACE, "GetSubTree");
150 method.append(path, 0, std::vector{interface});
151
152 auto mapperResponseMsg = bus.call(method);
153 mapperResponseMsg.read(rspObjects);
154 if (rspObjects.empty())
155 {
156 log<level::ERR>(
157 fmt::format(
158 "util::getServiceUsingSubTree: Failed getSubTree({},0,{})",
159 path.c_str(), interface)
160 .c_str());
161 }
162 else
163 {
164 path = rspObjects.begin()->first;
165 if (!rspObjects.begin()->second.empty())
166 {
167 service = rspObjects.begin()->second.begin()->first;
168 }
169 else
170 {
171 log<level::ERR>(
172 fmt::format(
173 "getServiceUsingSubTree: service not found for interface {} (path={})",
174 interface, path.c_str())
175 .c_str());
176 }
177 }
178
179 return service;
180}
181
George Liuf3b75142021-06-10 11:22:50 +0800182} // namespace utils
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +0530183} // namespace occ
184} // namespace open_power