blob: b92848b98fab67be144b90963f925d8d21dc5914 [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
5#include "dbus_utility.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -07006#include "generated/enums/resource.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08007#include "query.hpp"
8#include "registries/privilege_registry.hpp"
9#include "utils/collection.hpp"
10#include "utils/dbus_utils.hpp"
11#include "utils/json_utils.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080012
George Liue99073f2022-12-09 11:06:16 +080013#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070014#include <boost/url/format.hpp>
Krzysztof Grobelny89474492022-09-06 16:30:38 +020015#include <sdbusplus/asio/property.hpp>
16#include <sdbusplus/unpack_properties.hpp>
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060017
George Liu7a1dbc42022-12-07 16:03:22 +080018#include <array>
19#include <string_view>
20
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060021namespace redfish
22{
23/**
24 * @brief Fill cable specific properties.
25 * @param[in,out] resp HTTP response.
26 * @param[in] ec Error code corresponding to Async method call.
27 * @param[in] properties List of Cable Properties key/value pairs.
28 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040029inline void fillCableProperties(
30 crow::Response& resp, const boost::system::error_code& ec,
31 const dbus::utility::DBusPropertiesMap& properties)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060032{
33 if (ec)
34 {
Gunnar Millsf933a6a2024-03-28 21:55:01 -050035 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060036 messages::internalError(resp);
37 return;
38 }
39
Krzysztof Grobelny89474492022-09-06 16:30:38 +020040 const std::string* cableTypeDescription = nullptr;
41 const double* length = nullptr;
42
43 const bool success = sdbusplus::unpackPropertiesNoThrow(
44 dbus_utils::UnpackErrorPrinter(), properties, "CableTypeDescription",
45 cableTypeDescription, "Length", length);
46
47 if (!success)
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060048 {
Krzysztof Grobelny89474492022-09-06 16:30:38 +020049 messages::internalError(resp);
50 return;
51 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060052
Krzysztof Grobelny89474492022-09-06 16:30:38 +020053 if (cableTypeDescription != nullptr)
54 {
55 resp.jsonValue["CableType"] = *cableTypeDescription;
56 }
57
58 if (length != nullptr)
59 {
60 if (!std::isfinite(*length))
61 {
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050062 // Cable length is NaN by default, do not throw an error
63 if (!std::isnan(*length))
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060064 {
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050065 messages::internalError(resp);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060066 return;
67 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060068 }
Shantappa Teekappanavar043360d2022-11-03 13:37:24 -050069 else
70 {
71 resp.jsonValue["LengthMeters"] = *length;
72 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060073 }
74}
75
76/**
77 * @brief Api to get Cable properties.
78 * @param[in,out] asyncResp Async HTTP response.
79 * @param[in] cableObjectPath Object path of the Cable.
80 * @param[in] serviceMap A map to hold Service and corresponding
81 * interface list for the given cable id.
82 */
83inline void
84 getCableProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
85 const std::string& cableObjectPath,
86 const dbus::utility::MapperServiceMap& serviceMap)
87{
Ed Tanous62598e32023-07-17 17:06:25 -070088 BMCWEB_LOG_DEBUG("Get Properties for cable {}", cableObjectPath);
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060089
90 for (const auto& [service, interfaces] : serviceMap)
91 {
92 for (const auto& interface : interfaces)
93 {
Akshit Shah0c2ba592023-01-24 01:03:26 +000094 if (interface == "xyz.openbmc_project.Inventory.Item.Cable")
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -060095 {
Ed Tanousdeae6a72024-11-11 21:58:57 -080096 dbus::utility::getAllProperties(
Akshit Shah0c2ba592023-01-24 01:03:26 +000097 *crow::connections::systemBus, service, cableObjectPath,
98 interface,
99 [asyncResp](
100 const boost::system::error_code& ec,
101 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400102 fillCableProperties(asyncResp->res, ec, properties);
103 });
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600104 }
Akshit Shah0c2ba592023-01-24 01:03:26 +0000105 else if (interface == "xyz.openbmc_project.Inventory.Item")
106 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800107 dbus::utility::getProperty<bool>(
108 service, cableObjectPath, interface, "Present",
Akshit Shah0c2ba592023-01-24 01:03:26 +0000109 [asyncResp, cableObjectPath](
110 const boost::system::error_code& ec, bool present) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400111 if (ec)
Akshit Shah0c2ba592023-01-24 01:03:26 +0000112 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400113 BMCWEB_LOG_DEBUG(
114 "get presence failed for Cable {} with error {}",
115 cableObjectPath, ec);
116 if (ec.value() != EBADR)
117 {
118 messages::internalError(asyncResp->res);
119 }
120 return;
Akshit Shah0c2ba592023-01-24 01:03:26 +0000121 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600122
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400123 if (!present)
124 {
125 asyncResp->res.jsonValue["Status"]["State"] =
126 resource::State::Absent;
127 }
128 });
Akshit Shah0c2ba592023-01-24 01:03:26 +0000129 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600130 }
131 }
132}
133
134/**
135 * The Cable schema
136 */
137inline void requestRoutesCable(App& app)
138{
139 BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/")
140 .privileges(redfish::privileges::getCable)
141 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700142 [&app](const crow::Request& req,
143 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
144 const std::string& cableId) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400145 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -0700146 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400147 return;
Ed Tanous45ca1b82022-03-25 13:07:27 -0700148 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400149 BMCWEB_LOG_DEBUG("Cable Id: {}", cableId);
150 constexpr std::array<std::string_view, 1> interfaces = {
151 "xyz.openbmc_project.Inventory.Item.Cable"};
152 dbus::utility::getSubTree(
153 "/xyz/openbmc_project/inventory", 0, interfaces,
154 [asyncResp,
155 cableId](const boost::system::error_code& ec,
156 const dbus::utility::MapperGetSubTreeResponse&
157 subtree) {
158 if (ec.value() == EBADR)
159 {
160 messages::resourceNotFound(asyncResp->res, "Cable",
161 cableId);
162 return;
163 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600164
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400165 if (ec)
166 {
167 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
168 messages::internalError(asyncResp->res);
169 return;
170 }
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600171
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400172 for (const auto& [objectPath, serviceMap] : subtree)
173 {
174 sdbusplus::message::object_path path(objectPath);
175 if (path.filename() != cableId)
176 {
177 continue;
178 }
179
180 asyncResp->res.jsonValue["@odata.type"] =
181 "#Cable.v1_0_0.Cable";
182 asyncResp->res.jsonValue["@odata.id"] =
183 boost::urls::format("/redfish/v1/Cables/{}",
184 cableId);
185 asyncResp->res.jsonValue["Id"] = cableId;
186 asyncResp->res.jsonValue["Name"] = "Cable";
187 asyncResp->res.jsonValue["Status"]["State"] =
188 resource::State::Enabled;
189
190 getCableProperties(asyncResp, objectPath,
191 serviceMap);
192 return;
193 }
194 messages::resourceNotFound(asyncResp->res, "Cable",
195 cableId);
196 });
197 });
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600198}
199
200/**
201 * Collection of Cable resource instances
202 */
203inline void requestRoutesCableCollection(App& app)
204{
205 BMCWEB_ROUTE(app, "/redfish/v1/Cables/")
206 .privileges(redfish::privileges::getCableCollection)
207 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700208 [&app](const crow::Request& req,
209 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400210 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
211 {
212 return;
213 }
214 asyncResp->res.jsonValue["@odata.type"] =
215 "#CableCollection.CableCollection";
216 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
217 asyncResp->res.jsonValue["Name"] = "Cable Collection";
218 asyncResp->res.jsonValue["Description"] =
219 "Collection of Cable Entries";
220 constexpr std::array<std::string_view, 1> interfaces{
221 "xyz.openbmc_project.Inventory.Item.Cable"};
222 collection_util::getCollectionMembers(
223 asyncResp, boost::urls::url("/redfish/v1/Cables"),
224 interfaces, "/xyz/openbmc_project/inventory");
225 });
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -0600226}
227
228} // namespace redfish