1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 // SPDX-FileCopyrightText: Copyright 2019 Intel Corporation 4 #pragma once 5 6 #include "app.hpp" 7 #include "async_resp.hpp" 8 #include "generated/enums/resource.hpp" 9 #include "http_request.hpp" 10 #include "query.hpp" 11 #include "registries/privilege_registry.hpp" 12 13 namespace redfish 14 { 15 16 inline void populateStorageController( 17 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 18 const std::string& controllerId, const std::string& connectionName, 19 const std::string& path) 20 { 21 asyncResp->res.jsonValue["@odata.type"] = 22 "#StorageController.v1_6_0.StorageController"; 23 asyncResp->res.jsonValue["@odata.id"] = 24 boost::urls::format("/redfish/v1/Systems/{}/Storage/1/Controllers/{}", 25 BMCWEB_REDFISH_SYSTEM_URI_NAME, controllerId); 26 asyncResp->res.jsonValue["Name"] = controllerId; 27 asyncResp->res.jsonValue["Id"] = controllerId; 28 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 29 30 dbus::utility::getProperty<bool>( 31 connectionName, path, "xyz.openbmc_project.Inventory.Item", "Present", 32 [asyncResp](const boost::system::error_code& ec, bool isPresent) { 33 // this interface isn't necessary, only check it 34 // if we get a good return 35 if (ec) 36 { 37 BMCWEB_LOG_DEBUG("Failed to get Present property"); 38 return; 39 } 40 if (!isPresent) 41 { 42 asyncResp->res.jsonValue["Status"]["State"] = 43 resource::State::Absent; 44 } 45 }); 46 47 asset_utils::getAssetInfo(asyncResp, connectionName, path, ""_json_pointer, 48 false); 49 } 50 51 inline void getStorageControllerHandler( 52 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 53 const std::string& controllerId, const boost::system::error_code& ec, 54 const dbus::utility::MapperGetSubTreeResponse& subtree) 55 { 56 if (ec || subtree.empty()) 57 { 58 // doesn't have to be there 59 BMCWEB_LOG_DEBUG("Failed to handle StorageController"); 60 return; 61 } 62 63 for (const auto& [path, interfaceDict] : subtree) 64 { 65 sdbusplus::message::object_path object(path); 66 std::string id = object.filename(); 67 if (id.empty()) 68 { 69 BMCWEB_LOG_ERROR("Failed to find filename in {}", path); 70 return; 71 } 72 if (id != controllerId) 73 { 74 continue; 75 } 76 77 if (interfaceDict.size() != 1) 78 { 79 BMCWEB_LOG_ERROR("Connection size {}, greater than 1", 80 interfaceDict.size()); 81 messages::internalError(asyncResp->res); 82 return; 83 } 84 85 const std::string& connectionName = interfaceDict.front().first; 86 populateStorageController(asyncResp, controllerId, connectionName, 87 path); 88 } 89 } 90 91 inline void populateStorageControllerCollection( 92 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 93 const boost::system::error_code& ec, 94 const dbus::utility::MapperGetSubTreePathsResponse& controllerList) 95 { 96 nlohmann::json::array_t members; 97 if (ec || controllerList.empty()) 98 { 99 asyncResp->res.jsonValue["Members"] = std::move(members); 100 asyncResp->res.jsonValue["Members@odata.count"] = 0; 101 BMCWEB_LOG_DEBUG("Failed to find any StorageController"); 102 return; 103 } 104 105 for (const std::string& path : controllerList) 106 { 107 std::string id = sdbusplus::message::object_path(path).filename(); 108 if (id.empty()) 109 { 110 BMCWEB_LOG_ERROR("Failed to find filename in {}", path); 111 return; 112 } 113 nlohmann::json::object_t member; 114 member["@odata.id"] = boost::urls::format( 115 "/redfish/v1/Systems/{}/Storage/1/Controllers/{}", 116 BMCWEB_REDFISH_SYSTEM_URI_NAME, id); 117 members.emplace_back(member); 118 } 119 asyncResp->res.jsonValue["Members@odata.count"] = members.size(); 120 asyncResp->res.jsonValue["Members"] = std::move(members); 121 } 122 123 inline void handleSystemsStorageControllerGet( 124 App& app, const crow::Request& req, 125 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 126 const std::string& systemName, const std::string& controllerId) 127 { 128 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 129 { 130 BMCWEB_LOG_DEBUG("Failed to setup Redfish Route for StorageController"); 131 return; 132 } 133 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 134 { 135 messages::resourceNotFound(asyncResp->res, "ComputerSystem", 136 systemName); 137 BMCWEB_LOG_DEBUG("Failed to find ComputerSystem of {}", systemName); 138 return; 139 } 140 constexpr std::array<std::string_view, 1> interfaces = { 141 "xyz.openbmc_project.Inventory.Item.StorageController"}; 142 dbus::utility::getSubTree( 143 "/xyz/openbmc_project/inventory", 0, interfaces, 144 [asyncResp, 145 controllerId](const boost::system::error_code& ec, 146 const dbus::utility::MapperGetSubTreeResponse& subtree) { 147 getStorageControllerHandler(asyncResp, controllerId, ec, subtree); 148 }); 149 } 150 151 inline void handleSystemsStorageControllerCollectionGet( 152 App& app, const crow::Request& req, 153 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 154 const std::string& systemName) 155 { 156 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 157 { 158 BMCWEB_LOG_DEBUG( 159 "Failed to setup Redfish Route for StorageController Collection"); 160 return; 161 } 162 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME) 163 { 164 messages::resourceNotFound(asyncResp->res, "ComputerSystem", 165 systemName); 166 BMCWEB_LOG_DEBUG("Failed to find ComputerSystem of {}", systemName); 167 return; 168 } 169 170 asyncResp->res.jsonValue["@odata.type"] = 171 "#StorageControllerCollection.StorageControllerCollection"; 172 asyncResp->res.jsonValue["@odata.id"] = 173 std::format("/redfish/v1/Systems/{}/Storage/1/Controllers", 174 BMCWEB_REDFISH_SYSTEM_URI_NAME); 175 asyncResp->res.jsonValue["Name"] = "Storage Controller Collection"; 176 177 constexpr std::array<std::string_view, 1> interfaces = { 178 "xyz.openbmc_project.Inventory.Item.StorageController"}; 179 dbus::utility::getSubTreePaths( 180 "/xyz/openbmc_project/inventory", 0, interfaces, 181 [asyncResp](const boost::system::error_code& ec, 182 const dbus::utility::MapperGetSubTreePathsResponse& 183 controllerList) { 184 populateStorageControllerCollection(asyncResp, ec, controllerList); 185 }); 186 } 187 188 inline void requestRoutesStorageController(App& app) 189 { 190 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/1/Controllers/") 191 .privileges(redfish::privileges::getStorageControllerCollection) 192 .methods(boost::beast::http::verb::get)(std::bind_front( 193 handleSystemsStorageControllerCollectionGet, std::ref(app))); 194 195 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Storage/1/Controllers/<str>") 196 .privileges(redfish::privileges::getStorageController) 197 .methods(boost::beast::http::verb::get)( 198 std::bind_front(handleSystemsStorageControllerGet, std::ref(app))); 199 } 200 201 } // namespace redfish 202