mapper: Add GetAssociatedSubTreePathsById and GetAssociatedSubTreeById
dbus-interface change in:
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/69999
This commit implements two new methods: GetAssociatedSubTreePathsById
and GetAssociatedSubTreeById. These methods retrieve the paths of
associated endpoints corresponding to the provided identifier, filtering
based on their association with specified endpoint interfaces.
GetAssociatedSubTreePathsById returns the D-Bus paths of associated
endpoints, while GetAssociatedSubTreeById retrieves a dictionary of
D-Bus paths of associated endpoints mapped to corresponding services
associated with the provided identifier.
Tested:
'''
busctl call -j "xyz.openbmc_project.ObjectMapper" "/xyz/openbmc_project/object_mapper" \
"xyz.openbmc_project.ObjectMapper" "GetAssociatedSubTreePathsById" ssassas \
"chassis" \
"/xyz/openbmc_project/inventory" \
1 "xyz.openbmc_project.Inventory.Item.Chassis" \
"powered_by" \
1 "xyz.openbmc_project.Inventory.Item.PowerSupply"
{
"type" : "as",
"data" : [
[
"/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply2",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply3"
]
]
}
'''
Another example.
```
busctl call -j xyz.openbmc_project.ObjectMapper /xyz/openbmc_project/object_mapper \
xyz.openbmc_project.ObjectMapper GetAssociatedSubTreePathsById ssassas \
disk_backplane0 \
/xyz/openbmc_project/inventory \
1 xyz.openbmc_project.Inventory.Item.FabricAdapter \
connecting \
1 xyz.openbmc_project.Inventory.Connector.Port
{
"type" : "as",
"data" : [
[
"/xyz/openbmc_project/inventory/system/chassis/motherboard/disk_backplane0/dp0_connector0",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/disk_backplane0/dp0_connector1",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/disk_backplane0/dp0_connector2",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/disk_backplane0/dp0_connector3",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/disk_backplane0/dp0_connector4",
"/xyz/openbmc_project/inventory/system/chassis/motherboard/disk_backplane0/dp0_connector5"
]
]
}
```
Change-Id: Id55a9b41fe70f7204543d92b5396888f6914a1d4
Signed-off-by: Lakshmi Yadlapati <lakshmiy@us.ibm.com>
Signed-off-by: Myung Bae <myungbae@us.ibm.com>
diff --git a/src/handler.cpp b/src/handler.cpp
index 5983ad9..2c4b5d7 100644
--- a/src/handler.cpp
+++ b/src/handler.cpp
@@ -336,3 +336,118 @@
}
return output;
}
+
+// This function works like getSubTreePaths() but only matching id with
+// the leaf-name instead of full path.
+std::vector<std::string> getSubTreePathsById(
+ const InterfaceMapType& interfaceMap, const std::string& id,
+ const std::string& objectPath, std::vector<std::string>& interfaces)
+{
+ std::sort(interfaces.begin(), interfaces.end());
+
+ std::string localObjectPath = objectPath;
+
+ if (!localObjectPath.ends_with("/"))
+ {
+ localObjectPath += "/";
+ }
+ std::string_view objectPathStripped =
+ std::string_view(localObjectPath).substr(0, localObjectPath.size() - 1);
+
+ if (!objectPathStripped.empty() &&
+ interfaceMap.find(objectPathStripped) == interfaceMap.end())
+ {
+ throw sdbusplus::xyz::openbmc_project::Common::Error::
+ ResourceNotFound();
+ }
+
+ std::vector<std::string> output;
+ for (const auto& path : interfaceMap)
+ {
+ const auto& thisPath = path.first;
+
+ // Skip exact match on stripped search term or
+ // the path does not end with the id
+ if (thisPath == objectPathStripped || !thisPath.ends_with("/" + id))
+ {
+ continue;
+ }
+
+ if (thisPath.starts_with(objectPath))
+ {
+ for (const auto& interfaceMap : path.second)
+ {
+ std::vector<std::string> tempoutput(
+ std::min(interfaces.size(), interfaceMap.second.size()));
+ if (std::set_intersection(
+ interfaces.begin(), interfaces.end(),
+ interfaceMap.second.begin(), interfaceMap.second.end(),
+ tempoutput.begin()) != tempoutput.begin())
+ {
+ output.emplace_back(thisPath);
+ break;
+ }
+ }
+ }
+ }
+ if (output.empty())
+ {
+ throw sdbusplus::xyz::openbmc_project::Common::Error::
+ ResourceNotFound();
+ }
+ return output;
+}
+
+std::vector<InterfaceMapType::value_type> getAssociatedSubTreeById(
+ const InterfaceMapType& interfaceMap,
+ const AssociationMaps& associationMaps, const std::string& id,
+ const std::string& objectPath, std::vector<std::string>& subtreeInterfaces,
+ const std::string& association,
+ std::vector<std::string>& endpointInterfaces)
+{
+ std::vector<std::string> subtreePaths =
+ getSubTreePathsById(interfaceMap, id, objectPath, subtreeInterfaces);
+
+ std::vector<InterfaceMapType::value_type> output;
+ for (const auto& subtreePath : subtreePaths)
+ {
+ // Form the association path
+ std::string associationPathStr = subtreePath + "/" + association;
+ sdbusplus::message::object_path associationPath(associationPathStr);
+
+ auto associatedSubTree =
+ getAssociatedSubTree(interfaceMap, associationMaps, associationPath,
+ objectPath, 0, endpointInterfaces);
+
+ output.insert(output.end(), associatedSubTree.begin(),
+ associatedSubTree.end());
+ }
+ return output;
+}
+
+std::vector<std::string> getAssociatedSubTreePathsById(
+ const InterfaceMapType& interfaceMap,
+ const AssociationMaps& associationMaps, const std::string& id,
+ const std::string& objectPath, std::vector<std::string>& subtreeInterfaces,
+ const std::string& association,
+ std::vector<std::string>& endpointInterfaces)
+{
+ std::vector<std::string> subtreePaths =
+ getSubTreePathsById(interfaceMap, id, objectPath, subtreeInterfaces);
+ std::vector<std::string> output;
+ for (const auto& subtreePath : subtreePaths)
+ {
+ // Form the association path
+ std::string associationPathStr = subtreePath + "/" + association;
+ sdbusplus::message::object_path associationPath(associationPathStr);
+
+ auto associatedSubTree = getAssociatedSubTreePaths(
+ interfaceMap, associationMaps, associationPath, objectPath, 0,
+ endpointInterfaces);
+
+ output.insert(output.end(), associatedSubTree.begin(),
+ associatedSubTree.end());
+ }
+
+ return output;
+}