Move FruDevice to sdbusplus
This is more to work through the kinks of sdbusplus
asio, but is good to add none the less.
Change-Id: I43204dfc6455be62435eea45752d0029a54cfe79
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/.clang-format b/.clang-format
index 4e01c1a..bbc1bb1 100644
--- a/.clang-format
+++ b/.clang-format
@@ -81,4 +81,5 @@
Standard: Cpp11
TabWidth: 4
UseTab: Never
-...
\ No newline at end of file
+...
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b578ed2..cdf4622 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -67,6 +67,26 @@
ExternalProject_Get_Property(nlohmann-json install_dir)
include_directories(${install_dir}/src/nlohmann-json/src)
+ ExternalProject_Add(sdbusplus
+ PREFIX ${CMAKE_CURRENT_BINARY_DIR}/sdbusplus
+ GIT_REPOSITORY ssh://git-amr-2.devtools.intel.com:29418/sdbusplus
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION} -DBOOST_ROOT=${BOOST_ROOT}
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ LOG_DOWNLOAD ON
+ )
+ set(WANT_TRANSACTION 0)
+ configure_file(${CMAKE_BINARY_DIR}/sdbusplus-src/sdbusplus/server.hpp.in
+ ${CMAKE_BINARY_DIR}/prefix/include/sdbusplus/server.hpp @ONLY)
+ configure_file(${CMAKE_BINARY_DIR}/sdbusplus-src/sdbusplus/bus.hpp.in
+ ${CMAKE_BINARY_DIR}/prefix/include/sdbusplus/bus.hpp @ONLY)
+
+ ExternalProject_Get_Property(sdbusplus install_dir)
+ include_directories(${install_dir}/src/sdbusplus/include)
+
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/non-yocto)
+
option(ENABLE_TEST "Enable Google Test" OFF)
if(ENABLE_TEST)
hunter_add_package(GTest)
@@ -82,10 +102,10 @@
add_executable(fru-device src/FruDevice.cpp src/Utils.cpp)
-target_link_libraries(fru-device ${DBUS_LIBRARIES})
target_link_libraries(fru-device pthread)
target_link_libraries(fru-device stdc++fs)
target_link_libraries(fru-device ${Boost_LIBRARIES})
+target_link_libraries(fru-device -lsystemd)
add_executable(entity-manager src/EntityManager.cpp
src/Overlay.cpp
@@ -99,7 +119,7 @@
if(NOT YOCTO)
add_dependencies(entity-manager nlohmann-json)
add_dependencies(entity-manager boost-dbus)
- add_dependencies(fru-device boost-dbus)
+ add_dependencies(fru-device sdbusplus)
endif()
install (TARGETS fru-device entity-manager DESTINATION bin)
diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
index 223c5ea..a727693 100644
--- a/src/EntityManager.cpp
+++ b/src/EntityManager.cpp
@@ -220,58 +220,58 @@
{
switch (match.second.type())
{
- case nlohmann::json::value_t::string:
- {
- std::regex search(match.second.get<std::string>());
- std::smatch match;
-
- // convert value to string respresentation
- std::string probeValue = boost::apply_visitor(
- [](const auto &x) {
- return boost::lexical_cast<std::string>(x);
- },
- deviceValue->second);
- if (!std::regex_search(probeValue, match, search))
+ case nlohmann::json::value_t::string:
{
- deviceMatches = false;
+ std::regex search(match.second.get<std::string>());
+ std::smatch match;
+
+ // convert value to string respresentation
+ std::string probeValue = boost::apply_visitor(
+ [](const auto &x) {
+ return boost::lexical_cast<std::string>(x);
+ },
+ deviceValue->second);
+ if (!std::regex_search(probeValue, match, search))
+ {
+ deviceMatches = false;
+ break;
+ }
break;
}
- break;
- }
- case nlohmann::json::value_t::boolean:
- case nlohmann::json::value_t::number_unsigned:
- {
- unsigned int probeValue = boost::apply_visitor(
- VariantToUnsignedIntVisitor(), deviceValue->second);
-
- if (probeValue != match.second.get<unsigned int>())
+ case nlohmann::json::value_t::boolean:
+ case nlohmann::json::value_t::number_unsigned:
{
- deviceMatches = false;
- }
- break;
- }
- case nlohmann::json::value_t::number_integer:
- {
- int probeValue = boost::apply_visitor(VariantToIntVisitor(),
- deviceValue->second);
+ unsigned int probeValue = boost::apply_visitor(
+ VariantToUnsignedIntVisitor(), deviceValue->second);
- if (probeValue != match.second.get<int>())
- {
- deviceMatches = false;
+ if (probeValue != match.second.get<unsigned int>())
+ {
+ deviceMatches = false;
+ }
+ break;
}
- break;
- }
- case nlohmann::json::value_t::number_float:
- {
- float probeValue = boost::apply_visitor(
- VariantToFloatVisitor(), deviceValue->second);
+ case nlohmann::json::value_t::number_integer:
+ {
+ int probeValue = boost::apply_visitor(
+ VariantToIntVisitor(), deviceValue->second);
- if (probeValue != match.second.get<float>())
- {
- deviceMatches = false;
+ if (probeValue != match.second.get<int>())
+ {
+ deviceMatches = false;
+ }
+ break;
}
- break;
- }
+ case nlohmann::json::value_t::number_float:
+ {
+ float probeValue = boost::apply_visitor(
+ VariantToFloatVisitor(), deviceValue->second);
+
+ if (probeValue != match.second.get<float>())
+ {
+ deviceMatches = false;
+ }
+ break;
+ }
}
}
else
@@ -325,43 +325,44 @@
{
switch (probeType->second)
{
- case probe_type_codes::FALSE_T:
- {
- return false; // todo, actually evaluate?
- break;
- }
- case probe_type_codes::TRUE_T:
- {
- return true; // todo, actually evaluate?
- break;
- }
- case probe_type_codes::MATCH_ONE:
- {
- // set current value to last, this probe type shouldn't affect
- // the outcome
- cur = ret;
- matchOne = true;
- break;
- }
- /*case probe_type_codes::AND:
- break;
- case probe_type_codes::OR:
- break;
- // these are no-ops until the last command switch
- */
- case probe_type_codes::FOUND:
- {
- if (!std::regex_search(probe, match, command))
+ case probe_type_codes::FALSE_T:
{
- std::cerr << "found probe sytax error " << probe << "\n";
- return false;
+ return false; // todo, actually evaluate?
+ break;
}
- std::string commandStr = *(match.begin() + 1);
- boost::replace_all(commandStr, "'", "");
- cur = (std::find(PASSED_PROBES.begin(), PASSED_PROBES.end(),
- commandStr) != PASSED_PROBES.end());
- break;
- }
+ case probe_type_codes::TRUE_T:
+ {
+ return true; // todo, actually evaluate?
+ break;
+ }
+ case probe_type_codes::MATCH_ONE:
+ {
+ // set current value to last, this probe type shouldn't
+ // affect the outcome
+ cur = ret;
+ matchOne = true;
+ break;
+ }
+ /*case probe_type_codes::AND:
+ break;
+ case probe_type_codes::OR:
+ break;
+ // these are no-ops until the last command switch
+ */
+ case probe_type_codes::FOUND:
+ {
+ if (!std::regex_search(probe, match, command))
+ {
+ std::cerr << "found probe sytax error " << probe
+ << "\n";
+ return false;
+ }
+ std::string commandStr = *(match.begin() + 1);
+ boost::replace_all(commandStr, "'", "");
+ cur = (std::find(PASSED_PROBES.begin(), PASSED_PROBES.end(),
+ commandStr) != PASSED_PROBES.end());
+ break;
+ }
}
}
// look on dbus for object
@@ -400,15 +401,15 @@
// fact
switch (lastCommand)
{
- case probe_type_codes::AND:
- ret = cur && ret;
- break;
- case probe_type_codes::OR:
- ret = cur || ret;
- break;
- default:
- ret = cur;
- break;
+ case probe_type_codes::AND:
+ ret = cur && ret;
+ break;
+ case probe_type_codes::OR:
+ ret = cur || ret;
+ break;
+ default:
+ ret = cur;
+ break;
}
lastCommand = probeType != PROBE_TYPES.end()
? probeType->second
@@ -444,7 +445,7 @@
output.close();
auto flat = nlohmann::json::array();
- for (auto &pair : nlohmann::json::iterator_wrapper(systemConfiguration))
+ for (auto &pair : systemConfiguration.items())
{
auto value = pair.value();
auto exposes = value.find("exposes");
@@ -467,40 +468,40 @@
std::vector<std::pair<std::string, dbus::dbus_variant>> properties;
static size_t flushCount = 0;
- for (auto &dictPair : nlohmann::json::iterator_wrapper(dict))
+ for (auto &dictPair : dict.items())
{
switch (dictPair.value().type())
{
- case (nlohmann::json::value_t::boolean):
- {
- properties.emplace_back(std::string(dictPair.key()),
- dictPair.value().get<bool>());
- break;
- }
- case (nlohmann::json::value_t::number_integer):
- {
- properties.emplace_back(std::string(dictPair.key()),
- dictPair.value().get<int64_t>());
- break;
- }
- case (nlohmann::json::value_t::number_unsigned):
- {
- properties.emplace_back(std::string(dictPair.key()),
- dictPair.value().get<uint64_t>());
- break;
- }
- case (nlohmann::json::value_t::number_float):
- {
- properties.emplace_back(std::string(dictPair.key()),
- dictPair.value().get<float>());
- break;
- }
- case (nlohmann::json::value_t::string):
- {
- properties.emplace_back(std::string(dictPair.key()),
- dictPair.value().get<std::string>());
- break;
- }
+ case (nlohmann::json::value_t::boolean):
+ {
+ properties.emplace_back(std::string(dictPair.key()),
+ dictPair.value().get<bool>());
+ break;
+ }
+ case (nlohmann::json::value_t::number_integer):
+ {
+ properties.emplace_back(std::string(dictPair.key()),
+ dictPair.value().get<int64_t>());
+ break;
+ }
+ case (nlohmann::json::value_t::number_unsigned):
+ {
+ properties.emplace_back(std::string(dictPair.key()),
+ dictPair.value().get<uint64_t>());
+ break;
+ }
+ case (nlohmann::json::value_t::number_float):
+ {
+ properties.emplace_back(std::string(dictPair.key()),
+ dictPair.value().get<float>());
+ break;
+ }
+ case (nlohmann::json::value_t::string):
+ {
+ properties.emplace_back(std::string(dictPair.key()),
+ dictPair.value().get<std::string>());
+ break;
+ }
}
}
if (!properties.empty())
@@ -520,8 +521,7 @@
dbus::DbusObjectServer &objServer)
{
- for (auto &boardPair :
- nlohmann::json::iterator_wrapper(systemConfiguration))
+ for (auto &boardPair : systemConfiguration.items())
{
std::string boardKey = boardPair.key();
auto boardValues = boardPair.value();
@@ -554,7 +554,7 @@
boardObject->add_interface("xyz.openbmc_project.Inventory.Item." +
boardType);
populateInterfaceFromJson(boardIface.get(), boardValues, objServer);
- for (auto &boardField : nlohmann::json::iterator_wrapper(boardValues))
+ for (auto &boardField : boardValues.items())
{
if (boardField.value().type() == nlohmann::json::value_t::object)
{
@@ -606,7 +606,7 @@
populateInterfaceFromJson(itemIface.get(), item, objServer);
- for (auto &objectPair : nlohmann::json::iterator_wrapper(item))
+ for (auto &objectPair : item.items())
{
if (objectPair.value().type() ==
nlohmann::json::value_t::object)
@@ -870,8 +870,7 @@
std::string bind =
keyPair.key().substr(sizeof("bind_") - 1);
for (auto &configurationPair :
- nlohmann::json::iterator_wrapper(
- systemConfiguration))
+ systemConfiguration.items())
{
auto configListFind =
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
index 1fd7a37..781f7a1 100644
--- a/src/FruDevice.cpp
+++ b/src/FruDevice.cpp
@@ -17,9 +17,8 @@
#include <Utils.hpp>
#include <boost/container/flat_map.hpp>
#include <ctime>
-#include <dbus/connection.hpp>
-#include <dbus/endpoint.hpp>
-#include <dbus/message.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
#include <dbus/properties.hpp>
#include <fcntl.h>
#include <fstream>
@@ -41,7 +40,6 @@
static constexpr std::array<const char *, 5> FRU_AREAS = {
"INTERNAL", "CHASSIS", "BOARD", "PRODUCT", "MULTIRECORD"};
-const static constexpr char *POWER_OBJECT_NAME = "/org/openbmc/control/power0";
const static std::regex NON_ASCII_REGEX("[^\x01-\x7f]");
using DeviceMap = boost::container::flat_map<int, std::vector<char>>;
using BusMap = boost::container::flat_map<int, std::shared_ptr<DeviceMap>>;
@@ -238,7 +236,7 @@
return false;
}
std::vector<char>::const_iterator fruAreaOffsetField = fruBytes.begin();
- result["Common Format Version"] =
+ result["Common_Format_Version"] =
std::to_string(static_cast<int>(*fruAreaOffsetField));
const std::vector<const char *> *fieldData;
@@ -349,11 +347,11 @@
}
void AddFruObjectToDbus(
- std::shared_ptr<dbus::connection> dbusConn, std::vector<char> &device,
- dbus::DbusObjectServer &objServer,
+ std::shared_ptr<sdbusplus::asio::connection> dbusConn,
+ std::vector<char> &device, sdbusplus::asio::object_server &objServer,
boost::container::flat_map<std::pair<size_t, size_t>,
- std::shared_ptr<dbus::DbusObject>>
- &dbusObjectMap,
+ std::shared_ptr<sdbusplus::asio::dbus_interface>>
+ &dbusInterfaceMap,
int bus, size_t address)
{
boost::container::flat_map<std::string, std::string> formattedFru;
@@ -382,16 +380,15 @@
}
productName = "/xyz/openbmc_project/FruDevice/" + productName;
-
// avoid duplicates by checking to see if on a mux
if (bus > 0)
{
size_t index = 0;
- for (auto const &busObj : dbusObjectMap)
+ for (auto const &busIface : dbusInterfaceMap)
{
- if ((busObj.second->object_name == productName))
+ if ((busIface.second->get_object_path() == productName))
{
- if (isMuxBus(bus) && address == busObj.first.second)
+ if (isMuxBus(bus) && address == busIface.first.second)
{
continue;
}
@@ -409,17 +406,26 @@
}
}
}
- auto object = objServer.add_object(productName);
- dbusObjectMap[std::pair<size_t, size_t>(bus, address)] = object;
- auto iface = std::make_shared<dbus::DbusInterface>(
- "xyz.openbmc_project.FruDevice", dbusConn);
- object->register_interface(iface);
+ std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
+ objServer.add_interface(productName, "xyz.openbmc_project.FruDevice");
+ dbusInterfaceMap[std::pair<size_t, size_t>(bus, address)] = iface;
+
for (auto &property : formattedFru)
{
+
std::regex_replace(property.second.begin(), property.second.begin(),
property.second.end(), NON_ASCII_REGEX, "_");
- iface->set_property(property.first, property.second);
+ if (property.second.empty())
+ {
+ continue;
+ }
+ std::string key =
+ std::regex_replace(property.first, NON_ASCII_REGEX, "_");
+ if (!iface->register_property(key, property.second + '\0'))
+ {
+ std::cerr << "illegal key: " << key << "\n";
+ }
if (DEBUG)
{
std::cout << property.first << ": " << property.second << "\n";
@@ -430,11 +436,12 @@
{
std::stringstream data;
data << "0x" << std::hex << bus;
- iface->set_property("BUS", data.str());
+ iface->register_property("BUS", data.str());
data.str("");
data << "0x" << std::hex << address;
- iface->set_property("ADDRESS", data.str());
+ iface->register_property("ADDRESS", data.str());
}
+ iface->initialize();
}
static bool readBaseboardFru(std::vector<char> &baseboardFru)
@@ -456,12 +463,13 @@
return true;
}
-void rescanBusses(boost::container::flat_map<std::pair<size_t, size_t>,
- std::shared_ptr<dbus::DbusObject>>
- &dbusObjectMap,
- std::shared_ptr<dbus::connection> systemBus,
- dbus::DbusObjectServer &objServer,
- std::atomic_bool &pendingCallback)
+void rescanBusses(
+ boost::container::flat_map<std::pair<size_t, size_t>,
+ std::shared_ptr<sdbusplus::asio::dbus_interface>>
+ &dbusInterfaceMap,
+ std::shared_ptr<sdbusplus::asio::connection> systemBus,
+ sdbusplus::asio::object_server &objServer,
+ std::atomic_bool &pendingCallback)
{
do
@@ -481,12 +489,12 @@
std::sort(i2cBuses.begin(), i2cBuses.end());
BusMap busMap = FindI2CDevices(i2cBuses);
- for (auto &busObj : dbusObjectMap)
+ for (auto &busIface : dbusInterfaceMap)
{
- objServer.remove_object(busObj.second);
+ objServer.remove_interface(busIface.second);
}
- dbusObjectMap.clear();
+ dbusInterfaceMap.clear();
UNKNOWN_BUS_OBJECT_COUNT = 0;
for (auto &devicemap : busMap)
@@ -494,7 +502,7 @@
for (auto &device : *devicemap.second)
{
AddFruObjectToDbus(systemBus, device.second, objServer,
- dbusObjectMap, devicemap.first,
+ dbusInterfaceMap, devicemap.first,
device.first);
}
}
@@ -503,7 +511,7 @@
if (readBaseboardFru(baseboardFru))
{
AddFruObjectToDbus(systemBus, baseboardFru, objServer,
- dbusObjectMap, -1, -1);
+ dbusInterfaceMap, -1, -1);
}
} while (pendingCallback);
}
@@ -521,18 +529,19 @@
}
boost::asio::io_service io;
- auto systemBus = std::make_shared<dbus::connection>(io, dbus::bus::system);
- dbus::DbusObjectServer objServer(systemBus);
+ auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
+ auto objServer = sdbusplus::asio::object_server(systemBus);
systemBus->request_name("com.intel.FruDevice");
// this is a map with keys of pair(bus number, address) and values of the
// object on dbus
boost::container::flat_map<std::pair<size_t, size_t>,
- std::shared_ptr<dbus::DbusObject>>
- dbusObjectMap;
+ std::shared_ptr<sdbusplus::asio::dbus_interface>>
+ dbusInterfaceMap;
- auto iface = std::make_shared<dbus::DbusInterface>(
- "xyz.openbmc_project.FruDeviceManager", systemBus);
+ std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
+ objServer.add_interface("/xyz/openbmc_project/FruDevice",
+ "xyz.openbmc_project.FruDeviceManager");
std::atomic_bool threadRunning(false);
std::atomic_bool pendingCallback(false);
@@ -543,7 +552,7 @@
if (threadRunning.compare_exchange_strong(notRunning, true))
{
future = std::async(std::launch::async, [&] {
- rescanBusses(dbusObjectMap, systemBus, objServer,
+ rescanBusses(dbusInterfaceMap, systemBus, objServer,
pendingCallback);
threadRunning = false;
});
@@ -552,23 +561,18 @@
{
pendingCallback = true;
}
- return std::tuple<>(); // this is a bug in boost-dbus, needs some sort
- // of return
+ return;
});
+ iface->initialize();
- dbus::match powerChange(systemBus,
- "type='signal',path_namespace='" +
- std::string(POWER_OBJECT_NAME) + "'");
-
- dbus::filter filter(systemBus, [](dbus::message &m) {
- auto member = m.get_member();
- return member == "PropertiesChanged";
- });
- std::function<void(boost::system::error_code, dbus::message)> eventHandler =
- [&](boost::system::error_code ec, dbus::message s) {
- boost::container::flat_map<std::string, dbus::dbus_variant> values;
+ std::function<void(sdbusplus::message::message & message)> eventHandler =
+ [&](sdbusplus::message::message &message) {
std::string objectName;
- s.unpack(objectName, values);
+ boost::container::flat_map<
+ std::string, sdbusplus::message::variant<
+ std::string, bool, int64_t, uint64_t, double>>
+ values;
+ message.read(objectName, values);
auto findPgood = values.find("pgood");
if (findPgood != values.end())
{
@@ -576,7 +580,7 @@
if (threadRunning.compare_exchange_strong(notRunning, true))
{
future = std::async(std::launch::async, [&] {
- rescanBusses(dbusObjectMap, systemBus, objServer,
+ rescanBusses(dbusInterfaceMap, systemBus, objServer,
pendingCallback);
threadRunning = false;
});
@@ -586,10 +590,15 @@
pendingCallback = true;
}
}
- filter.async_dispatch(eventHandler);
-
};
- filter.async_dispatch(eventHandler);
+
+ sdbusplus::bus::match::match powerMatch = sdbusplus::bus::match::match(
+ static_cast<sdbusplus::bus::bus &>(*systemBus),
+ "type='signal',interface='org.freedesktop.DBus.Properties',path_"
+ "namespace='/org/openbmc/control/"
+ "power0',arg0='org.openbmc.control.Power'",
+ eventHandler);
+
int fd = inotify_init();
int wd = inotify_add_watch(fd, I2C_DEV_LOCATION,
IN_CREATE | IN_MOVED_TO | IN_DELETE);
@@ -614,13 +623,14 @@
pendingBuffer.data());
switch (iEvent->mask)
{
- case IN_CREATE:
- case IN_MOVED_TO:
- case IN_DELETE:
- if (boost::starts_with(std::string(iEvent->name), "i2c"))
- {
- devChange = true;
- }
+ case IN_CREATE:
+ case IN_MOVED_TO:
+ case IN_DELETE:
+ if (boost::starts_with(std::string(iEvent->name),
+ "i2c"))
+ {
+ devChange = true;
+ }
}
pendingBuffer.erase(0, sizeof(inotify_event) + iEvent->len);
@@ -631,7 +641,7 @@
{
future = std::async(std::launch::async, [&] {
std::this_thread::sleep_for(std::chrono::seconds(2));
- rescanBusses(dbusObjectMap, systemBus, objServer,
+ rescanBusses(dbusInterfaceMap, systemBus, objServer,
pendingCallback);
threadRunning = false;
});
@@ -645,14 +655,8 @@
};
dirWatch.async_read_some(boost::asio::buffer(readBuffer), watchI2cBusses);
-
// run the initial scan
- rescanBusses(dbusObjectMap, systemBus, objServer, pendingCallback);
-
- auto object = std::make_shared<dbus::DbusObject>(
- systemBus, "/xyz/openbmc_project/FruDevice");
- objServer.register_object(object);
- object->register_interface(iface);
+ rescanBusses(dbusInterfaceMap, systemBus, objServer, pendingCallback);
io.run();
return 0;