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