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