140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
39c929beaSShantappa Teekappanavar #pragma once
47a1dbc48SGeorge Liu
5d7857201SEd Tanous #include "app.hpp"
6d7857201SEd Tanous #include "async_resp.hpp"
7d7857201SEd Tanous #include "dbus_singleton.hpp"
87a1dbc48SGeorge Liu #include "dbus_utility.hpp"
9d7857201SEd Tanous #include "error_messages.hpp"
10539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
11d7857201SEd Tanous #include "http_request.hpp"
12d7857201SEd Tanous #include "http_response.hpp"
13d7857201SEd 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
19d7857201SEd Tanous #include <asm-generic/errno.h>
20d7857201SEd Tanous
21d7857201SEd Tanous #include <boost/beast/http/verb.hpp>
22e99073f5SGeorge Liu #include <boost/system/error_code.hpp>
23ef4c65b7SEd Tanous #include <boost/url/format.hpp>
24d7857201SEd Tanous #include <boost/url/url.hpp>
25d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp>
2689474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
279c929beaSShantappa Teekappanavar
287a1dbc48SGeorge Liu #include <array>
29d7857201SEd Tanous #include <cmath>
30*ab8cbe45SMyung Bae #include <functional>
31d7857201SEd Tanous #include <memory>
32d7857201SEd Tanous #include <string>
337a1dbc48SGeorge Liu #include <string_view>
347a1dbc48SGeorge Liu
359c929beaSShantappa Teekappanavar namespace redfish
369c929beaSShantappa Teekappanavar {
37*ab8cbe45SMyung Bae
38*ab8cbe45SMyung Bae constexpr std::array<std::string_view, 1> cableInterfaces = {
39*ab8cbe45SMyung Bae "xyz.openbmc_project.Inventory.Item.Cable"};
40*ab8cbe45SMyung Bae
419c929beaSShantappa Teekappanavar /**
429c929beaSShantappa Teekappanavar * @brief Fill cable specific properties.
43*ab8cbe45SMyung Bae * @param[in,out] asyncResp Async HTTP response.
449c929beaSShantappa Teekappanavar * @param[in] ec Error code corresponding to Async method call.
459c929beaSShantappa Teekappanavar * @param[in] properties List of Cable Properties key/value pairs.
469c929beaSShantappa Teekappanavar */
fillCableProperties(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const boost::system::error_code & ec,const dbus::utility::DBusPropertiesMap & properties)47bd79bce8SPatrick Williams inline void fillCableProperties(
48*ab8cbe45SMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
49*ab8cbe45SMyung Bae const boost::system::error_code& ec,
509c929beaSShantappa Teekappanavar const dbus::utility::DBusPropertiesMap& properties)
519c929beaSShantappa Teekappanavar {
529c929beaSShantappa Teekappanavar if (ec)
539c929beaSShantappa Teekappanavar {
54f933a6a0SGunnar Mills BMCWEB_LOG_ERROR("DBUS response error {}", ec);
55*ab8cbe45SMyung Bae messages::internalError(asyncResp->res);
569c929beaSShantappa Teekappanavar return;
579c929beaSShantappa Teekappanavar }
589c929beaSShantappa Teekappanavar
5989474494SKrzysztof Grobelny const std::string* cableTypeDescription = nullptr;
6089474494SKrzysztof Grobelny const double* length = nullptr;
6189474494SKrzysztof Grobelny
6289474494SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow(
6389474494SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "CableTypeDescription",
6489474494SKrzysztof Grobelny cableTypeDescription, "Length", length);
6589474494SKrzysztof Grobelny
6689474494SKrzysztof Grobelny if (!success)
679c929beaSShantappa Teekappanavar {
68*ab8cbe45SMyung Bae messages::internalError(asyncResp->res);
699c929beaSShantappa Teekappanavar return;
709c929beaSShantappa Teekappanavar }
7189474494SKrzysztof Grobelny
7289474494SKrzysztof Grobelny if (cableTypeDescription != nullptr)
7389474494SKrzysztof Grobelny {
74*ab8cbe45SMyung Bae asyncResp->res.jsonValue["CableType"] = *cableTypeDescription;
759c929beaSShantappa Teekappanavar }
769c929beaSShantappa Teekappanavar
7789474494SKrzysztof Grobelny if (length != nullptr)
789c929beaSShantappa Teekappanavar {
7989474494SKrzysztof Grobelny if (!std::isfinite(*length))
809c929beaSShantappa Teekappanavar {
81043360d0SShantappa Teekappanavar // Cable length is NaN by default, do not throw an error
82043360d0SShantappa Teekappanavar if (!std::isnan(*length))
8389474494SKrzysztof Grobelny {
84*ab8cbe45SMyung Bae BMCWEB_LOG_ERROR("Cable length value is invalid");
85*ab8cbe45SMyung Bae messages::internalError(asyncResp->res);
869c929beaSShantappa Teekappanavar return;
879c929beaSShantappa Teekappanavar }
88043360d0SShantappa Teekappanavar }
89043360d0SShantappa Teekappanavar else
90043360d0SShantappa Teekappanavar {
91*ab8cbe45SMyung Bae asyncResp->res.jsonValue["LengthMeters"] = *length;
929c929beaSShantappa Teekappanavar }
939c929beaSShantappa Teekappanavar }
94043360d0SShantappa Teekappanavar }
959c929beaSShantappa Teekappanavar
fillCableHealthState(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & cableObjectPath,const std::string & service)96*ab8cbe45SMyung Bae inline void fillCableHealthState(
97*ab8cbe45SMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
98*ab8cbe45SMyung Bae const std::string& cableObjectPath, const std::string& service)
99*ab8cbe45SMyung Bae {
100*ab8cbe45SMyung Bae dbus::utility::getProperty<bool>(
101*ab8cbe45SMyung Bae *crow::connections::systemBus, service, cableObjectPath,
102*ab8cbe45SMyung Bae "xyz.openbmc_project.Inventory.Item", "Present",
103*ab8cbe45SMyung Bae [asyncResp,
104*ab8cbe45SMyung Bae cableObjectPath](const boost::system::error_code& ec, bool present) {
105*ab8cbe45SMyung Bae if (ec)
106*ab8cbe45SMyung Bae {
107*ab8cbe45SMyung Bae if (ec.value() != EBADR)
108*ab8cbe45SMyung Bae {
109*ab8cbe45SMyung Bae BMCWEB_LOG_ERROR(
110*ab8cbe45SMyung Bae "get presence failed for Cable {} with error {}",
111*ab8cbe45SMyung Bae cableObjectPath, ec.value());
112*ab8cbe45SMyung Bae messages::internalError(asyncResp->res);
113*ab8cbe45SMyung Bae }
114*ab8cbe45SMyung Bae return;
115*ab8cbe45SMyung Bae }
116*ab8cbe45SMyung Bae
117*ab8cbe45SMyung Bae if (!present)
118*ab8cbe45SMyung Bae {
119*ab8cbe45SMyung Bae asyncResp->res.jsonValue["Status"]["State"] =
120*ab8cbe45SMyung Bae resource::State::Absent;
121*ab8cbe45SMyung Bae }
122*ab8cbe45SMyung Bae });
123*ab8cbe45SMyung Bae }
124*ab8cbe45SMyung Bae
1259c929beaSShantappa Teekappanavar /**
1269c929beaSShantappa Teekappanavar * @brief Api to get Cable properties.
1279c929beaSShantappa Teekappanavar * @param[in,out] asyncResp Async HTTP response.
1289c929beaSShantappa Teekappanavar * @param[in] cableObjectPath Object path of the Cable.
1299c929beaSShantappa Teekappanavar * @param[in] serviceMap A map to hold Service and corresponding
1309c929beaSShantappa Teekappanavar * interface list for the given cable id.
1319c929beaSShantappa Teekappanavar */
getCableProperties(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & cableObjectPath,const dbus::utility::MapperServiceMap & serviceMap)132504af5a0SPatrick Williams inline void getCableProperties(
133504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1349c929beaSShantappa Teekappanavar const std::string& cableObjectPath,
1359c929beaSShantappa Teekappanavar const dbus::utility::MapperServiceMap& serviceMap)
1369c929beaSShantappa Teekappanavar {
13762598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Properties for cable {}", cableObjectPath);
1389c929beaSShantappa Teekappanavar
1399c929beaSShantappa Teekappanavar for (const auto& [service, interfaces] : serviceMap)
1409c929beaSShantappa Teekappanavar {
1419c929beaSShantappa Teekappanavar for (const auto& interface : interfaces)
1429c929beaSShantappa Teekappanavar {
1430c2ba59dSAkshit Shah if (interface == "xyz.openbmc_project.Inventory.Item.Cable")
1449c929beaSShantappa Teekappanavar {
145deae6a78SEd Tanous dbus::utility::getAllProperties(
14689474494SKrzysztof Grobelny *crow::connections::systemBus, service, cableObjectPath,
147*ab8cbe45SMyung Bae interface, std::bind_front(fillCableProperties, asyncResp));
1489c929beaSShantappa Teekappanavar }
1490c2ba59dSAkshit Shah else if (interface == "xyz.openbmc_project.Inventory.Item")
1500c2ba59dSAkshit Shah {
151*ab8cbe45SMyung Bae fillCableHealthState(asyncResp, cableObjectPath, service);
1520c2ba59dSAkshit Shah }
1530c2ba59dSAkshit Shah }
1549c929beaSShantappa Teekappanavar }
1559c929beaSShantappa Teekappanavar }
1569c929beaSShantappa Teekappanavar
afterHandleCableGet(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & cableId,const boost::system::error_code & ec,const dbus::utility::MapperGetSubTreeResponse & subtree)157*ab8cbe45SMyung Bae inline void afterHandleCableGet(
1589c929beaSShantappa Teekappanavar const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
159*ab8cbe45SMyung Bae const std::string& cableId, const boost::system::error_code& ec,
160*ab8cbe45SMyung Bae const dbus::utility::MapperGetSubTreeResponse& subtree)
16145ca1b86SEd Tanous {
1629c929beaSShantappa Teekappanavar if (ec.value() == EBADR)
1639c929beaSShantappa Teekappanavar {
164*ab8cbe45SMyung Bae messages::resourceNotFound(asyncResp->res, "Cable", cableId);
1659c929beaSShantappa Teekappanavar return;
1669c929beaSShantappa Teekappanavar }
1679c929beaSShantappa Teekappanavar
1689c929beaSShantappa Teekappanavar if (ec)
1699c929beaSShantappa Teekappanavar {
170*ab8cbe45SMyung Bae BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
1719c929beaSShantappa Teekappanavar messages::internalError(asyncResp->res);
1729c929beaSShantappa Teekappanavar return;
1739c929beaSShantappa Teekappanavar }
1749c929beaSShantappa Teekappanavar
1759c929beaSShantappa Teekappanavar for (const auto& [objectPath, serviceMap] : subtree)
1769c929beaSShantappa Teekappanavar {
1779c929beaSShantappa Teekappanavar sdbusplus::message::object_path path(objectPath);
1789c929beaSShantappa Teekappanavar if (path.filename() != cableId)
1799c929beaSShantappa Teekappanavar {
1809c929beaSShantappa Teekappanavar continue;
1819c929beaSShantappa Teekappanavar }
1829c929beaSShantappa Teekappanavar
183*ab8cbe45SMyung Bae asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable";
1849c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["@odata.id"] =
185*ab8cbe45SMyung Bae boost::urls::format("/redfish/v1/Cables/{}", cableId);
1869c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["Id"] = cableId;
1879c929beaSShantappa Teekappanavar asyncResp->res.jsonValue["Name"] = "Cable";
188*ab8cbe45SMyung Bae asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
1899c929beaSShantappa Teekappanavar
190*ab8cbe45SMyung Bae getCableProperties(asyncResp, objectPath, serviceMap);
1919c929beaSShantappa Teekappanavar return;
1929c929beaSShantappa Teekappanavar }
193*ab8cbe45SMyung Bae messages::resourceNotFound(asyncResp->res, "Cable", cableId);
194*ab8cbe45SMyung Bae }
195*ab8cbe45SMyung Bae
handleCableGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & cableId)196*ab8cbe45SMyung Bae inline void handleCableGet(App& app, const crow::Request& req,
197*ab8cbe45SMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
198*ab8cbe45SMyung Bae const std::string& cableId)
199*ab8cbe45SMyung Bae {
200*ab8cbe45SMyung Bae if (!redfish::setUpRedfishRoute(app, req, asyncResp))
201*ab8cbe45SMyung Bae {
202*ab8cbe45SMyung Bae return;
203*ab8cbe45SMyung Bae }
204*ab8cbe45SMyung Bae
205*ab8cbe45SMyung Bae BMCWEB_LOG_DEBUG("Cable Id: {}", cableId);
206*ab8cbe45SMyung Bae
207*ab8cbe45SMyung Bae dbus::utility::getSubTree(
208*ab8cbe45SMyung Bae "/xyz/openbmc_project/inventory", 0, cableInterfaces,
209*ab8cbe45SMyung Bae std::bind_front(afterHandleCableGet, asyncResp, cableId));
210*ab8cbe45SMyung Bae }
211*ab8cbe45SMyung Bae
handleCableCollectionGet(App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)212*ab8cbe45SMyung Bae inline void handleCableCollectionGet(
213*ab8cbe45SMyung Bae App& app, const crow::Request& req,
214*ab8cbe45SMyung Bae const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
215*ab8cbe45SMyung Bae {
216*ab8cbe45SMyung Bae if (!redfish::setUpRedfishRoute(app, req, asyncResp))
217*ab8cbe45SMyung Bae {
218*ab8cbe45SMyung Bae return;
219*ab8cbe45SMyung Bae }
220*ab8cbe45SMyung Bae
221*ab8cbe45SMyung Bae asyncResp->res.jsonValue["@odata.type"] =
222*ab8cbe45SMyung Bae "#CableCollection.CableCollection";
223*ab8cbe45SMyung Bae asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
224*ab8cbe45SMyung Bae asyncResp->res.jsonValue["Name"] = "Cable Collection";
225*ab8cbe45SMyung Bae asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries";
226*ab8cbe45SMyung Bae collection_util::getCollectionMembers(
227*ab8cbe45SMyung Bae asyncResp, boost::urls::url("/redfish/v1/Cables"), cableInterfaces,
228*ab8cbe45SMyung Bae "/xyz/openbmc_project/inventory");
229*ab8cbe45SMyung Bae }
230*ab8cbe45SMyung Bae
231*ab8cbe45SMyung Bae /**
232*ab8cbe45SMyung Bae * The Cable schema
233*ab8cbe45SMyung Bae */
requestRoutesCable(App & app)234*ab8cbe45SMyung Bae inline void requestRoutesCable(App& app)
235*ab8cbe45SMyung Bae {
236*ab8cbe45SMyung Bae BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/")
237*ab8cbe45SMyung Bae .privileges(redfish::privileges::getCable)
238*ab8cbe45SMyung Bae .methods(boost::beast::http::verb::get)(
239*ab8cbe45SMyung Bae std::bind_front(handleCableGet, std::ref(app)));
2409c929beaSShantappa Teekappanavar }
2419c929beaSShantappa Teekappanavar
2429c929beaSShantappa Teekappanavar /**
2439c929beaSShantappa Teekappanavar * Collection of Cable resource instances
2449c929beaSShantappa Teekappanavar */
requestRoutesCableCollection(App & app)2459c929beaSShantappa Teekappanavar inline void requestRoutesCableCollection(App& app)
2469c929beaSShantappa Teekappanavar {
2479c929beaSShantappa Teekappanavar BMCWEB_ROUTE(app, "/redfish/v1/Cables/")
2489c929beaSShantappa Teekappanavar .privileges(redfish::privileges::getCableCollection)
2499c929beaSShantappa Teekappanavar .methods(boost::beast::http::verb::get)(
250*ab8cbe45SMyung Bae std::bind_front(handleCableCollectionGet, std::ref(app)));
2519c929beaSShantappa Teekappanavar }
2529c929beaSShantappa Teekappanavar
2539c929beaSShantappa Teekappanavar } // namespace redfish
254