blob: 05da5f61aed36d9784c120f81219ac996ddc2eff [file] [log] [blame]
Shantappa Teekappanavar9c929be2021-12-16 19:02:52 -06001#pragma once
2#include <boost/container/flat_map.hpp>
3#include <utils/json_utils.hpp>
4
5namespace redfish
6{
7/**
8 * @brief Fill cable specific properties.
9 * @param[in,out] resp HTTP response.
10 * @param[in] ec Error code corresponding to Async method call.
11 * @param[in] properties List of Cable Properties key/value pairs.
12 */
13inline void
14 fillCableProperties(crow::Response& resp,
15 const boost::system::error_code ec,
16 const dbus::utility::DBusPropertiesMap& properties)
17{
18 if (ec)
19 {
20 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
21 messages::internalError(resp);
22 return;
23 }
24
25 for (const auto& [propKey, propVariant] : properties)
26 {
27 if (propKey == "CableTypeDescription")
28 {
29 const std::string* cableTypeDescription =
30 std::get_if<std::string>(&propVariant);
31 if (cableTypeDescription == nullptr)
32 {
33 messages::internalError(resp);
34 return;
35 }
36 resp.jsonValue["CableType"] = *cableTypeDescription;
37 }
38 else if (propKey == "Length")
39 {
40 const double* cableLength = std::get_if<double>(&propVariant);
41 if (cableLength == nullptr)
42 {
43 messages::internalError(resp);
44 return;
45 }
46
47 if (!std::isfinite(*cableLength))
48 {
49 if (std::isnan(*cableLength))
50 {
51 continue;
52 }
53 messages::internalError(resp);
54 return;
55 }
56
57 resp.jsonValue["LengthMeters"] = *cableLength;
58 }
59 }
60}
61
62/**
63 * @brief Api to get Cable properties.
64 * @param[in,out] asyncResp Async HTTP response.
65 * @param[in] cableObjectPath Object path of the Cable.
66 * @param[in] serviceMap A map to hold Service and corresponding
67 * interface list for the given cable id.
68 */
69inline void
70 getCableProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
71 const std::string& cableObjectPath,
72 const dbus::utility::MapperServiceMap& serviceMap)
73{
74 BMCWEB_LOG_DEBUG << "Get Properties for cable " << cableObjectPath;
75
76 for (const auto& [service, interfaces] : serviceMap)
77 {
78 for (const auto& interface : interfaces)
79 {
80 if (interface != "xyz.openbmc_project.Inventory.Item.Cable")
81 {
82 continue;
83 }
84
85 crow::connections::systemBus->async_method_call(
86 [asyncResp](
87 const boost::system::error_code ec,
88 const dbus::utility::DBusPropertiesMap& properties) {
89 fillCableProperties(asyncResp->res, ec, properties);
90 },
91 service, cableObjectPath, "org.freedesktop.DBus.Properties",
92 "GetAll", interface);
93 }
94 }
95}
96
97/**
98 * The Cable schema
99 */
100inline void requestRoutesCable(App& app)
101{
102 BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/")
103 .privileges(redfish::privileges::getCable)
104 .methods(boost::beast::http::verb::get)(
105 [](const crow::Request&,
106 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
107 const std::string& cableId) {
108 BMCWEB_LOG_DEBUG << "Cable Id: " << cableId;
109 auto respHandler =
110 [asyncResp,
111 cableId](const boost::system::error_code ec,
112 const dbus::utility::MapperGetSubTreeResponse&
113 subtree) {
114 if (ec.value() == EBADR)
115 {
116 messages::resourceNotFound(
117 asyncResp->res, "#Cable.v1_0_0.Cable", cableId);
118 return;
119 }
120
121 if (ec)
122 {
123 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
124 messages::internalError(asyncResp->res);
125 return;
126 }
127
128 for (const auto& [objectPath, serviceMap] : subtree)
129 {
130 sdbusplus::message::object_path path(objectPath);
131 if (path.filename() != cableId)
132 {
133 continue;
134 }
135
136 asyncResp->res.jsonValue["@odata.type"] =
137 "#Cable.v1_0_0.Cable";
138 asyncResp->res.jsonValue["@odata.id"] =
139 "/redfish/v1/Cables/" + cableId;
140 asyncResp->res.jsonValue["Id"] = cableId;
141 asyncResp->res.jsonValue["Name"] = "Cable";
142
143 getCableProperties(asyncResp, objectPath,
144 serviceMap);
145 return;
146 }
147 messages::resourceNotFound(asyncResp->res, "Cable",
148 cableId);
149 };
150
151 crow::connections::systemBus->async_method_call(
152 respHandler, "xyz.openbmc_project.ObjectMapper",
153 "/xyz/openbmc_project/object_mapper",
154 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
155 "/xyz/openbmc_project/inventory", 0,
156 std::array<const char*, 1>{
157 "xyz.openbmc_project.Inventory.Item.Cable"});
158 });
159}
160
161/**
162 * Collection of Cable resource instances
163 */
164inline void requestRoutesCableCollection(App& app)
165{
166 BMCWEB_ROUTE(app, "/redfish/v1/Cables/")
167 .privileges(redfish::privileges::getCableCollection)
168 .methods(boost::beast::http::verb::get)(
169 [](const crow::Request&,
170 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
171 asyncResp->res.jsonValue["@odata.type"] =
172 "#CableCollection.CableCollection";
173 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
174 asyncResp->res.jsonValue["Name"] = "Cable Collection";
175 asyncResp->res.jsonValue["Description"] =
176 "Collection of Cable Entries";
177
178 collection_util::getCollectionMembers(
179 asyncResp, "/redfish/v1/Cables",
180 {"xyz.openbmc_project.Inventory.Item.Cable"});
181 });
182}
183
184} // namespace redfish