xref: /openbmc/bmcweb/redfish-core/lib/cable.hpp (revision ed76121b)
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             if (std::isnan(*length))
52             {
53                 return;
54             }
55             messages::internalError(resp);
56             return;
57         }
58 
59         resp.jsonValue["LengthMeters"] = *length;
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             sdbusplus::asio::getAllProperties(
87                 *crow::connections::systemBus, service, cableObjectPath,
88                 interface,
89                 [asyncResp](
90                     const boost::system::error_code ec,
91                     const dbus::utility::DBusPropertiesMap& properties) {
92                 fillCableProperties(asyncResp->res, ec, properties);
93                 });
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