1a25aeccfSNikhil Potade /* 2a25aeccfSNikhil Potade // Copyright (c) 2019 Intel Corporation 3a25aeccfSNikhil Potade // 4a25aeccfSNikhil Potade // Licensed under the Apache License, Version 2.0 (the "License"); 5a25aeccfSNikhil Potade // you may not use this file except in compliance with the License. 6a25aeccfSNikhil Potade // You may obtain a copy of the License at 7a25aeccfSNikhil Potade // 8a25aeccfSNikhil Potade // http://www.apache.org/licenses/LICENSE-2.0 9a25aeccfSNikhil Potade // 10a25aeccfSNikhil Potade // Unless required by applicable law or agreed to in writing, software 11a25aeccfSNikhil Potade // distributed under the License is distributed on an "AS IS" BASIS, 12a25aeccfSNikhil Potade // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a25aeccfSNikhil Potade // See the License for the specific language governing permissions and 14a25aeccfSNikhil Potade // limitations under the License. 15a25aeccfSNikhil Potade */ 16a25aeccfSNikhil Potade #pragma once 17a25aeccfSNikhil Potade 182ad9c2f6SJames Feist #include "health.hpp" 19*e284a7c1SJames Feist #include "openbmc_dbus_rest.hpp" 202ad9c2f6SJames Feist 21a25aeccfSNikhil Potade #include <node.hpp> 22a25aeccfSNikhil Potade 23a25aeccfSNikhil Potade namespace redfish 24a25aeccfSNikhil Potade { 25a25aeccfSNikhil Potade class StorageCollection : public Node 26a25aeccfSNikhil Potade { 27a25aeccfSNikhil Potade public: 28a25aeccfSNikhil Potade StorageCollection(CrowApp &app) : 29a25aeccfSNikhil Potade Node(app, "/redfish/v1/Systems/system/Storage/") 30a25aeccfSNikhil Potade { 31a25aeccfSNikhil Potade entityPrivileges = { 32a25aeccfSNikhil Potade {boost::beast::http::verb::get, {{"Login"}}}, 33a25aeccfSNikhil Potade {boost::beast::http::verb::head, {{"Login"}}}, 34a25aeccfSNikhil Potade {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 35a25aeccfSNikhil Potade {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 36a25aeccfSNikhil Potade {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 37a25aeccfSNikhil Potade {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 38a25aeccfSNikhil Potade } 39a25aeccfSNikhil Potade 40a25aeccfSNikhil Potade private: 41a25aeccfSNikhil Potade void doGet(crow::Response &res, const crow::Request &req, 42a25aeccfSNikhil Potade const std::vector<std::string> ¶ms) override 43a25aeccfSNikhil Potade { 44a25aeccfSNikhil Potade res.jsonValue["@odata.type"] = "#StorageCollection.StorageCollection"; 45a25aeccfSNikhil Potade res.jsonValue["@odata.context"] = 46a25aeccfSNikhil Potade "/redfish/v1/$metadata#StorageCollection.StorageCollection"; 47a25aeccfSNikhil Potade res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage"; 48a25aeccfSNikhil Potade res.jsonValue["Name"] = "Storage Collection"; 49a25aeccfSNikhil Potade res.jsonValue["Members"] = { 50a25aeccfSNikhil Potade {{"@odata.id", "/redfish/v1/Systems/system/Storage/1"}}}; 51a25aeccfSNikhil Potade res.jsonValue["Members@odata.count"] = 1; 52a25aeccfSNikhil Potade res.end(); 53a25aeccfSNikhil Potade } 54a25aeccfSNikhil Potade }; 55a25aeccfSNikhil Potade 56a25aeccfSNikhil Potade class Storage : public Node 57a25aeccfSNikhil Potade { 58a25aeccfSNikhil Potade public: 59a25aeccfSNikhil Potade Storage(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/Storage/1") 60a25aeccfSNikhil Potade { 61a25aeccfSNikhil Potade entityPrivileges = { 62a25aeccfSNikhil Potade {boost::beast::http::verb::get, {{"Login"}}}, 63a25aeccfSNikhil Potade {boost::beast::http::verb::head, {{"Login"}}}, 64a25aeccfSNikhil Potade {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 65a25aeccfSNikhil Potade {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 66a25aeccfSNikhil Potade {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 67a25aeccfSNikhil Potade {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 68a25aeccfSNikhil Potade } 69a25aeccfSNikhil Potade 70a25aeccfSNikhil Potade private: 71a25aeccfSNikhil Potade void doGet(crow::Response &res, const crow::Request &req, 72a25aeccfSNikhil Potade const std::vector<std::string> ¶ms) override 73a25aeccfSNikhil Potade { 74a25aeccfSNikhil Potade res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage"; 75a25aeccfSNikhil Potade res.jsonValue["@odata.context"] = 76a25aeccfSNikhil Potade "/redfish/v1/$metadata#Storage.Storage"; 77a25aeccfSNikhil Potade res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage/1"; 78*e284a7c1SJames Feist res.jsonValue["Name"] = "Storage"; 79a25aeccfSNikhil Potade res.jsonValue["Id"] = "1"; 802ad9c2f6SJames Feist res.jsonValue["Status"]["State"] = "Enabled"; 81a25aeccfSNikhil Potade 82a25aeccfSNikhil Potade auto asyncResp = std::make_shared<AsyncResp>(res); 83*e284a7c1SJames Feist auto health = std::make_shared<HealthPopulate>(asyncResp); 84*e284a7c1SJames Feist health->populate(); 85*e284a7c1SJames Feist 86a25aeccfSNikhil Potade crow::connections::systemBus->async_method_call( 87*e284a7c1SJames Feist [asyncResp, health](const boost::system::error_code ec, 88a25aeccfSNikhil Potade const std::vector<std::string> &storageList) { 89a25aeccfSNikhil Potade nlohmann::json &storageArray = 90a25aeccfSNikhil Potade asyncResp->res.jsonValue["Drives"]; 91a25aeccfSNikhil Potade storageArray = nlohmann::json::array(); 92*e284a7c1SJames Feist auto &count = asyncResp->res.jsonValue["Drives@odata.count"]; 93*e284a7c1SJames Feist count = 0; 942ad9c2f6SJames Feist 95a25aeccfSNikhil Potade if (ec) 96a25aeccfSNikhil Potade { 97a25aeccfSNikhil Potade BMCWEB_LOG_ERROR << "Drive mapper call error"; 98a25aeccfSNikhil Potade messages::internalError(asyncResp->res); 99a25aeccfSNikhil Potade return; 100a25aeccfSNikhil Potade } 1012ad9c2f6SJames Feist 102*e284a7c1SJames Feist health->inventory.insert(health->inventory.end(), 103*e284a7c1SJames Feist storageList.begin(), 104*e284a7c1SJames Feist storageList.end()); 1052ad9c2f6SJames Feist 106a25aeccfSNikhil Potade for (const std::string &objpath : storageList) 107a25aeccfSNikhil Potade { 108a25aeccfSNikhil Potade std::size_t lastPos = objpath.rfind("/"); 109a25aeccfSNikhil Potade if (lastPos == std::string::npos || 110a25aeccfSNikhil Potade (objpath.size() <= lastPos + 1)) 111a25aeccfSNikhil Potade { 112a25aeccfSNikhil Potade BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 113a25aeccfSNikhil Potade continue; 114a25aeccfSNikhil Potade } 115a25aeccfSNikhil Potade 116a25aeccfSNikhil Potade storageArray.push_back( 117a25aeccfSNikhil Potade {{"@odata.id", 118be13ceceSJames Feist "/redfish/v1/Systems/system/Storage/1/Drives/" + 119a25aeccfSNikhil Potade objpath.substr(lastPos + 1)}}); 120a25aeccfSNikhil Potade } 121a25aeccfSNikhil Potade 122*e284a7c1SJames Feist count = storageArray.size(); 123a25aeccfSNikhil Potade }, 124a25aeccfSNikhil Potade "xyz.openbmc_project.ObjectMapper", 125a25aeccfSNikhil Potade "/xyz/openbmc_project/object_mapper", 126a25aeccfSNikhil Potade "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 127a25aeccfSNikhil Potade "/xyz/openbmc_project/inventory", int32_t(0), 128a25aeccfSNikhil Potade std::array<const char *, 1>{ 129a25aeccfSNikhil Potade "xyz.openbmc_project.Inventory.Item.Drive"}); 130*e284a7c1SJames Feist 131*e284a7c1SJames Feist crow::connections::systemBus->async_method_call( 132*e284a7c1SJames Feist [asyncResp, 133*e284a7c1SJames Feist health](const boost::system::error_code ec, 134*e284a7c1SJames Feist const crow::openbmc_mapper::GetSubTreeType &subtree) { 135*e284a7c1SJames Feist if (ec || !subtree.size()) 136*e284a7c1SJames Feist { 137*e284a7c1SJames Feist messages::internalError(asyncResp->res); 138*e284a7c1SJames Feist return; 139*e284a7c1SJames Feist } 140*e284a7c1SJames Feist 141*e284a7c1SJames Feist nlohmann::json &root = 142*e284a7c1SJames Feist asyncResp->res.jsonValue["StorageControllers"]; 143*e284a7c1SJames Feist root = nlohmann::json::array(); 144*e284a7c1SJames Feist for (const auto &[path, interfaceDict] : subtree) 145*e284a7c1SJames Feist { 146*e284a7c1SJames Feist std::size_t lastPos = path.rfind("/"); 147*e284a7c1SJames Feist if (lastPos == std::string::npos || 148*e284a7c1SJames Feist (path.size() <= lastPos + 1)) 149*e284a7c1SJames Feist { 150*e284a7c1SJames Feist BMCWEB_LOG_ERROR << "Failed to find '/' in " << path; 151*e284a7c1SJames Feist return; 152*e284a7c1SJames Feist } 153*e284a7c1SJames Feist 154*e284a7c1SJames Feist if (interfaceDict.size() != 1) 155*e284a7c1SJames Feist { 156*e284a7c1SJames Feist BMCWEB_LOG_ERROR << "Connection size " 157*e284a7c1SJames Feist << interfaceDict.size() 158*e284a7c1SJames Feist << ", greater than 1"; 159*e284a7c1SJames Feist messages::internalError(asyncResp->res); 160*e284a7c1SJames Feist return; 161*e284a7c1SJames Feist } 162*e284a7c1SJames Feist 163*e284a7c1SJames Feist const std::string &connectionName = 164*e284a7c1SJames Feist interfaceDict.front().first; 165*e284a7c1SJames Feist 166*e284a7c1SJames Feist size_t index = root.size(); 167*e284a7c1SJames Feist nlohmann::json &storageController = 168*e284a7c1SJames Feist root.emplace_back(nlohmann::json::object()); 169*e284a7c1SJames Feist 170*e284a7c1SJames Feist std::string id = path.substr(lastPos + 1); 171*e284a7c1SJames Feist 172*e284a7c1SJames Feist storageController["@odata.type"] = 173*e284a7c1SJames Feist "#Storage.v1_7_0.StorageController"; 174*e284a7c1SJames Feist storageController["@odata.context"] = 175*e284a7c1SJames Feist "/redfish/v1/$metadata#Storage.StorageController"; 176*e284a7c1SJames Feist storageController["@odata.id"] = 177*e284a7c1SJames Feist "/redfish/v1/Systems/system/Storage/1" 178*e284a7c1SJames Feist "#/StorageControllers/" + 179*e284a7c1SJames Feist std::to_string(index); 180*e284a7c1SJames Feist storageController["Name"] = id; 181*e284a7c1SJames Feist storageController["MemberId"] = id; 182*e284a7c1SJames Feist storageController["Status"]["State"] = "Enabled"; 183*e284a7c1SJames Feist 184*e284a7c1SJames Feist crow::connections::systemBus->async_method_call( 185*e284a7c1SJames Feist [asyncResp, index](const boost::system::error_code ec, 186*e284a7c1SJames Feist const std::variant<bool> present) { 187*e284a7c1SJames Feist // this interface isn't necessary, only check it if 188*e284a7c1SJames Feist // we get a good return 189*e284a7c1SJames Feist if (ec) 190*e284a7c1SJames Feist { 191*e284a7c1SJames Feist return; 192*e284a7c1SJames Feist } 193*e284a7c1SJames Feist const bool *enabled = std::get_if<bool>(&present); 194*e284a7c1SJames Feist if (enabled == nullptr) 195*e284a7c1SJames Feist { 196*e284a7c1SJames Feist BMCWEB_LOG_DEBUG << "Illegal property present"; 197*e284a7c1SJames Feist messages::internalError(asyncResp->res); 198*e284a7c1SJames Feist return; 199*e284a7c1SJames Feist } 200*e284a7c1SJames Feist if (!(*enabled)) 201*e284a7c1SJames Feist { 202*e284a7c1SJames Feist asyncResp->res 203*e284a7c1SJames Feist .jsonValue["StorageControllers"][index] 204*e284a7c1SJames Feist ["Status"]["State"] = "Disabled"; 205*e284a7c1SJames Feist } 206*e284a7c1SJames Feist }, 207*e284a7c1SJames Feist connectionName, path, "org.freedesktop.DBus.Properties", 208*e284a7c1SJames Feist "Get", "xyz.openbmc_project.Inventory.Item", "Present"); 209*e284a7c1SJames Feist 210*e284a7c1SJames Feist crow::connections::systemBus->async_method_call( 211*e284a7c1SJames Feist [asyncResp, 212*e284a7c1SJames Feist index](const boost::system::error_code ec, 213*e284a7c1SJames Feist const std::vector<std::pair< 214*e284a7c1SJames Feist std::string, 215*e284a7c1SJames Feist std::variant<bool, std::string, uint64_t>>> 216*e284a7c1SJames Feist &propertiesList) { 217*e284a7c1SJames Feist if (ec) 218*e284a7c1SJames Feist { 219*e284a7c1SJames Feist // this interface isn't necessary 220*e284a7c1SJames Feist return; 221*e284a7c1SJames Feist } 222*e284a7c1SJames Feist for (const std::pair< 223*e284a7c1SJames Feist std::string, 224*e284a7c1SJames Feist std::variant<bool, std::string, uint64_t>> 225*e284a7c1SJames Feist &property : propertiesList) 226*e284a7c1SJames Feist { 227*e284a7c1SJames Feist // Store DBus properties that are also 228*e284a7c1SJames Feist // Redfish properties with same name and a 229*e284a7c1SJames Feist // string value 230*e284a7c1SJames Feist const std::string &propertyName = 231*e284a7c1SJames Feist property.first; 232*e284a7c1SJames Feist nlohmann::json &object = 233*e284a7c1SJames Feist asyncResp->res 234*e284a7c1SJames Feist .jsonValue["StorageControllers"][index]; 235*e284a7c1SJames Feist if ((propertyName == "PartNumber") || 236*e284a7c1SJames Feist (propertyName == "SerialNumber") || 237*e284a7c1SJames Feist (propertyName == "Manufacturer") || 238*e284a7c1SJames Feist (propertyName == "Model")) 239*e284a7c1SJames Feist { 240*e284a7c1SJames Feist const std::string *value = 241*e284a7c1SJames Feist std::get_if<std::string>( 242*e284a7c1SJames Feist &property.second); 243*e284a7c1SJames Feist if (value == nullptr) 244*e284a7c1SJames Feist { 245*e284a7c1SJames Feist // illegal property 246*e284a7c1SJames Feist messages::internalError(asyncResp->res); 247*e284a7c1SJames Feist continue; 248*e284a7c1SJames Feist } 249*e284a7c1SJames Feist object[propertyName] = *value; 250*e284a7c1SJames Feist } 251*e284a7c1SJames Feist } 252*e284a7c1SJames Feist }, 253*e284a7c1SJames Feist connectionName, path, "org.freedesktop.DBus.Properties", 254*e284a7c1SJames Feist "GetAll", 255*e284a7c1SJames Feist "xyz.openbmc_project.Inventory.Decorator.Asset"); 256*e284a7c1SJames Feist } 257*e284a7c1SJames Feist 258*e284a7c1SJames Feist // this is done after we know the json array will no longer be 259*e284a7c1SJames Feist // resized, as json::array uses vector underneath and we need 260*e284a7c1SJames Feist // references to its members that won't change 261*e284a7c1SJames Feist size_t count = 0; 262*e284a7c1SJames Feist for (const auto &[path, interfaceDict] : subtree) 263*e284a7c1SJames Feist { 264*e284a7c1SJames Feist auto subHealth = std::make_shared<HealthPopulate>( 265*e284a7c1SJames Feist asyncResp, root[count]["Status"]); 266*e284a7c1SJames Feist subHealth->inventory.emplace_back(path); 267*e284a7c1SJames Feist health->inventory.emplace_back(path); 268*e284a7c1SJames Feist health->children.emplace_back(subHealth); 269*e284a7c1SJames Feist count++; 270*e284a7c1SJames Feist } 271*e284a7c1SJames Feist }, 272*e284a7c1SJames Feist "xyz.openbmc_project.ObjectMapper", 273*e284a7c1SJames Feist "/xyz/openbmc_project/object_mapper", 274*e284a7c1SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 275*e284a7c1SJames Feist "/xyz/openbmc_project/inventory", int32_t(0), 276*e284a7c1SJames Feist std::array<const char *, 1>{ 277*e284a7c1SJames Feist "xyz.openbmc_project.Inventory.Item.StorageController"}); 278a25aeccfSNikhil Potade } 279a25aeccfSNikhil Potade }; 280a25aeccfSNikhil Potade 281a25aeccfSNikhil Potade class Drive : public Node 282a25aeccfSNikhil Potade { 283a25aeccfSNikhil Potade public: 284a25aeccfSNikhil Potade Drive(CrowApp &app) : 285be13ceceSJames Feist Node(app, "/redfish/v1/Systems/system/Storage/1/Drives/<str>/", 286a25aeccfSNikhil Potade std::string()) 287a25aeccfSNikhil Potade { 288a25aeccfSNikhil Potade entityPrivileges = { 289a25aeccfSNikhil Potade {boost::beast::http::verb::get, {{"Login"}}}, 290a25aeccfSNikhil Potade {boost::beast::http::verb::head, {{"Login"}}}, 291a25aeccfSNikhil Potade {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 292a25aeccfSNikhil Potade {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 293a25aeccfSNikhil Potade {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 294a25aeccfSNikhil Potade {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 295a25aeccfSNikhil Potade } 296a25aeccfSNikhil Potade 297a25aeccfSNikhil Potade private: 298a25aeccfSNikhil Potade void doGet(crow::Response &res, const crow::Request &req, 299a25aeccfSNikhil Potade const std::vector<std::string> ¶ms) override 300a25aeccfSNikhil Potade { 301*e284a7c1SJames Feist auto asyncResp = std::make_shared<AsyncResp>(res); 302*e284a7c1SJames Feist if (params.size() != 1) 303*e284a7c1SJames Feist { 304*e284a7c1SJames Feist messages::internalError(asyncResp->res); 305*e284a7c1SJames Feist return; 306*e284a7c1SJames Feist } 307a25aeccfSNikhil Potade const std::string &driveId = params[0]; 308a25aeccfSNikhil Potade 309a25aeccfSNikhil Potade crow::connections::systemBus->async_method_call( 310*e284a7c1SJames Feist [asyncResp, 311*e284a7c1SJames Feist driveId](const boost::system::error_code ec, 312*e284a7c1SJames Feist const crow::openbmc_mapper::GetSubTreeType &subtree) { 313a25aeccfSNikhil Potade if (ec) 314a25aeccfSNikhil Potade { 315a25aeccfSNikhil Potade BMCWEB_LOG_ERROR << "Drive mapper call error"; 316a25aeccfSNikhil Potade messages::internalError(asyncResp->res); 317a25aeccfSNikhil Potade return; 318a25aeccfSNikhil Potade } 319a25aeccfSNikhil Potade 320a25aeccfSNikhil Potade auto object = std::find_if( 321a25aeccfSNikhil Potade subtree.begin(), subtree.end(), [&driveId](auto &object) { 322a25aeccfSNikhil Potade const std::string &path = object.first; 323a25aeccfSNikhil Potade return boost::ends_with(path, "/" + driveId); 324a25aeccfSNikhil Potade }); 325a25aeccfSNikhil Potade 326a25aeccfSNikhil Potade if (object == subtree.end()) 327a25aeccfSNikhil Potade { 328a25aeccfSNikhil Potade messages::resourceNotFound(asyncResp->res, "Drive", 329a25aeccfSNikhil Potade driveId); 330a25aeccfSNikhil Potade return; 331a25aeccfSNikhil Potade } 332a25aeccfSNikhil Potade 333a25aeccfSNikhil Potade const std::string &path = object->first; 334a25aeccfSNikhil Potade const std::vector< 335a25aeccfSNikhil Potade std::pair<std::string, std::vector<std::string>>> 336a25aeccfSNikhil Potade &connectionNames = object->second; 337a25aeccfSNikhil Potade 338a25aeccfSNikhil Potade asyncResp->res.jsonValue["@odata.type"] = "#Drive.v1_7_0.Drive"; 339a25aeccfSNikhil Potade asyncResp->res.jsonValue["@odata.context"] = 340a25aeccfSNikhil Potade "/redfish/v1/$metadata#Drive.Drive"; 341a25aeccfSNikhil Potade asyncResp->res.jsonValue["@odata.id"] = 342be13ceceSJames Feist "/redfish/v1/Systems/system/Storage/1/Drives/" + driveId; 3432ad9c2f6SJames Feist asyncResp->res.jsonValue["Name"] = driveId; 3442ad9c2f6SJames Feist asyncResp->res.jsonValue["Id"] = driveId; 345a25aeccfSNikhil Potade 346a25aeccfSNikhil Potade if (connectionNames.size() != 1) 347a25aeccfSNikhil Potade { 348a25aeccfSNikhil Potade BMCWEB_LOG_ERROR << "Connection size " 349a25aeccfSNikhil Potade << connectionNames.size() 350a25aeccfSNikhil Potade << ", greater than 1"; 351a25aeccfSNikhil Potade messages::internalError(asyncResp->res); 352a25aeccfSNikhil Potade return; 353a25aeccfSNikhil Potade } 354a25aeccfSNikhil Potade 355a25aeccfSNikhil Potade getMainChassisId( 356a25aeccfSNikhil Potade asyncResp, [](const std::string &chassisId, 357a25aeccfSNikhil Potade std::shared_ptr<AsyncResp> aRsp) { 358a25aeccfSNikhil Potade aRsp->res.jsonValue["Links"]["Chassis"] = { 359a25aeccfSNikhil Potade {"@odata.id", "/redfish/v1/Chassis/" + chassisId}}; 360a25aeccfSNikhil Potade }); 361a25aeccfSNikhil Potade 362a25aeccfSNikhil Potade const std::string &connectionName = connectionNames[0].first; 363a25aeccfSNikhil Potade crow::connections::systemBus->async_method_call( 3642ad9c2f6SJames Feist [asyncResp](const boost::system::error_code ec, 365a25aeccfSNikhil Potade const std::vector<std::pair< 366a25aeccfSNikhil Potade std::string, 367a25aeccfSNikhil Potade std::variant<bool, std::string, uint64_t>>> 368a25aeccfSNikhil Potade &propertiesList) { 369a25aeccfSNikhil Potade if (ec) 370a25aeccfSNikhil Potade { 371a25aeccfSNikhil Potade // this interface isn't necessary 372a25aeccfSNikhil Potade return; 373a25aeccfSNikhil Potade } 374a25aeccfSNikhil Potade for (const std::pair<std::string, 375a25aeccfSNikhil Potade std::variant<bool, std::string, 376a25aeccfSNikhil Potade uint64_t>> &property : 377a25aeccfSNikhil Potade propertiesList) 378a25aeccfSNikhil Potade { 379a25aeccfSNikhil Potade // Store DBus properties that are also 380a25aeccfSNikhil Potade // Redfish properties with same name and a 381a25aeccfSNikhil Potade // string value 382a25aeccfSNikhil Potade const std::string &propertyName = property.first; 383a25aeccfSNikhil Potade if ((propertyName == "PartNumber") || 384a25aeccfSNikhil Potade (propertyName == "SerialNumber") || 385a25aeccfSNikhil Potade (propertyName == "Manufacturer") || 386a25aeccfSNikhil Potade (propertyName == "Model")) 387a25aeccfSNikhil Potade { 388a25aeccfSNikhil Potade const std::string *value = 389a25aeccfSNikhil Potade std::get_if<std::string>(&property.second); 390a25aeccfSNikhil Potade if (value == nullptr) 391a25aeccfSNikhil Potade { 392a25aeccfSNikhil Potade // illegal property 393a25aeccfSNikhil Potade messages::internalError(asyncResp->res); 394a25aeccfSNikhil Potade continue; 395a25aeccfSNikhil Potade } 396a25aeccfSNikhil Potade asyncResp->res.jsonValue[propertyName] = *value; 397a25aeccfSNikhil Potade } 398a25aeccfSNikhil Potade } 399a25aeccfSNikhil Potade }, 400a25aeccfSNikhil Potade connectionName, path, "org.freedesktop.DBus.Properties", 401a25aeccfSNikhil Potade "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); 402a25aeccfSNikhil Potade 403a25aeccfSNikhil Potade // default it to Enabled 404a25aeccfSNikhil Potade asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 405a25aeccfSNikhil Potade 4062ad9c2f6SJames Feist auto health = std::make_shared<HealthPopulate>(asyncResp); 407*e284a7c1SJames Feist health->inventory.emplace_back(path); 4082ad9c2f6SJames Feist health->populate(); 4092ad9c2f6SJames Feist 410a25aeccfSNikhil Potade crow::connections::systemBus->async_method_call( 411a25aeccfSNikhil Potade [asyncResp, path](const boost::system::error_code ec, 412a25aeccfSNikhil Potade const std::variant<bool> present) { 413a25aeccfSNikhil Potade // this interface isn't necessary, only check it if we 414a25aeccfSNikhil Potade // get a good return 4152ad9c2f6SJames Feist if (ec) 416a25aeccfSNikhil Potade { 4172ad9c2f6SJames Feist return; 4182ad9c2f6SJames Feist } 419a25aeccfSNikhil Potade const bool *enabled = std::get_if<bool>(&present); 420a25aeccfSNikhil Potade if (enabled == nullptr) 421a25aeccfSNikhil Potade { 422a25aeccfSNikhil Potade BMCWEB_LOG_DEBUG << "Illegal property present"; 423a25aeccfSNikhil Potade messages::internalError(asyncResp->res); 424a25aeccfSNikhil Potade return; 425a25aeccfSNikhil Potade } 426a25aeccfSNikhil Potade if (!(*enabled)) 427a25aeccfSNikhil Potade { 428a25aeccfSNikhil Potade asyncResp->res.jsonValue["Status"]["State"] = 429a25aeccfSNikhil Potade "Disabled"; 430a25aeccfSNikhil Potade } 431a25aeccfSNikhil Potade }, 432a25aeccfSNikhil Potade connectionName, path, "org.freedesktop.DBus.Properties", 433a25aeccfSNikhil Potade "Get", "xyz.openbmc_project.Inventory.Item", "Present"); 43422984074SJames Feist 43522984074SJames Feist crow::connections::systemBus->async_method_call( 43622984074SJames Feist [asyncResp](const boost::system::error_code ec, 43722984074SJames Feist const std::variant<bool> rebuilding) { 43822984074SJames Feist // this interface isn't necessary, only check it if we 43922984074SJames Feist // get a good return 44022984074SJames Feist if (ec) 44122984074SJames Feist { 44222984074SJames Feist return; 44322984074SJames Feist } 44422984074SJames Feist const bool *updating = std::get_if<bool>(&rebuilding); 44522984074SJames Feist if (updating == nullptr) 44622984074SJames Feist { 44722984074SJames Feist BMCWEB_LOG_DEBUG << "Illegal property present"; 44822984074SJames Feist messages::internalError(asyncResp->res); 44922984074SJames Feist return; 45022984074SJames Feist } 45122984074SJames Feist 45222984074SJames Feist // updating and disabled in the backend shouldn't be 45322984074SJames Feist // able to be set at the same time, so we don't need to 45422984074SJames Feist // check for the race condition of these two calls 45522984074SJames Feist if ((*updating)) 45622984074SJames Feist { 45722984074SJames Feist asyncResp->res.jsonValue["Status"]["State"] = 45822984074SJames Feist "Updating"; 45922984074SJames Feist } 46022984074SJames Feist }, 46122984074SJames Feist connectionName, path, "org.freedesktop.DBus.Properties", 46222984074SJames Feist "Get", "xyz.openbmc_project.State.Drive", "Rebuilding"); 463a25aeccfSNikhil Potade }, 464a25aeccfSNikhil Potade "xyz.openbmc_project.ObjectMapper", 465a25aeccfSNikhil Potade "/xyz/openbmc_project/object_mapper", 466a25aeccfSNikhil Potade "xyz.openbmc_project.ObjectMapper", "GetSubTree", 467a25aeccfSNikhil Potade "/xyz/openbmc_project/inventory", int32_t(0), 468a25aeccfSNikhil Potade std::array<const char *, 1>{ 469a25aeccfSNikhil Potade "xyz.openbmc_project.Inventory.Item.Drive"}); 470a25aeccfSNikhil Potade } 471a25aeccfSNikhil Potade }; 472a25aeccfSNikhil Potade } // namespace redfish 473