blob: a44ac1a274622dbf333c282a41797925d1dc6409 [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>
30#include <memory>
31#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080032#include <string_view>
33
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060034namespace redfish
35{
36/**
37 * @brief Fill cable specific properties.
38 * @param[in,out] resp HTTP response.
39 * @param[in] ec Error code corresponding to Async method call.
40 * @param[in] properties List of Cable Properties key/value pairs.
41 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040042inline void fillCableProperties(
43 crow::Response& resp, const boost::system::error_code& ec,
44 const dbus::utility::DBusPropertiesMap& properties)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060045{
46 if (ec)
47 {
Gunnar Millsf933a6a2024-03-28 21:55:01 -050048 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060049 messages::internalError(resp);
50 return;
51 }
52
Krzysztof Grobelny89474492022-09-06 16:30:38 +020053 const std::string* cableTypeDescription = nullptr;
54 const double* length = nullptr;
55
56 const bool success = sdbusplus::unpackPropertiesNoThrow(
57 dbus_utils::UnpackErrorPrinter(), properties, "CableTypeDescription",
58 cableTypeDescription, "Length", length);
59
60 if (!success)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060061 {
Krzysztof Grobelny89474492022-09-06 16:30:38 +020062 messages::internalError(resp);
63 return;
64 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060065
Krzysztof Grobelny89474492022-09-06 16:30:38 +020066 if (cableTypeDescription != nullptr)
67 {
68 resp.jsonValue["CableType"] = *cableTypeDescription;
69 }
70
71 if (length != nullptr)
72 {
73 if (!std::isfinite(*length))
74 {
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050075 // Cable length is NaN by default, do not throw an error
76 if (!std::isnan(*length))
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060077 {
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050078 messages::internalError(resp);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060079 return;
80 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060081 }
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050082 else
83 {
84 resp.jsonValue["LengthMeters"] = *length;
85 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060086 }
87}
88
89/**
90 * @brief Api to get Cable properties.
91 * @param[in,out] asyncResp Async HTTP response.
92 * @param[in] cableObjectPath Object path of the Cable.
93 * @param[in] serviceMap A map to hold Service and corresponding
94 * interface list for the given cable id.
95 */
Patrick Williams504af5a2025-02-03 14:29:03 -050096inline void getCableProperties(
97 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
98 const std::string& cableObjectPath,
99 const dbus::utility::MapperServiceMap& serviceMap)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600100{
Ed Tanous62598e32023-07-17 17:06:25 -0700101 BMCWEB_LOG_DEBUG("Get Properties for cable {}", cableObjectPath);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600102
103 for (const auto& [service, interfaces] : serviceMap)
104 {
105 for (const auto& interface : interfaces)
106 {
Akshit Shah0c2ba592023-01-24 01:03:26 +0000107 if (interface == "xyz.openbmc_project.Inventory.Item.Cable")
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600108 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800109 dbus::utility::getAllProperties(
Akshit Shah0c2ba592023-01-24 01:03:26 +0000110 *crow::connections::systemBus, service, cableObjectPath,
111 interface,
112 [asyncResp](
113 const boost::system::error_code& ec,
114 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400115 fillCableProperties(asyncResp->res, ec, properties);
116 });
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600117 }
Akshit Shah0c2ba592023-01-24 01:03:26 +0000118 else if (interface == "xyz.openbmc_project.Inventory.Item")
119 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800120 dbus::utility::getProperty<bool>(
121 service, cableObjectPath, interface, "Present",
Akshit Shah0c2ba592023-01-24 01:03:26 +0000122 [asyncResp, cableObjectPath](
123 const boost::system::error_code& ec, bool present) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400124 if (ec)
Akshit Shah0c2ba592023-01-24 01:03:26 +0000125 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400126 BMCWEB_LOG_DEBUG(
127 "get presence failed for Cable {} with error {}",
128 cableObjectPath, ec);
129 if (ec.value() != EBADR)
130 {
131 messages::internalError(asyncResp->res);
132 }
133 return;
Akshit Shah0c2ba592023-01-24 01:03:26 +0000134 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600135
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400136 if (!present)
137 {
138 asyncResp->res.jsonValue["Status"]["State"] =
139 resource::State::Absent;
140 }
141 });
Akshit Shah0c2ba592023-01-24 01:03:26 +0000142 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600143 }
144 }
145}
146
147/**
148 * The Cable schema
149 */
150inline void requestRoutesCable(App& app)
151{
152 BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/")
153 .privileges(redfish::privileges::getCable)
154 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700155 [&app](const crow::Request& req,
156 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
157 const std::string& cableId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400158 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -0700159 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400160 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -0700161 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400162 BMCWEB_LOG_DEBUG("Cable Id: {}", cableId);
163 constexpr std::array<std::string_view, 1> interfaces = {
164 "xyz.openbmc_project.Inventory.Item.Cable"};
165 dbus::utility::getSubTree(
166 "/xyz/openbmc_project/inventory", 0, interfaces,
167 [asyncResp,
168 cableId](const boost::system::error_code& ec,
169 const dbus::utility::MapperGetSubTreeResponse&
170 subtree) {
171 if (ec.value() == EBADR)
172 {
173 messages::resourceNotFound(asyncResp->res, "Cable",
174 cableId);
175 return;
176 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600177
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400178 if (ec)
179 {
180 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
181 messages::internalError(asyncResp->res);
182 return;
183 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600184
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400185 for (const auto& [objectPath, serviceMap] : subtree)
186 {
187 sdbusplus::message::object_path path(objectPath);
188 if (path.filename() != cableId)
189 {
190 continue;
191 }
192
193 asyncResp->res.jsonValue["@odata.type"] =
194 "#Cable.v1_0_0.Cable";
195 asyncResp->res.jsonValue["@odata.id"] =
196 boost::urls::format("/redfish/v1/Cables/{}",
197 cableId);
198 asyncResp->res.jsonValue["Id"] = cableId;
199 asyncResp->res.jsonValue["Name"] = "Cable";
200 asyncResp->res.jsonValue["Status"]["State"] =
201 resource::State::Enabled;
202
203 getCableProperties(asyncResp, objectPath,
204 serviceMap);
205 return;
206 }
207 messages::resourceNotFound(asyncResp->res, "Cable",
208 cableId);
209 });
210 });
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600211}
212
213/**
214 * Collection of Cable resource instances
215 */
216inline void requestRoutesCableCollection(App& app)
217{
218 BMCWEB_ROUTE(app, "/redfish/v1/Cables/")
219 .privileges(redfish::privileges::getCableCollection)
220 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700221 [&app](const crow::Request& req,
222 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400223 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
224 {
225 return;
226 }
227 asyncResp->res.jsonValue["@odata.type"] =
228 "#CableCollection.CableCollection";
229 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
230 asyncResp->res.jsonValue["Name"] = "Cable Collection";
231 asyncResp->res.jsonValue["Description"] =
232 "Collection of Cable Entries";
233 constexpr std::array<std::string_view, 1> interfaces{
234 "xyz.openbmc_project.Inventory.Item.Cable"};
235 collection_util::getCollectionMembers(
236 asyncResp, boost::urls::url("/redfish/v1/Cables"),
237 interfaces, "/xyz/openbmc_project/inventory");
238 });
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600239}
240
241} // namespace redfish