1*c5b2abe0SLewanczyk, Dawid /* 2*c5b2abe0SLewanczyk, Dawid // Copyright (c) 2018 Intel Corporation 3*c5b2abe0SLewanczyk, Dawid // 4*c5b2abe0SLewanczyk, Dawid // Licensed under the Apache License, Version 2.0 (the "License"); 5*c5b2abe0SLewanczyk, Dawid // you may not use this file except in compliance with the License. 6*c5b2abe0SLewanczyk, Dawid // You may obtain a copy of the License at 7*c5b2abe0SLewanczyk, Dawid // 8*c5b2abe0SLewanczyk, Dawid // http://www.apache.org/licenses/LICENSE-2.0 9*c5b2abe0SLewanczyk, Dawid // 10*c5b2abe0SLewanczyk, Dawid // Unless required by applicable law or agreed to in writing, software 11*c5b2abe0SLewanczyk, Dawid // distributed under the License is distributed on an "AS IS" BASIS, 12*c5b2abe0SLewanczyk, Dawid // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*c5b2abe0SLewanczyk, Dawid // See the License for the specific language governing permissions and 14*c5b2abe0SLewanczyk, Dawid // limitations under the License. 15*c5b2abe0SLewanczyk, Dawid */ 16*c5b2abe0SLewanczyk, Dawid #pragma once 17*c5b2abe0SLewanczyk, Dawid 18*c5b2abe0SLewanczyk, Dawid #include <error_messages.hpp> 19*c5b2abe0SLewanczyk, Dawid #include <utils/json_utils.hpp> 20*c5b2abe0SLewanczyk, Dawid #include "node.hpp" 21*c5b2abe0SLewanczyk, Dawid #include "boost/container/flat_map.hpp" 22*c5b2abe0SLewanczyk, Dawid 23*c5b2abe0SLewanczyk, Dawid namespace redfish { 24*c5b2abe0SLewanczyk, Dawid 25*c5b2abe0SLewanczyk, Dawid /** 26*c5b2abe0SLewanczyk, Dawid * SystemAsyncResp 27*c5b2abe0SLewanczyk, Dawid * Gathers data needed for response processing after async calls are done 28*c5b2abe0SLewanczyk, Dawid */ 29*c5b2abe0SLewanczyk, Dawid class SystemAsyncResp { 30*c5b2abe0SLewanczyk, Dawid public: 31*c5b2abe0SLewanczyk, Dawid SystemAsyncResp(crow::response &response) : res(response) {} 32*c5b2abe0SLewanczyk, Dawid 33*c5b2abe0SLewanczyk, Dawid ~SystemAsyncResp() { 34*c5b2abe0SLewanczyk, Dawid if (res.result() != (boost::beast::http::status::ok)) { 35*c5b2abe0SLewanczyk, Dawid // Reset the json object to clear out any data that made it in before the 36*c5b2abe0SLewanczyk, Dawid // error happened 37*c5b2abe0SLewanczyk, Dawid // todo(ed) handle error condition with proper code 38*c5b2abe0SLewanczyk, Dawid res.json_value = messages::internalError(); 39*c5b2abe0SLewanczyk, Dawid } 40*c5b2abe0SLewanczyk, Dawid res.end(); 41*c5b2abe0SLewanczyk, Dawid } 42*c5b2abe0SLewanczyk, Dawid 43*c5b2abe0SLewanczyk, Dawid void setErrorStatus() { 44*c5b2abe0SLewanczyk, Dawid res.result(boost::beast::http::status::internal_server_error); 45*c5b2abe0SLewanczyk, Dawid } 46*c5b2abe0SLewanczyk, Dawid 47*c5b2abe0SLewanczyk, Dawid crow::response &res; 48*c5b2abe0SLewanczyk, Dawid }; 49*c5b2abe0SLewanczyk, Dawid 50*c5b2abe0SLewanczyk, Dawid /** 51*c5b2abe0SLewanczyk, Dawid * OnDemandSystemsProvider 52*c5b2abe0SLewanczyk, Dawid * Board provider class that retrieves data directly from dbus, before seting 53*c5b2abe0SLewanczyk, Dawid * it into JSON output. This does not cache any data. 54*c5b2abe0SLewanczyk, Dawid * 55*c5b2abe0SLewanczyk, Dawid * Class can be a good example on how to scale different data providing 56*c5b2abe0SLewanczyk, Dawid * solutions to produce single schema output. 57*c5b2abe0SLewanczyk, Dawid * 58*c5b2abe0SLewanczyk, Dawid * TODO(Pawel) 59*c5b2abe0SLewanczyk, Dawid * This perhaps shall be different file, which has to be chosen on compile time 60*c5b2abe0SLewanczyk, Dawid * depending on OEM needs 61*c5b2abe0SLewanczyk, Dawid */ 62*c5b2abe0SLewanczyk, Dawid class OnDemandSystemsProvider { 63*c5b2abe0SLewanczyk, Dawid public: 64*c5b2abe0SLewanczyk, Dawid template <typename CallbackFunc> 65*c5b2abe0SLewanczyk, Dawid void getBaseboardList(CallbackFunc &&callback) { 66*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Get list of available boards."; 67*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 68*c5b2abe0SLewanczyk, Dawid [callback{std::move(callback)}](const boost::system::error_code ec, 69*c5b2abe0SLewanczyk, Dawid const std::vector<std::string> &resp) { 70*c5b2abe0SLewanczyk, Dawid // Callback requires vector<string> to retrieve all available board 71*c5b2abe0SLewanczyk, Dawid // list. 72*c5b2abe0SLewanczyk, Dawid std::vector<std::string> board_list; 73*c5b2abe0SLewanczyk, Dawid if (ec) { 74*c5b2abe0SLewanczyk, Dawid // Something wrong on DBus, the error_code is not important at this 75*c5b2abe0SLewanczyk, Dawid // moment, just return success=false, and empty output. Since size 76*c5b2abe0SLewanczyk, Dawid // of vector may vary depending on information from Entity Manager, 77*c5b2abe0SLewanczyk, Dawid // and empty output could not be treated same way as error. 78*c5b2abe0SLewanczyk, Dawid callback(false, board_list); 79*c5b2abe0SLewanczyk, Dawid return; 80*c5b2abe0SLewanczyk, Dawid } 81*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << resp.size() << " boards."; 82*c5b2abe0SLewanczyk, Dawid // Iterate over all retrieved ObjectPaths. 83*c5b2abe0SLewanczyk, Dawid for (const std::string &objpath : resp) { 84*c5b2abe0SLewanczyk, Dawid std::size_t last_pos = objpath.rfind("/"); 85*c5b2abe0SLewanczyk, Dawid if (last_pos != std::string::npos) { 86*c5b2abe0SLewanczyk, Dawid board_list.emplace_back(objpath.substr(last_pos + 1)); 87*c5b2abe0SLewanczyk, Dawid } 88*c5b2abe0SLewanczyk, Dawid } 89*c5b2abe0SLewanczyk, Dawid // Finally make a callback with useful data 90*c5b2abe0SLewanczyk, Dawid callback(true, board_list); 91*c5b2abe0SLewanczyk, Dawid }, 92*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.ObjectMapper", 93*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/object_mapper", 94*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 95*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/inventory", int32_t(0), 96*c5b2abe0SLewanczyk, Dawid std::array<const char *, 1>{ 97*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Inventory.Item.Board"}); 98*c5b2abe0SLewanczyk, Dawid }; 99*c5b2abe0SLewanczyk, Dawid 100*c5b2abe0SLewanczyk, Dawid /** 101*c5b2abe0SLewanczyk, Dawid * @brief Retrieves computer system properties over dbus 102*c5b2abe0SLewanczyk, Dawid * 103*c5b2abe0SLewanczyk, Dawid * @param[in] aResp Shared pointer for completing asynchronous calls 104*c5b2abe0SLewanczyk, Dawid * @param[in] name Computer system name from request 105*c5b2abe0SLewanczyk, Dawid * 106*c5b2abe0SLewanczyk, Dawid * @return None. 107*c5b2abe0SLewanczyk, Dawid */ 108*c5b2abe0SLewanczyk, Dawid void getComputerSystem(std::shared_ptr<SystemAsyncResp> aResp, 109*c5b2abe0SLewanczyk, Dawid const std::string &name) { 110*c5b2abe0SLewanczyk, Dawid const std::array<const char *, 5> interfaces = { 111*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Inventory.Decorator.Asset", 112*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Inventory.Item.Cpu", 113*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Inventory.Item.Dimm", 114*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Inventory.Item.System", 115*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Common.UUID", 116*c5b2abe0SLewanczyk, Dawid }; 117*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Get available system components."; 118*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 119*c5b2abe0SLewanczyk, Dawid [ name, aResp{std::move(aResp)} ]( 120*c5b2abe0SLewanczyk, Dawid const boost::system::error_code ec, 121*c5b2abe0SLewanczyk, Dawid const std::vector<std::pair< 122*c5b2abe0SLewanczyk, Dawid std::string, 123*c5b2abe0SLewanczyk, Dawid std::vector<std::pair<std::string, std::vector<std::string>>>>> 124*c5b2abe0SLewanczyk, Dawid &subtree) { 125*c5b2abe0SLewanczyk, Dawid if (ec) { 126*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "DBUS response error"; 127*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 128*c5b2abe0SLewanczyk, Dawid return; 129*c5b2abe0SLewanczyk, Dawid } 130*c5b2abe0SLewanczyk, Dawid bool foundName = false; 131*c5b2abe0SLewanczyk, Dawid // Iterate over all retrieved ObjectPaths. 132*c5b2abe0SLewanczyk, Dawid for (const std::pair<std::string, 133*c5b2abe0SLewanczyk, Dawid std::vector<std::pair<std::string, 134*c5b2abe0SLewanczyk, Dawid std::vector<std::string>>>> 135*c5b2abe0SLewanczyk, Dawid &object : subtree) { 136*c5b2abe0SLewanczyk, Dawid const std::string &path = object.first; 137*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got path: " << path; 138*c5b2abe0SLewanczyk, Dawid const std::vector<std::pair<std::string, std::vector<std::string>>> 139*c5b2abe0SLewanczyk, Dawid &connectionNames = object.second; 140*c5b2abe0SLewanczyk, Dawid if (connectionNames.size() < 1) { 141*c5b2abe0SLewanczyk, Dawid continue; 142*c5b2abe0SLewanczyk, Dawid } 143*c5b2abe0SLewanczyk, Dawid // Check if computer system exist 144*c5b2abe0SLewanczyk, Dawid if (boost::ends_with(path, name)) { 145*c5b2abe0SLewanczyk, Dawid foundName = true; 146*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Found name: " << name; 147*c5b2abe0SLewanczyk, Dawid const std::string connectionName = connectionNames[0].first; 148*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 149*c5b2abe0SLewanczyk, Dawid [ aResp, name(std::string(name)) ]( 150*c5b2abe0SLewanczyk, Dawid const boost::system::error_code ec, 151*c5b2abe0SLewanczyk, Dawid const std::vector<std::pair<std::string, VariantType>> 152*c5b2abe0SLewanczyk, Dawid &propertiesList) { 153*c5b2abe0SLewanczyk, Dawid if (ec) { 154*c5b2abe0SLewanczyk, Dawid CROW_LOG_ERROR << "DBUS response error: " << ec; 155*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 156*c5b2abe0SLewanczyk, Dawid return; 157*c5b2abe0SLewanczyk, Dawid } 158*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << propertiesList.size() 159*c5b2abe0SLewanczyk, Dawid << "properties for system"; 160*c5b2abe0SLewanczyk, Dawid for (const std::pair<std::string, VariantType> &property : 161*c5b2abe0SLewanczyk, Dawid propertiesList) { 162*c5b2abe0SLewanczyk, Dawid const std::string *value = 163*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<const std::string>(property.second); 164*c5b2abe0SLewanczyk, Dawid if (value != nullptr) { 165*c5b2abe0SLewanczyk, Dawid aResp->res.json_value[property.first] = *value; 166*c5b2abe0SLewanczyk, Dawid } 167*c5b2abe0SLewanczyk, Dawid } 168*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["Name"] = name; 169*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["Id"] = 170*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["SerialNumber"]; 171*c5b2abe0SLewanczyk, Dawid }, 172*c5b2abe0SLewanczyk, Dawid connectionName, path, "org.freedesktop.DBus.Properties", 173*c5b2abe0SLewanczyk, Dawid "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); 174*c5b2abe0SLewanczyk, Dawid } else { 175*c5b2abe0SLewanczyk, Dawid // This is not system, so check if it's cpu, dimm, UUID or BiosVer 176*c5b2abe0SLewanczyk, Dawid for (auto const &s : connectionNames) { 177*c5b2abe0SLewanczyk, Dawid for (auto const &i : s.second) { 178*c5b2abe0SLewanczyk, Dawid if (boost::ends_with(i, "Dimm")) { 179*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Found Dimm, now get it properties."; 180*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 181*c5b2abe0SLewanczyk, Dawid [&, aResp](const boost::system::error_code ec, 182*c5b2abe0SLewanczyk, Dawid const std::vector<std::pair< 183*c5b2abe0SLewanczyk, Dawid std::string, VariantType>> &properties) { 184*c5b2abe0SLewanczyk, Dawid if (ec) { 185*c5b2abe0SLewanczyk, Dawid CROW_LOG_ERROR << "DBUS response error " << ec; 186*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 187*c5b2abe0SLewanczyk, Dawid return; 188*c5b2abe0SLewanczyk, Dawid } 189*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << properties.size() 190*c5b2abe0SLewanczyk, Dawid << "Dimm properties."; 191*c5b2abe0SLewanczyk, Dawid for (const auto &p : properties) { 192*c5b2abe0SLewanczyk, Dawid if (p.first == "MemorySize") { 193*c5b2abe0SLewanczyk, Dawid const std::string *value = 194*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<const std::string>(p.second); 195*c5b2abe0SLewanczyk, Dawid if ((value != nullptr) && (*value != "NULL")) { 196*c5b2abe0SLewanczyk, Dawid // Remove units char 197*c5b2abe0SLewanczyk, Dawid int32_t unitCoeff; 198*c5b2abe0SLewanczyk, Dawid if (boost::ends_with(*value, "MB")) { 199*c5b2abe0SLewanczyk, Dawid unitCoeff = 1000; 200*c5b2abe0SLewanczyk, Dawid } else if (boost::ends_with(*value, "KB")) { 201*c5b2abe0SLewanczyk, Dawid unitCoeff = 1000000; 202*c5b2abe0SLewanczyk, Dawid } else { 203*c5b2abe0SLewanczyk, Dawid CROW_LOG_ERROR << "Unsupported memory units"; 204*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 205*c5b2abe0SLewanczyk, Dawid return; 206*c5b2abe0SLewanczyk, Dawid } 207*c5b2abe0SLewanczyk, Dawid 208*c5b2abe0SLewanczyk, Dawid auto memSize = boost::lexical_cast<int>( 209*c5b2abe0SLewanczyk, Dawid value->substr(0, value->length() - 2)); 210*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["TotalSystemMemoryGiB"] += 211*c5b2abe0SLewanczyk, Dawid memSize * unitCoeff; 212*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["MemorySummary"]["Status"] 213*c5b2abe0SLewanczyk, Dawid ["State"] = "Enabled"; 214*c5b2abe0SLewanczyk, Dawid } 215*c5b2abe0SLewanczyk, Dawid } 216*c5b2abe0SLewanczyk, Dawid } 217*c5b2abe0SLewanczyk, Dawid }, 218*c5b2abe0SLewanczyk, Dawid s.first, path, "org.freedesktop.DBus.Properties", 219*c5b2abe0SLewanczyk, Dawid "GetAll", "xyz.openbmc_project.Inventory.Item.Dimm"); 220*c5b2abe0SLewanczyk, Dawid } else if (boost::ends_with(i, "Cpu")) { 221*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Found Cpu, now get it properties."; 222*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 223*c5b2abe0SLewanczyk, Dawid [&, aResp](const boost::system::error_code ec, 224*c5b2abe0SLewanczyk, Dawid const std::vector<std::pair< 225*c5b2abe0SLewanczyk, Dawid std::string, VariantType>> &properties) { 226*c5b2abe0SLewanczyk, Dawid if (ec) { 227*c5b2abe0SLewanczyk, Dawid CROW_LOG_ERROR << "DBUS response error " << ec; 228*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 229*c5b2abe0SLewanczyk, Dawid return; 230*c5b2abe0SLewanczyk, Dawid } 231*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << properties.size() 232*c5b2abe0SLewanczyk, Dawid << "Cpu properties."; 233*c5b2abe0SLewanczyk, Dawid for (const auto &p : properties) { 234*c5b2abe0SLewanczyk, Dawid if (p.first == "ProcessorFamily") { 235*c5b2abe0SLewanczyk, Dawid const std::string *value = 236*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<const std::string>(p.second); 237*c5b2abe0SLewanczyk, Dawid if (value != nullptr) { 238*c5b2abe0SLewanczyk, Dawid aResp->res 239*c5b2abe0SLewanczyk, Dawid .json_value["ProcessorSummary"]["Count"] = 240*c5b2abe0SLewanczyk, Dawid aResp->res 241*c5b2abe0SLewanczyk, Dawid .json_value["ProcessorSummary"]["Count"] 242*c5b2abe0SLewanczyk, Dawid .get<int>() + 243*c5b2abe0SLewanczyk, Dawid 1; 244*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["ProcessorSummary"] 245*c5b2abe0SLewanczyk, Dawid ["Status"]["State"] = 246*c5b2abe0SLewanczyk, Dawid "Enabled"; 247*c5b2abe0SLewanczyk, Dawid aResp->res 248*c5b2abe0SLewanczyk, Dawid .json_value["ProcessorSummary"]["Model"] = 249*c5b2abe0SLewanczyk, Dawid *value; 250*c5b2abe0SLewanczyk, Dawid } 251*c5b2abe0SLewanczyk, Dawid } 252*c5b2abe0SLewanczyk, Dawid } 253*c5b2abe0SLewanczyk, Dawid }, 254*c5b2abe0SLewanczyk, Dawid s.first, path, "org.freedesktop.DBus.Properties", 255*c5b2abe0SLewanczyk, Dawid "GetAll", "xyz.openbmc_project.Inventory.Item.Cpu"); 256*c5b2abe0SLewanczyk, Dawid } else if (boost::ends_with(i, "UUID")) { 257*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Found UUID, now get it properties."; 258*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 259*c5b2abe0SLewanczyk, Dawid [aResp](const boost::system::error_code ec, 260*c5b2abe0SLewanczyk, Dawid const std::vector<std::pair< 261*c5b2abe0SLewanczyk, Dawid std::string, VariantType>> &properties) { 262*c5b2abe0SLewanczyk, Dawid if (ec) { 263*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "DBUS response error " << ec; 264*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 265*c5b2abe0SLewanczyk, Dawid return; 266*c5b2abe0SLewanczyk, Dawid } 267*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << properties.size() 268*c5b2abe0SLewanczyk, Dawid << "UUID properties."; 269*c5b2abe0SLewanczyk, Dawid for (const std::pair<std::string, VariantType> &p : 270*c5b2abe0SLewanczyk, Dawid properties) { 271*c5b2abe0SLewanczyk, Dawid if (p.first == "BIOSVer") { 272*c5b2abe0SLewanczyk, Dawid const std::string *value = 273*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<const std::string>(p.second); 274*c5b2abe0SLewanczyk, Dawid if (value != nullptr) { 275*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["BiosVersion"] = *value; 276*c5b2abe0SLewanczyk, Dawid } 277*c5b2abe0SLewanczyk, Dawid } 278*c5b2abe0SLewanczyk, Dawid if (p.first == "UUID") { 279*c5b2abe0SLewanczyk, Dawid const std::string *value = 280*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<const std::string>(p.second); 281*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "UUID = " << *value 282*c5b2abe0SLewanczyk, Dawid << " length " << value->length(); 283*c5b2abe0SLewanczyk, Dawid if (value != nullptr) { 284*c5b2abe0SLewanczyk, Dawid // Workaround for to short return str in smbios 285*c5b2abe0SLewanczyk, Dawid // demo app, 32 bytes are described by spec 286*c5b2abe0SLewanczyk, Dawid if (value->length() > 0 && 287*c5b2abe0SLewanczyk, Dawid value->length() < 32) { 288*c5b2abe0SLewanczyk, Dawid std::string correctedValue = *value; 289*c5b2abe0SLewanczyk, Dawid correctedValue.append(32 - value->length(), 290*c5b2abe0SLewanczyk, Dawid '0'); 291*c5b2abe0SLewanczyk, Dawid value = &correctedValue; 292*c5b2abe0SLewanczyk, Dawid } else if (value->length() == 32) { 293*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["UUID"] = 294*c5b2abe0SLewanczyk, Dawid value->substr(0, 8) + "-" + 295*c5b2abe0SLewanczyk, Dawid value->substr(8, 4) + "-" + 296*c5b2abe0SLewanczyk, Dawid value->substr(12, 4) + "-" + 297*c5b2abe0SLewanczyk, Dawid value->substr(16, 4) + "-" + 298*c5b2abe0SLewanczyk, Dawid value->substr(20, 12); 299*c5b2abe0SLewanczyk, Dawid } 300*c5b2abe0SLewanczyk, Dawid } 301*c5b2abe0SLewanczyk, Dawid } 302*c5b2abe0SLewanczyk, Dawid } 303*c5b2abe0SLewanczyk, Dawid }, 304*c5b2abe0SLewanczyk, Dawid s.first, path, "org.freedesktop.DBus.Properties", 305*c5b2abe0SLewanczyk, Dawid "GetAll", "xyz.openbmc_project.Common.UUID"); 306*c5b2abe0SLewanczyk, Dawid } 307*c5b2abe0SLewanczyk, Dawid } 308*c5b2abe0SLewanczyk, Dawid } 309*c5b2abe0SLewanczyk, Dawid } 310*c5b2abe0SLewanczyk, Dawid } 311*c5b2abe0SLewanczyk, Dawid if (foundName == false) { 312*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 313*c5b2abe0SLewanczyk, Dawid } 314*c5b2abe0SLewanczyk, Dawid }, 315*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.ObjectMapper", 316*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/object_mapper", 317*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.ObjectMapper", "GetSubTree", 318*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/inventory", int32_t(0), interfaces); 319*c5b2abe0SLewanczyk, Dawid } 320*c5b2abe0SLewanczyk, Dawid 321*c5b2abe0SLewanczyk, Dawid /** 322*c5b2abe0SLewanczyk, Dawid * @brief Retrieves identify led group properties over dbus 323*c5b2abe0SLewanczyk, Dawid * 324*c5b2abe0SLewanczyk, Dawid * @param[in] aResp Shared pointer for completing asynchronous calls. 325*c5b2abe0SLewanczyk, Dawid * @param[in] callback Callback for process retrieved data. 326*c5b2abe0SLewanczyk, Dawid * 327*c5b2abe0SLewanczyk, Dawid * @return None. 328*c5b2abe0SLewanczyk, Dawid */ 329*c5b2abe0SLewanczyk, Dawid template <typename CallbackFunc> 330*c5b2abe0SLewanczyk, Dawid void getLedGroupIdentify(std::shared_ptr<SystemAsyncResp> aResp, 331*c5b2abe0SLewanczyk, Dawid CallbackFunc &&callback) { 332*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Get led groups"; 333*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 334*c5b2abe0SLewanczyk, Dawid [ 335*c5b2abe0SLewanczyk, Dawid aResp{std::move(aResp)}, &callback 336*c5b2abe0SLewanczyk, Dawid ](const boost::system::error_code &ec, const ManagedObjectsType &resp) { 337*c5b2abe0SLewanczyk, Dawid if (ec) { 338*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "DBUS response error " << ec; 339*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 340*c5b2abe0SLewanczyk, Dawid return; 341*c5b2abe0SLewanczyk, Dawid } 342*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << resp.size() << "led group objects."; 343*c5b2abe0SLewanczyk, Dawid for (const auto &objPath : resp) { 344*c5b2abe0SLewanczyk, Dawid const std::string &path = objPath.first; 345*c5b2abe0SLewanczyk, Dawid if (path.rfind("enclosure_identify") != std::string::npos) { 346*c5b2abe0SLewanczyk, Dawid for (const auto &interface : objPath.second) { 347*c5b2abe0SLewanczyk, Dawid if (interface.first == "xyz.openbmc_project.Led.Group") { 348*c5b2abe0SLewanczyk, Dawid for (const auto &property : interface.second) { 349*c5b2abe0SLewanczyk, Dawid if (property.first == "Asserted") { 350*c5b2abe0SLewanczyk, Dawid const bool *asserted = 351*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<const bool>(property.second); 352*c5b2abe0SLewanczyk, Dawid if (nullptr != asserted) { 353*c5b2abe0SLewanczyk, Dawid callback(*asserted, aResp); 354*c5b2abe0SLewanczyk, Dawid } else { 355*c5b2abe0SLewanczyk, Dawid callback(false, aResp); 356*c5b2abe0SLewanczyk, Dawid } 357*c5b2abe0SLewanczyk, Dawid } 358*c5b2abe0SLewanczyk, Dawid } 359*c5b2abe0SLewanczyk, Dawid } 360*c5b2abe0SLewanczyk, Dawid } 361*c5b2abe0SLewanczyk, Dawid } 362*c5b2abe0SLewanczyk, Dawid } 363*c5b2abe0SLewanczyk, Dawid }, 364*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.LED.GroupManager", 365*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager", 366*c5b2abe0SLewanczyk, Dawid "GetManagedObjects"); 367*c5b2abe0SLewanczyk, Dawid } 368*c5b2abe0SLewanczyk, Dawid 369*c5b2abe0SLewanczyk, Dawid template <typename CallbackFunc> 370*c5b2abe0SLewanczyk, Dawid void getLedIdentify(std::shared_ptr<SystemAsyncResp> aResp, 371*c5b2abe0SLewanczyk, Dawid CallbackFunc &&callback) { 372*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Get identify led properties"; 373*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 374*c5b2abe0SLewanczyk, Dawid [ aResp{std::move(aResp)}, &callback ]( 375*c5b2abe0SLewanczyk, Dawid const boost::system::error_code ec, 376*c5b2abe0SLewanczyk, Dawid const PropertiesType &properties) { 377*c5b2abe0SLewanczyk, Dawid if (ec) { 378*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "DBUS response error " << ec; 379*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 380*c5b2abe0SLewanczyk, Dawid return; 381*c5b2abe0SLewanczyk, Dawid } 382*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << properties.size() << "led properties."; 383*c5b2abe0SLewanczyk, Dawid std::string output; 384*c5b2abe0SLewanczyk, Dawid for (const auto &property : properties) { 385*c5b2abe0SLewanczyk, Dawid if (property.first == "State") { 386*c5b2abe0SLewanczyk, Dawid const std::string *s = 387*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<std::string>(property.second); 388*c5b2abe0SLewanczyk, Dawid if (nullptr != s) { 389*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Identify Led State: " << *s; 390*c5b2abe0SLewanczyk, Dawid const auto pos = s->rfind('.'); 391*c5b2abe0SLewanczyk, Dawid if (pos != std::string::npos) { 392*c5b2abe0SLewanczyk, Dawid auto led = s->substr(pos + 1); 393*c5b2abe0SLewanczyk, Dawid for (const std::pair<const char *, const char *> &p : 394*c5b2abe0SLewanczyk, Dawid std::array<std::pair<const char *, const char *>, 3>{ 395*c5b2abe0SLewanczyk, Dawid {{"On", "Lit"}, 396*c5b2abe0SLewanczyk, Dawid {"Blink", "Blinking"}, 397*c5b2abe0SLewanczyk, Dawid {"Off", "Off"}}}) { 398*c5b2abe0SLewanczyk, Dawid if (led == p.first) { 399*c5b2abe0SLewanczyk, Dawid output = p.second; 400*c5b2abe0SLewanczyk, Dawid } 401*c5b2abe0SLewanczyk, Dawid } 402*c5b2abe0SLewanczyk, Dawid } 403*c5b2abe0SLewanczyk, Dawid } 404*c5b2abe0SLewanczyk, Dawid } 405*c5b2abe0SLewanczyk, Dawid } 406*c5b2abe0SLewanczyk, Dawid callback(output, aResp); 407*c5b2abe0SLewanczyk, Dawid }, 408*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.LED.Controller.identify", 409*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/led/physical/identify", 410*c5b2abe0SLewanczyk, Dawid "org.freedesktop.DBus.Properties", "GetAll", 411*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Led.Physical"); 412*c5b2abe0SLewanczyk, Dawid } 413*c5b2abe0SLewanczyk, Dawid 414*c5b2abe0SLewanczyk, Dawid /** 415*c5b2abe0SLewanczyk, Dawid * @brief Retrieves host state properties over dbus 416*c5b2abe0SLewanczyk, Dawid * 417*c5b2abe0SLewanczyk, Dawid * @param[in] aResp Shared pointer for completing asynchronous calls. 418*c5b2abe0SLewanczyk, Dawid * 419*c5b2abe0SLewanczyk, Dawid * @return None. 420*c5b2abe0SLewanczyk, Dawid */ 421*c5b2abe0SLewanczyk, Dawid void getHostState(std::shared_ptr<SystemAsyncResp> aResp) { 422*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Get host information."; 423*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 424*c5b2abe0SLewanczyk, Dawid [aResp{std::move(aResp)}](const boost::system::error_code ec, 425*c5b2abe0SLewanczyk, Dawid const PropertiesType &properties) { 426*c5b2abe0SLewanczyk, Dawid if (ec) { 427*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "DBUS response error " << ec; 428*c5b2abe0SLewanczyk, Dawid aResp->setErrorStatus(); 429*c5b2abe0SLewanczyk, Dawid return; 430*c5b2abe0SLewanczyk, Dawid } 431*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Got " << properties.size() << "host properties."; 432*c5b2abe0SLewanczyk, Dawid for (const auto &property : properties) { 433*c5b2abe0SLewanczyk, Dawid if (property.first == "CurrentHostState") { 434*c5b2abe0SLewanczyk, Dawid const std::string *s = 435*c5b2abe0SLewanczyk, Dawid mapbox::get_ptr<const std::string>(property.second); 436*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Host state: " << *s; 437*c5b2abe0SLewanczyk, Dawid if (nullptr != s) { 438*c5b2abe0SLewanczyk, Dawid const auto pos = s->rfind('.'); 439*c5b2abe0SLewanczyk, Dawid if (pos != std::string::npos) { 440*c5b2abe0SLewanczyk, Dawid // Verify Host State 441*c5b2abe0SLewanczyk, Dawid if (s->substr(pos + 1) == "Running") { 442*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["PowerState"] = "On"; 443*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["Status"]["State"] = "Enabled"; 444*c5b2abe0SLewanczyk, Dawid } else { 445*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["PowerState"] = "Off"; 446*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["Status"]["State"] = "Disabled"; 447*c5b2abe0SLewanczyk, Dawid } 448*c5b2abe0SLewanczyk, Dawid } 449*c5b2abe0SLewanczyk, Dawid } 450*c5b2abe0SLewanczyk, Dawid } 451*c5b2abe0SLewanczyk, Dawid } 452*c5b2abe0SLewanczyk, Dawid }, 453*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0", 454*c5b2abe0SLewanczyk, Dawid "org.freedesktop.DBus.Properties", "GetAll", 455*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.State.Host"); 456*c5b2abe0SLewanczyk, Dawid } 457*c5b2abe0SLewanczyk, Dawid }; 458*c5b2abe0SLewanczyk, Dawid 459*c5b2abe0SLewanczyk, Dawid /** 460*c5b2abe0SLewanczyk, Dawid * SystemsCollection derived class for delivering ComputerSystems Collection 461*c5b2abe0SLewanczyk, Dawid * Schema 462*c5b2abe0SLewanczyk, Dawid */ 463*c5b2abe0SLewanczyk, Dawid class SystemsCollection : public Node { 464*c5b2abe0SLewanczyk, Dawid public: 465*c5b2abe0SLewanczyk, Dawid SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/") { 466*c5b2abe0SLewanczyk, Dawid Node::json["@odata.type"] = 467*c5b2abe0SLewanczyk, Dawid "#ComputerSystemCollection.ComputerSystemCollection"; 468*c5b2abe0SLewanczyk, Dawid Node::json["@odata.id"] = "/redfish/v1/Systems"; 469*c5b2abe0SLewanczyk, Dawid Node::json["@odata.context"] = 470*c5b2abe0SLewanczyk, Dawid "/redfish/v1/" 471*c5b2abe0SLewanczyk, Dawid "$metadata#ComputerSystemCollection.ComputerSystemCollection"; 472*c5b2abe0SLewanczyk, Dawid Node::json["Name"] = "Computer System Collection"; 473*c5b2abe0SLewanczyk, Dawid 474*c5b2abe0SLewanczyk, Dawid entityPrivileges = { 475*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::get, {{"Login"}}}, 476*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::head, {{"Login"}}}, 477*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 478*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 479*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 480*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 481*c5b2abe0SLewanczyk, Dawid } 482*c5b2abe0SLewanczyk, Dawid 483*c5b2abe0SLewanczyk, Dawid private: 484*c5b2abe0SLewanczyk, Dawid /** 485*c5b2abe0SLewanczyk, Dawid * Functions triggers appropriate requests on DBus 486*c5b2abe0SLewanczyk, Dawid */ 487*c5b2abe0SLewanczyk, Dawid void doGet(crow::response &res, const crow::request &req, 488*c5b2abe0SLewanczyk, Dawid const std::vector<std::string> ¶ms) override { 489*c5b2abe0SLewanczyk, Dawid // Get board list, and call the below callback for JSON preparation 490*c5b2abe0SLewanczyk, Dawid provider.getBaseboardList( 491*c5b2abe0SLewanczyk, Dawid [&](const bool &success, const std::vector<std::string> &output) { 492*c5b2abe0SLewanczyk, Dawid if (success) { 493*c5b2abe0SLewanczyk, Dawid // ... prepare json array with appropriate @odata.id links 494*c5b2abe0SLewanczyk, Dawid nlohmann::json boardArray = nlohmann::json::array(); 495*c5b2abe0SLewanczyk, Dawid for (const std::string &board_item : output) { 496*c5b2abe0SLewanczyk, Dawid boardArray.push_back( 497*c5b2abe0SLewanczyk, Dawid {{"@odata.id", "/redfish/v1/Systems/" + board_item}}); 498*c5b2abe0SLewanczyk, Dawid } 499*c5b2abe0SLewanczyk, Dawid // Then attach members, count size and return, 500*c5b2abe0SLewanczyk, Dawid Node::json["Members"] = boardArray; 501*c5b2abe0SLewanczyk, Dawid Node::json["Members@odata.count"] = boardArray.size(); 502*c5b2abe0SLewanczyk, Dawid res.json_value = Node::json; 503*c5b2abe0SLewanczyk, Dawid } else { 504*c5b2abe0SLewanczyk, Dawid // ... otherwise, return INTERNALL ERROR 505*c5b2abe0SLewanczyk, Dawid res.result(boost::beast::http::status::internal_server_error); 506*c5b2abe0SLewanczyk, Dawid } 507*c5b2abe0SLewanczyk, Dawid res.end(); 508*c5b2abe0SLewanczyk, Dawid }); 509*c5b2abe0SLewanczyk, Dawid } 510*c5b2abe0SLewanczyk, Dawid 511*c5b2abe0SLewanczyk, Dawid OnDemandSystemsProvider provider; 512*c5b2abe0SLewanczyk, Dawid }; 513*c5b2abe0SLewanczyk, Dawid 514*c5b2abe0SLewanczyk, Dawid /** 515*c5b2abe0SLewanczyk, Dawid * Systems override class for delivering ComputerSystems Schema 516*c5b2abe0SLewanczyk, Dawid */ 517*c5b2abe0SLewanczyk, Dawid class Systems : public Node { 518*c5b2abe0SLewanczyk, Dawid public: 519*c5b2abe0SLewanczyk, Dawid /* 520*c5b2abe0SLewanczyk, Dawid * Default Constructor 521*c5b2abe0SLewanczyk, Dawid */ 522*c5b2abe0SLewanczyk, Dawid Systems(CrowApp &app) 523*c5b2abe0SLewanczyk, Dawid : Node(app, "/redfish/v1/Systems/<str>/", std::string()) { 524*c5b2abe0SLewanczyk, Dawid Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem"; 525*c5b2abe0SLewanczyk, Dawid Node::json["@odata.context"] = 526*c5b2abe0SLewanczyk, Dawid "/redfish/v1/$metadata#ComputerSystem.ComputerSystem"; 527*c5b2abe0SLewanczyk, Dawid Node::json["SystemType"] = "Physical"; 528*c5b2abe0SLewanczyk, Dawid Node::json["Description"] = "Computer System"; 529*c5b2abe0SLewanczyk, Dawid Node::json["Boot"]["BootSourceOverrideEnabled"] = 530*c5b2abe0SLewanczyk, Dawid "Disabled"; // TODO(Dawid), get real boot data 531*c5b2abe0SLewanczyk, Dawid Node::json["Boot"]["BootSourceOverrideTarget"] = 532*c5b2abe0SLewanczyk, Dawid "None"; // TODO(Dawid), get real boot data 533*c5b2abe0SLewanczyk, Dawid Node::json["Boot"]["BootSourceOverrideMode"] = 534*c5b2abe0SLewanczyk, Dawid "Legacy"; // TODO(Dawid), get real boot data 535*c5b2abe0SLewanczyk, Dawid Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] = { 536*c5b2abe0SLewanczyk, Dawid "None", "Pxe", "Hdd", "Cd", 537*c5b2abe0SLewanczyk, Dawid "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot data 538*c5b2abe0SLewanczyk, Dawid Node::json["ProcessorSummary"]["Count"] = int(0); 539*c5b2abe0SLewanczyk, Dawid Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled"; 540*c5b2abe0SLewanczyk, Dawid Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0); 541*c5b2abe0SLewanczyk, Dawid Node::json["MemorySummary"]["Status"]["State"] = "Disabled"; 542*c5b2abe0SLewanczyk, Dawid 543*c5b2abe0SLewanczyk, Dawid entityPrivileges = { 544*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::get, {{"Login"}}}, 545*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::head, {{"Login"}}}, 546*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 547*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 548*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 549*c5b2abe0SLewanczyk, Dawid {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 550*c5b2abe0SLewanczyk, Dawid } 551*c5b2abe0SLewanczyk, Dawid 552*c5b2abe0SLewanczyk, Dawid private: 553*c5b2abe0SLewanczyk, Dawid OnDemandSystemsProvider provider; 554*c5b2abe0SLewanczyk, Dawid 555*c5b2abe0SLewanczyk, Dawid /** 556*c5b2abe0SLewanczyk, Dawid * Functions triggers appropriate requests on DBus 557*c5b2abe0SLewanczyk, Dawid */ 558*c5b2abe0SLewanczyk, Dawid void doGet(crow::response &res, const crow::request &req, 559*c5b2abe0SLewanczyk, Dawid const std::vector<std::string> ¶ms) override { 560*c5b2abe0SLewanczyk, Dawid // Check if there is required param, truly entering this shall be 561*c5b2abe0SLewanczyk, Dawid // impossible 562*c5b2abe0SLewanczyk, Dawid if (params.size() != 1) { 563*c5b2abe0SLewanczyk, Dawid res.result(boost::beast::http::status::internal_server_error); 564*c5b2abe0SLewanczyk, Dawid res.end(); 565*c5b2abe0SLewanczyk, Dawid return; 566*c5b2abe0SLewanczyk, Dawid } 567*c5b2abe0SLewanczyk, Dawid 568*c5b2abe0SLewanczyk, Dawid const std::string &name = params[0]; 569*c5b2abe0SLewanczyk, Dawid 570*c5b2abe0SLewanczyk, Dawid res.json_value = Node::json; 571*c5b2abe0SLewanczyk, Dawid res.json_value["@odata.id"] = "/redfish/v1/Systems/" + name; 572*c5b2abe0SLewanczyk, Dawid 573*c5b2abe0SLewanczyk, Dawid auto asyncResp = std::make_shared<SystemAsyncResp>(res); 574*c5b2abe0SLewanczyk, Dawid 575*c5b2abe0SLewanczyk, Dawid provider.getLedGroupIdentify( 576*c5b2abe0SLewanczyk, Dawid asyncResp, [&](const bool &asserted, 577*c5b2abe0SLewanczyk, Dawid const std::shared_ptr<SystemAsyncResp> &aResp) { 578*c5b2abe0SLewanczyk, Dawid if (asserted) { 579*c5b2abe0SLewanczyk, Dawid // If led group is asserted, then another call is needed to 580*c5b2abe0SLewanczyk, Dawid // get led status 581*c5b2abe0SLewanczyk, Dawid provider.getLedIdentify( 582*c5b2abe0SLewanczyk, Dawid aResp, [](const std::string &ledStatus, 583*c5b2abe0SLewanczyk, Dawid const std::shared_ptr<SystemAsyncResp> &aResp) { 584*c5b2abe0SLewanczyk, Dawid if (!ledStatus.empty()) { 585*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["IndicatorLED"] = ledStatus; 586*c5b2abe0SLewanczyk, Dawid } 587*c5b2abe0SLewanczyk, Dawid }); 588*c5b2abe0SLewanczyk, Dawid } else { 589*c5b2abe0SLewanczyk, Dawid aResp->res.json_value["IndicatorLED"] = "Off"; 590*c5b2abe0SLewanczyk, Dawid } 591*c5b2abe0SLewanczyk, Dawid }); 592*c5b2abe0SLewanczyk, Dawid provider.getComputerSystem(asyncResp, name); 593*c5b2abe0SLewanczyk, Dawid provider.getHostState(asyncResp); 594*c5b2abe0SLewanczyk, Dawid } 595*c5b2abe0SLewanczyk, Dawid 596*c5b2abe0SLewanczyk, Dawid void doPatch(crow::response &res, const crow::request &req, 597*c5b2abe0SLewanczyk, Dawid const std::vector<std::string> ¶ms) override { 598*c5b2abe0SLewanczyk, Dawid // Check if there is required param, truly entering this shall be 599*c5b2abe0SLewanczyk, Dawid // impossible 600*c5b2abe0SLewanczyk, Dawid if (params.size() != 1) { 601*c5b2abe0SLewanczyk, Dawid res.result(boost::beast::http::status::internal_server_error); 602*c5b2abe0SLewanczyk, Dawid res.end(); 603*c5b2abe0SLewanczyk, Dawid return; 604*c5b2abe0SLewanczyk, Dawid } 605*c5b2abe0SLewanczyk, Dawid // Parse JSON request body 606*c5b2abe0SLewanczyk, Dawid nlohmann::json patch; 607*c5b2abe0SLewanczyk, Dawid if (!json_util::processJsonFromRequest(res, req, patch)) { 608*c5b2abe0SLewanczyk, Dawid return; 609*c5b2abe0SLewanczyk, Dawid } 610*c5b2abe0SLewanczyk, Dawid // Find key with new led value 611*c5b2abe0SLewanczyk, Dawid const std::string &name = params[0]; 612*c5b2abe0SLewanczyk, Dawid const std::string *reqLedState = nullptr; 613*c5b2abe0SLewanczyk, Dawid json_util::Result r = json_util::getString( 614*c5b2abe0SLewanczyk, Dawid "IndicatorLED", patch, reqLedState, 615*c5b2abe0SLewanczyk, Dawid static_cast<int>(json_util::MessageSetting::TYPE_ERROR) | 616*c5b2abe0SLewanczyk, Dawid static_cast<int>(json_util::MessageSetting::MISSING), 617*c5b2abe0SLewanczyk, Dawid res.json_value, std::string("/" + name + "/IndicatorLED")); 618*c5b2abe0SLewanczyk, Dawid if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr)) { 619*c5b2abe0SLewanczyk, Dawid res.result(boost::beast::http::status::bad_request); 620*c5b2abe0SLewanczyk, Dawid res.end(); 621*c5b2abe0SLewanczyk, Dawid return; 622*c5b2abe0SLewanczyk, Dawid } 623*c5b2abe0SLewanczyk, Dawid // Verify key value 624*c5b2abe0SLewanczyk, Dawid std::string dbusLedState; 625*c5b2abe0SLewanczyk, Dawid for (const auto &p : boost::container::flat_map<const char *, const char *>{ 626*c5b2abe0SLewanczyk, Dawid {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}}) { 627*c5b2abe0SLewanczyk, Dawid if (*reqLedState == p.second) { 628*c5b2abe0SLewanczyk, Dawid dbusLedState = p.first; 629*c5b2abe0SLewanczyk, Dawid } 630*c5b2abe0SLewanczyk, Dawid } 631*c5b2abe0SLewanczyk, Dawid 632*c5b2abe0SLewanczyk, Dawid // Update led status 633*c5b2abe0SLewanczyk, Dawid auto asyncResp = std::make_shared<SystemAsyncResp>(res); 634*c5b2abe0SLewanczyk, Dawid res.json_value = Node::json; 635*c5b2abe0SLewanczyk, Dawid res.json_value["@odata.id"] = "/redfish/v1/Systems/" + name; 636*c5b2abe0SLewanczyk, Dawid 637*c5b2abe0SLewanczyk, Dawid provider.getHostState(asyncResp); 638*c5b2abe0SLewanczyk, Dawid provider.getComputerSystem(asyncResp, name); 639*c5b2abe0SLewanczyk, Dawid 640*c5b2abe0SLewanczyk, Dawid if (dbusLedState.empty()) { 641*c5b2abe0SLewanczyk, Dawid messages::addMessageToJsonRoot( 642*c5b2abe0SLewanczyk, Dawid res.json_value, 643*c5b2abe0SLewanczyk, Dawid messages::propertyValueNotInList(*reqLedState, "IndicatorLED")); 644*c5b2abe0SLewanczyk, Dawid } else { 645*c5b2abe0SLewanczyk, Dawid // Update led group 646*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Update led group."; 647*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 648*c5b2abe0SLewanczyk, Dawid [&, asyncResp{std::move(asyncResp)} ]( 649*c5b2abe0SLewanczyk, Dawid const boost::system::error_code ec) { 650*c5b2abe0SLewanczyk, Dawid if (ec) { 651*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "DBUS response error " << ec; 652*c5b2abe0SLewanczyk, Dawid asyncResp->setErrorStatus(); 653*c5b2abe0SLewanczyk, Dawid return; 654*c5b2abe0SLewanczyk, Dawid } 655*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Led group update done."; 656*c5b2abe0SLewanczyk, Dawid }, 657*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.LED.GroupManager", 658*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/led/groups/enclosure_identify", 659*c5b2abe0SLewanczyk, Dawid "org.freedesktop.DBus.Properties", "Set", 660*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Led.Group", "Asserted", 661*c5b2abe0SLewanczyk, Dawid sdbusplus::message::variant<bool>( 662*c5b2abe0SLewanczyk, Dawid (dbusLedState == "Off" ? false : true))); 663*c5b2abe0SLewanczyk, Dawid // Update identify led status 664*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Update led SoftwareInventoryCollection."; 665*c5b2abe0SLewanczyk, Dawid crow::connections::system_bus->async_method_call( 666*c5b2abe0SLewanczyk, Dawid [&, asyncResp{std::move(asyncResp)} ]( 667*c5b2abe0SLewanczyk, Dawid const boost::system::error_code ec) { 668*c5b2abe0SLewanczyk, Dawid if (ec) { 669*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "DBUS response error " << ec; 670*c5b2abe0SLewanczyk, Dawid asyncResp->setErrorStatus(); 671*c5b2abe0SLewanczyk, Dawid return; 672*c5b2abe0SLewanczyk, Dawid } 673*c5b2abe0SLewanczyk, Dawid CROW_LOG_DEBUG << "Led state update done."; 674*c5b2abe0SLewanczyk, Dawid res.json_value["IndicatorLED"] = *reqLedState; 675*c5b2abe0SLewanczyk, Dawid }, 676*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.LED.Controller.identify", 677*c5b2abe0SLewanczyk, Dawid "/xyz/openbmc_project/led/physical/identify", 678*c5b2abe0SLewanczyk, Dawid "org.freedesktop.DBus.Properties", "Set", 679*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Led.Physical", "State", 680*c5b2abe0SLewanczyk, Dawid sdbusplus::message::variant<std::string>( 681*c5b2abe0SLewanczyk, Dawid "xyz.openbmc_project.Led.Physical.Action." + dbusLedState)); 682*c5b2abe0SLewanczyk, Dawid } 683*c5b2abe0SLewanczyk, Dawid } 684*c5b2abe0SLewanczyk, Dawid }; 685*c5b2abe0SLewanczyk, Dawid } // namespace redfish 686