blob: 6ce3f18528df098aa75163d9d2a930d234f9ac92 [file] [log] [blame]
/*
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include <Utils.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <experimental/filesystem>
#include <fstream>
#include <regex>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/bus/match.hpp>
namespace fs = std::experimental::filesystem;
const static constexpr char* POWER_INTERFACE_NAME =
"xyz.openbmc_project.Chassis.Control.Power";
const static constexpr char* POWER_OBJECT_NAME =
"/xyz/openbmc_project/Chassis/Control/Power0";
bool getSensorConfiguration(
const std::string& type,
const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
ManagedObjectType& resp, bool useCache)
{
static ManagedObjectType managedObj;
if (!useCache)
{
managedObj.clear();
sdbusplus::message::message getManagedObjects =
dbusConnection->new_method_call(
ENTITY_MANAGER_NAME, "/", "org.freedesktop.DBus.ObjectManager",
"GetManagedObjects");
bool err = false;
try
{
sdbusplus::message::message reply =
dbusConnection->call(getManagedObjects);
err = reply.is_method_error();
if (!err)
{
reply.read(managedObj);
}
}
catch (const sdbusplus::exception::exception&)
{
err = true;
}
if (err)
{
std::cerr << "Error communicating to entity manager\n";
return false;
}
}
for (const auto& pathPair : managedObj)
{
std::vector<boost::container::flat_map<std::string, BasicVariantType>>
sensorData;
bool correctType = false;
for (const auto& entry : pathPair.second)
{
if (boost::starts_with(entry.first, type))
{
correctType = true;
break;
}
}
if (correctType)
{
resp.emplace(pathPair);
}
}
return true;
}
bool find_files(const fs::path dir_path, const std::string& match_string,
std::vector<fs::path>& found_paths, unsigned int symlink_depth)
{
if (!fs::exists(dir_path))
return false;
fs::directory_iterator end_itr;
std::regex search(match_string);
std::smatch match;
for (auto& p : fs::recursive_directory_iterator(dir_path))
{
std::string path = p.path().string();
if (!is_directory(p))
{
if (std::regex_search(path, match, search))
found_paths.emplace_back(p.path());
}
// since we're using a recursive iterator, these should only be symlink
// dirs
else if (symlink_depth)
{
find_files(p.path(), match_string, found_paths, symlink_depth - 1);
}
}
return true;
}
// initially returns false, then sets up matches and returns status
// should be called once first to initialize
bool isPowerOn(const std::shared_ptr<sdbusplus::asio::connection>& conn)
{
static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
static bool powerStatusOn = false;
if (powerMatch != nullptr)
{
return powerStatusOn;
}
// create a match for powergood changes, first time do a method call to
// return the correct value
std::function<void(sdbusplus::message::message & message)> eventHandler =
[&powerStatusOn](sdbusplus::message::message& message) {
std::string objectName;
boost::container::flat_map<std::string,
sdbusplus::message::variant<int32_t>>
values;
message.read(objectName, values);
auto findPgood = values.find("pgood");
if (findPgood != values.end())
{
powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(
findPgood->second);
}
};
powerMatch = std::make_unique<sdbusplus::bus::match::match>(
static_cast<sdbusplus::bus::bus&>(*conn),
"type='signal',interface='org.freedesktop.DBus.Properties',path_"
"namespace='/xyz/openbmc_project/Chassis/Control/"
"power0',arg0='xyz.openbmc_project.Chassis.Control.Power'",
eventHandler);
conn->async_method_call(
[&powerStatusOn](boost::system::error_code ec,
const sdbusplus::message::variant<int32_t>& pgood) {
if (ec)
{
std::cerr << "Error getting initial power status\n";
return;
}
powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(pgood);
},
POWER_INTERFACE_NAME, POWER_OBJECT_NAME,
"org.freedesktop.DBus.Properties", "Get", "pgood");
return powerStatusOn;
}