forked from openbmc/bmcweb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New method to retrieve DBUS resources for systems
In an effort to support multi-host in bmcweb, a new method to retrieve dbus resources is needed. Since the long-term goal for bmcweb is to get rid of hardcoded URIs as much as possible to align with the redfish spec, this method shall handle single host as well. Initially bmcweb hardcoded object paths and services to retrieve various resources via dbus method calls. However, the introduction of multi host platforms also introduces new service names and object paths. Hardcoding them does not cut it anymore, since we don't necessarily know how they are called, nor should we do any assumptions on naming schemes by default. This method follows this idea and lets DBUS return needed paths and services, if any, primarily based on a systemName the user sends a request for. Change-Id: I67c17c3dd7a354fa9a2ebbc56d4def7a7e788909 Signed-off-by: Oliver Brewka <[email protected]>
- Loading branch information
Oliver Brewka
committed
Nov 3, 2024
1 parent
f408e67
commit eb9a959
Showing
4 changed files
with
1,264 additions
and
342 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
#include "dbus_utility.hpp" | ||
#include "error_messages.hpp" | ||
#include "human_sort.hpp" | ||
#include "str_utility.hpp" | ||
|
||
#include <boost/url/format.hpp> | ||
|
||
|
@@ -79,6 +80,11 @@ inline void handleSystemCollectionMembers( | |
asyncResp->res.jsonValue["[email protected]"] = membersArray.size(); | ||
} | ||
|
||
/** | ||
* Version 2 ---- WIP towards associations | ||
* | ||
*/ | ||
|
||
/** | ||
* @brief Populate the system collection members from a GetSubTreePaths search | ||
* of inventory | ||
|
@@ -105,4 +111,328 @@ inline void getSystemCollectionMembers( | |
"/xyz/openbmc_project/inventory", 0, interfaces, | ||
std::bind_front(handleSystemCollectionMembers, asyncResp)); | ||
} | ||
|
||
inline void getValidServiceName( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, const std::string& interface, | ||
const size_t computerSystemIndex, | ||
std::function<void(const sdbusplus::message::object_path& path, | ||
const std::string& service)>& callback, | ||
const boost::system::error_code& ec, | ||
const dbus::utility::MapperGetSubTreePathsResponse& paths) | ||
{ | ||
// match the found object paths against the index returned by | ||
// getManagedHostProperty. Then getObject call on found dbus object path and | ||
// the requested interface to find correct service name and finally call | ||
// callback with found object path and service | ||
|
||
BMCWEB_LOG_DEBUG("in getValidServiceName.."); | ||
sdbusplus::message::object_path path; | ||
|
||
if (ec) | ||
{ | ||
BMCWEB_LOG_ERROR("DBUS response error {}", ec); | ||
messages::resourceNotFound(asyncResp->res, "ComputerSystem", | ||
systemName); | ||
return; | ||
} | ||
|
||
BMCWEB_LOG_DEBUG("Got index: {}; Got paths:\n[", computerSystemIndex); | ||
for (const auto& p : paths) | ||
{ | ||
BMCWEB_LOG_DEBUG(" {}", p); | ||
} | ||
BMCWEB_LOG_DEBUG("]; determining dbus path.."); | ||
|
||
if (paths.size() == 1) | ||
{ | ||
// single host should only return a single path containing "host0" when | ||
// we run host specific queries | ||
path = paths.front(); | ||
} | ||
else | ||
{ | ||
// multi host will return multiple paths, find the correct one | ||
// naive approach, assuming that the chassis is fully slotted | ||
path = paths[computerSystemIndex - 1]; | ||
} | ||
|
||
BMCWEB_LOG_DEBUG("found path: {} .. calling getDbusObject", | ||
std::string(path)); | ||
std::array<std::string_view, 1> interfaces{interface}; | ||
dbus::utility::getDbusObject( | ||
path, interfaces, | ||
[asyncResp, systemName, callback = std::move(callback), | ||
path](const boost::system::error_code& ec2, | ||
const dbus::utility::MapperGetObject& object) { | ||
if (ec2 || object.empty()) | ||
{ | ||
BMCWEB_LOG_ERROR("DBUS response error on getDbusObject {}", | ||
ec2.value()); | ||
messages::internalError(asyncResp->res); | ||
return; | ||
} | ||
callback(path, object.begin()->first); | ||
}); | ||
} | ||
|
||
inline void getValidObjectPaths( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, const std::string& interface, | ||
std::function<void(const sdbusplus::message::object_path& path, | ||
const std::string& service)>& callback, | ||
const boost::system::error_code& ec, const size_t computerSystemIndex) | ||
|
||
{ | ||
// get all object paths that implement the requested interface | ||
|
||
BMCWEB_LOG_DEBUG("in getValidObjectPaths.. got index {}", | ||
computerSystemIndex); | ||
// getSubTreePaths search on interface to get all possible paths | ||
// afterwards match against the found index | ||
if (ec) | ||
{ | ||
BMCWEB_LOG_ERROR("DBUS response error {}", ec); | ||
messages::resourceNotFound(asyncResp->res, "ComputerSystem", | ||
systemName); | ||
return; | ||
} | ||
|
||
BMCWEB_LOG_DEBUG( | ||
"calling getSubTreePaths for interface: {} using getValidServiceName callback", | ||
interface); | ||
std::array<std::string_view, 1> interfaces{interface}; | ||
dbus::utility::getSubTreePaths( | ||
"/", 0, interfaces, | ||
std::bind_front(getValidServiceName, asyncResp, systemName, interface, | ||
computerSystemIndex, std::move(callback))); | ||
} | ||
|
||
inline void getManagedHostProperty( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, const std::string& interface, | ||
const boost::system::error_code& ec, const std::string& systemId, | ||
const std::string& serviceName, | ||
std::function<void(const sdbusplus::message::object_path& path, | ||
const std::string& service)>&& callback) | ||
{ | ||
// get HostIndex property associated with found system path | ||
|
||
BMCWEB_LOG_DEBUG("in getManagedHostProperty.."); | ||
if (ec) | ||
{ | ||
if (ec.value() == boost::system::errc::io_error) | ||
{ | ||
BMCWEB_LOG_DEBUG("EIO - System not found"); | ||
messages::resourceNotFound(asyncResp->res, "ComputerSystem", | ||
systemName); | ||
return; | ||
} | ||
|
||
BMCWEB_LOG_ERROR("DBus method call failed with error {}", ec.value()); | ||
messages::internalError(asyncResp->res); | ||
return; | ||
} | ||
if (systemId.empty() || serviceName.empty()) | ||
{ | ||
BMCWEB_LOG_WARNING("System not found"); | ||
messages::resourceNotFound(asyncResp->res, "ComputerSystem", | ||
systemName); | ||
return; | ||
} | ||
|
||
BMCWEB_LOG_DEBUG( | ||
"calling getProperty for HostIndex and binding getValidObjectPaths"); | ||
sdbusplus::asio::getProperty<uint64_t>( | ||
*crow::connections::systemBus, serviceName, systemId, | ||
"xyz.openbmc_project.Inventory.Decorator.ManagedHost", "HostIndex", | ||
std::bind_front(getValidObjectPaths, asyncResp, systemName, interface, | ||
std::move(callback))); | ||
} | ||
|
||
inline void afterGetValidSystemPaths( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, const std::string& interface, | ||
std::function<void(const sdbusplus::message::object_path& path, | ||
const std::string& service)>& callback, | ||
const boost::system::error_code& ec, | ||
const dbus::utility::MapperGetSubTreeResponse& subtree) | ||
{ | ||
// match systemName against found system paths | ||
|
||
BMCWEB_LOG_DEBUG("in afterGetValidSystemPaths"); | ||
std::string systemId; | ||
std::string serviceName; | ||
if (ec) | ||
{ | ||
getManagedHostProperty(asyncResp, systemName, interface, ec, systemId, | ||
serviceName, std::move(callback)); | ||
return; | ||
} | ||
|
||
for (const auto& [path, serviceMap] : subtree) | ||
{ | ||
systemId = sdbusplus::message::object_path(path).filename(); | ||
|
||
if (systemId == systemName) | ||
{ | ||
serviceName = serviceMap.begin()->first; | ||
systemId = path; | ||
break; | ||
} | ||
} | ||
BMCWEB_LOG_DEBUG( | ||
"found systemId: {}, serviceName: {} .. calling getManagedHostProperty", | ||
systemId, serviceName); | ||
|
||
getManagedHostProperty(asyncResp, systemName, interface, ec, systemId, | ||
serviceName, std::move(callback)); | ||
} | ||
|
||
inline void getValidSystemPaths( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, const std::string& interface, | ||
std::function<void(const sdbusplus::message::object_path& path, | ||
const std::string& service)>&& callback) | ||
{ | ||
// getSubTree call on ManagedHost dbus interface to retrieve all | ||
// available system paths | ||
BMCWEB_LOG_DEBUG( | ||
"in getValidSystemPaths: running getSubTree and binding afterGetValidSystemPaths"); | ||
constexpr std::array<std::string_view, 1> interfaces{ | ||
"xyz.openbmc_project.Inventory.Decorator.ManagedHost"}; | ||
dbus::utility::getSubTree( | ||
"/xyz/openbmc_project/inventory", 0, interfaces, | ||
std::bind_front(afterGetValidSystemPaths, asyncResp, systemName, | ||
interface, std::move(callback))); | ||
} | ||
|
||
/** | ||
* @brief Wrapper - Retrieve object path and associated service that implement | ||
* passed in interface | ||
* | ||
* @param[in] asyncResp Shared pointer for completing asynchronous calls | ||
* @param[in] systemName Name of the requested system | ||
* @param[in] interface D-Bus interface, to base search for path and service | ||
* on | ||
* @param[in] callback Function to call with the found path and service | ||
* | ||
* @return None. | ||
*/ | ||
inline void getComputerSystemDBusResourcesV2( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, const std::string& interface, | ||
std::function<void(const sdbusplus::message::object_path& path, | ||
const std::string& service)>&& callback) | ||
{ | ||
BMCWEB_LOG_DEBUG("calling getValidSystemPaths"); | ||
getValidSystemPaths(asyncResp, systemName, interface, std::move(callback)); | ||
} | ||
|
||
/** | ||
* Version 1 ---- WIP, manual path constructing via found HostIndex | ||
* | ||
*/ | ||
|
||
inline void getManagedHostPropertyV1( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, const boost::system::error_code& ec, | ||
const std::string& systemId, const std::string& serviceName, | ||
std::function<void(const uint64_t& computerSystemIndex)> callback) | ||
{ | ||
// get HostIndex property associated with found system path | ||
BMCWEB_LOG_DEBUG("in getManagedHostProperty.."); | ||
if (ec) | ||
{ | ||
if (ec.value() == boost::system::errc::io_error) | ||
{ | ||
BMCWEB_LOG_DEBUG("EIO - System not found"); | ||
messages::resourceNotFound(asyncResp->res, "ComputerSystem", | ||
systemName); | ||
return; | ||
} | ||
|
||
BMCWEB_LOG_ERROR("DBus method call failed with error {}", ec.value()); | ||
messages::internalError(asyncResp->res); | ||
return; | ||
} | ||
if (systemId.empty() || serviceName.empty()) | ||
{ | ||
BMCWEB_LOG_WARNING("System not found"); | ||
messages::resourceNotFound(asyncResp->res, "ComputerSystem", | ||
systemName); | ||
return; | ||
} | ||
|
||
BMCWEB_LOG_DEBUG( | ||
"calling getProperty for HostIndex and binding getValidObjectPaths"); | ||
sdbusplus::asio::getProperty<uint64_t>( | ||
*crow::connections::systemBus, serviceName, systemId, | ||
"xyz.openbmc_project.Inventory.Decorator.ManagedHost", "HostIndex", | ||
[asyncResp, systemName, serviceName, callback = std::move(callback)]( | ||
const boost::system::error_code& ec2, const uint64_t hostIndex) { | ||
if (ec2) | ||
{ | ||
BMCWEB_LOG_ERROR("DBUS response error {}", ec2); | ||
messages::resourceNotFound(asyncResp->res, "ComputerSystem", | ||
systemName); | ||
return; | ||
} | ||
|
||
callback(hostIndex); | ||
}); | ||
} | ||
|
||
inline void getValidSystemPathsV1( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, | ||
std::function<void(const uint64_t& computerSystemIndex)>&& callback) | ||
{ | ||
BMCWEB_LOG_DEBUG( | ||
"in getValidSystemPaths: running getSubTree and binding afterGetValidSystemPaths"); | ||
constexpr std::array<std::string_view, 1> interfaces{ | ||
"xyz.openbmc_project.Inventory.Decorator.ManagedHost"}; | ||
dbus::utility::getSubTree( | ||
"/xyz/openbmc_project/inventory", 0, interfaces, | ||
[asyncResp, systemName, callback = std::move(callback)]( | ||
const boost::system::error_code& ec, | ||
const dbus::utility::MapperGetSubTreeResponse& subtree) { | ||
BMCWEB_LOG_DEBUG("in afterGetValidSystemPaths"); | ||
std::string systemId; | ||
std::string serviceName; | ||
if (ec) | ||
{ | ||
getManagedHostPropertyV1(asyncResp, systemName, ec, systemId, | ||
serviceName, callback); | ||
return; | ||
} | ||
|
||
for (const auto& [path, serviceMap] : subtree) | ||
{ | ||
systemId = sdbusplus::message::object_path(path).filename(); | ||
|
||
if (systemId == systemName) | ||
{ | ||
serviceName = serviceMap.begin()->first; | ||
systemId = path; | ||
break; | ||
} | ||
} | ||
BMCWEB_LOG_DEBUG( | ||
"found systemId: {}, serviceName: {} .. calling getManagedHostProperty", | ||
systemId, serviceName); | ||
|
||
getManagedHostPropertyV1(asyncResp, systemName, ec, systemId, | ||
serviceName, callback); | ||
}); | ||
} | ||
|
||
inline void getComputerSystemIndexV1( | ||
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | ||
const std::string& systemName, | ||
std::function<void(const uint64_t& computerSystemIndex)>&& callback) | ||
{ | ||
getValidSystemPathsV1(asyncResp, systemName, std::move(callback)); | ||
} | ||
|
||
} // namespace redfish |
Oops, something went wrong.