xref: /openbmc/bmcweb/features/redfish/lib/cable.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
39c929beaSShantappa Teekappanavar #pragma once
47a1dbc48SGeorge Liu 
57a1dbc48SGeorge Liu #include "dbus_utility.hpp"
6539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
73ccb3adbSEd Tanous #include "query.hpp"
83ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
93ccb3adbSEd Tanous #include "utils/collection.hpp"
103ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
113ccb3adbSEd Tanous #include "utils/json_utils.hpp"
127a1dbc48SGeorge Liu 
13e99073f5SGeorge Liu #include <boost/system/error_code.hpp>
14ef4c65b7SEd Tanous #include <boost/url/format.hpp>
1589474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
1689474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
179c929beaSShantappa Teekappanavar 
187a1dbc48SGeorge Liu #include <array>
197a1dbc48SGeorge Liu #include <string_view>
207a1dbc48SGeorge Liu 
219c929beaSShantappa Teekappanavar namespace redfish
229c929beaSShantappa Teekappanavar {
239c929beaSShantappa Teekappanavar /**
249c929beaSShantappa Teekappanavar  * @brief Fill cable specific properties.
259c929beaSShantappa Teekappanavar  * @param[in,out]   resp        HTTP response.
269c929beaSShantappa Teekappanavar  * @param[in]       ec          Error code corresponding to Async method call.
279c929beaSShantappa Teekappanavar  * @param[in]       properties  List of Cable Properties key/value pairs.
289c929beaSShantappa Teekappanavar  */
29bd79bce8SPatrick Williams inline void fillCableProperties(
30bd79bce8SPatrick Williams     crow::Response& resp, const boost::system::error_code& ec,
319c929beaSShantappa Teekappanavar     const dbus::utility::DBusPropertiesMap& properties)
329c929beaSShantappa Teekappanavar {
339c929beaSShantappa Teekappanavar     if (ec)
349c929beaSShantappa Teekappanavar     {
35f933a6a0SGunnar Mills         BMCWEB_LOG_ERROR("DBUS response error {}", ec);
369c929beaSShantappa Teekappanavar         messages::internalError(resp);
379c929beaSShantappa Teekappanavar         return;
389c929beaSShantappa Teekappanavar     }
399c929beaSShantappa Teekappanavar 
4089474494SKrzysztof Grobelny     const std::string* cableTypeDescription = nullptr;
4189474494SKrzysztof Grobelny     const double* length = nullptr;
4289474494SKrzysztof Grobelny 
4389474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
4489474494SKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "CableTypeDescription",
4589474494SKrzysztof Grobelny         cableTypeDescription, "Length", length);
4689474494SKrzysztof Grobelny 
4789474494SKrzysztof Grobelny     if (!success)
489c929beaSShantappa Teekappanavar     {
499c929beaSShantappa Teekappanavar         messages::internalError(resp);
509c929beaSShantappa Teekappanavar         return;
519c929beaSShantappa Teekappanavar     }
5289474494SKrzysztof Grobelny 
5389474494SKrzysztof Grobelny     if (cableTypeDescription != nullptr)
5489474494SKrzysztof Grobelny     {
559c929beaSShantappa Teekappanavar         resp.jsonValue["CableType"] = *cableTypeDescription;
569c929beaSShantappa Teekappanavar     }
579c929beaSShantappa Teekappanavar 
5889474494SKrzysztof Grobelny     if (length != nullptr)
599c929beaSShantappa Teekappanavar     {
6089474494SKrzysztof Grobelny         if (!std::isfinite(*length))
619c929beaSShantappa Teekappanavar         {
62043360d0SShantappa Teekappanavar             // Cable length is NaN by default, do not throw an error
63043360d0SShantappa Teekappanavar             if (!std::isnan(*length))
6489474494SKrzysztof Grobelny             {
659c929beaSShantappa Teekappanavar                 messages::internalError(resp);
669c929beaSShantappa Teekappanavar                 return;
679c929beaSShantappa Teekappanavar             }
68043360d0SShantappa Teekappanavar         }
69043360d0SShantappa Teekappanavar         else
70043360d0SShantappa Teekappanavar         {
7189474494SKrzysztof Grobelny             resp.jsonValue["LengthMeters"] = *length;
729c929beaSShantappa Teekappanavar         }
739c929beaSShantappa Teekappanavar     }
74043360d0SShantappa Teekappanavar }
759c929beaSShantappa Teekappanavar 
769c929beaSShantappa Teekappanavar /**
779c929beaSShantappa Teekappanavar  * @brief Api to get Cable properties.
789c929beaSShantappa Teekappanavar  * @param[in,out]   asyncResp       Async HTTP response.
799c929beaSShantappa Teekappanavar  * @param[in]       cableObjectPath Object path of the Cable.
809c929beaSShantappa Teekappanavar  * @param[in]       serviceMap      A map to hold Service and corresponding
819c929beaSShantappa Teekappanavar  * interface list for the given cable id.
829c929beaSShantappa Teekappanavar  */
839c929beaSShantappa Teekappanavar inline void
849c929beaSShantappa Teekappanavar     getCableProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
859c929beaSShantappa Teekappanavar                        const std::string& cableObjectPath,
869c929beaSShantappa Teekappanavar                        const dbus::utility::MapperServiceMap& serviceMap)
879c929beaSShantappa Teekappanavar {
8862598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Properties for cable {}", cableObjectPath);
899c929beaSShantappa Teekappanavar 
909c929beaSShantappa Teekappanavar     for (const auto& [service, interfaces] : serviceMap)
919c929beaSShantappa Teekappanavar     {
929c929beaSShantappa Teekappanavar         for (const auto& interface : interfaces)
939c929beaSShantappa Teekappanavar         {
940c2ba59dSAkshit Shah             if (interface == "xyz.openbmc_project.Inventory.Item.Cable")
959c929beaSShantappa Teekappanavar             {
96deae6a78SEd Tanous                 dbus::utility::getAllProperties(
9789474494SKrzysztof Grobelny                     *crow::connections::systemBus, service, cableObjectPath,
9889474494SKrzysztof Grobelny                     interface,
999c929beaSShantappa Teekappanavar                     [asyncResp](
1005e7e2dc5SEd Tanous                         const boost::system::error_code& ec,
1019c929beaSShantappa Teekappanavar                         const dbus::utility::DBusPropertiesMap& properties) {
1029c929beaSShantappa Teekappanavar                         fillCableProperties(asyncResp->res, ec, properties);
10389474494SKrzysztof Grobelny                     });
1049c929beaSShantappa Teekappanavar             }
1050c2ba59dSAkshit Shah             else if (interface == "xyz.openbmc_project.Inventory.Item")
1060c2ba59dSAkshit Shah             {
107deae6a78SEd Tanous                 dbus::utility::getProperty<bool>(
108deae6a78SEd Tanous                     service, cableObjectPath, interface, "Present",
1090c2ba59dSAkshit Shah                     [asyncResp, cableObjectPath](
1100c2ba59dSAkshit Shah                         const boost::system::error_code& ec, bool present) {
1110c2ba59dSAkshit Shah                         if (ec)
1120c2ba59dSAkshit Shah                         {
1130c2ba59dSAkshit Shah                             BMCWEB_LOG_DEBUG(
1140c2ba59dSAkshit Shah                                 "get presence failed for Cable {} with error {}",
1150c2ba59dSAkshit Shah                                 cableObjectPath, ec);
1160c2ba59dSAkshit Shah                             if (ec.value() != EBADR)
1170c2ba59dSAkshit Shah                             {
1180c2ba59dSAkshit Shah                                 messages::internalError(asyncResp->res);
1190c2ba59dSAkshit Shah                             }
1200c2ba59dSAkshit Shah                             return;
1210c2ba59dSAkshit Shah                         }
1220c2ba59dSAkshit Shah 
1230c2ba59dSAkshit Shah                         if (!present)
1240c2ba59dSAkshit Shah                         {
125539d8c6bSEd Tanous                             asyncResp->res.jsonValue["Status"]["State"] =
126539d8c6bSEd Tanous                                 resource::State::Absent;
1270c2ba59dSAkshit Shah                         }
1280c2ba59dSAkshit Shah                     });
1290c2ba59dSAkshit Shah             }
1300c2ba59dSAkshit Shah         }
1319c929beaSShantappa Teekappanavar     }
1329c929beaSShantappa Teekappanavar }
1339c929beaSShantappa Teekappanavar 
1349c929beaSShantappa Teekappanavar /**
1359c929beaSShantappa Teekappanavar  * The Cable schema
1369c929beaSShantappa Teekappanavar  */
1379c929beaSShantappa Teekappanavar inline void requestRoutesCable(App& app)
1389c929beaSShantappa Teekappanavar {
1399c929beaSShantappa Teekappanavar     BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/")
1409c929beaSShantappa Teekappanavar         .privileges(redfish::privileges::getCable)
1419c929beaSShantappa Teekappanavar         .methods(boost::beast::http::verb::get)(
14245ca1b86SEd Tanous             [&app](const crow::Request& req,
1439c929beaSShantappa Teekappanavar                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1449c929beaSShantappa Teekappanavar                    const std::string& cableId) {
1453ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
14645ca1b86SEd Tanous                 {
14745ca1b86SEd Tanous                     return;
14845ca1b86SEd Tanous                 }
14962598e31SEd Tanous                 BMCWEB_LOG_DEBUG("Cable Id: {}", cableId);
150e99073f5SGeorge Liu                 constexpr std::array<std::string_view, 1> interfaces = {
151e99073f5SGeorge Liu                     "xyz.openbmc_project.Inventory.Item.Cable"};
152e99073f5SGeorge Liu                 dbus::utility::getSubTree(
153e99073f5SGeorge Liu                     "/xyz/openbmc_project/inventory", 0, interfaces,
1549c929beaSShantappa Teekappanavar                     [asyncResp,
155e99073f5SGeorge Liu                      cableId](const boost::system::error_code& ec,
156bd79bce8SPatrick Williams                               const dbus::utility::MapperGetSubTreeResponse&
157bd79bce8SPatrick Williams                                   subtree) {
1589c929beaSShantappa Teekappanavar                         if (ec.value() == EBADR)
1599c929beaSShantappa Teekappanavar                         {
160bd79bce8SPatrick Williams                             messages::resourceNotFound(asyncResp->res, "Cable",
161bd79bce8SPatrick Williams                                                        cableId);
1629c929beaSShantappa Teekappanavar                             return;
1639c929beaSShantappa Teekappanavar                         }
1649c929beaSShantappa Teekappanavar 
1659c929beaSShantappa Teekappanavar                         if (ec)
1669c929beaSShantappa Teekappanavar                         {
16762598e31SEd Tanous                             BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1689c929beaSShantappa Teekappanavar                             messages::internalError(asyncResp->res);
1699c929beaSShantappa Teekappanavar                             return;
1709c929beaSShantappa Teekappanavar                         }
1719c929beaSShantappa Teekappanavar 
1729c929beaSShantappa Teekappanavar                         for (const auto& [objectPath, serviceMap] : subtree)
1739c929beaSShantappa Teekappanavar                         {
1749c929beaSShantappa Teekappanavar                             sdbusplus::message::object_path path(objectPath);
1759c929beaSShantappa Teekappanavar                             if (path.filename() != cableId)
1769c929beaSShantappa Teekappanavar                             {
1779c929beaSShantappa Teekappanavar                                 continue;
1789c929beaSShantappa Teekappanavar                             }
1799c929beaSShantappa Teekappanavar 
180bd79bce8SPatrick Williams                             asyncResp->res.jsonValue["@odata.type"] =
181bd79bce8SPatrick Williams                                 "#Cable.v1_0_0.Cable";
1829c929beaSShantappa Teekappanavar                             asyncResp->res.jsonValue["@odata.id"] =
183bd79bce8SPatrick Williams                                 boost::urls::format("/redfish/v1/Cables/{}",
184bd79bce8SPatrick Williams                                                     cableId);
1859c929beaSShantappa Teekappanavar                             asyncResp->res.jsonValue["Id"] = cableId;
1869c929beaSShantappa Teekappanavar                             asyncResp->res.jsonValue["Name"] = "Cable";
187539d8c6bSEd Tanous                             asyncResp->res.jsonValue["Status"]["State"] =
188539d8c6bSEd Tanous                                 resource::State::Enabled;
1899c929beaSShantappa Teekappanavar 
190bd79bce8SPatrick Williams                             getCableProperties(asyncResp, objectPath,
191bd79bce8SPatrick Williams                                                serviceMap);
1929c929beaSShantappa Teekappanavar                             return;
1939c929beaSShantappa Teekappanavar                         }
194bd79bce8SPatrick Williams                         messages::resourceNotFound(asyncResp->res, "Cable",
195bd79bce8SPatrick Williams                                                    cableId);
196e99073f5SGeorge Liu                     });
1979c929beaSShantappa Teekappanavar             });
1989c929beaSShantappa Teekappanavar }
1999c929beaSShantappa Teekappanavar 
2009c929beaSShantappa Teekappanavar /**
2019c929beaSShantappa Teekappanavar  * Collection of Cable resource instances
2029c929beaSShantappa Teekappanavar  */
2039c929beaSShantappa Teekappanavar inline void requestRoutesCableCollection(App& app)
2049c929beaSShantappa Teekappanavar {
2059c929beaSShantappa Teekappanavar     BMCWEB_ROUTE(app, "/redfish/v1/Cables/")
2069c929beaSShantappa Teekappanavar         .privileges(redfish::privileges::getCableCollection)
2079c929beaSShantappa Teekappanavar         .methods(boost::beast::http::verb::get)(
20845ca1b86SEd Tanous             [&app](const crow::Request& req,
2099c929beaSShantappa Teekappanavar                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2103ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
21145ca1b86SEd Tanous                 {
21245ca1b86SEd Tanous                     return;
21345ca1b86SEd Tanous                 }
2149c929beaSShantappa Teekappanavar                 asyncResp->res.jsonValue["@odata.type"] =
2159c929beaSShantappa Teekappanavar                     "#CableCollection.CableCollection";
2169c929beaSShantappa Teekappanavar                 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
2179c929beaSShantappa Teekappanavar                 asyncResp->res.jsonValue["Name"] = "Cable Collection";
218bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Description"] =
219bd79bce8SPatrick Williams                     "Collection of Cable Entries";
2207a1dbc48SGeorge Liu                 constexpr std::array<std::string_view, 1> interfaces{
2217a1dbc48SGeorge Liu                     "xyz.openbmc_project.Inventory.Item.Cable"};
2229c929beaSShantappa Teekappanavar                 collection_util::getCollectionMembers(
223bd79bce8SPatrick Williams                     asyncResp, boost::urls::url("/redfish/v1/Cables"),
224bd79bce8SPatrick Williams                     interfaces, "/xyz/openbmc_project/inventory");
2259c929beaSShantappa Teekappanavar             });
2269c929beaSShantappa Teekappanavar }
2279c929beaSShantappa Teekappanavar 
2289c929beaSShantappa Teekappanavar } // namespace redfish
229