blob: 4927916169dd066e2c6681dacde61b24d10964ec [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -06003#pragma once
George Liu7a1dbc42022-12-07 16:03:22 +08004
Ed Tanousd7857202025-01-28 15:32:26 -08005#include "app.hpp"
6#include "async_resp.hpp"
7#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +08008#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070010#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080011#include "http_request.hpp"
12#include "http_response.hpp"
13#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080014#include "query.hpp"
15#include "registries/privilege_registry.hpp"
16#include "utils/collection.hpp"
17#include "utils/dbus_utils.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080018
Ed Tanousd7857202025-01-28 15:32:26 -080019#include <asm-generic/errno.h>
20
21#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080022#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070023#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080024#include <boost/url/url.hpp>
25#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelny89474492022-09-06 16:30:38 +020026#include <sdbusplus/unpack_properties.hpp>
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060027
George Liu7a1dbc42022-12-07 16:03:22 +080028#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080029#include <cmath>
Myung Baeab8cbe42025-03-05 06:12:02 -080030#include <functional>
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <memory>
32#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080033#include <string_view>
34
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060035namespace redfish
36{
Myung Baeab8cbe42025-03-05 06:12:02 -080037
38constexpr std::array<std::string_view, 1> cableInterfaces = {
39 "xyz.openbmc_project.Inventory.Item.Cable"};
40
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060041/**
42 * @brief Fill cable specific properties.
Myung Baeab8cbe42025-03-05 06:12:02 -080043 * @param[in,out] asyncResp Async HTTP response.
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060044 * @param[in] ec Error code corresponding to Async method call.
45 * @param[in] properties List of Cable Properties key/value pairs.
46 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040047inline void fillCableProperties(
Myung Baeab8cbe42025-03-05 06:12:02 -080048 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
49 const boost::system::error_code& ec,
Patrick Williamsbd79bce2024-08-16 15:22:20 -040050 const dbus::utility::DBusPropertiesMap& properties)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060051{
52 if (ec)
53 {
Gunnar Millsf933a6a2024-03-28 21:55:01 -050054 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Myung Baeab8cbe42025-03-05 06:12:02 -080055 messages::internalError(asyncResp->res);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060056 return;
57 }
58
Krzysztof Grobelny89474492022-09-06 16:30:38 +020059 const std::string* cableTypeDescription = nullptr;
60 const double* length = nullptr;
61
62 const bool success = sdbusplus::unpackPropertiesNoThrow(
63 dbus_utils::UnpackErrorPrinter(), properties, "CableTypeDescription",
64 cableTypeDescription, "Length", length);
65
66 if (!success)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060067 {
Myung Baeab8cbe42025-03-05 06:12:02 -080068 messages::internalError(asyncResp->res);
Krzysztof Grobelny89474492022-09-06 16:30:38 +020069 return;
70 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060071
Krzysztof Grobelny89474492022-09-06 16:30:38 +020072 if (cableTypeDescription != nullptr)
73 {
Myung Baeab8cbe42025-03-05 06:12:02 -080074 asyncResp->res.jsonValue["CableType"] = *cableTypeDescription;
Krzysztof Grobelny89474492022-09-06 16:30:38 +020075 }
76
77 if (length != nullptr)
78 {
79 if (!std::isfinite(*length))
80 {
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050081 // Cable length is NaN by default, do not throw an error
82 if (!std::isnan(*length))
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060083 {
Myung Baeab8cbe42025-03-05 06:12:02 -080084 BMCWEB_LOG_ERROR("Cable length value is invalid");
85 messages::internalError(asyncResp->res);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060086 return;
87 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060088 }
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050089 else
90 {
Myung Baeab8cbe42025-03-05 06:12:02 -080091 asyncResp->res.jsonValue["LengthMeters"] = *length;
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050092 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060093 }
94}
95
Myung Baeab8cbe42025-03-05 06:12:02 -080096inline void fillCableHealthState(
97 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
98 const std::string& cableObjectPath, const std::string& service)
99{
100 dbus::utility::getProperty<bool>(
101 *crow::connections::systemBus, service, cableObjectPath,
102 "xyz.openbmc_project.Inventory.Item", "Present",
103 [asyncResp,
104 cableObjectPath](const boost::system::error_code& ec, bool present) {
105 if (ec)
106 {
107 if (ec.value() != EBADR)
108 {
109 BMCWEB_LOG_ERROR(
110 "get presence failed for Cable {} with error {}",
111 cableObjectPath, ec.value());
112 messages::internalError(asyncResp->res);
113 }
114 return;
115 }
116
117 if (!present)
118 {
119 asyncResp->res.jsonValue["Status"]["State"] =
120 resource::State::Absent;
121 }
122 });
123}
124
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600125/**
126 * @brief Api to get Cable properties.
127 * @param[in,out] asyncResp Async HTTP response.
128 * @param[in] cableObjectPath Object path of the Cable.
129 * @param[in] serviceMap A map to hold Service and corresponding
130 * interface list for the given cable id.
131 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500132inline void getCableProperties(
133 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
134 const std::string& cableObjectPath,
135 const dbus::utility::MapperServiceMap& serviceMap)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600136{
Ed Tanous62598e32023-07-17 17:06:25 -0700137 BMCWEB_LOG_DEBUG("Get Properties for cable {}", cableObjectPath);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600138
139 for (const auto& [service, interfaces] : serviceMap)
140 {
141 for (const auto& interface : interfaces)
142 {
Akshit Shah0c2ba592023-01-24 01:03:26 +0000143 if (interface == "xyz.openbmc_project.Inventory.Item.Cable")
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600144 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800145 dbus::utility::getAllProperties(
Akshit Shah0c2ba592023-01-24 01:03:26 +0000146 *crow::connections::systemBus, service, cableObjectPath,
Myung Baeab8cbe42025-03-05 06:12:02 -0800147 interface, std::bind_front(fillCableProperties, asyncResp));
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600148 }
Akshit Shah0c2ba592023-01-24 01:03:26 +0000149 else if (interface == "xyz.openbmc_project.Inventory.Item")
150 {
Myung Baeab8cbe42025-03-05 06:12:02 -0800151 fillCableHealthState(asyncResp, cableObjectPath, service);
Akshit Shah0c2ba592023-01-24 01:03:26 +0000152 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600153 }
154 }
155}
156
Myung Baeab8cbe42025-03-05 06:12:02 -0800157inline void afterHandleCableGet(
158 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
159 const std::string& cableId, const boost::system::error_code& ec,
160 const dbus::utility::MapperGetSubTreeResponse& subtree)
161{
162 if (ec.value() == EBADR)
163 {
164 messages::resourceNotFound(asyncResp->res, "Cable", cableId);
165 return;
166 }
167
168 if (ec)
169 {
170 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
171 messages::internalError(asyncResp->res);
172 return;
173 }
174
175 for (const auto& [objectPath, serviceMap] : subtree)
176 {
177 sdbusplus::message::object_path path(objectPath);
178 if (path.filename() != cableId)
179 {
180 continue;
181 }
182
183 asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable";
184 asyncResp->res.jsonValue["@odata.id"] =
185 boost::urls::format("/redfish/v1/Cables/{}", cableId);
186 asyncResp->res.jsonValue["Id"] = cableId;
187 asyncResp->res.jsonValue["Name"] = "Cable";
188 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
189
190 getCableProperties(asyncResp, objectPath, serviceMap);
191 return;
192 }
193 messages::resourceNotFound(asyncResp->res, "Cable", cableId);
194}
195
196inline void handleCableGet(App& app, const crow::Request& req,
197 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
198 const std::string& cableId)
199{
200 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
201 {
202 return;
203 }
204
205 BMCWEB_LOG_DEBUG("Cable Id: {}", cableId);
206
207 dbus::utility::getSubTree(
208 "/xyz/openbmc_project/inventory", 0, cableInterfaces,
209 std::bind_front(afterHandleCableGet, asyncResp, cableId));
210}
211
212inline void handleCableCollectionGet(
213 App& app, const crow::Request& req,
214 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
215{
216 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
217 {
218 return;
219 }
220
221 asyncResp->res.jsonValue["@odata.type"] =
222 "#CableCollection.CableCollection";
223 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
224 asyncResp->res.jsonValue["Name"] = "Cable Collection";
225 asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries";
226 collection_util::getCollectionMembers(
227 asyncResp, boost::urls::url("/redfish/v1/Cables"), cableInterfaces,
228 "/xyz/openbmc_project/inventory");
229}
230
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600231/**
232 * The Cable schema
233 */
234inline void requestRoutesCable(App& app)
235{
236 BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/")
237 .privileges(redfish::privileges::getCable)
238 .methods(boost::beast::http::verb::get)(
Myung Baeab8cbe42025-03-05 06:12:02 -0800239 std::bind_front(handleCableGet, std::ref(app)));
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600240}
241
242/**
243 * Collection of Cable resource instances
244 */
245inline void requestRoutesCableCollection(App& app)
246{
247 BMCWEB_ROUTE(app, "/redfish/v1/Cables/")
248 .privileges(redfish::privileges::getCableCollection)
249 .methods(boost::beast::http::verb::get)(
Myung Baeab8cbe42025-03-05 06:12:02 -0800250 std::bind_front(handleCableCollectionGet, std::ref(app)));
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600251}
252
253} // namespace redfish