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 // Cable length is NaN by default, do not throw an error 52 if (!std::isnan(*length)) 53 { 54 messages::internalError(resp); 55 return; 56 } 57 } 58 else 59 { 60 resp.jsonValue["LengthMeters"] = *length; 61 } 62 } 63 } 64 65 /** 66 * @brief Api to get Cable properties. 67 * @param[in,out] asyncResp Async HTTP response. 68 * @param[in] cableObjectPath Object path of the Cable. 69 * @param[in] serviceMap A map to hold Service and corresponding 70 * interface list for the given cable id. 71 */ 72 inline void 73 getCableProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 74 const std::string& cableObjectPath, 75 const dbus::utility::MapperServiceMap& serviceMap) 76 { 77 BMCWEB_LOG_DEBUG << "Get Properties for cable " << cableObjectPath; 78 79 for (const auto& [service, interfaces] : serviceMap) 80 { 81 for (const auto& interface : interfaces) 82 { 83 if (interface != "xyz.openbmc_project.Inventory.Item.Cable") 84 { 85 continue; 86 } 87 88 sdbusplus::asio::getAllProperties( 89 *crow::connections::systemBus, service, cableObjectPath, 90 interface, 91 [asyncResp]( 92 const boost::system::error_code ec, 93 const dbus::utility::DBusPropertiesMap& properties) { 94 fillCableProperties(asyncResp->res, ec, properties); 95 }); 96 } 97 } 98 } 99 100 /** 101 * The Cable schema 102 */ 103 inline void requestRoutesCable(App& app) 104 { 105 BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/") 106 .privileges(redfish::privileges::getCable) 107 .methods(boost::beast::http::verb::get)( 108 [&app](const crow::Request& req, 109 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 110 const std::string& cableId) { 111 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 112 { 113 return; 114 } 115 BMCWEB_LOG_DEBUG << "Cable Id: " << cableId; 116 auto respHandler = 117 [asyncResp, 118 cableId](const boost::system::error_code ec, 119 const dbus::utility::MapperGetSubTreeResponse& subtree) { 120 if (ec.value() == EBADR) 121 { 122 messages::resourceNotFound(asyncResp->res, "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"] = "#Cable.v1_0_0.Cable"; 142 asyncResp->res.jsonValue["@odata.id"] = 143 "/redfish/v1/Cables/" + cableId; 144 asyncResp->res.jsonValue["Id"] = cableId; 145 asyncResp->res.jsonValue["Name"] = "Cable"; 146 147 getCableProperties(asyncResp, objectPath, serviceMap); 148 return; 149 } 150 messages::resourceNotFound(asyncResp->res, "Cable", cableId); 151 }; 152 153 crow::connections::systemBus->async_method_call( 154 respHandler, "xyz.openbmc_project.ObjectMapper", 155 "/xyz/openbmc_project/object_mapper", 156 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 157 "/xyz/openbmc_project/inventory", 0, 158 std::array<const char*, 1>{ 159 "xyz.openbmc_project.Inventory.Item.Cable"}); 160 }); 161 } 162 163 /** 164 * Collection of Cable resource instances 165 */ 166 inline void requestRoutesCableCollection(App& app) 167 { 168 BMCWEB_ROUTE(app, "/redfish/v1/Cables/") 169 .privileges(redfish::privileges::getCableCollection) 170 .methods(boost::beast::http::verb::get)( 171 [&app](const crow::Request& req, 172 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 173 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 174 { 175 return; 176 } 177 asyncResp->res.jsonValue["@odata.type"] = 178 "#CableCollection.CableCollection"; 179 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables"; 180 asyncResp->res.jsonValue["Name"] = "Cable Collection"; 181 asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries"; 182 183 collection_util::getCollectionMembers( 184 asyncResp, boost::urls::url("/redfish/v1/Cables"), 185 {"xyz.openbmc_project.Inventory.Item.Cable"}); 186 }); 187 } 188 189 } // namespace redfish 190