blob: 833b141b4ce5908555ae6f2f79234f14196669c4 [file] [log] [blame]
James Feist6714a252018-09-10 15:26:18 -07001/*
2// Copyright (c) 2017 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
Patrick Ventureca44b2f2019-10-31 11:02:26 -070017#include "Utils.hpp"
18
James Feist6714a252018-09-10 15:26:18 -070019#include <boost/algorithm/string/predicate.hpp>
James Feist24f02f22019-04-15 11:05:39 -070020#include <filesystem>
James Feist6714a252018-09-10 15:26:18 -070021#include <fstream>
22#include <regex>
23#include <sdbusplus/asio/connection.hpp>
James Feist82bac4c2019-03-11 11:16:53 -070024#include <sdbusplus/asio/object_server.hpp>
James Feist6714a252018-09-10 15:26:18 -070025#include <sdbusplus/bus/match.hpp>
26
James Feistcf3bce62019-01-08 10:07:19 -080027namespace fs = std::filesystem;
James Feist6714a252018-09-10 15:26:18 -070028
James Feist6ef20402019-01-07 16:45:08 -080029static bool powerStatusOn = false;
James Feistfc94b212019-02-06 16:14:51 -080030static bool biosHasPost = false;
James Feist58295ad2019-05-30 15:01:41 -070031
James Feist6ef20402019-01-07 16:45:08 -080032static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
James Feist52497fd2019-06-07 13:01:33 -070033static std::unique_ptr<sdbusplus::bus::match::match> postMatch = nullptr;
James Feist71d31b22019-01-02 16:57:54 -080034
James Feist6714a252018-09-10 15:26:18 -070035bool getSensorConfiguration(
36 const std::string& type,
37 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
38 ManagedObjectType& resp, bool useCache)
39{
40 static ManagedObjectType managedObj;
41
42 if (!useCache)
43 {
44 managedObj.clear();
45 sdbusplus::message::message getManagedObjects =
46 dbusConnection->new_method_call(
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070047 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
James Feist6714a252018-09-10 15:26:18 -070048 "GetManagedObjects");
49 bool err = false;
50 try
51 {
52 sdbusplus::message::message reply =
53 dbusConnection->call(getManagedObjects);
Yoo, Jae Hyun0e022052018-10-15 14:05:37 -070054 reply.read(managedObj);
James Feist6714a252018-09-10 15:26:18 -070055 }
Jason Ling5747fab2019-10-02 16:46:23 -070056 catch (const sdbusplus::exception::exception& e)
James Feist6714a252018-09-10 15:26:18 -070057 {
Jason Ling5747fab2019-10-02 16:46:23 -070058 std::cerr << "While calling GetManagedObjects on service:"
59 << entityManagerName << " exception name:" << e.name()
60 << "and description:" << e.description()
61 << " was thrown\n";
James Feist6714a252018-09-10 15:26:18 -070062 err = true;
63 }
64
65 if (err)
66 {
67 std::cerr << "Error communicating to entity manager\n";
68 return false;
69 }
70 }
71 for (const auto& pathPair : managedObj)
72 {
James Feist6714a252018-09-10 15:26:18 -070073 bool correctType = false;
74 for (const auto& entry : pathPair.second)
75 {
76 if (boost::starts_with(entry.first, type))
77 {
78 correctType = true;
79 break;
80 }
81 }
82 if (correctType)
83 {
84 resp.emplace(pathPair);
85 }
86 }
87 return true;
88}
89
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070090bool findFiles(const fs::path dirPath, const std::string& matchString,
91 std::vector<fs::path>& foundPaths, unsigned int symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -070092{
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070093 if (!fs::exists(dirPath))
James Feist6714a252018-09-10 15:26:18 -070094 return false;
95
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070096 std::regex search(matchString);
James Feist6714a252018-09-10 15:26:18 -070097 std::smatch match;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070098 for (auto& p : fs::recursive_directory_iterator(dirPath))
James Feist6714a252018-09-10 15:26:18 -070099 {
100 std::string path = p.path().string();
101 if (!is_directory(p))
102 {
103 if (std::regex_search(path, match, search))
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700104 foundPaths.emplace_back(p.path());
James Feist6714a252018-09-10 15:26:18 -0700105 }
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700106 else if (is_symlink(p) && symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -0700107 {
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700108 findFiles(p.path(), matchString, foundPaths, symlinkDepth - 1);
James Feist6714a252018-09-10 15:26:18 -0700109 }
110 }
111 return true;
112}
113
James Feist71d31b22019-01-02 16:57:54 -0800114bool isPowerOn(void)
James Feist6714a252018-09-10 15:26:18 -0700115{
James Feist71d31b22019-01-02 16:57:54 -0800116 if (!powerMatch)
James Feist6714a252018-09-10 15:26:18 -0700117 {
James Feist71d31b22019-01-02 16:57:54 -0800118 throw std::runtime_error("Power Match Not Created");
James Feist6714a252018-09-10 15:26:18 -0700119 }
James Feist71d31b22019-01-02 16:57:54 -0800120 return powerStatusOn;
121}
122
James Feistfc94b212019-02-06 16:14:51 -0800123bool hasBiosPost(void)
124{
James Feist52497fd2019-06-07 13:01:33 -0700125 if (!postMatch)
James Feistfc94b212019-02-06 16:14:51 -0800126 {
James Feist52497fd2019-06-07 13:01:33 -0700127 throw std::runtime_error("Post Match Not Created");
James Feistfc94b212019-02-06 16:14:51 -0800128 }
129 return biosHasPost;
130}
131
James Feist71d31b22019-01-02 16:57:54 -0800132void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn)
133{
James Feist43d32fe2019-09-04 10:35:20 -0700134 static boost::asio::steady_timer timer(conn->get_io_context());
James Feist6714a252018-09-10 15:26:18 -0700135 // create a match for powergood changes, first time do a method call to
James Feist71d31b22019-01-02 16:57:54 -0800136 // cache the correct value
James Feist52497fd2019-06-07 13:01:33 -0700137 if (powerMatch)
138 {
139 return;
140 }
James Feist6714a252018-09-10 15:26:18 -0700141
142 powerMatch = std::make_unique<sdbusplus::bus::match::match>(
143 static_cast<sdbusplus::bus::bus&>(*conn),
James Feist52497fd2019-06-07 13:01:33 -0700144 "type='signal',interface='" + std::string(properties::interface) +
145 "',path='" + std::string(power::path) + "',arg0='" +
146 std::string(power::interface) + "'",
147 [](sdbusplus::message::message& message) {
148 std::string objectName;
149 boost::container::flat_map<std::string, std::variant<std::string>>
150 values;
151 message.read(objectName, values);
152 auto findState = values.find(power::property);
153 if (findState != values.end())
James Feist6714a252018-09-10 15:26:18 -0700154 {
James Feist43d32fe2019-09-04 10:35:20 -0700155 bool on = boost::ends_with(
James Feist52497fd2019-06-07 13:01:33 -0700156 std::get<std::string>(findState->second), "Running");
James Feist43d32fe2019-09-04 10:35:20 -0700157 if (!on)
158 {
159 timer.cancel();
160 powerStatusOn = false;
161 return;
162 }
163 // on comes too quickly
164 timer.expires_after(std::chrono::seconds(10));
165 timer.async_wait([](boost::system::error_code ec) {
166 if (ec == boost::asio::error::operation_aborted)
167 {
168 return;
169 }
170 else if (ec)
171 {
172 std::cerr << "Timer error " << ec.message() << "\n";
173 return;
174 }
175 powerStatusOn = true;
176 });
James Feist6714a252018-09-10 15:26:18 -0700177 }
James Feist52497fd2019-06-07 13:01:33 -0700178 });
179
180 postMatch = std::make_unique<sdbusplus::bus::match::match>(
181 static_cast<sdbusplus::bus::bus&>(*conn),
182 "type='signal',interface='" + std::string(properties::interface) +
183 "',path='" + std::string(post::path) + "',arg0='" +
184 std::string(post::interface) + "'",
185 [](sdbusplus::message::message& message) {
186 std::string objectName;
187 boost::container::flat_map<std::string, std::variant<std::string>>
188 values;
189 message.read(objectName, values);
190 auto findState = values.find(post::property);
191 if (findState != values.end())
192 {
193 biosHasPost =
194 std::get<std::string>(findState->second) != "Inactive";
195 }
196 });
James Feistfc94b212019-02-06 16:14:51 -0800197
198 conn->async_method_call(
199 [](boost::system::error_code ec,
James Feist52497fd2019-06-07 13:01:33 -0700200 const std::variant<std::string>& state) {
James Feistfc94b212019-02-06 16:14:51 -0800201 if (ec)
202 {
James Feistcee4ef22019-04-04 11:04:08 -0700203 // we commonly come up before power control, we'll capture the
204 // property change later
James Feistfc94b212019-02-06 16:14:51 -0800205 return;
206 }
James Feist52497fd2019-06-07 13:01:33 -0700207 powerStatusOn =
208 boost::ends_with(std::get<std::string>(state), "Running");
James Feistfc94b212019-02-06 16:14:51 -0800209 },
James Feist52497fd2019-06-07 13:01:33 -0700210 power::busname, power::path, properties::interface, properties::get,
211 power::interface, power::property);
212
213 conn->async_method_call(
214 [](boost::system::error_code ec,
215 const std::variant<std::string>& state) {
216 if (ec)
217 {
218 // we commonly come up before power control, we'll capture the
219 // property change later
220 return;
221 }
222 biosHasPost = std::get<std::string>(state) != "Inactive";
223 },
224 post::busname, post::path, properties::interface, properties::get,
225 post::interface, post::property);
James Feist3f0e8762018-11-27 11:30:42 -0800226}
James Feist87d713a2018-12-06 16:06:24 -0800227
228// replaces limits if MinReading and MaxReading are found.
229void findLimits(std::pair<double, double>& limits,
230 const SensorBaseConfiguration* data)
231{
232 if (!data)
233 {
234 return;
235 }
236 auto maxFind = data->second.find("MaxReading");
237 auto minFind = data->second.find("MinReading");
238
239 if (minFind != data->second.end())
240 {
James Feist3eb82622019-02-08 13:10:22 -0800241 limits.first = std::visit(VariantToDoubleVisitor(), minFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800242 }
243 if (maxFind != data->second.end())
244 {
James Feist3eb82622019-02-08 13:10:22 -0800245 limits.second = std::visit(VariantToDoubleVisitor(), maxFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800246 }
James Feistfc94b212019-02-06 16:14:51 -0800247}
James Feist82bac4c2019-03-11 11:16:53 -0700248
249void createAssociation(
250 std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
251 const std::string& path)
252{
253 if (association)
254 {
James Feistd2543f82019-04-09 11:10:06 -0700255 std::filesystem::path p(path);
256
James Feist82bac4c2019-03-11 11:16:53 -0700257 std::vector<Association> associations;
James Feistd2543f82019-04-09 11:10:06 -0700258 associations.push_back(
James Feistd8bd5622019-06-26 12:09:05 -0700259 Association("chassis", "all_sensors", p.parent_path().string()));
James Feist2adc95c2019-09-30 14:55:28 -0700260 association->register_property("Associations", associations);
James Feist82bac4c2019-03-11 11:16:53 -0700261 association->initialize();
262 }
James Feist43d32fe2019-09-04 10:35:20 -0700263}
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800264
265void setInventoryAssociation(
266 std::shared_ptr<sdbusplus::asio::dbus_interface> association,
267 const std::string& path, const std::string& chassisPath)
268{
269 if (association)
270 {
271 std::filesystem::path p(path);
272
273 std::vector<Association> associations;
274 associations.push_back(
275 Association("inventory", "sensors", p.parent_path().string()));
276 associations.push_back(
277 Association("chassis", "all_sensors", chassisPath));
James Feist2adc95c2019-09-30 14:55:28 -0700278 association->register_property("Associations", associations);
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800279 association->initialize();
280 }
281}
282
283void createInventoryAssoc(
284 std::shared_ptr<sdbusplus::asio::connection> conn,
285 std::shared_ptr<sdbusplus::asio::dbus_interface> association,
286 const std::string& path)
287{
288 if (!association)
289 {
290 return;
291 }
292 conn->async_method_call(
293 [association, path](const boost::system::error_code ec,
294 const std::vector<std::string>& ret) {
295 if (ec)
296 {
297 std::cerr << "Error calling mapper\n";
298 return;
299 }
300 for (const auto& object : ret)
301 {
302 setInventoryAssociation(association, path, object);
303 }
304 },
305 mapper::busName, mapper::path, mapper::interface, "GetSubTreePaths",
306 "/xyz/openbmc_project/inventory/system", 2,
307 std::array<std::string, 1>{
308 "xyz.openbmc_project.Inventory.Item.System"});
309}