xref: /openbmc/bmcweb/redfish-core/lib/cable.hpp (revision 4cee35e7)
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->res))
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&
118                                   subtree) {
119                         if (ec.value() == EBADR)
120                         {
121                             messages::resourceNotFound(
122                                 asyncResp->res, "#Cable.v1_0_0.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"] =
142                                 "#Cable.v1_0_0.Cable";
143                             asyncResp->res.jsonValue["@odata.id"] =
144                                 "/redfish/v1/Cables/" + cableId;
145                             asyncResp->res.jsonValue["Id"] = cableId;
146                             asyncResp->res.jsonValue["Name"] = "Cable";
147 
148                             getCableProperties(asyncResp, objectPath,
149                                                serviceMap);
150                             return;
151                         }
152                         messages::resourceNotFound(asyncResp->res, "Cable",
153                                                    cableId);
154                     };
155 
156                 crow::connections::systemBus->async_method_call(
157                     respHandler, "xyz.openbmc_project.ObjectMapper",
158                     "/xyz/openbmc_project/object_mapper",
159                     "xyz.openbmc_project.ObjectMapper", "GetSubTree",
160                     "/xyz/openbmc_project/inventory", 0,
161                     std::array<const char*, 1>{
162                         "xyz.openbmc_project.Inventory.Item.Cable"});
163             });
164 }
165 
166 /**
167  * Collection of Cable resource instances
168  */
169 inline void requestRoutesCableCollection(App& app)
170 {
171     BMCWEB_ROUTE(app, "/redfish/v1/Cables/")
172         .privileges(redfish::privileges::getCableCollection)
173         .methods(boost::beast::http::verb::get)(
174             [&app](const crow::Request& req,
175                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
176                 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
177                 {
178                     return;
179                 }
180                 asyncResp->res.jsonValue["@odata.type"] =
181                     "#CableCollection.CableCollection";
182                 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
183                 asyncResp->res.jsonValue["Name"] = "Cable Collection";
184                 asyncResp->res.jsonValue["Description"] =
185                     "Collection of Cable Entries";
186 
187                 collection_util::getCollectionMembers(
188                     asyncResp, "/redfish/v1/Cables",
189                     {"xyz.openbmc_project.Inventory.Item.Cable"});
190             });
191 }
192 
193 } // namespace redfish
194