1e37f8451SRapkiewicz, Pawel /* 2e37f8451SRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 3e37f8451SRapkiewicz, Pawel // 4e37f8451SRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 5e37f8451SRapkiewicz, Pawel // you may not use this file except in compliance with the License. 6e37f8451SRapkiewicz, Pawel // You may obtain a copy of the License at 7e37f8451SRapkiewicz, Pawel // 8e37f8451SRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 9e37f8451SRapkiewicz, Pawel // 10e37f8451SRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 11e37f8451SRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 12e37f8451SRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e37f8451SRapkiewicz, Pawel // See the License for the specific language governing permissions and 14e37f8451SRapkiewicz, Pawel // limitations under the License. 15e37f8451SRapkiewicz, Pawel */ 16e37f8451SRapkiewicz, Pawel #pragma once 17e37f8451SRapkiewicz, Pawel 18e37f8451SRapkiewicz, Pawel #include "node.hpp" 191abe55efSEd Tanous 20e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp> 21e37f8451SRapkiewicz, Pawel 221abe55efSEd Tanous namespace redfish 231abe55efSEd Tanous { 24e37f8451SRapkiewicz, Pawel 25e37f8451SRapkiewicz, Pawel /** 26e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 27e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 28e37f8451SRapkiewicz, Pawel */ 2955c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get 30aa2e59c1SEd Tanous // values, it should be as simple as possible 31aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type 3204a258f4SEd Tanous using VariantType = sdbusplus::message::variant<bool, std::string, uint64_t>; 33aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 34aa2e59c1SEd Tanous sdbusplus::message::object_path, 35aa2e59c1SEd Tanous std::vector<std::pair<std::string, 36aa2e59c1SEd Tanous std::vector<std::pair<std::string, VariantType>>>>>>; 37e37f8451SRapkiewicz, Pawel 38aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>; 39e37f8451SRapkiewicz, Pawel 40e37f8451SRapkiewicz, Pawel /** 41e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 42e37f8451SRapkiewicz, Pawel */ 431abe55efSEd Tanous class ChassisCollection : public Node 441abe55efSEd Tanous { 45e37f8451SRapkiewicz, Pawel public: 461abe55efSEd Tanous ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/") 471abe55efSEd Tanous { 48e0d918bcSEd Tanous entityPrivileges = { 49e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 50e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 51e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 52e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 53e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 54e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 55e37f8451SRapkiewicz, Pawel } 56e37f8451SRapkiewicz, Pawel 57e37f8451SRapkiewicz, Pawel private: 58e37f8451SRapkiewicz, Pawel /** 59e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 60e37f8451SRapkiewicz, Pawel */ 6155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 621abe55efSEd Tanous const std::vector<std::string> ¶ms) override 631abe55efSEd Tanous { 64*8f1ac8e9SGunnar Mills const std::array<const char *, 3> interfaces = { 6562d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Board", 6662d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Chassis", 67*8f1ac8e9SGunnar Mills "xyz.openbmc_project.Inventory.Item.PowerSupply"}; 680f74e643SEd Tanous res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection"; 690f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 700f74e643SEd Tanous res.jsonValue["@odata.context"] = 710f74e643SEd Tanous "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; 720f74e643SEd Tanous res.jsonValue["Name"] = "Chassis Collection"; 730f74e643SEd Tanous 7462d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 7562d5e2e4SEd Tanous crow::connections::systemBus->async_method_call( 7662d5e2e4SEd Tanous [asyncResp](const boost::system::error_code ec, 7762d5e2e4SEd Tanous const std::vector<std::string> &chassisList) { 7862d5e2e4SEd Tanous if (ec) 791abe55efSEd Tanous { 80f12894f8SJason M. Bills messages::internalError(asyncResp->res); 8162d5e2e4SEd Tanous return; 82e37f8451SRapkiewicz, Pawel } 8362d5e2e4SEd Tanous nlohmann::json &chassisArray = 8462d5e2e4SEd Tanous asyncResp->res.jsonValue["Members"]; 8562d5e2e4SEd Tanous chassisArray = nlohmann::json::array(); 8662d5e2e4SEd Tanous for (const std::string &objpath : chassisList) 8762d5e2e4SEd Tanous { 8862d5e2e4SEd Tanous std::size_t lastPos = objpath.rfind("/"); 8962d5e2e4SEd Tanous if (lastPos == std::string::npos) 9062d5e2e4SEd Tanous { 9162d5e2e4SEd Tanous BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 9262d5e2e4SEd Tanous continue; 9362d5e2e4SEd Tanous } 9462d5e2e4SEd Tanous chassisArray.push_back( 9562d5e2e4SEd Tanous {{"@odata.id", "/redfish/v1/Chassis/" + 9662d5e2e4SEd Tanous objpath.substr(lastPos + 1)}}); 97e37f8451SRapkiewicz, Pawel } 98e37f8451SRapkiewicz, Pawel 9962d5e2e4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10062d5e2e4SEd Tanous chassisArray.size(); 10162d5e2e4SEd Tanous }, 10262d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", 10362d5e2e4SEd Tanous "/xyz/openbmc_project/object_mapper", 10462d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 10562d5e2e4SEd Tanous "/xyz/openbmc_project/inventory", int32_t(3), interfaces); 10662d5e2e4SEd Tanous } 107e37f8451SRapkiewicz, Pawel }; 108e37f8451SRapkiewicz, Pawel 109e37f8451SRapkiewicz, Pawel /** 110e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 111e37f8451SRapkiewicz, Pawel */ 1121abe55efSEd Tanous class Chassis : public Node 1131abe55efSEd Tanous { 114e37f8451SRapkiewicz, Pawel public: 1151abe55efSEd Tanous Chassis(CrowApp &app) : 1161abe55efSEd Tanous Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 1171abe55efSEd Tanous { 118e0d918bcSEd Tanous entityPrivileges = { 119e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 120e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 121e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 122e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 123e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 124e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 125e37f8451SRapkiewicz, Pawel } 126e37f8451SRapkiewicz, Pawel 127e37f8451SRapkiewicz, Pawel private: 128e37f8451SRapkiewicz, Pawel /** 129e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 130e37f8451SRapkiewicz, Pawel */ 13155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 1321abe55efSEd Tanous const std::vector<std::string> ¶ms) override 1331abe55efSEd Tanous { 134e37f8451SRapkiewicz, Pawel // Check if there is required param, truly entering this shall be 135e37f8451SRapkiewicz, Pawel // impossible. 1361abe55efSEd Tanous if (params.size() != 1) 1371abe55efSEd Tanous { 138f12894f8SJason M. Bills messages::internalError(res); 139e37f8451SRapkiewicz, Pawel res.end(); 140e37f8451SRapkiewicz, Pawel return; 141e37f8451SRapkiewicz, Pawel } 142e37f8451SRapkiewicz, Pawel 1430f74e643SEd Tanous res.jsonValue["@odata.type"] = "#Chassis.v1_4_0.Chassis"; 1440f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1450f74e643SEd Tanous res.jsonValue["@odata.context"] = 1460f74e643SEd Tanous "/redfish/v1/$metadata#Chassis.Chassis"; 1470f74e643SEd Tanous res.jsonValue["Name"] = "Chassis Collection"; 1480f74e643SEd Tanous res.jsonValue["ChassisType"] = "RackMount"; 1490f74e643SEd Tanous res.jsonValue["PowerState"] = "On"; 1500f74e643SEd Tanous 15155c7b7a2SEd Tanous const std::string &chassisId = params[0]; 15262d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 15355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 15462d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 15562d5e2e4SEd Tanous const boost::system::error_code ec, 156daf36e2eSEd Tanous const std::vector<std::pair< 1571abe55efSEd Tanous std::string, std::vector<std::pair< 1581abe55efSEd Tanous std::string, std::vector<std::string>>>>> 159daf36e2eSEd Tanous &subtree) { 16062d5e2e4SEd Tanous if (ec) 1611abe55efSEd Tanous { 162f12894f8SJason M. Bills messages::internalError(asyncResp->res); 163daf36e2eSEd Tanous return; 164daf36e2eSEd Tanous } 165daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 1661abe55efSEd Tanous for (const std::pair< 1671abe55efSEd Tanous std::string, 1681abe55efSEd Tanous std::vector< 1691abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>>> 1701abe55efSEd Tanous &object : subtree) 1711abe55efSEd Tanous { 172daf36e2eSEd Tanous const std::string &path = object.first; 1731abe55efSEd Tanous const std::vector< 1741abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>> 175daf36e2eSEd Tanous &connectionNames = object.second; 176e0d918bcSEd Tanous 1771abe55efSEd Tanous if (!boost::ends_with(path, chassisId)) 1781abe55efSEd Tanous { 179daf36e2eSEd Tanous continue; 180daf36e2eSEd Tanous } 1811abe55efSEd Tanous if (connectionNames.size() < 1) 1821abe55efSEd Tanous { 1831abe55efSEd Tanous BMCWEB_LOG_ERROR << "Only got " 1841abe55efSEd Tanous << connectionNames.size() 18555c7b7a2SEd Tanous << " Connection names"; 186e0d918bcSEd Tanous continue; 187daf36e2eSEd Tanous } 188e0d918bcSEd Tanous 189daf36e2eSEd Tanous const std::string connectionName = connectionNames[0].first; 19055c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 19162d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 19262d5e2e4SEd Tanous const boost::system::error_code ec, 1931abe55efSEd Tanous const std::vector<std::pair< 1941abe55efSEd Tanous std::string, VariantType>> &propertiesList) { 1951abe55efSEd Tanous for (const std::pair<std::string, VariantType> 1961abe55efSEd Tanous &property : propertiesList) 1971abe55efSEd Tanous { 198daf36e2eSEd Tanous const std::string *value = 1991b6b96c5SEd Tanous sdbusplus::message::variant_ns::get_if< 2001b6b96c5SEd Tanous std::string>(&property.second); 2011abe55efSEd Tanous if (value != nullptr) 2021abe55efSEd Tanous { 20362d5e2e4SEd Tanous asyncResp->res.jsonValue[property.first] = 20462d5e2e4SEd Tanous *value; 205daf36e2eSEd Tanous } 206daf36e2eSEd Tanous } 20762d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 20862d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 20962d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 2101abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2111abe55efSEd Tanous chassisId + "/Thermal"}}; 2122474adfaSEd Tanous // Power object 2132474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 2142474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2152474adfaSEd Tanous chassisId + "/Power"}}; 2162474adfaSEd Tanous 2172474adfaSEd Tanous // TODO: An array of references to computer systems 2182474adfaSEd Tanous // contained in this chassis. 2192474adfaSEd Tanous // res.jsonValue["Links"]["ComputerSystems"] 2202474adfaSEd Tanous // = 2212474adfaSEd Tanous // {{{"@odata.id", 2222474adfaSEd Tanous // "/redfish/v1/Systems/1"}}}; 2232474adfaSEd Tanous // An array of references to the Managers 2242474adfaSEd Tanous // responsible for managing this chassis. 2252474adfaSEd Tanous // res.jsonValue["Links"]["ManagedBy"] = 2262474adfaSEd Tanous // {{{"@odata.id", 2272474adfaSEd Tanous // "/redfish/v1/Managers/1"}}}; 228daf36e2eSEd Tanous }, 229daf36e2eSEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 2301abe55efSEd Tanous "GetAll", 2311abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 232daf36e2eSEd Tanous return; 233daf36e2eSEd Tanous } 234e0d918bcSEd Tanous 235daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 236f12894f8SJason M. Bills messages::resourceNotFound( 237f12894f8SJason M. Bills asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId); 238daf36e2eSEd Tanous }, 239daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 240daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 241daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 242daf36e2eSEd Tanous "/xyz/openbmc_project/inventory", int32_t(0), 243daf36e2eSEd Tanous std::array<const char *, 1>{ 244daf36e2eSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"}); 245e37f8451SRapkiewicz, Pawel } 24662d5e2e4SEd Tanous }; 247e37f8451SRapkiewicz, Pawel } // namespace redfish 248