xref: /openbmc/bmcweb/features/redfish/lib/cable.hpp (revision d78572018fc2022091ff8b8eb5a7fef2172ba3d6)
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