Support the new association defs interface
An xyz.openbmc_project version of the org.openbmc_project.Associations
interface was just created:
xyz.openbmc_project.Association.Definitions
property: Associations
Support this interface as well as the original org.openbmc one.
Change-Id: Idc5a0e5afab51ec96f18a2759446707146b077d1
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/src/main.cpp b/src/main.cpp
index 5dd4698..e6ea2bb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -5,6 +5,7 @@
#include <tinyxml2.h>
#include <atomic>
+#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/container/flat_map.hpp>
#include <chrono>
@@ -128,7 +129,8 @@
void do_associations(sdbusplus::asio::connection* system_bus,
sdbusplus::asio::object_server& objectServer,
- const std::string& processName, const std::string& path)
+ const std::string& processName, const std::string& path,
+ const std::string& assocDefIface)
{
system_bus->async_method_call(
[&objectServer, path, processName](
@@ -146,7 +148,7 @@
associationOwners, associationInterfaces);
},
processName, path, "org.freedesktop.DBus.Properties", "Get",
- ASSOCIATIONS_INTERFACE, "associations");
+ assocDefIface, getAssocDefPropName(assocDefIface));
}
void do_introspect(sdbusplus::asio::connection* system_bus,
@@ -194,14 +196,13 @@
continue;
}
- std::string iface{iface_name};
-
thisPathMap[transaction->process_name].emplace(iface_name);
- if (std::strcmp(iface_name, ASSOCIATIONS_INTERFACE) == 0)
+ if (isAssocDefIface(iface_name))
{
do_associations(system_bus, objectServer,
- transaction->process_name, path);
+ transaction->process_name, path,
+ iface_name);
}
pElement = pElement->NextSiblingElement("interface");
@@ -543,7 +544,7 @@
continue;
}
- if (interface == ASSOCIATIONS_INTERFACE)
+ if (isAssocDefIface(interface))
{
removeAssociation(obj_path.str, sender, server,
associationOwners, associationInterfaces);
@@ -573,38 +574,52 @@
interfacesRemovedHandler);
std::function<void(sdbusplus::message::message & message)>
- associationChangedHandler =
- [&server, &name_owners](sdbusplus::message::message& message) {
- std::string objectName;
- boost::container::flat_map<
- std::string,
- sdbusplus::message::variant<std::vector<Association>>>
- values;
- message.read(objectName, values);
- auto findAssociations = values.find("associations");
- if (findAssociations != values.end())
- {
- std::vector<Association> associations =
- sdbusplus::message::variant_ns::get<
- std::vector<Association>>(findAssociations->second);
+ associationChangedHandler = [&server, &name_owners](
+ sdbusplus::message::message& message) {
+ std::string objectName;
+ boost::container::flat_map<
+ std::string,
+ sdbusplus::message::variant<std::vector<Association>>>
+ values;
+ message.read(objectName, values);
- std::string well_known;
- if (!getWellKnown(name_owners, message.get_sender(),
- well_known))
- {
- return;
- }
- associationChanged(server, associations, message.get_path(),
- well_known, associationOwners,
- associationInterfaces);
+ auto prop =
+ std::find_if(values.begin(), values.end(), [](const auto& v) {
+ using namespace boost::algorithm;
+ return to_lower_copy(v.first) == "associations";
+ });
+
+ if (prop != values.end())
+ {
+ std::vector<Association> associations =
+ sdbusplus::message::variant_ns::get<
+ std::vector<Association>>(prop->second);
+
+ std::string well_known;
+ if (!getWellKnown(name_owners, message.get_sender(),
+ well_known))
+ {
+ return;
}
- };
- sdbusplus::bus::match::match associationChanged(
+ associationChanged(server, associations, message.get_path(),
+ well_known, associationOwners,
+ associationInterfaces);
+ }
+ };
+ sdbusplus::bus::match::match assocChangedMatch(
static_cast<sdbusplus::bus::bus&>(*system_bus),
sdbusplus::bus::match::rules::interface(
"org.freedesktop.DBus.Properties") +
sdbusplus::bus::match::rules::member("PropertiesChanged") +
- sdbusplus::bus::match::rules::argN(0, ASSOCIATIONS_INTERFACE),
+ sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
+ associationChangedHandler);
+
+ sdbusplus::bus::match::match orgOpenbmcAssocChangedMatch(
+ static_cast<sdbusplus::bus::bus&>(*system_bus),
+ sdbusplus::bus::match::rules::interface(
+ "org.freedesktop.DBus.Properties") +
+ sdbusplus::bus::match::rules::member("PropertiesChanged") +
+ sdbusplus::bus::match::rules::argN(0, orgOpenBMCAssocDefsInterface),
associationChangedHandler);
std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
diff --git a/src/processing.cpp b/src/processing.cpp
index 6dd6493..3c7e7fb 100644
--- a/src/processing.cpp
+++ b/src/processing.cpp
@@ -64,8 +64,9 @@
auto ifaces = pathIt->second.find(wellKnown);
if (ifaces != pathIt->second.end())
{
- auto assoc = std::find(ifaces->second.begin(), ifaces->second.end(),
- ASSOCIATIONS_INTERFACE);
+ auto assoc = std::find_if(
+ ifaces->second.begin(), ifaces->second.end(),
+ [](const auto& iface) { return isAssocDefIface(iface); });
if (assoc != ifaces->second.end())
{
removeAssociation(pathIt->first, wellKnown, server, assocOwners,
@@ -98,13 +99,13 @@
{
ifaceList[wellKnown].emplace(interfacePair.first);
- if (interfacePair.first == ASSOCIATIONS_INTERFACE)
+ if (isAssocDefIface(interfacePair.first))
{
const sdbusplus::message::variant<std::vector<Association>>*
variantAssociations = nullptr;
for (const auto& interface : interfacePair.second)
{
- if (interface.first == "associations")
+ if (interface.first == getAssocDefPropName(interfacePair.first))
{
variantAssociations = &(interface.second);
}
diff --git a/src/processing.hpp b/src/processing.hpp
index d5ed2b4..475133d 100644
--- a/src/processing.hpp
+++ b/src/processing.hpp
@@ -4,13 +4,44 @@
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
+#include <cassert>
#include <string>
/** @brief Define white list and black list data structure */
using WhiteBlackList = boost::container::flat_set<std::string>;
-/** @brief Dbus interface which contains org.openbmc Associations */
-constexpr const char* ASSOCIATIONS_INTERFACE = "org.openbmc.Associations";
+/** @brief The old associations definitions interface */
+constexpr const char* orgOpenBMCAssocDefsInterface = "org.openbmc.Associations";
+/** @brief The new associations definitions interface */
+constexpr const char* assocDefsInterface =
+ "xyz.openbmc_project.Association.Definitions";
+
+/** @brief Says if the interface is the association definition interface.
+ * Supports either the new or old interface.
+ *
+ * @param[in] iface - the interface to check
+ * @return bool - if the interface is one of the association definition
+ * ones.
+ */
+inline bool isAssocDefIface(std::string_view iface)
+{
+ return (iface == assocDefsInterface) ||
+ (iface == orgOpenBMCAssocDefsInterface);
+}
+
+/** @brief Returns the property name used by the defs iface.
+ *
+ * The old interface broke convention and used a lower case property
+ * name. This was resolved with the new interface.
+ *
+ * @param[in] iface - the interface to check
+ * @return std::string - the property name
+ */
+inline std::string getAssocDefPropName(std::string_view iface)
+{
+ assert(isAssocDefIface(iface));
+ return (iface == assocDefsInterface) ? "Associations" : "associations";
+}
/** @brief interface_map_type is the underlying datastructure the mapper uses.
*
diff --git a/src/test/interfaces_added.cpp b/src/test/interfaces_added.cpp
index 6fbeead..a48c254 100644
--- a/src/test/interfaces_added.cpp
+++ b/src/test/interfaces_added.cpp
@@ -16,7 +16,8 @@
// This is the data structure that comes in via the InterfacesAdded
// signal
-InterfacesAdded createInterfacesAdded()
+InterfacesAdded createInterfacesAdded(const std::string& interface,
+ const std::string& property)
{
std::vector<Association> associations = {
{"inventory", "error",
@@ -25,8 +26,8 @@
associations};
std::vector<std::pair<
std::string, sdbusplus::message::variant<std::vector<Association>>>>
- vecMethToAssoc = {{"associations", sdbVecAssoc}};
- InterfacesAdded intfAdded = {{ASSOCIATIONS_INTERFACE, vecMethToAssoc}};
+ vecMethToAssoc = {{property, sdbVecAssoc}};
+ InterfacesAdded intfAdded = {{interface, vecMethToAssoc}};
return intfAdded;
}
@@ -36,7 +37,35 @@
interface_map_type interfaceMap;
AssociationOwnersType assocOwners;
AssociationInterfaces assocInterfaces;
- auto intfAdded = createInterfacesAdded();
+ auto intfAdded = createInterfacesAdded(
+ assocDefsInterface, getAssocDefPropName(assocDefsInterface));
+
+ processInterfaceAdded(interfaceMap, DEFAULT_SOURCE_PATH, intfAdded,
+ DEFAULT_DBUS_SVC, assocOwners, assocInterfaces,
+ *server);
+
+ // Interface map will get the following:
+ // /logging/entry/1 /logging/entry /logging/ /
+ // dump_InterfaceMapType(interfaceMap);
+ EXPECT_EQ(interfaceMap.size(), 4);
+
+ // New association ower created so ensure it now contains a single entry
+ // dump_AssociationOwnersType(assocOwners);
+ EXPECT_EQ(assocOwners.size(), 1);
+
+ // Ensure the 2 association interfaces were created
+ // dump_AssociationInterfaces(assocInterfaces);
+ EXPECT_EQ(assocInterfaces.size(), 2);
+}
+
+TEST_F(TestInterfacesAdded, OrgOpenBmcInterfacesAddedGoodPath)
+{
+ interface_map_type interfaceMap;
+ AssociationOwnersType assocOwners;
+ AssociationInterfaces assocInterfaces;
+ auto intfAdded = createInterfacesAdded(
+ orgOpenBMCAssocDefsInterface,
+ getAssocDefPropName(orgOpenBMCAssocDefsInterface));
processInterfaceAdded(interfaceMap, DEFAULT_SOURCE_PATH, intfAdded,
DEFAULT_DBUS_SVC, assocOwners, assocInterfaces,
diff --git a/src/test/name_change.cpp b/src/test/name_change.cpp
index f4a9662..a6d18e4 100644
--- a/src/test/name_change.cpp
+++ b/src/test/name_change.cpp
@@ -33,7 +33,7 @@
{":1.99", DEFAULT_DBUS_SVC}};
std::string oldOwner = {":1.99"};
boost::container::flat_set<std::string> assocInterfacesSet = {
- ASSOCIATIONS_INTERFACE};
+ assocDefsInterface};
// Build up these objects so that an associated interface will match
// with the associated owner being removed