140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 39c929beaSShantappa Teekappanavar #pragma once 47a1dbc48SGeorge Liu 5*d7857201SEd Tanous #include "app.hpp" 6*d7857201SEd Tanous #include "async_resp.hpp" 7*d7857201SEd Tanous #include "dbus_singleton.hpp" 87a1dbc48SGeorge Liu #include "dbus_utility.hpp" 9*d7857201SEd Tanous #include "error_messages.hpp" 10539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 11*d7857201SEd Tanous #include "http_request.hpp" 12*d7857201SEd Tanous #include "http_response.hpp" 13*d7857201SEd Tanous #include "logging.hpp" 143ccb3adbSEd Tanous #include "query.hpp" 153ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 163ccb3adbSEd Tanous #include "utils/collection.hpp" 173ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 187a1dbc48SGeorge Liu 19*d7857201SEd Tanous #include <asm-generic/errno.h> 20*d7857201SEd Tanous 21*d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 22e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 23ef4c65b7SEd Tanous #include <boost/url/format.hpp> 24*d7857201SEd Tanous #include <boost/url/url.hpp> 25*d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 2689474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 279c929beaSShantappa Teekappanavar 287a1dbc48SGeorge Liu #include <array> 29*d7857201SEd Tanous #include <cmath> 30*d7857201SEd Tanous #include <memory> 31*d7857201SEd Tanous #include <string> 327a1dbc48SGeorge Liu #include <string_view> 337a1dbc48SGeorge Liu 349c929beaSShantappa Teekappanavar namespace redfish 359c929beaSShantappa Teekappanavar { 369c929beaSShantappa Teekappanavar /** 379c929beaSShantappa Teekappanavar * @brief Fill cable specific properties. 389c929beaSShantappa Teekappanavar * @param[in,out] resp HTTP response. 399c929beaSShantappa Teekappanavar * @param[in] ec Error code corresponding to Async method call. 409c929beaSShantappa Teekappanavar * @param[in] properties List of Cable Properties key/value pairs. 419c929beaSShantappa Teekappanavar */ 42bd79bce8SPatrick Williams inline void fillCableProperties( 43bd79bce8SPatrick Williams crow::Response& resp, const boost::system::error_code& ec, 449c929beaSShantappa Teekappanavar const dbus::utility::DBusPropertiesMap& properties) 459c929beaSShantappa Teekappanavar { 469c929beaSShantappa Teekappanavar if (ec) 479c929beaSShantappa Teekappanavar { 48f933a6a0SGunnar Mills BMCWEB_LOG_ERROR("DBUS response error {}", ec); 499c929beaSShantappa Teekappanavar messages::internalError(resp); 509c929beaSShantappa Teekappanavar return; 519c929beaSShantappa Teekappanavar } 529c929beaSShantappa Teekappanavar 5389474494SKrzysztof Grobelny const std::string* cableTypeDescription = nullptr; 5489474494SKrzysztof Grobelny const double* length = nullptr; 5589474494SKrzysztof Grobelny 5689474494SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 5789474494SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "CableTypeDescription", 5889474494SKrzysztof Grobelny cableTypeDescription, "Length", length); 5989474494SKrzysztof Grobelny 6089474494SKrzysztof Grobelny if (!success) 619c929beaSShantappa Teekappanavar { 629c929beaSShantappa Teekappanavar messages::internalError(resp); 639c929beaSShantappa Teekappanavar return; 649c929beaSShantappa Teekappanavar } 6589474494SKrzysztof Grobelny 6689474494SKrzysztof Grobelny if (cableTypeDescription != nullptr) 6789474494SKrzysztof Grobelny { 689c929beaSShantappa Teekappanavar resp.jsonValue["CableType"] = *cableTypeDescription; 699c929beaSShantappa Teekappanavar } 709c929beaSShantappa Teekappanavar 7189474494SKrzysztof Grobelny if (length != nullptr) 729c929beaSShantappa Teekappanavar { 7389474494SKrzysztof Grobelny if (!std::isfinite(*length)) 749c929beaSShantappa Teekappanavar { 75043360d0SShantappa Teekappanavar // Cable length is NaN by default, do not throw an error 76043360d0SShantappa Teekappanavar if (!std::isnan(*length)) 7789474494SKrzysztof Grobelny { 789c929beaSShantappa Teekappanavar messages::internalError(resp); 799c929beaSShantappa Teekappanavar return; 809c929beaSShantappa Teekappanavar } 81043360d0SShantappa Teekappanavar } 82043360d0SShantappa Teekappanavar else 83043360d0SShantappa Teekappanavar { 8489474494SKrzysztof Grobelny resp.jsonValue["LengthMeters"] = *length; 859c929beaSShantappa Teekappanavar } 869c929beaSShantappa Teekappanavar } 87043360d0SShantappa Teekappanavar } 889c929beaSShantappa Teekappanavar 899c929beaSShantappa Teekappanavar /** 909c929beaSShantappa Teekappanavar * @brief Api to get Cable properties. 919c929beaSShantappa Teekappanavar * @param[in,out] asyncResp Async HTTP response. 929c929beaSShantappa Teekappanavar * @param[in] cableObjectPath Object path of the Cable. 939c929beaSShantappa Teekappanavar * @param[in] serviceMap A map to hold Service and corresponding 949c929beaSShantappa Teekappanavar * interface list for the given cable id. 959c929beaSShantappa Teekappanavar */ 969c929beaSShantappa Teekappanavar inline void 979c929beaSShantappa Teekappanavar getCableProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 989c929beaSShantappa Teekappanavar const std::string& cableObjectPath, 999c929beaSShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap) 1009c929beaSShantappa Teekappanavar { 10162598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Properties for cable {}", cableObjectPath); 1029c929beaSShantappa Teekappanavar 1039c929beaSShantappa Teekappanavar for (const auto& [service, interfaces] : serviceMap) 1049c929beaSShantappa Teekappanavar { 1059c929beaSShantappa Teekappanavar for (const auto& interface : interfaces) 1069c929beaSShantappa Teekappanavar { 1070c2ba59dSAkshit Shah if (interface == "xyz.openbmc_project.Inventory.Item.Cable") 1089c929beaSShantappa Teekappanavar { 109deae6a78SEd Tanous dbus::utility::getAllProperties( 11089474494SKrzysztof Grobelny *crow::connections::systemBus, service, cableObjectPath, 11189474494SKrzysztof Grobelny interface, 1129c929beaSShantappa Teekappanavar [asyncResp]( 1135e7e2dc5SEd Tanous const boost::system::error_code& ec, 1149c929beaSShantappa Teekappanavar const dbus::utility::DBusPropertiesMap& properties) { 1159c929beaSShantappa Teekappanavar fillCableProperties(asyncResp->res, ec, properties); 11689474494SKrzysztof Grobelny }); 1179c929beaSShantappa Teekappanavar } 1180c2ba59dSAkshit Shah else if (interface == "xyz.openbmc_project.Inventory.Item") 1190c2ba59dSAkshit Shah { 120deae6a78SEd Tanous dbus::utility::getProperty<bool>( 121deae6a78SEd Tanous service, cableObjectPath, interface, "Present", 1220c2ba59dSAkshit Shah [asyncResp, cableObjectPath]( 1230c2ba59dSAkshit Shah const boost::system::error_code& ec, bool present) { 1240c2ba59dSAkshit Shah if (ec) 1250c2ba59dSAkshit Shah { 1260c2ba59dSAkshit Shah BMCWEB_LOG_DEBUG( 1270c2ba59dSAkshit Shah "get presence failed for Cable {} with error {}", 1280c2ba59dSAkshit Shah cableObjectPath, ec); 1290c2ba59dSAkshit Shah if (ec.value() != EBADR) 1300c2ba59dSAkshit Shah { 1310c2ba59dSAkshit Shah messages::internalError(asyncResp->res); 1320c2ba59dSAkshit Shah } 1330c2ba59dSAkshit Shah return; 1340c2ba59dSAkshit Shah } 1350c2ba59dSAkshit Shah 1360c2ba59dSAkshit Shah if (!present) 1370c2ba59dSAkshit Shah { 138539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 139539d8c6bSEd Tanous resource::State::Absent; 1400c2ba59dSAkshit Shah } 1410c2ba59dSAkshit Shah }); 1420c2ba59dSAkshit Shah } 1430c2ba59dSAkshit Shah } 1449c929beaSShantappa Teekappanavar } 1459c929beaSShantappa Teekappanavar } 1469c929beaSShantappa Teekappanavar 1479c929beaSShantappa Teekappanavar /** 1489c929beaSShantappa Teekappanavar * The Cable schema 1499c929beaSShantappa Teekappanavar */ 1509c929beaSShantappa Teekappanavar inline void requestRoutesCable(App& app) 1519c929beaSShantappa Teekappanavar { 1529c929beaSShantappa Teekappanavar BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/") 1539c929beaSShantappa Teekappanavar .privileges(redfish::privileges::getCable) 1549c929beaSShantappa Teekappanavar .methods(boost::beast::http::verb::get)( 15545ca1b86SEd Tanous [&app](const crow::Request& req, 1569c929beaSShantappa Teekappanavar const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1579c929beaSShantappa Teekappanavar const std::string& cableId) { 1583ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 15945ca1b86SEd Tanous { 16045ca1b86SEd Tanous return; 16145ca1b86SEd Tanous } 16262598e31SEd Tanous BMCWEB_LOG_DEBUG("Cable Id: {}", cableId); 163e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 164e99073f5SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cable"}; 165e99073f5SGeorge Liu dbus::utility::getSubTree( 166e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 1679c929beaSShantappa Teekappanavar [asyncResp, 168e99073f5SGeorge Liu cableId](const boost::system::error_code& ec, 169bd79bce8SPatrick Williams const dbus::utility::MapperGetSubTreeResponse& 170bd79bce8SPatrick Williams subtree) { 1719c929beaSShantappa Teekappanavar if (ec.value() == EBADR) 1729c929beaSShantappa Teekappanavar { 173bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Cable", 174bd79bce8SPatrick Williams cableId); 1759c929beaSShantappa Teekappanavar return; 1769c929beaSShantappa Teekappanavar } 1779c929beaSShantappa Teekappanavar 1789c929beaSShantappa Teekappanavar if (ec) 1799c929beaSShantappa Teekappanavar { 18062598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 1819c929beaSShantappa Teekappanavar messages::internalError(asyncResp->res); 1829c929beaSShantappa Teekappanavar return; 1839c929beaSShantappa Teekappanavar } 1849c929beaSShantappa Teekappanavar 1859c929beaSShantappa Teekappanavar for (const auto& [objectPath, serviceMap] : subtree) 1869c929beaSShantappa Teekappanavar { 1879c929beaSShantappa Teekappanavar sdbusplus::message::object_path path(objectPath); 1889c929beaSShantappa Teekappanavar if (path.filename() != cableId) 1899c929beaSShantappa Teekappanavar { 1909c929beaSShantappa Teekappanavar continue; 1919c929beaSShantappa Teekappanavar } 1929c929beaSShantappa Teekappanavar 193bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.type"] = 194bd79bce8SPatrick Williams "#Cable.v1_0_0.Cable"; 1959c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["@odata.id"] = 196bd79bce8SPatrick Williams boost::urls::format("/redfish/v1/Cables/{}", 197bd79bce8SPatrick Williams cableId); 1989c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["Id"] = cableId; 1999c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["Name"] = "Cable"; 200539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 201539d8c6bSEd Tanous resource::State::Enabled; 2029c929beaSShantappa Teekappanavar 203bd79bce8SPatrick Williams getCableProperties(asyncResp, objectPath, 204bd79bce8SPatrick Williams serviceMap); 2059c929beaSShantappa Teekappanavar return; 2069c929beaSShantappa Teekappanavar } 207bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Cable", 208bd79bce8SPatrick Williams cableId); 209e99073f5SGeorge Liu }); 2109c929beaSShantappa Teekappanavar }); 2119c929beaSShantappa Teekappanavar } 2129c929beaSShantappa Teekappanavar 2139c929beaSShantappa Teekappanavar /** 2149c929beaSShantappa Teekappanavar * Collection of Cable resource instances 2159c929beaSShantappa Teekappanavar */ 2169c929beaSShantappa Teekappanavar inline void requestRoutesCableCollection(App& app) 2179c929beaSShantappa Teekappanavar { 2189c929beaSShantappa Teekappanavar BMCWEB_ROUTE(app, "/redfish/v1/Cables/") 2199c929beaSShantappa Teekappanavar .privileges(redfish::privileges::getCableCollection) 2209c929beaSShantappa Teekappanavar .methods(boost::beast::http::verb::get)( 22145ca1b86SEd Tanous [&app](const crow::Request& req, 2229c929beaSShantappa Teekappanavar const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2233ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 22445ca1b86SEd Tanous { 22545ca1b86SEd Tanous return; 22645ca1b86SEd Tanous } 2279c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["@odata.type"] = 2289c929beaSShantappa Teekappanavar "#CableCollection.CableCollection"; 2299c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables"; 2309c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["Name"] = "Cable Collection"; 231bd79bce8SPatrick Williams asyncResp->res.jsonValue["Description"] = 232bd79bce8SPatrick Williams "Collection of Cable Entries"; 2337a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces{ 2347a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Cable"}; 2359c929beaSShantappa Teekappanavar collection_util::getCollectionMembers( 236bd79bce8SPatrick Williams asyncResp, boost::urls::url("/redfish/v1/Cables"), 237bd79bce8SPatrick Williams interfaces, "/xyz/openbmc_project/inventory"); 2389c929beaSShantappa Teekappanavar }); 2399c929beaSShantappa Teekappanavar } 2409c929beaSShantappa Teekappanavar 2419c929beaSShantappa Teekappanavar } // namespace redfish 242