xref: /openbmc/bmcweb/redfish-core/lib/cable.hpp (revision 6bbda2ca)
1 #pragma once
2 #include <boost/container/flat_map.hpp>
3 #include <utils/json_utils.hpp>
4 
5 namespace 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  */
13 inline 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  */
69 inline 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  */
100 inline 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  */
164 inline 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
185