xref: /openbmc/bmcweb/features/redfish/lib/cable.hpp (revision d8a5d5d8e07f6dec97ed0cbc84052656165f6172)
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, "Cable", cableId);
121                 return;
122             }
123 
124             if (ec)
125             {
126                 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
127                 messages::internalError(asyncResp->res);
128                 return;
129             }
130 
131             for (const auto& [objectPath, serviceMap] : subtree)
132             {
133                 sdbusplus::message::object_path path(objectPath);
134                 if (path.filename() != cableId)
135                 {
136                     continue;
137                 }
138 
139                 asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable";
140                 asyncResp->res.jsonValue["@odata.id"] =
141                     "/redfish/v1/Cables/" + cableId;
142                 asyncResp->res.jsonValue["Id"] = cableId;
143                 asyncResp->res.jsonValue["Name"] = "Cable";
144 
145                 getCableProperties(asyncResp, objectPath, serviceMap);
146                 return;
147             }
148             messages::resourceNotFound(asyncResp->res, "Cable", 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             [&app](const crow::Request& req,
170                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
171         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
172         {
173             return;
174         }
175         asyncResp->res.jsonValue["@odata.type"] =
176             "#CableCollection.CableCollection";
177         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
178         asyncResp->res.jsonValue["Name"] = "Cable Collection";
179         asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries";
180 
181         collection_util::getCollectionMembers(
182             asyncResp, "/redfish/v1/Cables",
183             {"xyz.openbmc_project.Inventory.Item.Cable"});
184         });
185 }
186 
187 } // namespace redfish
188