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