#pragma once #include "dbus_utility.hpp" #include "query.hpp" #include "registries/privilege_registry.hpp" #include "utils/collection.hpp" #include "utils/dbus_utils.hpp" #include "utils/json_utils.hpp" #include #include #include #include #include #include namespace redfish { /** * @brief Fill cable specific properties. * @param[in,out] resp HTTP response. * @param[in] ec Error code corresponding to Async method call. * @param[in] properties List of Cable Properties key/value pairs. */ inline void fillCableProperties(crow::Response& resp, const boost::system::error_code& ec, const dbus::utility::DBusPropertiesMap& properties) { if (ec) { BMCWEB_LOG_ERROR("DBUS response error {}", ec); messages::internalError(resp); return; } const std::string* cableTypeDescription = nullptr; const double* length = nullptr; const bool success = sdbusplus::unpackPropertiesNoThrow( dbus_utils::UnpackErrorPrinter(), properties, "CableTypeDescription", cableTypeDescription, "Length", length); if (!success) { messages::internalError(resp); return; } if (cableTypeDescription != nullptr) { resp.jsonValue["CableType"] = *cableTypeDescription; } if (length != nullptr) { if (!std::isfinite(*length)) { // Cable length is NaN by default, do not throw an error if (!std::isnan(*length)) { messages::internalError(resp); return; } } else { resp.jsonValue["LengthMeters"] = *length; } } } /** * @brief Api to get Cable properties. * @param[in,out] asyncResp Async HTTP response. * @param[in] cableObjectPath Object path of the Cable. * @param[in] serviceMap A map to hold Service and corresponding * interface list for the given cable id. */ inline void getCableProperties(const std::shared_ptr& asyncResp, const std::string& cableObjectPath, const dbus::utility::MapperServiceMap& serviceMap) { BMCWEB_LOG_DEBUG("Get Properties for cable {}", cableObjectPath); for (const auto& [service, interfaces] : serviceMap) { for (const auto& interface : interfaces) { if (interface == "xyz.openbmc_project.Inventory.Item.Cable") { sdbusplus::asio::getAllProperties( *crow::connections::systemBus, service, cableObjectPath, interface, [asyncResp]( const boost::system::error_code& ec, const dbus::utility::DBusPropertiesMap& properties) { fillCableProperties(asyncResp->res, ec, properties); }); } else if (interface == "xyz.openbmc_project.Inventory.Item") { sdbusplus::asio::getProperty( *crow::connections::systemBus, service, cableObjectPath, interface, "Present", [asyncResp, cableObjectPath]( const boost::system::error_code& ec, bool present) { if (ec) { BMCWEB_LOG_DEBUG( "get presence failed for Cable {} with error {}", cableObjectPath, ec); if (ec.value() != EBADR) { messages::internalError(asyncResp->res); } return; } if (!present) { asyncResp->res.jsonValue["Status"]["State"] = "Absent"; } }); } } } } /** * The Cable schema */ inline void requestRoutesCable(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Cables//") .privileges(redfish::privileges::getCable) .methods(boost::beast::http::verb::get)( [&app](const crow::Request& req, const std::shared_ptr& asyncResp, const std::string& cableId) { if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { return; } BMCWEB_LOG_DEBUG("Cable Id: {}", cableId); constexpr std::array interfaces = { "xyz.openbmc_project.Inventory.Item.Cable"}; dbus::utility::getSubTree( "/xyz/openbmc_project/inventory", 0, interfaces, [asyncResp, cableId](const boost::system::error_code& ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { if (ec.value() == EBADR) { messages::resourceNotFound(asyncResp->res, "Cable", cableId); return; } if (ec) { BMCWEB_LOG_ERROR("DBUS response error {}", ec); messages::internalError(asyncResp->res); return; } for (const auto& [objectPath, serviceMap] : subtree) { sdbusplus::message::object_path path(objectPath); if (path.filename() != cableId) { continue; } asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable"; asyncResp->res.jsonValue["@odata.id"] = boost::urls::format("/redfish/v1/Cables/{}", cableId); asyncResp->res.jsonValue["Id"] = cableId; asyncResp->res.jsonValue["Name"] = "Cable"; asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; getCableProperties(asyncResp, objectPath, serviceMap); return; } messages::resourceNotFound(asyncResp->res, "Cable", cableId); }); }); } /** * Collection of Cable resource instances */ inline void requestRoutesCableCollection(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Cables/") .privileges(redfish::privileges::getCableCollection) .methods(boost::beast::http::verb::get)( [&app](const crow::Request& req, const std::shared_ptr& asyncResp) { if (!redfish::setUpRedfishRoute(app, req, asyncResp)) { return; } asyncResp->res.jsonValue["@odata.type"] = "#CableCollection.CableCollection"; asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables"; asyncResp->res.jsonValue["Name"] = "Cable Collection"; asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries"; constexpr std::array interfaces{ "xyz.openbmc_project.Inventory.Item.Cable"}; collection_util::getCollectionMembers( asyncResp, boost::urls::url("/redfish/v1/Cables"), interfaces, "/xyz/openbmc_project/inventory"); }); } } // namespace redfish